diff options
Diffstat (limited to 'ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_FileFILE.cpp')
-rw-r--r-- | ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_FileFILE.cpp | 575 |
1 files changed, 575 insertions, 0 deletions
diff --git a/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_FileFILE.cpp b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_FileFILE.cpp new file mode 100644 index 0000000..ee71a41 --- /dev/null +++ b/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_FileFILE.cpp @@ -0,0 +1,575 @@ +/************************************************************************** + +Filename : OVR_FileFILE.cpp +Content : File wrapper class implementation (Win32) + +Created : April 5, 1999 +Authors : Michael Antonov + +Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. + +Licensed under the Oculus Master SDK License Version 1.0 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/oculusmastersdk-1.0 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +**************************************************************************/ + +#define GFILE_CXX + +#include "OVR_Types.h" + +// Standard C library (Captain Obvious guarantees!) +#include <stdio.h> +#ifndef OVR_OS_WINCE +#include <sys/stat.h> +#endif + +#include "OVR_SysFile.h" + +#ifndef OVR_OS_WINCE +#include <errno.h> +#endif + +namespace OVR { + +// ***** File interface + +// ***** FILEFile - C streams file + +static int SFerror() { + if (errno == ENOENT) + return FileConstants::Error_FileNotFound; + else if (errno == EACCES || errno == EPERM) + return FileConstants::Error_Access; + else if (errno == ENOSPC) + return FileConstants::Error_DiskFull; + else + return FileConstants::Error_IOError; +}; + +#if defined(OVR_CC_MSVC) +#include "share.h" +#endif + +#if defined(OVR_OS_WIN32) +#include "OVR_Win32_IncludeWindows.h" + +// A simple helper class to disable/enable system error mode, if necessary +// Disabling happens conditionally only if a drive name is involved +class SysErrorModeDisabler { + BOOL Disabled; + UINT OldMode; + + public: + SysErrorModeDisabler(const char* pfileName) { + if (pfileName && (pfileName[0] != 0) && pfileName[1] == ':') { + Disabled = TRUE; + OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS); + } else { + Disabled = 0; + OldMode = 0; + } + } + + ~SysErrorModeDisabler() { + if (Disabled) + ::SetErrorMode(OldMode); + } +}; +#else +class SysErrorModeDisabler { + public: + SysErrorModeDisabler(const char* pfileName) { + OVR_UNUSED(pfileName); + } +}; +#endif // OVR_OS_WIN32 + +// This macro enables verification of I/O results after seeks against a pre-loaded +// full file buffer copy. This is generally not necessary, but can been used to debug +// memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory +// under FMOD with XP64 (32-bit) and Realtek HA Audio driver. +//#define GFILE_VERIFY_SEEK_ERRORS + +// This is the simplest possible file implementation, it wraps around the descriptor +// This file is delegated to by SysFile. + +class FILEFile : public File { + protected: + // Allocated filename + String FileName; + + // File handle & open mode + bool Opened; + FILE* fs; + int OpenFlags; + // Error code for last request + int ErrorCode; + + int LastOp; + +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + uint8_t* pFileTestBuffer; + unsigned FileTestLength; + unsigned TestPos; // File pointer position during tests. +#endif + + public: + FILEFile() + : FileName(), + Opened(false), + fs(NULL), + OpenFlags(0), + ErrorCode(0), + LastOp(0) +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + , + pFileTestBuffer(NULL), + FileTestLength(0), + TestPos(0) +#endif + { + } + + // Initialize file by opening it + FILEFile(const String& fileName, int flags, int Mode); + + // The 'pfileName' should be encoded as UTF-8 to support international file names. + FILEFile(const char* pfileName, int flags, int Mode); + + ~FILEFile() { + if (Opened) + Close(); + } + + virtual const char* GetFilePath(); + + // ** File Information + virtual bool IsValid(); + virtual bool IsWritable(); + + // Return position / file size + virtual int Tell(); + virtual int64_t LTell(); + virtual int GetLength(); + virtual int64_t LGetLength(); + + // virtual bool Stat(FileStats *pfs); + virtual int GetErrorCode(); + + // ** Stream implementation & I/O + virtual int Write(const uint8_t* pbuffer, int numBytes); + virtual int Read(uint8_t* pbuffer, int numBytes); + virtual int SkipBytes(int numBytes); + virtual int BytesAvailable(); + virtual bool Flush(); + virtual int Seek(int offset, int origin); + virtual int64_t LSeek(int64_t offset, int origin); + + virtual int CopyFromStream(File* pStream, int byteSize); + virtual bool Close(); + + private: + void init(); +}; + +// Initialize file by opening it +FILEFile::FILEFile(const String& fileName, int flags, int mode) + : FileName(fileName), OpenFlags(flags) { + OVR_UNUSED(mode); + init(); +} + +// The 'pfileName' should be encoded as UTF-8 to support international file names. +FILEFile::FILEFile(const char* pfileName, int flags, int mode) + : FileName(pfileName), OpenFlags(flags) { + OVR_UNUSED(mode); + init(); +} + +void FILEFile::init() { + // Open mode for file's open + const char* omode = "rb"; + + if (OpenFlags & Open_Truncate) { + if (OpenFlags & Open_Read) + omode = "w+b"; + else + omode = "wb"; + } else if (OpenFlags & Open_Create) { + if (OpenFlags & Open_Read) + omode = "a+b"; + else + omode = "ab"; + } else if (OpenFlags & Open_Write) + omode = "r+b"; + +#if defined(OVR_OS_MS) + SysErrorModeDisabler disabler(FileName.ToCStr()); +#endif + +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) + wchar_t womode[16]; + auto fileNameLength = (size_t)UTF8Util::GetLength(FileName.ToCStr()) + 1; + wchar_t* pwFileName = (wchar_t*)OVR_ALLOC(fileNameLength * sizeof(pwFileName[0])); + auto requiredUTF8Length = OVR::UTF8Util::Strlcpy(pwFileName, fileNameLength, FileName.ToCStr()); + if (requiredUTF8Length < fileNameLength) { + requiredUTF8Length = OVR::UTF8Util::Strlcpy(womode, OVR_ARRAY_COUNT(womode), omode); + OVR_ASSERT(requiredUTF8Length < OVR_ARRAY_COUNT(womode)); + fs = _wfsopen( + pwFileName, womode, _SH_DENYWR); // Allow others to read the file when we are writing it. + } + OVR_FREE(pwFileName); +#else + fs = fopen(FileName.ToCStr(), omode); +#endif + if (fs) + rewind(fs); + Opened = (fs != NULL); + // Set error code + if (!Opened) + ErrorCode = SFerror(); + else { +// If we are testing file seek correctness, pre-load the entire file so +// that we can do comparison tests later. +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + TestPos = 0; + fseek(fs, 0, SEEK_END); + FileTestLength = ftell(fs); + fseek(fs, 0, SEEK_SET); + pFileTestBuffer = (uint8_t*)OVR_ALLOC(FileTestLength); + if (pFileTestBuffer) { + OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength)); + Seek(0, Seek_Set); + } +#endif + + ErrorCode = 0; + } + LastOp = 0; +} + +const char* FILEFile::GetFilePath() { + return FileName.ToCStr(); +} + +// ** File Information +bool FILEFile::IsValid() { + return Opened; +} +bool FILEFile::IsWritable() { + return IsValid() && (OpenFlags & Open_Write); +} +/* +bool FILEFile::IsRecoverable() +{ + return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC); +} +*/ + +// Return position / file size +int FILEFile::Tell() { + int pos = (int)ftell(fs); + if (pos < 0) + ErrorCode = SFerror(); + return pos; +} + +int64_t FILEFile::LTell() { + int64_t pos = ftell(fs); + if (pos < 0) + ErrorCode = SFerror(); + return pos; +} + +int FILEFile::GetLength() { + int pos = Tell(); + if (pos >= 0) { + Seek(0, Seek_End); + int size = Tell(); + Seek(pos, Seek_Set); + return size; + } + return -1; +} +int64_t FILEFile::LGetLength() { + int64_t pos = LTell(); + if (pos >= 0) { + LSeek(0, Seek_End); + int64_t size = LTell(); + LSeek(pos, Seek_Set); + return size; + } + return -1; +} + +int FILEFile::GetErrorCode() { + return ErrorCode; +} + +// ** Stream implementation & I/O +int FILEFile::Write(const uint8_t* pbuffer, int numBytes) { + if (LastOp && LastOp != Open_Write) + fflush(fs); + LastOp = Open_Write; + int written = (int)fwrite(pbuffer, 1, numBytes, fs); + if (written < numBytes) + ErrorCode = SFerror(); + +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + if (written > 0) + TestPos += written; +#endif + + return written; +} + +int FILEFile::Read(uint8_t* pbuffer, int numBytes) { + if (LastOp && LastOp != Open_Read) + fflush(fs); + LastOp = Open_Read; + int read = (int)fread(pbuffer, 1, numBytes, fs); + if (read < numBytes) + ErrorCode = SFerror(); + +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + if (read > 0) { + // Read-in data must match our pre-loaded buffer data! + uint8_t* pcompareBuffer = pFileTestBuffer + TestPos; + for (int i = 0; i < read; i++) { + OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]); + } + + // OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read)); + TestPos += read; + OVR_ASSERT(ftell(fs) == (int)TestPos); + } +#endif + + return read; +} + +// Seeks ahead to skip bytes +int FILEFile::SkipBytes(int numBytes) { + int64_t pos = LTell(); + int64_t newPos = LSeek(numBytes, Seek_Cur); + + // Return -1 for major error + if ((pos == -1) || (newPos == -1)) { + return -1; + } + // ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0; + + return int(newPos - (int)pos); +} + +// Return # of bytes till EOF +int FILEFile::BytesAvailable() { + int64_t pos = LTell(); + int64_t endPos = LGetLength(); + + // Return -1 for major error + if ((pos == -1) || (endPos == -1)) { + ErrorCode = SFerror(); + return 0; + } else + ErrorCode = 0; + + return int(endPos - (int)pos); +} + +// Flush file contents +bool FILEFile::Flush() { + return !fflush(fs); +} + +int FILEFile::Seek(int offset, int origin) { + int newOrigin = 0; + switch (origin) { + case Seek_Set: + newOrigin = SEEK_SET; + break; + case Seek_Cur: + newOrigin = SEEK_CUR; + break; + case Seek_End: + newOrigin = SEEK_END; + break; + } + + if (newOrigin == SEEK_SET && offset == Tell()) + return Tell(); + + if (fseek(fs, offset, newOrigin)) { +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + OVR_ASSERT(0); +#endif + return -1; + } + +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + // Track file position after seeks for read verification later. + switch (origin) { + case Seek_Set: + TestPos = offset; + break; + case Seek_Cur: + TestPos += offset; + break; + case Seek_End: + TestPos = FileTestLength + offset; + break; + } + OVR_ASSERT((int)TestPos == Tell()); +#endif + + return (int)Tell(); +} + +int64_t FILEFile::LSeek(int64_t offset, int origin) { + return Seek((int)offset, origin); +} + +int FILEFile::CopyFromStream(File* pstream, int byteSize) { + uint8_t* buff = new uint8_t[0x4000]; + int count = 0; + int szRequest, szRead, szWritten; + + while (byteSize) { + szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; + + szRead = pstream->Read(buff, szRequest); + szWritten = 0; + if (szRead > 0) + szWritten = Write(buff, szRead); + + count += szWritten; + byteSize -= szWritten; + if (szWritten < szRequest) + break; + } + + delete[] buff; + + return count; +} + +bool FILEFile::Close() { +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS + if (pFileTestBuffer) { + OVR_FREE(pFileTestBuffer); + pFileTestBuffer = 0; + FileTestLength = 0; + } +#endif + + bool closeRet = !fclose(fs); + + if (!closeRet) { + ErrorCode = SFerror(); + return 0; + } else { + Opened = 0; + fs = 0; + ErrorCode = 0; + } + + // Handle safe truncate + /* + if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC) + { + // Delete original file (if it existed) + DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName); + if (oldAttributes!=0xFFFFFFFF) + if (!FileUtilWin32::DeleteFile(FileName)) + { + // Try to remove the readonly attribute + FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) + ); + // And delete the file again + if (!FileUtilWin32::DeleteFile(FileName)) + return 0; + } + + // Rename temp file to real filename + if (!FileUtilWin32::MoveFile(TempName, FileName)) + { + //ErrorCode = errno; + return 0; + } + } + */ + return 1; +} + +/* +bool FILEFile::CloseCancel() +{ + bool closeRet = (bool)::CloseHandle(fd); + + if (!closeRet) + { + //ErrorCode = errno; + return 0; + } + else + { + Opened = 0; + fd = INVALID_HANDLE_VALUE; + ErrorCode = 0; + } + + // Handle safe truncate (delete tmp file, leave original unchanged) + if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC) + if (!FileUtilWin32::DeleteFile(TempName)) + { + //ErrorCode = errno; + return 0; + } + return 1; +} +*/ + +Ptr<File> FileFILEOpen(const String& path, int flags, int mode) { + Ptr<File> result = *new FILEFile(path, flags, mode); + return result; +} + +// Helper function: obtain file information time. +bool SysFile::GetFileStat(FileStat* pfileStat, const String& path) { +#if defined(OVR_OS_MS) + // 64-bit implementation on Windows. + struct __stat64 fileStat {}; + auto pathLength = (size_t)UTF8Util::GetLength(path.ToCStr()) + 1; + wchar_t* pwPath = (wchar_t*)OVR_ALLOC(pathLength * sizeof(pwPath[0])); + auto requiredUTF8Length = OVR::UTF8Util::Strlcpy(pwPath, pathLength, path.ToCStr()); + int ret = -1; // Stat returns 0 for success. + if (requiredUTF8Length < pathLength) + ret = _wstat64(pwPath, &fileStat); + OVR_FREE(pwPath); + if (ret) + return false; +#else + struct stat fileStat {}; + // Stat returns 0 for success. + if (stat(path, &fileStat) != 0) + return false; +#endif + pfileStat->AccessTime = fileStat.st_atime; + pfileStat->ModifyTime = fileStat.st_mtime; + pfileStat->FileSize = fileStat.st_size; + return true; +} + +} // Namespace OVR |