diff --git a/bridge/include/IFileSystemBridge.h b/bridge/include/IFileSystemBridge.h index 73fdec8d60..4c62506f76 100644 --- a/bridge/include/IFileSystemBridge.h +++ b/bridge/include/IFileSystemBridge.h @@ -44,6 +44,7 @@ class IFileSystemBridge virtual char *ReadLine(char *pOutput, int maxChars, FileHandle_t file) = 0; virtual bool EndOfFile(FileHandle_t file) = 0; virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0; + virtual unsigned int Size(FileHandle_t file) = 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; diff --git a/core/logic/smn_filesystem.cpp b/core/logic/smn_filesystem.cpp index 032f951e60..3d9b302d62 100644 --- a/core/logic/smn_filesystem.cpp +++ b/core/logic/smn_filesystem.cpp @@ -73,6 +73,7 @@ class FileObject public: virtual ~FileObject() {} + virtual size_t Size() = 0; virtual size_t Read(void *pOut, int size) = 0; virtual char *ReadLine(char *pOut, int size) = 0; virtual size_t Write(const void *pData, int size) = 0; @@ -119,6 +120,10 @@ class ValveFile : public FileObject return true; } + size_t Size() override { + return (size_t)bridge->filesystem->Size(handle_); + } + size_t Read(void *pOut, int size) override { return (size_t)bridge->filesystem->Read(pOut, size, handle_); } @@ -183,6 +188,30 @@ class SystemFile : public FileObject return unlink(path) == 0; } + size_t Size() override { +#ifdef PLATFORM_WINDOWS + struct _stat s; + int fd = _fileno(fp_); + if (fd == -1) + return -1; + if (_fstat(fd, &s) != 0) + return -1; + if (s.st_mode & S_IFREG) + return static_cast(s.st_size); + return -1; +#elif defined PLATFORM_POSIX + struct stat s; + int fd = fileno(fp_); + if (fd == -1) + return -1; + if (fstat(fd, &s) != 0) + return -1; + if (S_ISREG(s.st_mode)) + return static_cast(s.st_size); + return -1; +#endif + } + size_t Read(void *pOut, int size) override { return fread(pOut, 1, size, fp_); } @@ -1125,6 +1154,15 @@ static cell_t sm_RemoveGameLogHook(IPluginContext *pContext, const cell_t *param return 1; } +static cell_t File_Size(IPluginContext *pContext, const cell_t *params) +{ + OpenHandle file(pContext, params[1], g_FileType); + if (!file.Ok()) + return -1; + + return file->Size(); +} + template static cell_t File_ReadTyped(IPluginContext *pContext, const cell_t *params) { @@ -1197,6 +1235,7 @@ REGISTER_NATIVES(filesystem) {"File.Seek", sm_FileSeek}, {"File.Flush", sm_FlushFile}, {"File.Position.get", sm_FilePosition}, + {"File.Size", File_Size}, {"File.ReadInt8", File_ReadTyped}, {"File.ReadUint8", File_ReadTyped}, {"File.ReadInt16", File_ReadTyped}, diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index a718c32345..4cc1128a78 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -138,6 +138,10 @@ class VFileSystem_Logic : public IFileSystemBridge { return filesystem->FileExists(pFileName, pPathID); } + unsigned int Size(FileHandle_t file) override + { + return filesystem->Size(file); + } unsigned int Size(const char *pFileName, const char *pPathID = 0) override { return filesystem->Size(pFileName, pPathID); diff --git a/plugins/include/files.inc b/plugins/include/files.inc index 1d8fd3b309..78efd65cc2 100644 --- a/plugins/include/files.inc +++ b/plugins/include/files.inc @@ -112,6 +112,11 @@ methodmap File < Handle CloseHandle(this); } + // Get the file size in bytes. + // + // @return File size in bytes, -1 on error. + public native int Size(); + // Reads a line of text from a file. // // @param buffer String buffer to hold the line.