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