rev |
line source |
nuclear@0
|
1 /**************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 Filename : OVR_FileFILE.cpp
|
nuclear@0
|
4 Content : File wrapper class implementation (Win32)
|
nuclear@0
|
5
|
nuclear@0
|
6 Created : April 5, 1999
|
nuclear@0
|
7 Authors : Michael Antonov
|
nuclear@0
|
8
|
nuclear@0
|
9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
10
|
nuclear@0
|
11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
13 which is provided at the time of installation or download, or which
|
nuclear@0
|
14 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
15
|
nuclear@0
|
16 You may obtain a copy of the License at
|
nuclear@0
|
17
|
nuclear@0
|
18 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
19
|
nuclear@0
|
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
21 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
23 See the License for the specific language governing permissions and
|
nuclear@0
|
24 limitations under the License.
|
nuclear@0
|
25
|
nuclear@0
|
26 **************************************************************************/
|
nuclear@0
|
27
|
nuclear@0
|
28 #define GFILE_CXX
|
nuclear@0
|
29
|
nuclear@0
|
30 #include "OVR_Types.h"
|
nuclear@0
|
31 #include "OVR_Log.h"
|
nuclear@0
|
32
|
nuclear@0
|
33 // Standard C library (Captain Obvious guarantees!)
|
nuclear@0
|
34 #include <stdio.h>
|
nuclear@0
|
35 #ifndef OVR_OS_WINCE
|
nuclear@0
|
36 #include <sys/stat.h>
|
nuclear@0
|
37 #endif
|
nuclear@0
|
38
|
nuclear@0
|
39 #include "OVR_SysFile.h"
|
nuclear@0
|
40
|
nuclear@0
|
41 #ifndef OVR_OS_WINCE
|
nuclear@0
|
42 #include <errno.h>
|
nuclear@0
|
43 #endif
|
nuclear@0
|
44
|
nuclear@0
|
45 namespace OVR {
|
nuclear@0
|
46
|
nuclear@0
|
47 // ***** File interface
|
nuclear@0
|
48
|
nuclear@0
|
49 // ***** FILEFile - C streams file
|
nuclear@0
|
50
|
nuclear@0
|
51 static int SFerror ()
|
nuclear@0
|
52 {
|
nuclear@0
|
53 if (errno == ENOENT)
|
nuclear@0
|
54 return FileConstants::Error_FileNotFound;
|
nuclear@0
|
55 else if (errno == EACCES || errno == EPERM)
|
nuclear@0
|
56 return FileConstants::Error_Access;
|
nuclear@0
|
57 else if (errno == ENOSPC)
|
nuclear@0
|
58 return FileConstants::Error_DiskFull;
|
nuclear@0
|
59 else
|
nuclear@0
|
60 return FileConstants::Error_IOError;
|
nuclear@0
|
61 };
|
nuclear@0
|
62
|
nuclear@0
|
63 #if defined(OVR_OS_WIN32)
|
nuclear@0
|
64 #define WIN32_LEAN_AND_MEAN
|
nuclear@0
|
65 #include "windows.h"
|
nuclear@0
|
66 // A simple helper class to disable/enable system error mode, if necessary
|
nuclear@0
|
67 // Disabling happens conditionally only if a drive name is involved
|
nuclear@0
|
68 class SysErrorModeDisabler
|
nuclear@0
|
69 {
|
nuclear@0
|
70 BOOL Disabled;
|
nuclear@0
|
71 UINT OldMode;
|
nuclear@0
|
72 public:
|
nuclear@0
|
73 SysErrorModeDisabler(const char* pfileName)
|
nuclear@0
|
74 {
|
nuclear@0
|
75 if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
|
nuclear@0
|
76 {
|
nuclear@0
|
77 Disabled = TRUE;
|
nuclear@0
|
78 OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
|
nuclear@0
|
79 }
|
nuclear@0
|
80 else
|
nuclear@0
|
81 {
|
nuclear@0
|
82 Disabled = 0;
|
nuclear@0
|
83 OldMode = 0;
|
nuclear@0
|
84 }
|
nuclear@0
|
85 }
|
nuclear@0
|
86
|
nuclear@0
|
87 ~SysErrorModeDisabler()
|
nuclear@0
|
88 {
|
nuclear@0
|
89 if (Disabled)
|
nuclear@0
|
90 ::SetErrorMode(OldMode);
|
nuclear@0
|
91 }
|
nuclear@0
|
92 };
|
nuclear@0
|
93 #else
|
nuclear@0
|
94 class SysErrorModeDisabler
|
nuclear@0
|
95 {
|
nuclear@0
|
96 public:
|
nuclear@0
|
97 SysErrorModeDisabler(const char* pfileName) { OVR_UNUSED(pfileName); }
|
nuclear@0
|
98 };
|
nuclear@0
|
99 #endif // OVR_OS_WIN32
|
nuclear@0
|
100
|
nuclear@0
|
101
|
nuclear@0
|
102 // This macro enables verification of I/O results after seeks against a pre-loaded
|
nuclear@0
|
103 // full file buffer copy. This is generally not necessary, but can been used to debug
|
nuclear@0
|
104 // memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory
|
nuclear@0
|
105 // under FMOD with XP64 (32-bit) and Realtek HA Audio driver.
|
nuclear@0
|
106 //#define GFILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
107
|
nuclear@0
|
108
|
nuclear@0
|
109 // This is the simplest possible file implementation, it wraps around the descriptor
|
nuclear@0
|
110 // This file is delegated to by SysFile.
|
nuclear@0
|
111
|
nuclear@0
|
112 class FILEFile : public File
|
nuclear@0
|
113 {
|
nuclear@0
|
114 protected:
|
nuclear@0
|
115
|
nuclear@0
|
116 // Allocated filename
|
nuclear@0
|
117 String FileName;
|
nuclear@0
|
118
|
nuclear@0
|
119 // File handle & open mode
|
nuclear@0
|
120 bool Opened;
|
nuclear@0
|
121 FILE* fs;
|
nuclear@0
|
122 int OpenFlags;
|
nuclear@0
|
123 // Error code for last request
|
nuclear@0
|
124 int ErrorCode;
|
nuclear@0
|
125
|
nuclear@0
|
126 int LastOp;
|
nuclear@0
|
127
|
nuclear@0
|
128 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
129 uint8_t* pFileTestBuffer;
|
nuclear@0
|
130 unsigned FileTestLength;
|
nuclear@0
|
131 unsigned TestPos; // File pointer position during tests.
|
nuclear@0
|
132 #endif
|
nuclear@0
|
133
|
nuclear@0
|
134 public:
|
nuclear@0
|
135
|
nuclear@0
|
136 FILEFile() :
|
nuclear@0
|
137 FileName(),
|
nuclear@0
|
138 Opened(false),
|
nuclear@0
|
139 fs(NULL),
|
nuclear@0
|
140 OpenFlags(0),
|
nuclear@0
|
141 ErrorCode(0),
|
nuclear@0
|
142 LastOp(0)
|
nuclear@0
|
143 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
144 ,pFileTestBuffer(NULL)
|
nuclear@0
|
145 ,FileTestLength(0)
|
nuclear@0
|
146 ,TestPos(0)
|
nuclear@0
|
147 #endif
|
nuclear@0
|
148 {
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 // Initialize file by opening it
|
nuclear@0
|
152 FILEFile(const String& fileName, int flags, int Mode);
|
nuclear@0
|
153
|
nuclear@0
|
154 // The 'pfileName' should be encoded as UTF-8 to support international file names.
|
nuclear@0
|
155 FILEFile(const char* pfileName, int flags, int Mode);
|
nuclear@0
|
156
|
nuclear@0
|
157 ~FILEFile()
|
nuclear@0
|
158 {
|
nuclear@0
|
159 if (Opened)
|
nuclear@0
|
160 Close();
|
nuclear@0
|
161 }
|
nuclear@0
|
162
|
nuclear@0
|
163 virtual const char* GetFilePath();
|
nuclear@0
|
164
|
nuclear@0
|
165 // ** File Information
|
nuclear@0
|
166 virtual bool IsValid();
|
nuclear@0
|
167 virtual bool IsWritable();
|
nuclear@0
|
168
|
nuclear@0
|
169 // Return position / file size
|
nuclear@0
|
170 virtual int Tell();
|
nuclear@0
|
171 virtual int64_t LTell();
|
nuclear@0
|
172 virtual int GetLength();
|
nuclear@0
|
173 virtual int64_t LGetLength();
|
nuclear@0
|
174
|
nuclear@0
|
175 // virtual bool Stat(FileStats *pfs);
|
nuclear@0
|
176 virtual int GetErrorCode();
|
nuclear@0
|
177
|
nuclear@0
|
178 // ** Stream implementation & I/O
|
nuclear@0
|
179 virtual int Write(const uint8_t *pbuffer, int numBytes);
|
nuclear@0
|
180 virtual int Read(uint8_t *pbuffer, int numBytes);
|
nuclear@0
|
181 virtual int SkipBytes(int numBytes);
|
nuclear@0
|
182 virtual int BytesAvailable();
|
nuclear@0
|
183 virtual bool Flush();
|
nuclear@0
|
184 virtual int Seek(int offset, int origin);
|
nuclear@0
|
185 virtual int64_t LSeek(int64_t offset, int origin);
|
nuclear@0
|
186
|
nuclear@0
|
187 virtual int CopyFromStream(File *pStream, int byteSize);
|
nuclear@0
|
188 virtual bool Close();
|
nuclear@0
|
189 private:
|
nuclear@0
|
190 void init();
|
nuclear@0
|
191 };
|
nuclear@0
|
192
|
nuclear@0
|
193
|
nuclear@0
|
194 // Initialize file by opening it
|
nuclear@0
|
195 FILEFile::FILEFile(const String& fileName, int flags, int mode)
|
nuclear@0
|
196 : FileName(fileName), OpenFlags(flags)
|
nuclear@0
|
197 {
|
nuclear@0
|
198 OVR_UNUSED(mode);
|
nuclear@0
|
199 init();
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 // The 'pfileName' should be encoded as UTF-8 to support international file names.
|
nuclear@0
|
203 FILEFile::FILEFile(const char* pfileName, int flags, int mode)
|
nuclear@0
|
204 : FileName(pfileName), OpenFlags(flags)
|
nuclear@0
|
205 {
|
nuclear@0
|
206 OVR_UNUSED(mode);
|
nuclear@0
|
207 init();
|
nuclear@0
|
208 }
|
nuclear@0
|
209
|
nuclear@0
|
210 void FILEFile::init()
|
nuclear@0
|
211 {
|
nuclear@0
|
212 // Open mode for file's open
|
nuclear@0
|
213 const char *omode = "rb";
|
nuclear@0
|
214
|
nuclear@0
|
215 if (OpenFlags & Open_Truncate)
|
nuclear@0
|
216 {
|
nuclear@0
|
217 if (OpenFlags & Open_Read)
|
nuclear@0
|
218 omode = "w+b";
|
nuclear@0
|
219 else
|
nuclear@0
|
220 omode = "wb";
|
nuclear@0
|
221 }
|
nuclear@0
|
222 else if (OpenFlags & Open_Create)
|
nuclear@0
|
223 {
|
nuclear@0
|
224 if (OpenFlags & Open_Read)
|
nuclear@0
|
225 omode = "a+b";
|
nuclear@0
|
226 else
|
nuclear@0
|
227 omode = "ab";
|
nuclear@0
|
228 }
|
nuclear@0
|
229 else if (OpenFlags & Open_Write)
|
nuclear@0
|
230 omode = "r+b";
|
nuclear@0
|
231
|
nuclear@0
|
232 #if defined(OVR_OS_MS)
|
nuclear@0
|
233 SysErrorModeDisabler disabler(FileName.ToCStr());
|
nuclear@0
|
234 #endif
|
nuclear@0
|
235
|
nuclear@0
|
236 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
|
nuclear@0
|
237 wchar_t womode[16];
|
nuclear@0
|
238 wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
|
nuclear@0
|
239 UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
|
nuclear@0
|
240 OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
|
nuclear@0
|
241 UTF8Util::DecodeString(womode, omode);
|
nuclear@0
|
242 _wfopen_s(&fs, pwFileName, womode);
|
nuclear@0
|
243 OVR_FREE(pwFileName);
|
nuclear@0
|
244 #else
|
nuclear@0
|
245 fs = fopen(FileName.ToCStr(), omode);
|
nuclear@0
|
246 #endif
|
nuclear@0
|
247 if (fs)
|
nuclear@0
|
248 rewind (fs);
|
nuclear@0
|
249 Opened = (fs != NULL);
|
nuclear@0
|
250 // Set error code
|
nuclear@0
|
251 if (!Opened)
|
nuclear@0
|
252 ErrorCode = SFerror();
|
nuclear@0
|
253 else
|
nuclear@0
|
254 {
|
nuclear@0
|
255 // If we are testing file seek correctness, pre-load the entire file so
|
nuclear@0
|
256 // that we can do comparison tests later.
|
nuclear@0
|
257 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
258 TestPos = 0;
|
nuclear@0
|
259 fseek(fs, 0, SEEK_END);
|
nuclear@0
|
260 FileTestLength = ftell(fs);
|
nuclear@0
|
261 fseek(fs, 0, SEEK_SET);
|
nuclear@0
|
262 pFileTestBuffer = (uint8_t*)OVR_ALLOC(FileTestLength);
|
nuclear@0
|
263 if (pFileTestBuffer)
|
nuclear@0
|
264 {
|
nuclear@0
|
265 OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
|
nuclear@0
|
266 Seek(0, Seek_Set);
|
nuclear@0
|
267 }
|
nuclear@0
|
268 #endif
|
nuclear@0
|
269
|
nuclear@0
|
270 ErrorCode = 0;
|
nuclear@0
|
271 }
|
nuclear@0
|
272 LastOp = 0;
|
nuclear@0
|
273 }
|
nuclear@0
|
274
|
nuclear@0
|
275
|
nuclear@0
|
276 const char* FILEFile::GetFilePath()
|
nuclear@0
|
277 {
|
nuclear@0
|
278 return FileName.ToCStr();
|
nuclear@0
|
279 }
|
nuclear@0
|
280
|
nuclear@0
|
281
|
nuclear@0
|
282 // ** File Information
|
nuclear@0
|
283 bool FILEFile::IsValid()
|
nuclear@0
|
284 {
|
nuclear@0
|
285 return Opened;
|
nuclear@0
|
286 }
|
nuclear@0
|
287 bool FILEFile::IsWritable()
|
nuclear@0
|
288 {
|
nuclear@0
|
289 return IsValid() && (OpenFlags&Open_Write);
|
nuclear@0
|
290 }
|
nuclear@0
|
291 /*
|
nuclear@0
|
292 bool FILEFile::IsRecoverable()
|
nuclear@0
|
293 {
|
nuclear@0
|
294 return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC);
|
nuclear@0
|
295 }
|
nuclear@0
|
296 */
|
nuclear@0
|
297
|
nuclear@0
|
298 // Return position / file size
|
nuclear@0
|
299 int FILEFile::Tell()
|
nuclear@0
|
300 {
|
nuclear@0
|
301 int pos = (int)ftell (fs);
|
nuclear@0
|
302 if (pos < 0)
|
nuclear@0
|
303 ErrorCode = SFerror();
|
nuclear@0
|
304 return pos;
|
nuclear@0
|
305 }
|
nuclear@0
|
306
|
nuclear@0
|
307 int64_t FILEFile::LTell()
|
nuclear@0
|
308 {
|
nuclear@0
|
309 int64_t pos = ftell(fs);
|
nuclear@0
|
310 if (pos < 0)
|
nuclear@0
|
311 ErrorCode = SFerror();
|
nuclear@0
|
312 return pos;
|
nuclear@0
|
313 }
|
nuclear@0
|
314
|
nuclear@0
|
315 int FILEFile::GetLength()
|
nuclear@0
|
316 {
|
nuclear@0
|
317 int pos = Tell();
|
nuclear@0
|
318 if (pos >= 0)
|
nuclear@0
|
319 {
|
nuclear@0
|
320 Seek (0, Seek_End);
|
nuclear@0
|
321 int size = Tell();
|
nuclear@0
|
322 Seek (pos, Seek_Set);
|
nuclear@0
|
323 return size;
|
nuclear@0
|
324 }
|
nuclear@0
|
325 return -1;
|
nuclear@0
|
326 }
|
nuclear@0
|
327 int64_t FILEFile::LGetLength()
|
nuclear@0
|
328 {
|
nuclear@0
|
329 int64_t pos = LTell();
|
nuclear@0
|
330 if (pos >= 0)
|
nuclear@0
|
331 {
|
nuclear@0
|
332 LSeek (0, Seek_End);
|
nuclear@0
|
333 int64_t size = LTell();
|
nuclear@0
|
334 LSeek (pos, Seek_Set);
|
nuclear@0
|
335 return size;
|
nuclear@0
|
336 }
|
nuclear@0
|
337 return -1;
|
nuclear@0
|
338 }
|
nuclear@0
|
339
|
nuclear@0
|
340 int FILEFile::GetErrorCode()
|
nuclear@0
|
341 {
|
nuclear@0
|
342 return ErrorCode;
|
nuclear@0
|
343 }
|
nuclear@0
|
344
|
nuclear@0
|
345 // ** Stream implementation & I/O
|
nuclear@0
|
346 int FILEFile::Write(const uint8_t *pbuffer, int numBytes)
|
nuclear@0
|
347 {
|
nuclear@0
|
348 if (LastOp && LastOp != Open_Write)
|
nuclear@0
|
349 fflush(fs);
|
nuclear@0
|
350 LastOp = Open_Write;
|
nuclear@0
|
351 int written = (int) fwrite(pbuffer, 1, numBytes, fs);
|
nuclear@0
|
352 if (written < numBytes)
|
nuclear@0
|
353 ErrorCode = SFerror();
|
nuclear@0
|
354
|
nuclear@0
|
355 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
356 if (written > 0)
|
nuclear@0
|
357 TestPos += written;
|
nuclear@0
|
358 #endif
|
nuclear@0
|
359
|
nuclear@0
|
360 return written;
|
nuclear@0
|
361 }
|
nuclear@0
|
362
|
nuclear@0
|
363 int FILEFile::Read(uint8_t *pbuffer, int numBytes)
|
nuclear@0
|
364 {
|
nuclear@0
|
365 if (LastOp && LastOp != Open_Read)
|
nuclear@0
|
366 fflush(fs);
|
nuclear@0
|
367 LastOp = Open_Read;
|
nuclear@0
|
368 int read = (int) fread(pbuffer, 1, numBytes, fs);
|
nuclear@0
|
369 if (read < numBytes)
|
nuclear@0
|
370 ErrorCode = SFerror();
|
nuclear@0
|
371
|
nuclear@0
|
372 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
373 if (read > 0)
|
nuclear@0
|
374 {
|
nuclear@0
|
375 // Read-in data must match our pre-loaded buffer data!
|
nuclear@0
|
376 uint8_t* pcompareBuffer = pFileTestBuffer + TestPos;
|
nuclear@0
|
377 for (int i=0; i< read; i++)
|
nuclear@0
|
378 {
|
nuclear@0
|
379 OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
|
nuclear@0
|
380 }
|
nuclear@0
|
381
|
nuclear@0
|
382 //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read));
|
nuclear@0
|
383 TestPos += read;
|
nuclear@0
|
384 OVR_ASSERT(ftell(fs) == (int)TestPos);
|
nuclear@0
|
385 }
|
nuclear@0
|
386 #endif
|
nuclear@0
|
387
|
nuclear@0
|
388 return read;
|
nuclear@0
|
389 }
|
nuclear@0
|
390
|
nuclear@0
|
391 // Seeks ahead to skip bytes
|
nuclear@0
|
392 int FILEFile::SkipBytes(int numBytes)
|
nuclear@0
|
393 {
|
nuclear@0
|
394 int64_t pos = LTell();
|
nuclear@0
|
395 int64_t newPos = LSeek(numBytes, Seek_Cur);
|
nuclear@0
|
396
|
nuclear@0
|
397 // Return -1 for major error
|
nuclear@0
|
398 if ((pos==-1) || (newPos==-1))
|
nuclear@0
|
399 {
|
nuclear@0
|
400 return -1;
|
nuclear@0
|
401 }
|
nuclear@0
|
402 //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0;
|
nuclear@0
|
403
|
nuclear@0
|
404 return int (newPos-(int)pos);
|
nuclear@0
|
405 }
|
nuclear@0
|
406
|
nuclear@0
|
407 // Return # of bytes till EOF
|
nuclear@0
|
408 int FILEFile::BytesAvailable()
|
nuclear@0
|
409 {
|
nuclear@0
|
410 int64_t pos = LTell();
|
nuclear@0
|
411 int64_t endPos = LGetLength();
|
nuclear@0
|
412
|
nuclear@0
|
413 // Return -1 for major error
|
nuclear@0
|
414 if ((pos==-1) || (endPos==-1))
|
nuclear@0
|
415 {
|
nuclear@0
|
416 ErrorCode = SFerror();
|
nuclear@0
|
417 return 0;
|
nuclear@0
|
418 }
|
nuclear@0
|
419 else
|
nuclear@0
|
420 ErrorCode = 0;
|
nuclear@0
|
421
|
nuclear@0
|
422 return int (endPos-(int)pos);
|
nuclear@0
|
423 }
|
nuclear@0
|
424
|
nuclear@0
|
425 // Flush file contents
|
nuclear@0
|
426 bool FILEFile::Flush()
|
nuclear@0
|
427 {
|
nuclear@0
|
428 return !fflush(fs);
|
nuclear@0
|
429 }
|
nuclear@0
|
430
|
nuclear@0
|
431 int FILEFile::Seek(int offset, int origin)
|
nuclear@0
|
432 {
|
nuclear@0
|
433 int newOrigin = 0;
|
nuclear@0
|
434 switch(origin)
|
nuclear@0
|
435 {
|
nuclear@0
|
436 case Seek_Set: newOrigin = SEEK_SET; break;
|
nuclear@0
|
437 case Seek_Cur: newOrigin = SEEK_CUR; break;
|
nuclear@0
|
438 case Seek_End: newOrigin = SEEK_END; break;
|
nuclear@0
|
439 }
|
nuclear@0
|
440
|
nuclear@0
|
441 if (newOrigin == SEEK_SET && offset == Tell())
|
nuclear@0
|
442 return Tell();
|
nuclear@0
|
443
|
nuclear@0
|
444 if (fseek (fs, offset, newOrigin))
|
nuclear@0
|
445 {
|
nuclear@0
|
446 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
447 OVR_ASSERT(0);
|
nuclear@0
|
448 #endif
|
nuclear@0
|
449 return -1;
|
nuclear@0
|
450 }
|
nuclear@0
|
451
|
nuclear@0
|
452 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
453 // Track file position after seeks for read verification later.
|
nuclear@0
|
454 switch(origin)
|
nuclear@0
|
455 {
|
nuclear@0
|
456 case Seek_Set: TestPos = offset; break;
|
nuclear@0
|
457 case Seek_Cur: TestPos += offset; break;
|
nuclear@0
|
458 case Seek_End: TestPos = FileTestLength + offset; break;
|
nuclear@0
|
459 }
|
nuclear@0
|
460 OVR_ASSERT((int)TestPos == Tell());
|
nuclear@0
|
461 #endif
|
nuclear@0
|
462
|
nuclear@0
|
463 return (int)Tell();
|
nuclear@0
|
464 }
|
nuclear@0
|
465
|
nuclear@0
|
466 int64_t FILEFile::LSeek(int64_t offset, int origin)
|
nuclear@0
|
467 {
|
nuclear@0
|
468 return Seek((int)offset,origin);
|
nuclear@0
|
469 }
|
nuclear@0
|
470
|
nuclear@0
|
471 int FILEFile::CopyFromStream(File *pstream, int byteSize)
|
nuclear@0
|
472 {
|
nuclear@0
|
473 uint8_t* buff = new uint8_t[0x4000];
|
nuclear@0
|
474 int count = 0;
|
nuclear@0
|
475 int szRequest, szRead, szWritten;
|
nuclear@0
|
476
|
nuclear@0
|
477 while (byteSize)
|
nuclear@0
|
478 {
|
nuclear@0
|
479 szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
|
nuclear@0
|
480
|
nuclear@0
|
481 szRead = pstream->Read(buff, szRequest);
|
nuclear@0
|
482 szWritten = 0;
|
nuclear@0
|
483 if (szRead > 0)
|
nuclear@0
|
484 szWritten = Write(buff, szRead);
|
nuclear@0
|
485
|
nuclear@0
|
486 count += szWritten;
|
nuclear@0
|
487 byteSize -= szWritten;
|
nuclear@0
|
488 if (szWritten < szRequest)
|
nuclear@0
|
489 break;
|
nuclear@0
|
490 }
|
nuclear@0
|
491
|
nuclear@0
|
492 delete[] buff;
|
nuclear@0
|
493
|
nuclear@0
|
494 return count;
|
nuclear@0
|
495 }
|
nuclear@0
|
496
|
nuclear@0
|
497
|
nuclear@0
|
498 bool FILEFile::Close()
|
nuclear@0
|
499 {
|
nuclear@0
|
500 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
|
nuclear@0
|
501 if (pFileTestBuffer)
|
nuclear@0
|
502 {
|
nuclear@0
|
503 OVR_FREE(pFileTestBuffer);
|
nuclear@0
|
504 pFileTestBuffer = 0;
|
nuclear@0
|
505 FileTestLength = 0;
|
nuclear@0
|
506 }
|
nuclear@0
|
507 #endif
|
nuclear@0
|
508
|
nuclear@0
|
509 bool closeRet = !fclose(fs);
|
nuclear@0
|
510
|
nuclear@0
|
511 if (!closeRet)
|
nuclear@0
|
512 {
|
nuclear@0
|
513 ErrorCode = SFerror();
|
nuclear@0
|
514 return 0;
|
nuclear@0
|
515 }
|
nuclear@0
|
516 else
|
nuclear@0
|
517 {
|
nuclear@0
|
518 Opened = 0;
|
nuclear@0
|
519 fs = 0;
|
nuclear@0
|
520 ErrorCode = 0;
|
nuclear@0
|
521 }
|
nuclear@0
|
522
|
nuclear@0
|
523 // Handle safe truncate
|
nuclear@0
|
524 /*
|
nuclear@0
|
525 if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
|
nuclear@0
|
526 {
|
nuclear@0
|
527 // Delete original file (if it existed)
|
nuclear@0
|
528 DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName);
|
nuclear@0
|
529 if (oldAttributes!=0xFFFFFFFF)
|
nuclear@0
|
530 if (!FileUtilWin32::DeleteFile(FileName))
|
nuclear@0
|
531 {
|
nuclear@0
|
532 // Try to remove the readonly attribute
|
nuclear@0
|
533 FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) );
|
nuclear@0
|
534 // And delete the file again
|
nuclear@0
|
535 if (!FileUtilWin32::DeleteFile(FileName))
|
nuclear@0
|
536 return 0;
|
nuclear@0
|
537 }
|
nuclear@0
|
538
|
nuclear@0
|
539 // Rename temp file to real filename
|
nuclear@0
|
540 if (!FileUtilWin32::MoveFile(TempName, FileName))
|
nuclear@0
|
541 {
|
nuclear@0
|
542 //ErrorCode = errno;
|
nuclear@0
|
543 return 0;
|
nuclear@0
|
544 }
|
nuclear@0
|
545 }
|
nuclear@0
|
546 */
|
nuclear@0
|
547 return 1;
|
nuclear@0
|
548 }
|
nuclear@0
|
549
|
nuclear@0
|
550 /*
|
nuclear@0
|
551 bool FILEFile::CloseCancel()
|
nuclear@0
|
552 {
|
nuclear@0
|
553 bool closeRet = (bool)::CloseHandle(fd);
|
nuclear@0
|
554
|
nuclear@0
|
555 if (!closeRet)
|
nuclear@0
|
556 {
|
nuclear@0
|
557 //ErrorCode = errno;
|
nuclear@0
|
558 return 0;
|
nuclear@0
|
559 }
|
nuclear@0
|
560 else
|
nuclear@0
|
561 {
|
nuclear@0
|
562 Opened = 0;
|
nuclear@0
|
563 fd = INVALID_HANDLE_VALUE;
|
nuclear@0
|
564 ErrorCode = 0;
|
nuclear@0
|
565 }
|
nuclear@0
|
566
|
nuclear@0
|
567 // Handle safe truncate (delete tmp file, leave original unchanged)
|
nuclear@0
|
568 if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
|
nuclear@0
|
569 if (!FileUtilWin32::DeleteFile(TempName))
|
nuclear@0
|
570 {
|
nuclear@0
|
571 //ErrorCode = errno;
|
nuclear@0
|
572 return 0;
|
nuclear@0
|
573 }
|
nuclear@0
|
574 return 1;
|
nuclear@0
|
575 }
|
nuclear@0
|
576 */
|
nuclear@0
|
577
|
nuclear@0
|
578 Ptr<File> FileFILEOpen(const String& path, int flags, int mode)
|
nuclear@0
|
579 {
|
nuclear@0
|
580 Ptr<File> result = *new FILEFile(path, flags, mode);
|
nuclear@0
|
581 return result;
|
nuclear@0
|
582 }
|
nuclear@0
|
583
|
nuclear@0
|
584 // Helper function: obtain file information time.
|
nuclear@0
|
585 bool SysFile::GetFileStat(FileStat* pfileStat, const String& path)
|
nuclear@0
|
586 {
|
nuclear@0
|
587 #if defined(OVR_OS_MS)
|
nuclear@0
|
588 // 64-bit implementation on Windows.
|
nuclear@0
|
589 struct __stat64 fileStat;
|
nuclear@0
|
590 // Stat returns 0 for success.
|
nuclear@0
|
591 wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
|
nuclear@0
|
592 UTF8Util::DecodeString(pwpath, path.ToCStr());
|
nuclear@0
|
593
|
nuclear@0
|
594 int ret = _wstat64(pwpath, &fileStat);
|
nuclear@0
|
595 OVR_FREE(pwpath);
|
nuclear@0
|
596 if (ret) return false;
|
nuclear@0
|
597 #else
|
nuclear@0
|
598 struct stat fileStat;
|
nuclear@0
|
599 // Stat returns 0 for success.
|
nuclear@0
|
600 if (stat(path, &fileStat) != 0)
|
nuclear@0
|
601 return false;
|
nuclear@0
|
602 #endif
|
nuclear@0
|
603 pfileStat->AccessTime = fileStat.st_atime;
|
nuclear@0
|
604 pfileStat->ModifyTime = fileStat.st_mtime;
|
nuclear@0
|
605 pfileStat->FileSize = fileStat.st_size;
|
nuclear@0
|
606 return true;
|
nuclear@0
|
607 }
|
nuclear@0
|
608
|
nuclear@0
|
609 } // Namespace OVR
|