summaryrefslogtreecommitdiffhomepage
path: root/ovr_sdk_win_23.0.0/LibOVRKernel/Src/Kernel/OVR_FileFILE.cpp
diff options
context:
space:
mode:
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.cpp575
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