From c11635328595ae9fe33fdac7150bcca2c41cd34d Mon Sep 17 00:00:00 2001 From: Ruben Gonzalez Date: Thu, 31 Jul 2014 20:56:07 -0400 Subject: [PATCH 01/12] WiP addition of support for ValveFS to many more filesystem natives. --- core/logic/intercom.h | 7 +- core/logic/smn_filesystem.cpp | 306 ++++++++++++++++++++++++---------- core/logic_bridge.cpp | 20 +++ 3 files changed, 246 insertions(+), 87 deletions(-) diff --git a/core/logic/intercom.h b/core/logic/intercom.h index 5d86853d..ed098435 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -52,7 +52,7 @@ using namespace SourceHook; * Add 1 to the RHS of this expression to bump the intercom file * This is to prevent mismatching core/logic binaries */ -#define SM_LOGIC_MAGIC (0x0F47C0DE - 28) +#define SM_LOGIC_MAGIC (0x0F47C0DE - 29) #if defined SM_LOGIC class IVEngineServer @@ -90,6 +90,11 @@ public: virtual bool EndOfFile(FileHandle_t file) = 0; virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0; virtual unsigned int Size(const char *pFileName, const char *pPathID = 0) = 0; + virtual int Read(void* pOutput, int size, FileHandle_t file) = 0; + virtual void Seek(FileHandle_t file, int post, int seekType) = 0; + virtual unsigned int Tell(FileHandle_t file) = 0; + virtual int WriteFileLine(FileHandle_t file, const char *pLine) = 0; + virtual void Flush(FileHandle_t file) = 0; }; namespace SourceMod diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 26575acf..bf166291 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -40,6 +40,7 @@ #include "common_logic.h" HandleType_t g_FileType; +HandleType_t g_ValveFileType; HandleType_t g_DirType; IChangeableForward *g_pLogHook = NULL; @@ -55,6 +56,7 @@ public: virtual void OnSourceModAllInitialized() { g_FileType = handlesys->CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL); + g_ValveFileType = handlesys->CreateType("ValveFile", this, 0, NULL, NULL, g_pCoreIdent, NULL); g_DirType = handlesys->CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL); g_pLogHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 1, NULL, Param_String); pluginsys->AddPluginsListener(this); @@ -65,8 +67,10 @@ public: forwardsys->ReleaseForward(g_pLogHook); handlesys->RemoveType(g_DirType, g_pCoreIdent); handlesys->RemoveType(g_FileType, g_pCoreIdent); + handlesys->RemoveType(g_ValveFileType, g_pCoreIdent); g_DirType = 0; g_FileType = 0; + g_ValveFileType = 0; } virtual void OnHandleDestroy(HandleType_t type, void *object) { @@ -80,6 +84,11 @@ public: IDirectory *pDir = (IDirectory *)object; libsys->CloseDirectory(pDir); } + else if (type == g_ValveFileType) + { + FileHandle_t fp = (FileHandle_t) object; + smcore.filesystem->Close(fp); + } } virtual void AddLogHook(IPluginFunction *pFunc) { @@ -191,16 +200,29 @@ static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params) return 0; } - char realpath[PLATFORM_MAX_PATH]; - g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); + Handle_t handle = 0; - FILE *pFile = fopen(realpath, mode); - if (!pFile) + if (params[0] <= 2 || !params[3]) { - return 0; + char realpath[PLATFORM_MAX_PATH]; + g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); + + FILE *pFile = fopen(realpath, mode); + if (pFile) + { + handle = handlesys->CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); + } + } + else + { + FileHandle_t pFile = smcore.filesystem->Open(name, mode); // Should we allow pathID? + if (pFile) + { + handle = handlesys->CreateHandle(g_ValveFileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); + } } - return handlesys->CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); + return handle; } static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params) @@ -224,18 +246,12 @@ static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - FILE *pFile; int err; + void *pTempFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) - { - return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); - } - char *buf; if ((err=pContext->LocalToString(params[2], &buf)) != SP_ERROR_NONE) { @@ -243,9 +259,25 @@ static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params) return 0; } - if (fgets(buf, params[3], pFile) == NULL) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) { - return 0; + FILE *pFile = (FILE *) pTempFile; + if (fgets(buf, params[3], pFile) == NULL) + { + return 0; + } + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + if (smcore.filesystem->ReadLine(buf, params[3], pFile) == NULL) + { + return 0; + } + } + else + { + return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } return 1; @@ -256,18 +288,28 @@ static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - FILE *pFile; + void *pTempFile; + cell_t ret; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FILE *pFile = (FILE *) pTempFile; + ret = feof(pFile) ? 1 : 0; + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + ret = smcore.filesystem->EndOfFile(pFile) ? 1 : 0; + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return (feof(pFile)) ? 1 : 0; + return ret; } static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params) @@ -275,18 +317,25 @@ static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - FILE *pFile; + void *pTempFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FILE *pFile = (FILE *) pTempFile; + fseek(pFile, params[2], params[3]); + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + smcore.filesystem->Seek(pFile, params[2], params[3]); + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - - fseek(pFile, params[2], params[3]); return 1; } @@ -296,18 +345,28 @@ static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - FILE *pFile; + void *pTempFile; + cell_t ret; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FILE *pFile = (FILE *) pTempFile; + ret = ftell(pFile); + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + ret = smcore.filesystem->Tell(pFile); + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return ftell(pFile); + return ret; } static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params) @@ -501,19 +560,14 @@ static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - FILE *pFile; + void *pTempFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) - { - return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); - } - char *fmt; int err; + if ((err=pContext->LocalToString(params[2], &fmt)) != SP_ERROR_NONE) { pContext->ThrowNativeErrorEx(err, NULL); @@ -522,8 +576,23 @@ static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params) char buffer[2048]; int arg = 3; - smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg); - fprintf(pFile, "%s\n", buffer); + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FILE *pFile = (FILE *) pTempFile; + smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg); + fprintf(pFile, "%s\n", buffer); + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg); + sprintf(buffer, "%s\n", buffer); + smcore.filesystem->WriteFileLine(pFile, buffer); + } + else + { + return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); + } return 1; } @@ -533,18 +602,28 @@ static cell_t sm_FlushFile(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - FILE *pFile; + void *pTempFile; + cell_t ret = 1; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FILE *pFile = (FILE *) pTempFile; + ret = (fflush(pFile) == 0) ? 1 : 0; + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + smcore.filesystem->Flush(pFile);// This doesnt have a return assume 1? + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return (fflush(pFile) == 0) ? 1 : 0; + return ret; } static cell_t sm_BuildPath(IPluginContext *pContext, const cell_t *params) @@ -709,57 +788,112 @@ static cell_t sm_ReadFile(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); - FILE *pFile; size_t read = 0; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + void *pTempFile = NULL; + + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FILE *pFile = (FILE *) pTempFile; + + if (params[4] != 1 && params[4] != 2 && params[4] != 4) + { + return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]); + } + + cell_t *data; + pContext->LocalToPhysAddr(params[2], &data); + + if (params[4] == 4) + { + read = fread(data, sizeof(cell_t), params[3], pFile); + } + else if (params[4] == 2) + { + uint16_t val; + for (cell_t i = 0; i < params[3]; i++) + { + if (fread(&val, sizeof(uint16_t), 1, pFile) != 1) + { + break; + } + data[read++] = val; + } + } + else if (params[4] == 1) + { + uint8_t val; + for (cell_t i = 0; i < params[3]; i++) + { + if (fread(&val, sizeof(uint8_t), 1, pFile) != 1) + { + break; + } + data[read++] = val; + } + } + + if (read != (size_t) params[3] && ferror(pFile) != 0) + { + return -1; + } + } + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + { + FileHandle_t pFile = (FileHandle_t) pTempFile; + + if (params[4] != 1 && params[4] != 2 && params[4] != 4) + { + return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]); + } + + cell_t *data; + pContext->LocalToPhysAddr(params[2], &data); + + if (params[4] == 4) + { + read = 1; + if (smcore.filesystem->Read(data, sizeof(cell_t), pFile) != sizeof(cell_t)) + { + read = 0; + } + } + else if (params[4] == 2) + { + uint16_t val; + for (cell_t i = 0; i < params[3]; i++) + { + if (smcore.filesystem->Read(&val, sizeof(uint16_t), pFile) != sizeof(uint16_t)) + { + break; + } + data[read++] = val; + } + } + else if (params[4] == 1) + { + uint8_t val; + for (cell_t i = 0; i < params[3]; i++) + { + if (smcore.filesystem->Read(&val, sizeof(uint8_t), pFile) != sizeof(uint8_t)) + { + break; + } + data[read++] = val; + } + } + + if (read != (size_t) params[3]) + { + return -1; + } + } + + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - if (params[4] != 1 && params[4] != 2 && params[4] != 4) - { - return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]); - } - - cell_t *data; - pContext->LocalToPhysAddr(params[2], &data); - - if (params[4] == 4) - { - read = fread(data, sizeof(cell_t), params[3], pFile); - } - else if (params[4] == 2) - { - uint16_t val; - for (cell_t i = 0; i < params[3]; i++) - { - if (fread(&val, sizeof(uint16_t), 1, pFile) != 1) - { - break; - } - data[read++] = val; - } - } - else if (params[4] == 1) - { - uint8_t val; - for (cell_t i = 0; i < params[3]; i++) - { - if (fread(&val, sizeof(uint8_t), 1, pFile) != 1) - { - break; - } - data[read++] = val; - } - } - - if (read != (size_t)params[3] && ferror(pFile) != 0) - { - return -1; - } - return read; } diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 057f660c..e1cb0b4d 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -174,6 +174,26 @@ public: { return filesystem->Size(pFileName, pPathID); } + int Read(void* pOutput, int size, FileHandle_t file) + { + return filesystem->Read(pOutput, size, file); + } + void Seek(FileHandle_t file, int pos, int seekType) + { + filesystem->Seek(file, pos, (FileSystemSeek_t) seekType); + } + unsigned int Tell(FileHandle_t file) + { + return filesystem->Tell(file); + } + int WriteFileLine(FileHandle_t file, const char *pLine) + { + return filesystem->FPrintf(file, pLine); + } + void Flush(FileHandle_t file) + { + filesystem->Flush(file); + } }; static VFileSystem_Logic logic_filesystem; From 5e7e7ce551f09213186b8446ad63d2c3bc8b6f12 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 1 Aug 2014 06:09:09 -0700 Subject: [PATCH 02/12] Improved FPrint(f) passthrough --- core/logic/intercom.h | 2 +- core/logic/smn_filesystem.cpp | 2 +- core/logic_bridge.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/logic/intercom.h b/core/logic/intercom.h index ed098435..09f52b2f 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -93,7 +93,7 @@ public: virtual int Read(void* pOutput, int size, FileHandle_t file) = 0; virtual void Seek(FileHandle_t file, int post, int seekType) = 0; virtual unsigned int Tell(FileHandle_t file) = 0; - virtual int WriteFileLine(FileHandle_t file, const char *pLine) = 0; + virtual int FPrint(FileHandle_t file, const char *pData) = 0; virtual void Flush(FileHandle_t file) = 0; }; diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index bf166291..18693cb8 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -587,7 +587,7 @@ static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params) FileHandle_t pFile = (FileHandle_t) pTempFile; smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg); sprintf(buffer, "%s\n", buffer); - smcore.filesystem->WriteFileLine(pFile, buffer); + smcore.filesystem->FPrint(pFile, buffer); } else { diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index e1cb0b4d..751ba6ad 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -186,9 +186,9 @@ public: { return filesystem->Tell(file); } - int WriteFileLine(FileHandle_t file, const char *pLine) + int FPrint(FileHandle_t file, const char *pData) { - return filesystem->FPrintf(file, pLine); + return filesystem->FPrintf(file, "%s", pData); } void Flush(FileHandle_t file) { From 573aea20fb204f03fb6f52a377f5c3f00a3c1872 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 1 Aug 2014 12:38:51 -0700 Subject: [PATCH 03/12] More progress: Abstracted many fs funcs with helper class. Removed much duplicated code. Fixed ReadFile assuming FS errors for ValveFS. Added ValveFS support for ReadFileString, WriteFile, WriteFileString, DeleteFile. Added missing param in doc for OpenFile. --- core/logic/intercom.h | 3 + core/logic/smn_filesystem.cpp | 452 ++++++++++++++++++++-------------- core/logic_bridge.cpp | 12 + plugins/include/files.inc | 12 +- 4 files changed, 296 insertions(+), 183 deletions(-) diff --git a/core/logic/intercom.h b/core/logic/intercom.h index 09f52b2f..3df0a5b4 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -91,10 +91,13 @@ public: virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0; virtual unsigned int Size(const char *pFileName, const char *pPathID = 0) = 0; virtual int Read(void* pOutput, int size, FileHandle_t file) = 0; + virtual int Write(void const* pInput, int size, FileHandle_t file) = 0; virtual void Seek(FileHandle_t file, int post, int seekType) = 0; virtual unsigned int Tell(FileHandle_t file) = 0; virtual int FPrint(FileHandle_t file, const char *pData) = 0; virtual void Flush(FileHandle_t file) = 0; + virtual bool IsOk(FileHandle_t file) = 0; + virtual void RemoveFile(const char *pRelativePath, const char *pathID = 0) = 0; }; namespace SourceMod diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 18693cb8..7e1536a1 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -44,6 +44,111 @@ HandleType_t g_ValveFileType; HandleType_t g_DirType; IChangeableForward *g_pLogHook = NULL; +enum class FSType +{ + STDIO, + VALVE, +}; + +class FSHelper +{ +public: + void SetFSType(FSType fstype) + { + _fstype = fstype; + } +public: + inline void *Open(const char *filename, const char *mode) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->Open(filename, mode); + else + return fopen(filename, mode); + } + + inline int Read(void *pOut, int size, void *pFile) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->Read(pOut, size, (FileHandle_t)pFile); + else + return fread(pOut, 1, size, (FILE *)pFile) * size; + } + + inline char *ReadLine(char *pOut, int size, void *pFile) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->ReadLine(pOut, size, (FileHandle_t)pFile); + else + return fgets(pOut, size, (FILE *)pFile); + } + + inline size_t Write(const void *pData, int size, void *pFile) + { + if (_fstype == FSType::VALVE) + return (size_t)smcore.filesystem->Write(pData, size, (FileHandle_t)pFile); + else + return fwrite(pData, 1, size, (FILE *)pFile); + } + + inline void Seek(void *pFile, int pos, int seekType) + { + if (_fstype == FSType::VALVE) + smcore.filesystem->Seek((FileHandle_t)pFile, pos, seekType); + else + fseek((FILE *)pFile, pos, seekType); + } + + inline int Tell(void *pFile) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->Tell((FileHandle_t)pFile); + else + return ftell((FILE *)pFile); + } + + inline bool HasError(void *pFile) + { + if (_fstype == FSType::VALVE) + return !smcore.filesystem->IsOk((FileHandle_t)pFile); + else + return ferror((FILE *)pFile) != 0; + } + + inline void Close(void *pFile) + { + if (_fstype == FSType::VALVE) + smcore.filesystem->Close((FileHandle_t)pFile); + else + fclose((FILE *)pFile); + } + + inline bool Remove(const char *pFilePath) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->RemoveFile(pFilePath), true; + else + return unlink(pFilePath) == 0; + } + + inline bool EndOfFile(void *pFile) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->EndOfFile((FileHandle_t)pFile); + else + return feof((FILE *)pFile) != 0; + } + + inline bool Flush(void *pFile) + { + if (_fstype == FSType::VALVE) + return smcore.filesystem->Flush((FileHandle_t)pFile), true; + else + return fflush((FILE *)pFile) == 0; + } +private: + FSType _fstype; +}; + class FileNatives : public SMGlobalClass, public IHandleTypeDispatch, @@ -201,25 +306,29 @@ static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params) } Handle_t handle = 0; - + HandleType_t handleType; + FSHelper fshelper; + const char *openpath; if (params[0] <= 2 || !params[3]) { + handleType = g_FileType; + fshelper.SetFSType(FSType::STDIO); + char realpath[PLATFORM_MAX_PATH]; g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); - - FILE *pFile = fopen(realpath, mode); - if (pFile) - { - handle = handlesys->CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); - } + openpath = realpath; } else { - FileHandle_t pFile = smcore.filesystem->Open(name, mode); // Should we allow pathID? - if (pFile) - { - handle = handlesys->CreateHandle(g_ValveFileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); - } + handleType = g_ValveFileType; + fshelper.SetFSType(FSType::VALVE); + openpath = name; + } + + void *pFile = fshelper.Open(openpath, mode); + if (pFile) + { + handle = handlesys->CreateHandle(handleType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); } return handle; @@ -235,10 +344,22 @@ static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params) return 0; } - char realpath[PLATFORM_MAX_PATH]; - g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); + FSHelper fshelper; + const char *filepath; + if (params[0] < 2 || !params[2]) + { + fshelper.SetFSType(FSType::STDIO); + char realpath[PLATFORM_MAX_PATH]; + g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); + filepath = realpath; + } + else + { + fshelper.SetFSType(FSType::VALVE); + filepath = name; + } - return (unlink(realpath)) ? 0 : 1; + return fshelper.Remove(filepath) ? 1 : 0; } static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params) @@ -248,7 +369,7 @@ static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params) HandleSecurity sec; int err; - void *pTempFile; + void *pFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; @@ -259,28 +380,22 @@ static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params) return 0; } - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + FSHelper fshelper; + + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) { - FILE *pFile = (FILE *) pTempFile; - if (fgets(buf, params[3], pFile) == NULL) - { - return 0; - } + fshelper.SetFSType(FSType::STDIO); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) { - FileHandle_t pFile = (FileHandle_t) pTempFile; - if (smcore.filesystem->ReadLine(buf, params[3], pFile) == NULL) - { - return 0; - } + fshelper.SetFSType(FSType::VALVE); } else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return 1; + return fshelper.ReadLine(buf, params[3], pFile) == NULL ? 0 : 1; } static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params) @@ -288,28 +403,26 @@ static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - void *pTempFile; - cell_t ret; + void *pFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + FSHelper fshelper; + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) { - FILE *pFile = (FILE *) pTempFile; - ret = feof(pFile) ? 1 : 0; + fshelper.SetFSType(FSType::STDIO); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) { - FileHandle_t pFile = (FileHandle_t) pTempFile; - ret = smcore.filesystem->EndOfFile(pFile) ? 1 : 0; + fshelper.SetFSType(FSType::VALVE); } else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return ret; + return fshelper.EndOfFile(pFile) ? 1 : 0; } static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params) @@ -317,25 +430,26 @@ static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - void *pTempFile; + void *pFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + FSHelper fshelper; + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) { - FILE *pFile = (FILE *) pTempFile; - fseek(pFile, params[2], params[3]); + fshelper.SetFSType(FSType::STDIO); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) { - FileHandle_t pFile = (FileHandle_t) pTempFile; - smcore.filesystem->Seek(pFile, params[2], params[3]); + fshelper.SetFSType(FSType::VALVE); } else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } + + fshelper.Seek(pFile, params[2], params[3]); return 1; } @@ -345,28 +459,27 @@ static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - void *pTempFile; - cell_t ret; + void *pFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + FSHelper fshelper; + + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) { - FILE *pFile = (FILE *) pTempFile; - ret = ftell(pFile); + fshelper.SetFSType(FSType::STDIO); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) { - FileHandle_t pFile = (FileHandle_t) pTempFile; - ret = smcore.filesystem->Tell(pFile); + fshelper.SetFSType(FSType::VALVE); } else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return ret; + return (cell_t)fshelper.Tell(pFile); } static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params) @@ -576,13 +689,13 @@ static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params) char buffer[2048]; int arg = 3; - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pTempFile)) == HandleError_None) { FILE *pFile = (FILE *) pTempFile; smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg); fprintf(pFile, "%s\n", buffer); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pTempFile)) == HandleError_None) { FileHandle_t pFile = (FileHandle_t) pTempFile; smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg); @@ -602,28 +715,26 @@ static cell_t sm_FlushFile(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec; - void *pTempFile; - cell_t ret = 1; + void *pFile; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + FSHelper fshelper; + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) { - FILE *pFile = (FILE *) pTempFile; - ret = (fflush(pFile) == 0) ? 1 : 0; + fshelper.SetFSType(FSType::STDIO); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) { - FileHandle_t pFile = (FileHandle_t) pTempFile; - smcore.filesystem->Flush(pFile);// This doesnt have a return assume 1? + fshelper.SetFSType(FSType::VALVE); } else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return ret; + return fshelper.Flush(pFile) ? 1 : 0; } static cell_t sm_BuildPath(IPluginContext *pContext, const cell_t *params) @@ -790,111 +901,65 @@ static cell_t sm_ReadFile(IPluginContext *pContext, const cell_t *params) HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); size_t read = 0; - void *pTempFile = NULL; + void *pFile = NULL; + FSHelper fshelper; - if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, (void **) &pTempFile)) == HandleError_None) + if ((herr = handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) { - FILE *pFile = (FILE *) pTempFile; - - if (params[4] != 1 && params[4] != 2 && params[4] != 4) - { - return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]); - } - - cell_t *data; - pContext->LocalToPhysAddr(params[2], &data); - - if (params[4] == 4) - { - read = fread(data, sizeof(cell_t), params[3], pFile); - } - else if (params[4] == 2) - { - uint16_t val; - for (cell_t i = 0; i < params[3]; i++) - { - if (fread(&val, sizeof(uint16_t), 1, pFile) != 1) - { - break; - } - data[read++] = val; - } - } - else if (params[4] == 1) - { - uint8_t val; - for (cell_t i = 0; i < params[3]; i++) - { - if (fread(&val, sizeof(uint8_t), 1, pFile) != 1) - { - break; - } - data[read++] = val; - } - } - - if (read != (size_t) params[3] && ferror(pFile) != 0) - { - return -1; - } + fshelper.SetFSType(FSType::STDIO); } - else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, (void **) &pTempFile)) == HandleError_None) + else if ((herr = handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) { - FileHandle_t pFile = (FileHandle_t) pTempFile; - - if (params[4] != 1 && params[4] != 2 && params[4] != 4) - { - return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]); - } - - cell_t *data; - pContext->LocalToPhysAddr(params[2], &data); - - if (params[4] == 4) - { - read = 1; - if (smcore.filesystem->Read(data, sizeof(cell_t), pFile) != sizeof(cell_t)) - { - read = 0; - } - } - else if (params[4] == 2) - { - uint16_t val; - for (cell_t i = 0; i < params[3]; i++) - { - if (smcore.filesystem->Read(&val, sizeof(uint16_t), pFile) != sizeof(uint16_t)) - { - break; - } - data[read++] = val; - } - } - else if (params[4] == 1) - { - uint8_t val; - for (cell_t i = 0; i < params[3]; i++) - { - if (smcore.filesystem->Read(&val, sizeof(uint8_t), pFile) != sizeof(uint8_t)) - { - break; - } - data[read++] = val; - } - } - - if (read != (size_t) params[3]) - { - return -1; - } + fshelper.SetFSType(FSType::VALVE); } - else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - return read; + if (params[4] != 1 && params[4] != 2 && params[4] != 4) + { + return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]); + } + + cell_t *data; + pContext->LocalToPhysAddr(params[2], &data); + + if (params[4] == 4) + { + read = fshelper.Read(data, sizeof(cell_t) * params[3], pFile); + } + else if (params[4] == 2) + { + uint16_t val; + for (cell_t i = 0; i < params[3]; i++) + { + if (fshelper.Read(&val, sizeof(uint16_t), pFile) != 1) + { + break; + } + data[read += sizeof(uint16_t)] = val; + } + } + else if (params[4] == 1) + { + uint8_t val; + for (cell_t i = 0; i < params[3]; i++) + { + if (fshelper.Read(&val, sizeof(uint8_t), pFile) != 1) + { + break; + } + data[read += sizeof(uint8_t)] = val; + } + } + + if (read != ((size_t)params[3] * params[4]) && fshelper.HasError(pFile)) + { + return -1; + } + + return read / params[4]; } static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params) @@ -902,18 +967,27 @@ static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); - FILE *pFile; + void *pFile; cell_t num_read = 0; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) - { - return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); - } - char *buffer; pContext->LocalToString(params[2], &buffer); + FSHelper fshelper; + + if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) + { + fshelper.SetFSType(FSType::STDIO); + } + else if ((herr=handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) + { + fshelper.SetFSType(FSType::VALVE); + } + else + { + return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); + } + if (params[4] != -1) { if (size_t(params[4]) > size_t(params[3])) @@ -923,9 +997,9 @@ static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params) params[3]); } - num_read = (cell_t)fread(buffer, 1, params[4], pFile); + num_read = (cell_t)fshelper.Read(buffer, params[4], pFile); - if (num_read != params[4] && ferror(pFile)) + if (num_read != params[4] && fshelper.HasError(pFile)) { return -1; } @@ -940,9 +1014,9 @@ static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params) { break; } - if (fread(&val, sizeof(val), 1, pFile) != 1) + if (fshelper.Read(&val, sizeof(val), pFile) != 1) { - if (ferror(pFile)) + if (fshelper.HasError(pFile)) { return -1; } @@ -971,10 +1045,18 @@ static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); - FILE *pFile; + void *pFile; + FSHelper fshelper; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) + { + fshelper.SetFSType(FSType::STDIO); + } + else if ((herr=handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) + { + fshelper.SetFSType(FSType::VALVE); + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } @@ -991,7 +1073,7 @@ static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params) if (params[4] == 4) { - if (fwrite(data, sizeof(cell_t), params[3], pFile) != (size_t)params[3]) + if (fshelper.Write(data, sizeof(cell_t) * params[3], pFile) != (sizeof(cell_t) * (size_t)params[3])) { return 0; } @@ -1000,7 +1082,7 @@ static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params) { for (cell_t i = 0; i < params[3]; i++) { - if (fwrite(&data[i], sizeof(int16_t), 1, pFile) != 1) + if (fshelper.Write(&data[i], sizeof(int16_t), pFile) != sizeof(int16_t)) { return 0; } @@ -1010,7 +1092,7 @@ static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params) { for (cell_t i = 0; i < params[3]; i++) { - if (fwrite(&data[i], sizeof(int8_t), 1, pFile) != 1) + if (fshelper.Write(&data[i], sizeof(int8_t), pFile) != sizeof(int8_t)) { return 0; } @@ -1025,10 +1107,18 @@ static cell_t sm_WriteFileString(IPluginContext *pContext, const cell_t *params) Handle_t hndl = static_cast(params[1]); HandleError herr; HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); - FILE *pFile; + void *pFile; + FSHelper fshelper; - if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile)) - != HandleError_None) + if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, &pFile)) == HandleError_None) + { + fshelper.SetFSType(FSType::STDIO); + } + else if ((herr=handlesys->ReadHandle(hndl, g_ValveFileType, &sec, &pFile)) == HandleError_None) + { + fshelper.SetFSType(FSType::VALVE); + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } @@ -1043,7 +1133,7 @@ static cell_t sm_WriteFileString(IPluginContext *pContext, const cell_t *params) len++; } - return (fwrite(buffer, sizeof(char), len, pFile) == len) ? 1 : 0; + return (fshelper.Write(buffer, len, pFile) == len) ? 1 : 0; } static cell_t sm_AddGameLogHook(IPluginContext *pContext, const cell_t *params) diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 751ba6ad..3603dd85 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -178,6 +178,10 @@ public: { return filesystem->Read(pOutput, size, file); } + int Write(void const* pInput, int size, FileHandle_t file) + { + return filesystem->Write(pInput, size, file); + } void Seek(FileHandle_t file, int pos, int seekType) { filesystem->Seek(file, pos, (FileSystemSeek_t) seekType); @@ -194,6 +198,14 @@ public: { filesystem->Flush(file); } + bool IsOk(FileHandle_t file) + { + return filesystem->IsOk(file); + } + void RemoveFile(const char *pRelativePath, const char *pathID) + { + filesystem->RemoveFile(pRelativePath, pathID); + } }; static VFileSystem_Logic logic_filesystem; diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 4da32671..5986b184 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -136,17 +136,25 @@ native bool:ReadDirEntry(Handle:dir, String:buffer[], maxlength, &FileType:type= * * @param file File to open. * @param mode Open mode. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in any of + * the GAME search paths, rather than solely files + * existing directly in the gamedir. * @return A Handle to the file, INVALID_HANDLE on open error. */ -native Handle:OpenFile(const String:file[], const String:mode[]); +native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_fs=false); /** * Deletes a file. * * @param path Path of the file to delete. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in any of + * the GAME search paths, rather than solely files + * existing directly in the gamedir. * @return True on success, false otherwise. */ -native bool:DeleteFile(const String:path[]); +native bool:DeleteFile(const String:path[], bool:use_valve_fs=false); /** * Reads a line from a text file. From f2b19e6c8795369a54768b8b9552e249c4efab61 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Sun, 3 Aug 2014 09:10:02 -0400 Subject: [PATCH 04/12] Add more accurate return value for DeleteFile when using Valve FS. --- core/logic/smn_filesystem.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 7e1536a1..e2f2add4 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -125,9 +125,21 @@ public: inline bool Remove(const char *pFilePath) { if (_fstype == FSType::VALVE) - return smcore.filesystem->RemoveFile(pFilePath), true; + { + if (!smcore.filesystem->FileExists(pFilePath)) + return false; + + smcore.filesystem->RemoveFile(pFilePath); + + if (smcore.filesystem->FileExists(pFilePath)) + return false; + + return true; + } else + { return unlink(pFilePath) == 0; + } } inline bool EndOfFile(void *pFile) From 4e5b1a58cef2166249e4e44369bce7e33d52bf52 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Wed, 6 Aug 2014 13:15:24 -0700 Subject: [PATCH 05/12] Add ValveFS support to more filesystem functions: OpenDirectory (CloseHandle on directory) ReadDirEntry DirExists CreateDirectory RenameFile --- core/logic/intercom.h | 5 + core/logic/smn_filesystem.cpp | 202 ++++++++++++++++++++++++++-------- core/logic_bridge.cpp | 20 ++++ plugins/include/files.inc | 30 +++-- 4 files changed, 205 insertions(+), 52 deletions(-) diff --git a/core/logic/intercom.h b/core/logic/intercom.h index 3df0a5b4..16b96f43 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -82,7 +82,9 @@ class IFileSystem_Logic { public: virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0; + virtual const char *FindFirst(const char *pWildCard, FileFindHandle_t *pHandle) = 0; virtual const char *FindNext(FileFindHandle_t handle) = 0; + virtual bool FindIsDirectory(FileFindHandle_t handle) = 0; virtual void FindClose(FileFindHandle_t handle) = 0; virtual FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) = 0; virtual void Close(FileHandle_t file) = 0; @@ -98,6 +100,9 @@ public: virtual void Flush(FileHandle_t file) = 0; virtual bool IsOk(FileHandle_t file) = 0; virtual void RemoveFile(const char *pRelativePath, const char *pathID = 0) = 0; + virtual void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID = 0) = 0; + virtual bool IsDirectory(const char *pFileName, const char *pathID = 0) = 0; + virtual void CreateDirHierarchy(const char *path, const char *pathID = 0) = 0; }; namespace SourceMod diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index e2f2add4..71147762 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -42,6 +42,7 @@ HandleType_t g_FileType; HandleType_t g_ValveFileType; HandleType_t g_DirType; +HandleType_t g_ValveDirType; IChangeableForward *g_pLogHook = NULL; enum class FSType @@ -161,6 +162,13 @@ private: FSType _fstype; }; +struct ValveDirectory +{ + FileFindHandle_t hndl; + char szFirstPath[PLATFORM_MAX_PATH]; + bool bHandledFirstPath; +}; + class FileNatives : public SMGlobalClass, public IHandleTypeDispatch, @@ -175,6 +183,7 @@ public: g_FileType = handlesys->CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL); g_ValveFileType = handlesys->CreateType("ValveFile", this, 0, NULL, NULL, g_pCoreIdent, NULL); g_DirType = handlesys->CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL); + g_ValveDirType = handlesys->CreateType("ValveDirectory", this, 0, NULL, NULL, g_pCoreIdent, NULL); g_pLogHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 1, NULL, Param_String); pluginsys->AddPluginsListener(this); } @@ -185,9 +194,11 @@ public: handlesys->RemoveType(g_DirType, g_pCoreIdent); handlesys->RemoveType(g_FileType, g_pCoreIdent); handlesys->RemoveType(g_ValveFileType, g_pCoreIdent); + handlesys->RemoveType(g_ValveDirType, g_pCoreIdent); g_DirType = 0; g_FileType = 0; g_ValveFileType = 0; + g_ValveDirType = 0; } virtual void OnHandleDestroy(HandleType_t type, void *object) { @@ -206,6 +217,12 @@ public: FileHandle_t fp = (FileHandle_t) object; smcore.filesystem->Close(fp); } + else if (type == g_ValveDirType) + { + ValveDirectory *valveDir = (ValveDirectory *)object; + smcore.filesystem->FindClose(valveDir->hndl); + delete valveDir; + } } virtual void AddLogHook(IPluginFunction *pFunc) { @@ -238,23 +255,48 @@ static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params) pContext->ThrowNativeErrorEx(err, NULL); return 0; } - - char realpath[PLATFORM_MAX_PATH]; - g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path); - - IDirectory *pDir = libsys->OpenDirectory(realpath); - if (!pDir) + + Handle_t handle = 0; + + if (params[0] <= 1 || !params[2]) { - return 0; + char wildcardedPath[PLATFORM_MAX_PATH]; + snprintf(wildcardedPath, sizeof(wildcardedPath), "%s*", path); + ValveDirectory *valveDir = new ValveDirectory; + const char *pFirst = smcore.filesystem->FindFirst(wildcardedPath, &valveDir->hndl); + if (pFirst) + { + valveDir->bHandledFirstPath = false; + strncpy(valveDir->szFirstPath, pFirst, sizeof(ValveDirectory::szFirstPath)); + } + else + { + valveDir->bHandledFirstPath = true; + } + + handle = handlesys->CreateHandle(g_ValveDirType, valveDir, pContext->GetIdentity(), g_pCoreIdent, NULL); } + else + { + char realpath[PLATFORM_MAX_PATH]; + g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path); - return handlesys->CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL); + IDirectory *pDir = libsys->OpenDirectory(realpath); + if (!pDir) + { + return 0; + } + + handle = handlesys->CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL); + } + + return handle; } static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params) { Handle_t hndl = static_cast(params[1]); - IDirectory *pDir; + void *pTempDir; HandleError herr; HandleSecurity sec; int err; @@ -262,44 +304,90 @@ static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params) sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; - if ((herr=handlesys->ReadHandle(hndl, g_DirType, &sec, (void **)&pDir)) - != HandleError_None) + if ((herr=handlesys->ReadHandle(hndl, g_DirType, &sec, &pTempDir)) == HandleError_None) + { + IDirectory *pDir = (IDirectory *)pTempDir; + if (!pDir->MoreFiles()) + { + return 0; + } + + cell_t *filetype; + if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + if (pDir->IsEntryDirectory()) + { + *filetype = 1; + } else if (pDir->IsEntryFile()) { + *filetype = 2; + } else { + *filetype = 0; + } + + const char *path = pDir->GetEntryName(); + if ((err=pContext->StringToLocalUTF8(params[2], params[3], path, NULL)) + != SP_ERROR_NONE) + { + return pContext->ThrowNativeErrorEx(err, NULL); + } + + pDir->NextEntry(); + } + else if ((herr=handlesys->ReadHandle(hndl, g_ValveDirType, &sec, &pTempDir)) == HandleError_None) + { + ValveDirectory *valveDir = (ValveDirectory *)pTempDir; + + const char *pEntry = NULL; + if (!valveDir->bHandledFirstPath) + { + if (valveDir->szFirstPath[0]) + { + pEntry = valveDir->szFirstPath; + } + } + else + { + pEntry = smcore.filesystem->FindNext(valveDir->hndl); + } + + valveDir->bHandledFirstPath = true; + + // No more entries + if (!pEntry) + { + return 0; + } + + if ((err=pContext->StringToLocalUTF8(params[2], params[3], pEntry, NULL)) + != SP_ERROR_NONE) + { + return pContext->ThrowNativeErrorEx(err, NULL); + } + + cell_t *filetype; + if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + if (smcore.filesystem->FindIsDirectory(valveDir->hndl)) + { + *filetype = 1; + } else { + *filetype = 2; + } + } + else { return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); } - if (!pDir->MoreFiles()) - { - return false; - } - - cell_t *filetype; - if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE) - { - pContext->ThrowNativeErrorEx(err, NULL); - return 0; - } - - if (pDir->IsEntryDirectory()) - { - *filetype = 1; - } else if (pDir->IsEntryFile()) { - *filetype = 2; - } else { - *filetype = 0; - } - - const char *path = pDir->GetEntryName(); - if ((err=pContext->StringToLocalUTF8(params[2], params[3], path, NULL)) - != SP_ERROR_NONE) - { - pContext->ThrowNativeErrorEx(err, NULL); - return 0; - } - - pDir->NextEntry(); - - return true; + return 1; } static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params) @@ -550,6 +638,12 @@ static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params) pContext->ThrowNativeErrorEx(err, NULL); return 0; } + + if (params[0] >= 3 && params[3] == 1) + { + smcore.filesystem->RenameFile(oldpath, newpath); + return 1; + } char new_realpath[PLATFORM_MAX_PATH]; g_pSM->BuildPath(Path_Game, new_realpath, sizeof(new_realpath), "%s", newpath); @@ -572,6 +666,11 @@ static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params) pContext->ThrowNativeErrorEx(err, NULL); return 0; } + + if (params[0] >= 2 && params[2] == 1) + { + return smcore.filesystem->IsDirectory(name) ? 1 : 0; + } char realpath[PLATFORM_MAX_PATH]; g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); @@ -652,9 +751,22 @@ static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params) static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params) { char *name; - char realpath[PLATFORM_MAX_PATH]; - pContext->LocalToString(params[1], &name); + + if (params[0] >= 3 && params[3] == 1) + { + if (smcore.filesystem->IsDirectory(name)) + return 0; + + smcore.filesystem->CreateDirHierarchy(name); + + if (smcore.filesystem->IsDirectory(name)) + return 1; + + return 0; + } + + char realpath[PLATFORM_MAX_PATH]; g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name); #if defined PLATFORM_WINDOWS diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 3603dd85..7ddf8a62 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -142,10 +142,18 @@ public: { return filesystem->FindFirstEx(pWildCard, pPathID, pHandle); } + const char *FindFirst(const char *pWildCard, FileFindHandle_t *pHandle) + { + return filesystem->FindFirst(pWildCard, pHandle); + } const char *FindNext(FileFindHandle_t handle) { return filesystem->FindNext(handle); } + bool FindIsDirectory(FileFindHandle_t handle) + { + return filesystem->FindIsDirectory(handle); + } void FindClose(FileFindHandle_t handle) { filesystem->FindClose(handle); @@ -206,6 +214,18 @@ public: { filesystem->RemoveFile(pRelativePath, pathID); } + void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID) + { + filesystem->RenameFile(pOldPath, pNewPath, pathID); + } + bool IsDirectory(const char *pFileName, const char *pathID) + { + return filesystem->IsDirectory(pFileName, pathID); + } + void CreateDirHierarchy(const char *path, const char *pathID) + { + filesystem->CreateDirHierarchy(path, pathID); + } }; static VFileSystem_Logic logic_filesystem; diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 5986b184..742ac3ce 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -108,9 +108,13 @@ native BuildPath(PathType:type, String:buffer[], maxlength, const String:fmt[], * @note OpenDirectory() supports the "file://" notation. * * @param path Path to open. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in any of + * the GAME search paths, rather than solely files + * existing directly in the gamedir. * @return A Handle to the directory, INVALID_HANDLE on open error. */ -native Handle:OpenDirectory(const String:path[]); +native Handle:OpenDirectory(const String:path[], bool:use_valve_fs=false); /** * Reads the current directory entry as a local filename, then moves to the next file. @@ -149,8 +153,8 @@ native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_ * * @param path Path of the file to delete. * @param use_valve_fs If true, the Valve file system will be used instead. - * This can be used to find files existing in any of - * the GAME search paths, rather than solely files + * This can be used to delete files existing in the game's + * DEFAULT_WRITE_PATH search path, rather than solely files * existing directly in the gamedir. * @return True on success, false otherwise. */ @@ -323,17 +327,24 @@ native bool:FileExists(const String:path[], bool:use_valve_fs=false); * * @param newpath New path to the file. * @param oldpath Path to the existing file. - * @return True on success, false otherwise. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to rename files in the game's + * DEFAULT_WRITE_PATH search path, rather than directly in the gamedir. + * @return True on success or use_valve_fs specified, false otherwise. */ -native bool:RenameFile(const String:newpath[], const String:oldpath[]); +native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_valve_fs=false); /** * Checks if a directory exists. * * @param path Path to the directory. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to find files existing in any of + * the GAME search paths, rather than solely files + * existing directly in the gamedir. * @return True if the directory exists, false otherwise. */ -native bool:DirExists(const String:path[]); +native bool:DirExists(const String:path[], bool:use_valve_fs=false); /** * Get the file size in bytes. @@ -352,7 +363,8 @@ native FileSize(const String:path[], bool:use_valve_fs=false); * is immediately written to the file. * * @param file Handle to the file. - * @return True on success, false on failure. + * @return True on success or use_valve_fs specified with OpenFile, + * otherwise false on failure. */ native FlushFile(Handle:file); @@ -381,6 +393,10 @@ native bool:RemoveDir(const String:path[]); * @param path Path to create. * @param mode Permissions (default is o=rx,g=rx,u=rwx). Note that folders must have * the execute bit set on Linux. On Windows, the mode is ignored. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to create folders in the game's + * DEFAULT_WRITE_PATH search path, rather than directly in the gamedir. + * In this case, mode is ignored. */ native bool:CreateDirectory(const String:path[], mode); From 5716927cbf5812d6541d1587106aca1a844d4006 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Wed, 20 Aug 2014 21:37:47 -0400 Subject: [PATCH 06/12] Fix compile error on with MSVC. --- core/logic/smn_filesystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 71147762..4d270d9d 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -267,7 +267,7 @@ static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params) if (pFirst) { valveDir->bHandledFirstPath = false; - strncpy(valveDir->szFirstPath, pFirst, sizeof(ValveDirectory::szFirstPath)); + strncpy(valveDir->szFirstPath, pFirst, sizeof(valveDir->szFirstPath)); } else { From e1158889e55c321752c01602b469a96fa9e8f0af Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 22 Aug 2014 05:56:23 -0700 Subject: [PATCH 07/12] Fix backwards use_valve_fs logic for OpenDirectory --- core/logic/smn_filesystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 4d270d9d..17ee986c 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -258,7 +258,7 @@ static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params) Handle_t handle = 0; - if (params[0] <= 1 || !params[2]) + if (params[0] >= 2 && params[2]) { char wildcardedPath[PLATFORM_MAX_PATH]; snprintf(wildcardedPath, sizeof(wildcardedPath), "%s*", path); From b95e7ff1451c05e02978558b3ec387ad275c9ade Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 22 Aug 2014 05:59:41 -0700 Subject: [PATCH 08/12] Add missing use_valve_fs param to CreateDirectory native def --- plugins/include/files.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 742ac3ce..81dee0db 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -398,7 +398,7 @@ native bool:RemoveDir(const String:path[]); * DEFAULT_WRITE_PATH search path, rather than directly in the gamedir. * In this case, mode is ignored. */ -native bool:CreateDirectory(const String:path[], mode); +native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false); /** * Returns a file timestamp as a unix timestamp. From 73115f7afa92e2cb1b6ded8e5ac6c7362cade46f Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 22 Aug 2014 06:00:43 -0700 Subject: [PATCH 09/12] Add support for specifying gameinfo search path when using valveFS in file natives --- core/logic/intercom.h | 1 - core/logic/smn_filesystem.cpp | 97 +++++++++++++++++++++++++++++------ core/logic_bridge.cpp | 4 -- plugins/include/files.inc | 46 ++++++++++------- 4 files changed, 107 insertions(+), 41 deletions(-) diff --git a/core/logic/intercom.h b/core/logic/intercom.h index 16b96f43..929a59a3 100644 --- a/core/logic/intercom.h +++ b/core/logic/intercom.h @@ -82,7 +82,6 @@ class IFileSystem_Logic { public: virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0; - virtual const char *FindFirst(const char *pWildCard, FileFindHandle_t *pHandle) = 0; virtual const char *FindNext(FileFindHandle_t handle) = 0; virtual bool FindIsDirectory(FileFindHandle_t handle) = 0; virtual void FindClose(FileFindHandle_t handle) = 0; diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 17ee986c..cd1c4e21 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -59,10 +59,10 @@ public: _fstype = fstype; } public: - inline void *Open(const char *filename, const char *mode) + inline void *Open(const char *filename, const char *mode, const char *pathID) { if (_fstype == FSType::VALVE) - return smcore.filesystem->Open(filename, mode); + return smcore.filesystem->Open(filename, mode, pathID); else return fopen(filename, mode); } @@ -123,16 +123,16 @@ public: fclose((FILE *)pFile); } - inline bool Remove(const char *pFilePath) + inline bool Remove(const char *pFilePath, const char *pathID) { if (_fstype == FSType::VALVE) { - if (!smcore.filesystem->FileExists(pFilePath)) + if (!smcore.filesystem->FileExists(pFilePath, pathID)) return false; - smcore.filesystem->RemoveFile(pFilePath); + smcore.filesystem->RemoveFile(pFilePath, pathID); - if (smcore.filesystem->FileExists(pFilePath)) + if (smcore.filesystem->FileExists(pFilePath, pathID)) return false; return true; @@ -263,7 +263,15 @@ static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params) char wildcardedPath[PLATFORM_MAX_PATH]; snprintf(wildcardedPath, sizeof(wildcardedPath), "%s*", path); ValveDirectory *valveDir = new ValveDirectory; - const char *pFirst = smcore.filesystem->FindFirst(wildcardedPath, &valveDir->hndl); + + char *pathID; + if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + const char *pFirst = smcore.filesystem->FindFirstEx(wildcardedPath, pathID, &valveDir->hndl); if (pFirst) { valveDir->bHandledFirstPath = false; @@ -409,6 +417,7 @@ static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params) HandleType_t handleType; FSHelper fshelper; const char *openpath; + char *pathID; if (params[0] <= 2 || !params[3]) { handleType = g_FileType; @@ -420,12 +429,18 @@ static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params) } else { + if ((err=pContext->LocalToStringNULL(params[4], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + handleType = g_ValveFileType; fshelper.SetFSType(FSType::VALVE); openpath = name; } - void *pFile = fshelper.Open(openpath, mode); + void *pFile = fshelper.Open(openpath, mode, pathID); if (pFile) { handle = handlesys->CreateHandle(handleType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL); @@ -446,6 +461,7 @@ static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params) FSHelper fshelper; const char *filepath; + char *pathID; if (params[0] < 2 || !params[2]) { fshelper.SetFSType(FSType::STDIO); @@ -455,11 +471,17 @@ static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params) } else { + if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + fshelper.SetFSType(FSType::VALVE); filepath = name; } - return fshelper.Remove(filepath) ? 1 : 0; + return fshelper.Remove(filepath, pathID) ? 1 : 0; } static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params) @@ -594,7 +616,17 @@ static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params) if (params[0] >= 2 && params[2] == 1) { - return smcore.filesystem->FileExists(name) ? 1 : 0; + char *pathID = NULL; + if (params[0] >= 3) + { + if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + } + + return smcore.filesystem->FileExists(name, pathID) ? 1 : 0; } char realpath[PLATFORM_MAX_PATH]; @@ -641,7 +673,14 @@ static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params) if (params[0] >= 3 && params[3] == 1) { - smcore.filesystem->RenameFile(oldpath, newpath); + char *pathID; + if ((err=pContext->LocalToStringNULL(params[4], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + smcore.filesystem->RenameFile(oldpath, newpath, pathID); return 1; } @@ -669,7 +708,14 @@ static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params) if (params[0] >= 2 && params[2] == 1) { - return smcore.filesystem->IsDirectory(name) ? 1 : 0; + char *pathID; + if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + return smcore.filesystem->IsDirectory(name, pathID) ? 1 : 0; } char realpath[PLATFORM_MAX_PATH]; @@ -711,9 +757,19 @@ static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params) if (params[0] >= 2 && params[2] == 1) { - if (smcore.filesystem->FileExists(name)) + char *pathID = NULL; + if (params[0] >= 3) { - return smcore.filesystem->Size(name); + if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return -1; + } + } + + if (smcore.filesystem->FileExists(name, pathID)) + { + return smcore.filesystem->Size(name, pathID); } else { @@ -755,12 +811,19 @@ static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params) if (params[0] >= 3 && params[3] == 1) { - if (smcore.filesystem->IsDirectory(name)) + int err; + char *pathID; + if ((err=pContext->LocalToStringNULL(params[4], &pathID)) != SP_ERROR_NONE) + { + return pContext->ThrowNativeErrorEx(err, NULL); + } + + if (smcore.filesystem->IsDirectory(name, pathID)) return 0; - smcore.filesystem->CreateDirHierarchy(name); + smcore.filesystem->CreateDirHierarchy(name, pathID); - if (smcore.filesystem->IsDirectory(name)) + if (smcore.filesystem->IsDirectory(name, pathID)) return 1; return 0; diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 7ddf8a62..f7d0babe 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -142,10 +142,6 @@ public: { return filesystem->FindFirstEx(pWildCard, pPathID, pHandle); } - const char *FindFirst(const char *pWildCard, FileFindHandle_t *pHandle) - { - return filesystem->FindFirst(pWildCard, pHandle); - } const char *FindNext(FileFindHandle_t handle) { return filesystem->FindNext(handle); diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 81dee0db..f44e47c5 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -110,11 +110,12 @@ native BuildPath(PathType:type, String:buffer[], maxlength, const String:fmt[], * @param path Path to open. * @param use_valve_fs If true, the Valve file system will be used instead. * This can be used to find files existing in any of - * the GAME search paths, rather than solely files + * the Valve search paths, rather than solely files * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return A Handle to the directory, INVALID_HANDLE on open error. */ -native Handle:OpenDirectory(const String:path[], bool:use_valve_fs=false); +native Handle:OpenDirectory(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME"); /** * Reads the current directory entry as a local filename, then moves to the next file. @@ -141,24 +142,26 @@ native bool:ReadDirEntry(Handle:dir, String:buffer[], maxlength, &FileType:type= * @param file File to open. * @param mode Open mode. * @param use_valve_fs If true, the Valve file system will be used instead. - * This can be used to find files existing in any of - * the GAME search paths, rather than solely files - * existing directly in the gamedir. + * This can be used to find files existing in valve + * search paths, rather than solely files existing directly + * in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return A Handle to the file, INVALID_HANDLE on open error. */ -native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_fs=false); +native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME"); /** * Deletes a file. * * @param path Path of the file to delete. * @param use_valve_fs If true, the Valve file system will be used instead. - * This can be used to delete files existing in the game's - * DEFAULT_WRITE_PATH search path, rather than solely files - * existing directly in the gamedir. + * This can be used to delete files existing in the Valve + * search path, rather than solely files existing directly + * in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True on success, false otherwise. */ -native bool:DeleteFile(const String:path[], bool:use_valve_fs=false); +native bool:DeleteFile(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="DEFAULT_WRITE_PATH"); /** * Reads a line from a text file. @@ -316,11 +319,12 @@ native FilePosition(Handle:file); * @param path Path to the file. * @param use_valve_fs If true, the Valve file system will be used instead. * This can be used to find files existing in any of - * the GAME search paths, rather than solely files + * the Valve search paths, rather than solely files * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True if the file exists, false otherwise. */ -native bool:FileExists(const String:path[], bool:use_valve_fs=false); +native bool:FileExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="GAME"); /** * Renames a file. @@ -329,10 +333,11 @@ native bool:FileExists(const String:path[], bool:use_valve_fs=false); * @param oldpath Path to the existing file. * @param use_valve_fs If true, the Valve file system will be used instead. * This can be used to rename files in the game's - * DEFAULT_WRITE_PATH search path, rather than directly in the gamedir. + * Valve search paths, rather than directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True on success or use_valve_fs specified, false otherwise. */ -native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_valve_fs=false); +native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_valve_fs=false, const String:valve_path_id="DEFAULT_WRITE_PATH"); /** * Checks if a directory exists. @@ -340,11 +345,12 @@ native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_ * @param path Path to the directory. * @param use_valve_fs If true, the Valve file system will be used instead. * This can be used to find files existing in any of - * the GAME search paths, rather than solely files + * the Valve search paths, rather than solely files * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True if the directory exists, false otherwise. */ -native bool:DirExists(const String:path[], bool:use_valve_fs=false); +native bool:DirExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="GAME"); /** * Get the file size in bytes. @@ -352,11 +358,12 @@ native bool:DirExists(const String:path[], bool:use_valve_fs=false); * @param path Path to the file. * @param use_valve_fs If true, the Valve file system will be used instead. * This can be used to find files existing in any of - * the GAME search paths, rather than solely files + * the Valve search paths, rather than solely files * existing directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return File size in bytes, -1 if file not found. */ -native FileSize(const String:path[], bool:use_valve_fs=false); +native FileSize(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="GAME"); /** * Flushes a file's buffered output; any buffered output @@ -395,7 +402,8 @@ native bool:RemoveDir(const String:path[]); * the execute bit set on Linux. On Windows, the mode is ignored. * @param use_valve_fs If true, the Valve file system will be used instead. * This can be used to create folders in the game's - * DEFAULT_WRITE_PATH search path, rather than directly in the gamedir. + * Valve search paths, rather than directly in the gamedir. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default. * In this case, mode is ignored. */ native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false); From 8d60fecb96eecf65bd4ba99082280c358379cc99 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 22 Aug 2014 06:30:25 -0700 Subject: [PATCH 10/12] Fix syntax errors in files.inc --- plugins/include/files.inc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/include/files.inc b/plugins/include/files.inc index f44e47c5..36adea6b 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -161,7 +161,7 @@ native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_ * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True on success, false otherwise. */ -native bool:DeleteFile(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="DEFAULT_WRITE_PATH"); +native bool:DeleteFile(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH"); /** * Reads a line from a text file. @@ -324,7 +324,7 @@ native FilePosition(Handle:file); * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True if the file exists, false otherwise. */ -native bool:FileExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="GAME"); +native bool:FileExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME"); /** * Renames a file. @@ -337,7 +337,7 @@ native bool:FileExists(const String:path[], bool:use_valve_fs=false, const Strin * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True on success or use_valve_fs specified, false otherwise. */ -native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_valve_fs=false, const String:valve_path_id="DEFAULT_WRITE_PATH"); +native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH"); /** * Checks if a directory exists. @@ -350,7 +350,7 @@ native bool:RenameFile(const String:newpath[], const String:oldpath[], bool:use_ * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return True if the directory exists, false otherwise. */ -native bool:DirExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="GAME"); +native bool:DirExists(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME"); /** * Get the file size in bytes. @@ -363,7 +363,7 @@ native bool:DirExists(const String:path[], bool:use_valve_fs=false, const String * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * @return File size in bytes, -1 if file not found. */ -native FileSize(const String:path[], bool:use_valve_fs=false, const String:valve_path_id="GAME"); +native FileSize(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="GAME"); /** * Flushes a file's buffered output; any buffered output @@ -406,7 +406,7 @@ native bool:RemoveDir(const String:path[]); * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default. * In this case, mode is ignored. */ -native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false); +native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false, const String:valve_path_id="DEFAULT_WRITE_PATH"); /** * Returns a file timestamp as a unix timestamp. From 9d6fea857b0909dae0818261cb1746af42380d05 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 22 Aug 2014 06:55:45 -0700 Subject: [PATCH 11/12] Fix another syntax error in files.inc --- plugins/include/files.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 36adea6b..beee0fc3 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -406,7 +406,7 @@ native bool:RemoveDir(const String:path[]); * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default. * In this case, mode is ignored. */ -native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false, const String:valve_path_id="DEFAULT_WRITE_PATH"); +native bool:CreateDirectory(const String:path[], mode, bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH"); /** * Returns a file timestamp as a unix timestamp. From 51d32bca77dbf3c3bd062746ea6264d117ebc6c6 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Fri, 22 Aug 2014 07:21:12 -0700 Subject: [PATCH 12/12] Clarify return value commit on RemoveFile --- plugins/include/files.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/include/files.inc b/plugins/include/files.inc index beee0fc3..34e772f2 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -159,7 +159,7 @@ native Handle:OpenFile(const String:file[], const String:mode[], bool:use_valve_ * search path, rather than solely files existing directly * in the gamedir. * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. - * @return True on success, false otherwise. + * @return True on success, false on failure or if file not immediately removed. */ native bool:DeleteFile(const String:path[], bool:use_valve_fs=false, const String:valve_path_id[]="DEFAULT_WRITE_PATH");