ezEngine  Milestone 7
OSFile_posix.h
1 #pragma once
2 
3 #include <unistd.h>
4 #include <errno.h>
5 #include <sys/stat.h>
6 
7 #if EZ_ENABLED(EZ_PLATFORM_OSX)
8 #include <CoreFoundation/CoreFoundation.h>
9 #endif
10 
11 ezResult ezOSFile::InternalOpen(const char* szFile, ezFileMode::Enum OpenMode)
12 {
13  switch (OpenMode)
14  {
15  case ezFileMode::Read:
16  m_FileData.m_pFileHandle = fopen(szFile, "rb");
17  break;
18  case ezFileMode::Write:
19  m_FileData.m_pFileHandle = fopen(szFile, "wb");
20  break;
21  case ezFileMode::Append:
22  m_FileData.m_pFileHandle = fopen(szFile, "ab");
23 
24  // in append mode we need to set the file pointer to the end explicitly, otherwise GetFilePosition might return 0 the first time
25  if (m_FileData.m_pFileHandle != nullptr)
26  InternalSetFilePosition(0, ezFilePos::FromEnd);
27 
28  break;
29  default:
30  break;
31  }
32 
33  return m_FileData.m_pFileHandle != nullptr ? EZ_SUCCESS : EZ_FAILURE;
34 }
35 
36 void ezOSFile::InternalClose()
37 {
38  fclose(m_FileData.m_pFileHandle);
39 }
40 
41 ezResult ezOSFile::InternalWrite(const void* pBuffer, ezUInt64 uiBytes)
42 {
43  const ezUInt32 uiBatchBytes = 1024 * 1024 * 1024; // 1 GB
44 
45  // first write out all the data in 1GB batches
46  while (uiBytes > uiBatchBytes)
47  {
48  if (fwrite(pBuffer, 1, uiBatchBytes, m_FileData.m_pFileHandle) != uiBatchBytes)
49  return EZ_FAILURE;
50 
51  uiBytes -= uiBatchBytes;
52  pBuffer = ezMemoryUtils::AddByteOffsetConst(pBuffer, uiBatchBytes);
53  }
54 
55  if (uiBytes > 0)
56  {
57  const ezUInt32 uiBytes32 = static_cast<ezUInt32>(uiBytes);
58 
59  if (fwrite(pBuffer, 1, uiBytes32, m_FileData.m_pFileHandle) != uiBytes)
60  return EZ_FAILURE;
61  }
62 
63  return EZ_SUCCESS;
64 }
65 
66 ezUInt64 ezOSFile::InternalRead(void* pBuffer, ezUInt64 uiBytes)
67 {
68  ezUInt64 uiBytesRead = 0;
69 
70  const ezUInt32 uiBatchBytes = 1024 * 1024 * 1024; // 1 GB
71 
72  // first write out all the data in 1GB batches
73  while (uiBytes > uiBatchBytes)
74  {
75  const ezUInt64 uiReadThisTime = fread(pBuffer, 1, uiBatchBytes, m_FileData.m_pFileHandle);
76  uiBytesRead += uiReadThisTime;
77 
78  if (uiReadThisTime != uiBatchBytes)
79  return uiBytesRead;
80 
81  uiBytes -= uiBatchBytes;
82  pBuffer = ezMemoryUtils::AddByteOffset(pBuffer, uiBatchBytes);
83  }
84 
85  if (uiBytes > 0)
86  {
87  const ezUInt32 uiBytes32 = static_cast<ezUInt32>(uiBytes);
88 
89  uiBytesRead += fread(pBuffer, 1, uiBytes32, m_FileData.m_pFileHandle);
90  }
91 
92  return uiBytesRead;
93 }
94 
95 ezUInt64 ezOSFile::InternalGetFilePosition() const
96 {
97  return static_cast<ezUInt64>(ftello(m_FileData.m_pFileHandle));
98 }
99 
100 void ezOSFile::InternalSetFilePosition(ezInt64 iDistance, ezFilePos::Enum Pos) const
101 {
102  switch (Pos)
103  {
105  EZ_VERIFY(fseeko(m_FileData.m_pFileHandle, iDistance, SEEK_SET) == 0, "Seek Failed");
106  break;
107  case ezFilePos::FromEnd:
108  EZ_VERIFY(fseeko(m_FileData.m_pFileHandle, iDistance, SEEK_END) == 0, "Seek Failed");
109  break;
111  EZ_VERIFY(fseeko(m_FileData.m_pFileHandle, iDistance, SEEK_CUR) == 0, "Seek Failed");
112  break;
113  }
114 }
115 
116 bool ezOSFile::InternalExistsFile(const char* szFile)
117 {
118  FILE* pFile = fopen(szFile, "r");
119 
120  if (pFile == nullptr)
121  return false;
122 
123  fclose(pFile);
124  return true;
125 }
126 
127 bool ezOSFile::InternalExistsDirectory(const char* szDirectory)
128 {
129  struct stat sb;
130  return (stat(szDirectory, &sb) == 0 && S_ISDIR(sb.st_mode));
131 }
132 
133 ezResult ezOSFile::InternalDeleteFile(const char* szFile)
134 {
135  int iRes = unlink(szFile);
136 
137  if (iRes == 0 || (iRes == -1 && errno == ENOENT))
138  return EZ_SUCCESS;
139 
140  return EZ_FAILURE;
141 }
142 
143 ezResult ezOSFile::InternalCreateDirectory(const char* szDirectory)
144 {
145  // handle drive letters as always successful
146  if (ezStringUtils::GetCharacterCount(szDirectory) <= 1) // '/'
147  return EZ_SUCCESS;
148 
149  int iRes = mkdir(szDirectory, 0777);
150 
151  if (iRes == 0 || (iRes == -1 && errno == EEXIST))
152  return EZ_SUCCESS;
153 
154  return EZ_FAILURE;
155 }
156 
157 #if EZ_ENABLED(EZ_SUPPORTS_FILE_STATS)
158 ezResult ezOSFile::InternalGetFileStats(const char* szFileOrFolder, ezFileStats& out_Stats)
159 {
160  stat tempStat;
161  int iRes = stat(szFileOrFolder, &tempStat);
162 
163  if (iRes != 0)
164  return EZ_FAILURE;
165 
166  out_Stats.m_bIsDirectory = S_ISDIR(tempStat.st_mode);
167  out_Stats.m_uiFileSize = tempStat.st_size;
168  out_Stats.m_sFileName = "";
169  out_Stats.m_LastModificationTime.SetInt64(tempStat.st_mtime, ezSIUnitOfTime::Second);
170 
171  return EZ_SUCCESS;
172 }
173 #endif
174 
176 {
177 #if EZ_ENABLED(EZ_PLATFORM_OSX)
178 
179  static ezString256 s_Path;
180 
181  if(s_Path.IsEmpty())
182  {
183  CFBundleRef appBundle = CFBundleGetMainBundle();
184  CFURLRef bundleURL = CFBundleCopyBundleURL(appBundle);
185  CFStringRef bundlePath = CFURLCopyFileSystemPath( bundleURL, kCFURLPOSIXPathStyle );
186 
187  if(bundlePath != nullptr)
188  {
189  CFIndex length = CFStringGetLength(bundlePath);
190  CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
191 
192  ezArrayPtr<char> temp = EZ_DEFAULT_NEW_ARRAY(char, maxSize);
193 
194  if(CFStringGetCString(bundlePath, temp.GetPtr(), maxSize, kCFStringEncodingUTF8))
195  {
196  s_Path = temp.GetPtr();
197  }
198 
200  }
201 
202  CFRelease(bundlePath);
203  CFRelease(bundleURL);
204  CFRelease(appBundle);
205  }
206 
207  return s_Path.GetData();
208 
209 #else
210  #warning Not yet implemented.
211 #endif
212 
213  return nullptr;
214 }
215