00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #define GFILE_CXX
00018
00019 #include "OVR_Types.h"
00020 #include "OVR_Log.h"
00021
00022
00023 #include <stdio.h>
00024 #ifndef OVR_OS_WINCE
00025 #include <sys/stat.h>
00026 #endif
00027
00028 #include "OVR_SysFile.h"
00029
00030 #ifndef OVR_OS_WINCE
00031 #include <errno.h>
00032 #endif
00033
00034 namespace OVR {
00035
00036
00037
00038
00039
00040 static int SFerror ()
00041 {
00042 if (errno == ENOENT)
00043 return FileConstants::Error_FileNotFound;
00044 else if (errno == EACCES || errno == EPERM)
00045 return FileConstants::Error_Access;
00046 else if (errno == ENOSPC)
00047 return FileConstants::Error_DiskFull;
00048 else
00049 return FileConstants::Error_IOError;
00050 };
00051
00052 #ifdef OVR_OS_WIN32
00053 #include "windows.h"
00054
00055
00056 class SysErrorModeDisabler
00057 {
00058 BOOL Disabled;
00059 UINT OldMode;
00060 public:
00061 SysErrorModeDisabler(const char* pfileName)
00062 {
00063 if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
00064 {
00065 Disabled = 1;
00066 OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
00067 }
00068 else
00069 Disabled = 0;
00070 }
00071
00072 ~SysErrorModeDisabler()
00073 {
00074 if (Disabled) ::SetErrorMode(OldMode);
00075 }
00076 };
00077 #else
00078 class SysErrorModeDisabler
00079 {
00080 public:
00081 SysErrorModeDisabler(const char* pfileName) { }
00082 };
00083 #endif // OVR_OS_WIN32
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 class FILEFile : public File
00097 {
00098 protected:
00099
00100
00101 String FileName;
00102
00103
00104 bool Opened;
00105 FILE* fs;
00106 int OpenFlags;
00107
00108 int ErrorCode;
00109
00110 int LastOp;
00111
00112 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00113 UByte* pFileTestBuffer;
00114 unsigned FileTestLength;
00115 unsigned TestPos;
00116 #endif
00117
00118 public:
00119
00120 FILEFile()
00121 {
00122 Opened = 0; FileName = "";
00123
00124 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00125 pFileTestBuffer =0;
00126 FileTestLength =0;
00127 TestPos =0;
00128 #endif
00129 }
00130
00131 FILEFile(const String& fileName, int flags, int Mode);
00132
00133 FILEFile(const char* pfileName, int flags, int Mode);
00134
00135 ~FILEFile()
00136 {
00137 if (Opened)
00138 Close();
00139 }
00140
00141 virtual const char* GetFilePath();
00142
00143
00144 virtual bool IsValid();
00145 virtual bool IsWritable();
00146
00147
00148 virtual int Tell();
00149 virtual SInt64 LTell();
00150 virtual int GetLength();
00151 virtual SInt64 LGetLength();
00152
00153
00154 virtual int GetErrorCode();
00155
00156
00157 virtual int Write(const UByte *pbuffer, int numBytes);
00158 virtual int Read(UByte *pbuffer, int numBytes);
00159 virtual int SkipBytes(int numBytes);
00160 virtual int BytesAvailable();
00161 virtual bool Flush();
00162 virtual int Seek(int offset, int origin);
00163 virtual SInt64 LSeek(SInt64 offset, int origin);
00164
00165 virtual int CopyFromStream(File *pStream, int byteSize);
00166 virtual bool Close();
00167 private:
00168 void init();
00169 };
00170
00171
00172
00173 FILEFile::FILEFile(const String& fileName, int flags, int mode)
00174 : FileName(fileName), OpenFlags(flags)
00175 {
00176 OVR_UNUSED(mode);
00177 init();
00178 }
00179
00180
00181 FILEFile::FILEFile(const char* pfileName, int flags, int mode)
00182 : FileName(pfileName), OpenFlags(flags)
00183 {
00184 OVR_UNUSED(mode);
00185 init();
00186 }
00187
00188 void FILEFile::init()
00189 {
00190
00191 const char *omode = "rb";
00192
00193 if (OpenFlags & Open_Truncate)
00194 {
00195 if (OpenFlags & Open_Read)
00196 omode = "w+b";
00197 else
00198 omode = "wb";
00199 }
00200 else if (OpenFlags & Open_Create)
00201 {
00202 if (OpenFlags & Open_Read)
00203 omode = "a+b";
00204 else
00205 omode = "ab";
00206 }
00207 else if (OpenFlags & Open_Write)
00208 omode = "r+b";
00209
00210 #ifdef OVR_OS_WIN32
00211 SysErrorModeDisabler disabler(FileName.ToCStr());
00212 #endif
00213
00214 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
00215 wchar_t womode[16];
00216 wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
00217 UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
00218 OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
00219 UTF8Util::DecodeString(womode, omode);
00220 _wfopen_s(&fs, pwFileName, womode);
00221 OVR_FREE(pwFileName);
00222 #else
00223 fs = fopen(FileName.ToCStr(), omode);
00224 #endif
00225 if (fs)
00226 rewind (fs);
00227 Opened = (fs != NULL);
00228
00229 if (!Opened)
00230 ErrorCode = SFerror();
00231 else
00232 {
00233
00234
00235 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00236 TestPos = 0;
00237 fseek(fs, 0, SEEK_END);
00238 FileTestLength = ftell(fs);
00239 fseek(fs, 0, SEEK_SET);
00240 pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength);
00241 if (pFileTestBuffer)
00242 {
00243 OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
00244 Seek(0, Seek_Set);
00245 }
00246 #endif
00247
00248 ErrorCode = 0;
00249 }
00250 LastOp = 0;
00251 }
00252
00253
00254 const char* FILEFile::GetFilePath()
00255 {
00256 return FileName.ToCStr();
00257 }
00258
00259
00260
00261 bool FILEFile::IsValid()
00262 {
00263 return Opened;
00264 }
00265 bool FILEFile::IsWritable()
00266 {
00267 return IsValid() && (OpenFlags&Open_Write);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 int FILEFile::Tell()
00278 {
00279 int pos = (int)ftell (fs);
00280 if (pos < 0)
00281 ErrorCode = SFerror();
00282 return pos;
00283 }
00284
00285 SInt64 FILEFile::LTell()
00286 {
00287 SInt64 pos = ftell(fs);
00288 if (pos < 0)
00289 ErrorCode = SFerror();
00290 return pos;
00291 }
00292
00293 int FILEFile::GetLength()
00294 {
00295 int pos = Tell();
00296 if (pos >= 0)
00297 {
00298 Seek (0, Seek_End);
00299 int size = Tell();
00300 Seek (pos, Seek_Set);
00301 return size;
00302 }
00303 return -1;
00304 }
00305 SInt64 FILEFile::LGetLength()
00306 {
00307 SInt64 pos = LTell();
00308 if (pos >= 0)
00309 {
00310 LSeek (0, Seek_End);
00311 SInt64 size = LTell();
00312 LSeek (pos, Seek_Set);
00313 return size;
00314 }
00315 return -1;
00316 }
00317
00318 int FILEFile::GetErrorCode()
00319 {
00320 return ErrorCode;
00321 }
00322
00323
00324 int FILEFile::Write(const UByte *pbuffer, int numBytes)
00325 {
00326 if (LastOp && LastOp != Open_Write)
00327 fflush(fs);
00328 LastOp = Open_Write;
00329 int written = (int) fwrite(pbuffer, 1, numBytes, fs);
00330 if (written < numBytes)
00331 ErrorCode = SFerror();
00332
00333 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00334 if (written > 0)
00335 TestPos += written;
00336 #endif
00337
00338 return written;
00339 }
00340
00341 int FILEFile::Read(UByte *pbuffer, int numBytes)
00342 {
00343 if (LastOp && LastOp != Open_Read)
00344 fflush(fs);
00345 LastOp = Open_Read;
00346 int read = (int) fread(pbuffer, 1, numBytes, fs);
00347 if (read < numBytes)
00348 ErrorCode = SFerror();
00349
00350 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00351 if (read > 0)
00352 {
00353
00354 UByte* pcompareBuffer = pFileTestBuffer + TestPos;
00355 for (int i=0; i< read; i++)
00356 {
00357 OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
00358 }
00359
00360
00361 TestPos += read;
00362 OVR_ASSERT(ftell(fs) == (int)TestPos);
00363 }
00364 #endif
00365
00366 return read;
00367 }
00368
00369
00370 int FILEFile::SkipBytes(int numBytes)
00371 {
00372 SInt64 pos = LTell();
00373 SInt64 newPos = LSeek(numBytes, Seek_Cur);
00374
00375
00376 if ((pos==-1) || (newPos==-1))
00377 {
00378 return -1;
00379 }
00380
00381
00382 return int (newPos-(int)pos);
00383 }
00384
00385
00386 int FILEFile::BytesAvailable()
00387 {
00388 SInt64 pos = LTell();
00389 SInt64 endPos = LGetLength();
00390
00391
00392 if ((pos==-1) || (endPos==-1))
00393 {
00394 ErrorCode = SFerror();
00395 return 0;
00396 }
00397 else
00398 ErrorCode = 0;
00399
00400 return int (endPos-(int)pos);
00401 }
00402
00403
00404 bool FILEFile::Flush()
00405 {
00406 return !fflush(fs);
00407 }
00408
00409 int FILEFile::Seek(int offset, int origin)
00410 {
00411 int newOrigin = 0;
00412 switch(origin)
00413 {
00414 case Seek_Set: newOrigin = SEEK_SET; break;
00415 case Seek_Cur: newOrigin = SEEK_CUR; break;
00416 case Seek_End: newOrigin = SEEK_END; break;
00417 }
00418
00419 if (newOrigin == SEEK_SET && offset == Tell())
00420 return Tell();
00421
00422 if (fseek (fs, offset, newOrigin))
00423 {
00424 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00425 OVR_ASSERT(0);
00426 #endif
00427 return -1;
00428 }
00429
00430 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00431
00432 switch(origin)
00433 {
00434 case Seek_Set: TestPos = offset; break;
00435 case Seek_Cur: TestPos += offset; break;
00436 case Seek_End: TestPos = FileTestLength + offset; break;
00437 }
00438 OVR_ASSERT((int)TestPos == Tell());
00439 #endif
00440
00441 return (int)Tell();
00442 }
00443
00444 SInt64 FILEFile::LSeek(SInt64 offset, int origin)
00445 {
00446 return Seek((int)offset,origin);
00447 }
00448
00449 int FILEFile::CopyFromStream(File *pstream, int byteSize)
00450 {
00451 UByte buff[0x4000];
00452 int count = 0;
00453 int szRequest, szRead, szWritten;
00454
00455 while (byteSize)
00456 {
00457 szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
00458
00459 szRead = pstream->Read(buff, szRequest);
00460 szWritten = 0;
00461 if (szRead > 0)
00462 szWritten = Write(buff, szRead);
00463
00464 count += szWritten;
00465 byteSize -= szWritten;
00466 if (szWritten < szRequest)
00467 break;
00468 }
00469 return count;
00470 }
00471
00472
00473 bool FILEFile::Close()
00474 {
00475 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
00476 if (pFileTestBuffer)
00477 {
00478 OVR_FREE(pFileTestBuffer);
00479 pFileTestBuffer = 0;
00480 FileTestLength = 0;
00481 }
00482 #endif
00483
00484 bool closeRet = !fclose(fs);
00485
00486 if (!closeRet)
00487 {
00488 ErrorCode = SFerror();
00489 return 0;
00490 }
00491 else
00492 {
00493 Opened = 0;
00494 fs = 0;
00495 ErrorCode = 0;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 return 1;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 File *FileFILEOpen(const String& path, int flags, int mode)
00554 {
00555 return new FILEFile(path, flags, mode);
00556 }
00557
00558
00559 bool SysFile::GetFileStat(FileStat* pfileStat, const String& path)
00560 {
00561 #if defined(OVR_OS_WIN32)
00562
00563 struct __stat64 fileStat;
00564
00565 wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
00566 UTF8Util::DecodeString(pwpath, path.ToCStr());
00567
00568 int ret = _wstat64(pwpath, &fileStat);
00569 OVR_FREE(pwpath);
00570 if (ret) return false;
00571 #else
00572 struct stat fileStat;
00573
00574 if (stat(path, &fileStat) != 0)
00575 return false;
00576 #endif
00577 pfileStat->AccessTime = fileStat.st_atime;
00578 pfileStat->ModifyTime = fileStat.st_mtime;
00579 pfileStat->FileSize = fileStat.st_size;
00580 return true;
00581 }
00582
00583 }