Merge pull request #217 from Arkshine/feature/valve-fs-support
Add support for Valve FS to natives that use file handles
This commit is contained in:
		| @@ -93,6 +93,7 @@ binary.sources = [ | ||||
|   'cvars.cpp', | ||||
|   '../public/memtools/CDetour/detours.cpp', | ||||
|   '../public/memtools/CDetour/asm/asm.c', | ||||
|   'CLibrarySys.cpp', | ||||
| ] | ||||
|  | ||||
| if builder.target_platform == 'windows': | ||||
|   | ||||
							
								
								
									
										256
									
								
								amxmodx/CFileSystem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								amxmodx/CFileSystem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,256 @@ | ||||
| // vim: set ts=4 sw=4 tw=99 noet: | ||||
| // | ||||
| // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). | ||||
| // Copyright (C) The AMX Mod X Development Team. | ||||
| // | ||||
| // This software is licensed under the GNU General Public License, version 3 or higher. | ||||
| // Additional exceptions apply. For full license details, see LICENSE.txt or visit: | ||||
| //     https://alliedmods.net/amxmodx-license | ||||
|  | ||||
| #ifndef _INCLUDE_CFILESYSTEM_H_ | ||||
| #define _INCLUDE_CFILESYSTEM_H_ | ||||
|  | ||||
| #include <FileSystem.h> // IFileSystem, FileSystemSeek_t, FileHandle_t (HLSDK) | ||||
| #include <stdio.h>      // FILE* | ||||
| #include <am-cxx.h>     // KE_OVERRIDE | ||||
|  | ||||
| extern IFileSystem* g_FileSystem; | ||||
|  | ||||
| class ValveFile; | ||||
| class SystemFile; | ||||
|  | ||||
| class FileObject | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		virtual ~FileObject() {}; | ||||
|  | ||||
| 		virtual size_t Read(void* pOut, size_t size) = 0; | ||||
| 		virtual char* ReadLine(char* pOut, size_t size) = 0; | ||||
| 		virtual size_t Write(const void* pData, size_t size) = 0; | ||||
|  | ||||
| 		virtual bool Seek(int pos, int seek_type) = 0; | ||||
| 		virtual int Tell() = 0; | ||||
| 		virtual int Flush() = 0; | ||||
|  | ||||
| 		virtual bool HasError() = 0; | ||||
|  | ||||
| 		virtual bool EndOfFile() = 0; | ||||
| 		virtual void Close() = 0; | ||||
|  | ||||
| 		virtual ValveFile *AsValveFile()  | ||||
| 		{ | ||||
| 			return nullptr; | ||||
| 		} | ||||
|  | ||||
| 		virtual SystemFile *AsSystemFile() | ||||
| 		{ | ||||
| 			return nullptr; | ||||
| 		} | ||||
| }; | ||||
|  | ||||
| class ValveFile : public FileObject | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		ValveFile(FileHandle_t handle) : handle_(handle) {} | ||||
|  | ||||
| 		~ValveFile()  | ||||
| 		{ | ||||
| 			Close(); | ||||
| 		} | ||||
|  | ||||
| 		static bool Exists(const char* file) | ||||
| 		{ | ||||
| 			return g_FileSystem->FileExists(file); | ||||
| 		} | ||||
|  | ||||
| 		static ValveFile* Open(const char* filename, const char* mode, const char* pathID)  | ||||
| 		{ | ||||
| 			FileHandle_t handle = g_FileSystem->OpenFromCacheForRead(filename, mode, pathID); | ||||
| 			 | ||||
| 			if (!handle) | ||||
| 			{ | ||||
| 				return nullptr; | ||||
| 			} | ||||
|  | ||||
| 			return new ValveFile(handle); | ||||
| 		} | ||||
|  | ||||
| 		static bool Delete(const char* filename, const char* pathID)  | ||||
| 		{ | ||||
| 			if (!Exists(filename)) | ||||
| 			{ | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 			g_FileSystem->RemoveFile(filename, pathID); | ||||
|  | ||||
| 			if (Exists(filename)) | ||||
| 			{ | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		size_t Read(void* pOut, size_t size) KE_OVERRIDE | ||||
| 		{ | ||||
| 			return static_cast<size_t>(g_FileSystem->Read(pOut, size, handle_)); | ||||
| 		} | ||||
| 		 | ||||
| 		char* ReadLine(char* pOut, size_t size) KE_OVERRIDE | ||||
| 		{ | ||||
| 			return g_FileSystem->ReadLine(pOut, size, handle_); | ||||
| 		} | ||||
|  | ||||
| 		size_t Write(const void* pData, size_t size) KE_OVERRIDE | ||||
| 		{ | ||||
| 			return static_cast<size_t>(g_FileSystem->Write(pData, size, handle_)); | ||||
| 		} | ||||
| 		 | ||||
| 		bool Seek(int pos, int seek_type) KE_OVERRIDE | ||||
| 		{ | ||||
| 			g_FileSystem->Seek(handle_, pos, static_cast<FileSystemSeek_t>(seek_type)); | ||||
| 			return !HasError(); | ||||
| 		} | ||||
| 		 | ||||
| 		int Tell() KE_OVERRIDE | ||||
| 		{ | ||||
| 			return g_FileSystem->Tell(handle_); | ||||
| 		} | ||||
| 		 | ||||
| 		bool HasError() KE_OVERRIDE | ||||
| 		{ | ||||
| 			return !handle_ || !g_FileSystem->IsOk(handle_); | ||||
| 		} | ||||
| 		 | ||||
| 		int Flush() KE_OVERRIDE | ||||
| 		{ | ||||
| 			g_FileSystem->Flush(handle_); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		 | ||||
| 		bool EndOfFile() KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return g_FileSystem->EndOfFile(handle_); | ||||
| 		} | ||||
| 	 | ||||
| 		void Close() KE_OVERRIDE  | ||||
| 		{ | ||||
| 			if (handle_) | ||||
| 			{ | ||||
| 				g_FileSystem->Close(handle_); | ||||
| 				handle_ = nullptr;; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		virtual ValveFile* AsValveFile()  | ||||
| 		{ | ||||
| 			return this; | ||||
| 		} | ||||
|  | ||||
| 		FileHandle_t handle() const | ||||
| 		{ | ||||
| 			return handle_; | ||||
| 		} | ||||
|  | ||||
| 	private: | ||||
|  | ||||
| 		FileHandle_t handle_; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class SystemFile : public FileObject | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		SystemFile(FILE* fp) : fp_(fp) {} | ||||
|  | ||||
| 		~SystemFile()  | ||||
| 		{ | ||||
| 			Close(); | ||||
| 		} | ||||
|  | ||||
| 		static SystemFile* Open(const char* path, const char* mode)  | ||||
| 		{ | ||||
| 			FILE* fp = fopen(path, mode); | ||||
|  | ||||
| 			if (!fp) | ||||
| 			{ | ||||
| 				return nullptr; | ||||
| 			} | ||||
|  | ||||
| 			return new SystemFile(fp); | ||||
| 		} | ||||
|  | ||||
| 		static bool Delete(const char* path)  | ||||
| 		{ | ||||
| 			return unlink(path) == 0; | ||||
| 		} | ||||
|  | ||||
| 		size_t Read(void* pOut, size_t size) KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return fread(pOut, 1, size, fp_); | ||||
| 		} | ||||
| 		 | ||||
| 		char* ReadLine(char* pOut, size_t size) KE_OVERRIDE | ||||
| 		{ | ||||
| 			return fgets(pOut, size, fp_); | ||||
| 		} | ||||
| 		 | ||||
| 		size_t Write(const void* pData, size_t size) KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return fwrite(pData, 1, size, fp_); | ||||
| 		} | ||||
| 		 | ||||
| 		bool Seek(int pos, int seek_type) KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return fseek(fp_, pos, seek_type) == 0; | ||||
| 		} | ||||
| 		 | ||||
| 		int Tell() KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return ftell(fp_); | ||||
| 		} | ||||
| 		 | ||||
| 		bool HasError() KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return ferror(fp_) != 0; | ||||
| 		} | ||||
| 		 | ||||
| 		int Flush() KE_OVERRIDE  | ||||
| 		{ | ||||
| 			return fflush(fp_); | ||||
| 		} | ||||
| 		 | ||||
| 		bool EndOfFile() KE_OVERRIDE | ||||
| 		{ | ||||
| 			return feof(fp_) != 0; | ||||
| 		} | ||||
| 		 | ||||
| 		void Close() KE_OVERRIDE  | ||||
| 		{ | ||||
| 			if (fp_) | ||||
| 			{ | ||||
| 				fclose(fp_); | ||||
| 				fp_ = nullptr; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		virtual SystemFile* AsSystemFile() | ||||
| 		{ | ||||
| 			return this; | ||||
| 		} | ||||
|  | ||||
| 		FILE* handle() const | ||||
| 		{ | ||||
| 			return fp_; | ||||
| 		} | ||||
|  | ||||
| 	private: | ||||
|  | ||||
| 		FILE* fp_; | ||||
| }; | ||||
|  | ||||
| #endif // _INCLUDE_CFILESYSTEM_H_ | ||||
| @@ -12,6 +12,8 @@ | ||||
| #include "CLang.h" | ||||
| #include "format.h" | ||||
|  | ||||
| CVector<FILE *> FileList; | ||||
|  | ||||
| #define LITIDX_NONE			0 | ||||
| #define LITIDX_BRACKET		1 | ||||
| #define LITIDX_DEFINITION	2 | ||||
|   | ||||
							
								
								
									
										532
									
								
								amxmodx/CLibrarySys.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										532
									
								
								amxmodx/CLibrarySys.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,532 @@ | ||||
| // vim: set ts=4 sw=4 tw=99 noet: | ||||
| // | ||||
| // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). | ||||
| // Copyright (C) The AMX Mod X Development Team. | ||||
| // | ||||
| // This software is licensed under the GNU General Public License, version 3 or higher. | ||||
| // Additional exceptions apply. For full license details, see LICENSE.txt or visit: | ||||
| //     https://alliedmods.net/amxmodx-license | ||||
|  | ||||
| #include "CLibrarySys.h" | ||||
| #include <amxmodx.h> | ||||
|  | ||||
| LibrarySystem g_LibSys; | ||||
|  | ||||
| /******************/ | ||||
| /* Directory Code */ | ||||
| /******************/ | ||||
|  | ||||
| CDirectory::CDirectory(const char *path) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	char newpath[PLATFORM_MAX_PATH]; | ||||
| 	UTIL_Format(newpath, sizeof(newpath) - 1, "%s\\*.*", path); | ||||
|  | ||||
| 	m_dir = FindFirstFile(newpath, &m_fd); | ||||
|  | ||||
| 	if (!IsValid()) | ||||
| 	{ | ||||
| 		m_fd.cFileName[0] = '\0'; | ||||
| 	} | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	m_dir = opendir(path); | ||||
|  | ||||
| 	if (IsValid()) | ||||
| 	{ | ||||
| 		m_ep = readdir(m_dir); // TODO: we need to read past "." and ".."! | ||||
| 		UTIL_Format(m_origpath, sizeof(m_origpath) - 1, "%s", path); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		m_ep = nullptr; | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
|  | ||||
| CDirectory::~CDirectory() | ||||
| { | ||||
| 	if (IsValid()) | ||||
| 	{ | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 		FindClose(m_dir); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 		closedir(m_dir); | ||||
| #endif | ||||
| 	} | ||||
| } | ||||
|  | ||||
| DirHandle CDirectory::GetHandle() | ||||
| { | ||||
| 	return m_dir; | ||||
| } | ||||
|  | ||||
| void CDirectory::NextEntry() | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	if (FindNextFile(m_dir, &m_fd) == 0) | ||||
| 	{ | ||||
| 		FindClose(m_dir); | ||||
| 		m_dir = INVALID_HANDLE_VALUE; | ||||
| 	} | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	if (!(m_ep = readdir(m_dir))) | ||||
| 	{ | ||||
| 		closedir(m_dir); | ||||
| 		m_dir = nullptr; | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool CDirectory::IsEntryValid() | ||||
| { | ||||
| 	return IsValid(); | ||||
| } | ||||
|  | ||||
| bool CDirectory::IsEntryDirectory() | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	char temppath[PLATFORM_MAX_PATH]; | ||||
| 	UTIL_Format(temppath, sizeof(temppath) - 1, "%s/%s", m_origpath, GetEntryName()); | ||||
|  | ||||
| 	return g_LibSys.IsPathDirectory(temppath); | ||||
|  | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool CDirectory::IsEntryFile() | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	char temppath[PLATFORM_MAX_PATH]; | ||||
| 	UTIL_Format(temppath, sizeof(temppath) - 1, "%s/%s", m_origpath, GetEntryName()); | ||||
|  | ||||
| 	return g_LibSys.IsPathFile(temppath); | ||||
|  | ||||
| #endif | ||||
| } | ||||
|  | ||||
| const char* CDirectory::GetEntryName() | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return m_fd.cFileName; | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	return m_ep ? m_ep->d_name : ""; | ||||
|  | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool CDirectory::MoreFiles() | ||||
| { | ||||
| 	return IsValid(); | ||||
| } | ||||
|  | ||||
| bool CDirectory::IsValid() | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return (m_dir != INVALID_HANDLE_VALUE); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	return (m_dir != nullptr); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| /****************/ | ||||
| /* Library Code */ | ||||
| /****************/ | ||||
|  | ||||
| CLibrary::~CLibrary() | ||||
| { | ||||
| 	if (m_lib) | ||||
| 	{ | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 		FreeLibrary(m_lib); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 		dlclose(m_lib); | ||||
| #endif | ||||
| 		m_lib = nullptr; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CLibrary::CLibrary(LibraryHandle me) | ||||
| { | ||||
| 	m_lib = me; | ||||
| } | ||||
|  | ||||
| void CLibrary::CloseLibrary() | ||||
| { | ||||
| 	delete this; | ||||
| } | ||||
|  | ||||
| void *CLibrary::GetSymbolAddress(const char* symname) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return GetProcAddress(m_lib, symname); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	return dlsym(m_lib, symname); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| /***********************/ | ||||
| /* Library System Code */ | ||||
| /***********************/ | ||||
|  | ||||
| bool LibrarySystem::PathExists(const char *path) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	DWORD attr = GetFileAttributesA(path); | ||||
|  | ||||
| 	return (attr != INVALID_FILE_ATTRIBUTES); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	struct stat s; | ||||
|  | ||||
| 	return (stat(path, &s) == 0); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool LibrarySystem::IsPathFile(const char* path) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	DWORD attr = GetFileAttributes(path); | ||||
|  | ||||
| 	if (attr == INVALID_FILE_ATTRIBUTES) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	if (attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	struct stat s; | ||||
|  | ||||
| 	if (stat(path, &s) != 0) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	return S_ISREG(s.st_mode) ? true : false; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool LibrarySystem::IsPathDirectory(const char* path) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	DWORD attr = GetFileAttributes(path); | ||||
|  | ||||
| 	if (attr == INVALID_FILE_ATTRIBUTES) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	if (attr & FILE_ATTRIBUTE_DIRECTORY) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	struct stat s; | ||||
|  | ||||
| 	if (stat(path, &s) != 0) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	if (S_ISDIR(s.st_mode)) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| CDirectory *LibrarySystem::OpenDirectory(const char* path) | ||||
| { | ||||
| 	CDirectory* dir = new CDirectory(path); | ||||
|  | ||||
| 	if (!dir->IsValid()) | ||||
| 	{ | ||||
| 		delete dir; | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	return dir; | ||||
| } | ||||
|  | ||||
| CLibrary* LibrarySystem::OpenLibrary(const char* path, char* error, size_t maxlength) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	LibraryHandle lib = LoadLibrary(path); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	LibraryHandle lib = dlopen(path, RTLD_NOW); | ||||
| #endif | ||||
|  | ||||
| 	if (!lib) | ||||
| 	{ | ||||
| 		if (error && maxlength) | ||||
| 		{ | ||||
| 			GetLoaderError(error, maxlength); | ||||
| 		} | ||||
|  | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	return new CLibrary(lib); | ||||
| } | ||||
|  | ||||
| void LibrarySystem::GetPlatformError(char* error, size_t maxlength) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return GetPlatformErrorEx(GetLastError(), error, maxlength); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	return GetPlatformErrorEx(errno, error, maxlength); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void LibrarySystem::GetPlatformErrorEx(int code, char* error, size_t maxlength) | ||||
| { | ||||
| 	if (error && maxlength) | ||||
| 	{ | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 		if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | ||||
| 			nullptr, | ||||
| 			(DWORD)code, | ||||
| 			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||||
| 			(LPSTR)error, | ||||
| 			maxlength, | ||||
| 			nullptr) == 0) | ||||
| 		{ | ||||
| 			UTIL_Format(error, maxlength, "error code %08x", code); | ||||
| 		} | ||||
|  | ||||
| #elif defined PLATFORM_LINUX | ||||
|  | ||||
| 		const char *ae = strerror_r(code, error, maxlength); | ||||
|  | ||||
| 		if (ae != error) | ||||
| 		{ | ||||
| 			UTIL_Format(error, maxlength, "%s", ae); | ||||
| 		} | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 		strerror_r(code, error, maxlength); | ||||
| #endif | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void LibrarySystem::GetLoaderError(char* buffer, size_t maxlength) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	GetPlatformError(buffer, maxlength); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	if (buffer && maxlength) | ||||
| 	{ | ||||
| 		strncopy(buffer, dlerror(), maxlength); | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void LibrarySystem::CloseDirectory(CDirectory *dir) | ||||
| { | ||||
| 	delete dir; | ||||
| } | ||||
|  | ||||
| size_t LibrarySystem::PathFormat(char* buffer, size_t len, const char* fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	va_start(ap, fmt); | ||||
| 	size_t mylen = vsnprintf(buffer, len, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	if (mylen >= len) | ||||
| 	{ | ||||
| 		mylen = len - 1; | ||||
| 		buffer[mylen] = '\0'; | ||||
| 	} | ||||
|  | ||||
| 	for (size_t i = 0; i < mylen; i++) | ||||
| 	{ | ||||
| 		if (buffer[i] == PLATFORM_SEP_ALTCHAR) | ||||
| 		{ | ||||
| 			buffer[i] = PLATFORM_SEP_CHAR; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return mylen; | ||||
| } | ||||
|  | ||||
| char* LibrarySystem::PathFormat(const char* fmt, ...) | ||||
| { | ||||
| 	static char buffer[PLATFORM_MAX_PATH]; | ||||
|  | ||||
| 	va_list ap; | ||||
| 	va_start(ap, fmt); | ||||
| 	size_t mylen = vsnprintf(buffer, sizeof(buffer), fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	if (mylen >= sizeof(buffer)) | ||||
| 	{ | ||||
| 		mylen = sizeof(buffer) - 1; | ||||
| 		buffer[mylen] = '\0'; | ||||
| 	} | ||||
|  | ||||
| 	for (size_t i = 0; i < mylen; i++) | ||||
| 	{ | ||||
| 		if (buffer[i] == PLATFORM_SEP_ALTCHAR) | ||||
| 		{ | ||||
| 			buffer[i] = PLATFORM_SEP_CHAR; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return buffer; | ||||
| } | ||||
|  | ||||
| const char* LibrarySystem::GetFileExtension(const char* filename) | ||||
| { | ||||
| 	size_t len, end; | ||||
|  | ||||
| 	len = strlen(filename); | ||||
|  | ||||
| 	/* Minimum string length for filename with ext would be 3; example: a.a */ | ||||
| 	if (len < 3) | ||||
| 	{ | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	end = len - 1; | ||||
|  | ||||
| 	for (size_t i = end; i <= end; i--) | ||||
| 	{ | ||||
| 		if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR) | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if (filename[i] == '.' && i != end && i != 0) | ||||
| 		{ | ||||
| 			return &filename[++i]; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| bool LibrarySystem::CreateFolder(const char* path) | ||||
| { | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	return (mkdir(path) != -1); | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	return (mkdir(path, 0775) != -1); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| size_t LibrarySystem::GetFileFromPath(char* buffer, size_t maxlength, const char* path) | ||||
| { | ||||
| 	size_t length = strlen(path); | ||||
|  | ||||
| 	for (size_t i = length - 1; i <= length - 1; i--) | ||||
| 	{ | ||||
| 		if (path[i] == '/' | ||||
| #if defined PLATFORM_WINDOWS | ||||
| 			|| path[i] == '\\' | ||||
| #endif | ||||
| 			) | ||||
| 		{ | ||||
| 			return UTIL_Format(buffer, maxlength, "%s", &path[i + 1]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* We scanned and found no path separator */ | ||||
| 	return UTIL_Format(buffer, maxlength, "%s", path); | ||||
| } | ||||
|  | ||||
| bool LibrarySystem::FileTime(const char* path, FileTimeType type, time_t* pTime) | ||||
| { | ||||
| 	struct stat s; | ||||
|  | ||||
| 	if (stat(path, &s) != 0) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 		case FileTime_LastAccess: | ||||
| 		{ | ||||
| 			*pTime = s.st_atime; | ||||
| 			break; | ||||
| 		} | ||||
| 		case FileTime_Created: | ||||
| 		{ | ||||
| 			*pTime = s.st_ctime; | ||||
| 			break; | ||||
| 		} | ||||
| 		case FileTime_LastChange: | ||||
| 		{ | ||||
| 			*pTime = s.st_mtime; | ||||
| 			break; | ||||
| 		} | ||||
| 		default: | ||||
| 		{ | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
							
								
								
									
										182
									
								
								amxmodx/CLibrarySys.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								amxmodx/CLibrarySys.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | ||||
| // vim: set ts=4 sw=4 tw=99 noet: | ||||
| // | ||||
| // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). | ||||
| // Copyright (C) The AMX Mod X Development Team. | ||||
| // | ||||
| // This software is licensed under the GNU General Public License, version 3 or higher. | ||||
| // Additional exceptions apply. For full license details, see LICENSE.txt or visit: | ||||
| //     https://alliedmods.net/amxmodx-license | ||||
|  | ||||
| #ifndef _INCLUDE_LIBRARY_SYS_H_ | ||||
| #define _INCLUDE_LIBRARY_SYS_H_ | ||||
|  | ||||
| #include "amx.h"        // cell | ||||
| #include <interface.h>  // Interface (HLSDK) | ||||
| #include <am-utility.h> // AutoPtr | ||||
|  | ||||
| #if defined(WIN32) | ||||
| #  ifndef PLATFORM_WINDOWS | ||||
| #  define PLATFORM_WINDOWS  1 | ||||
| #  endif | ||||
| #  ifndef WIN32_LEAN_AND_MEAN | ||||
| #  define WIN32_LEAN_AND_MEAN | ||||
| #  endif | ||||
| #  include <windows.h> | ||||
| #  include <direct.h> | ||||
| #  include <io.h> | ||||
| #  define PLATFORM_LIB_EXT      "dll" | ||||
| #  define PLATFORM_SEP_CHAR     '\\' | ||||
| #  define PLATFORM_SEP_ALTCHAR  '/' | ||||
| #  define PLATFORM_EXTERN_C     extern "C" __declspec(dllexport) | ||||
| #elif defined(__linux__) || defined(__APPLE__) | ||||
| #  if defined(__linux__) | ||||
| #    define PLATFORM_LINUX      1 | ||||
| #    define PLATFORM_LIB_EXT    "so" | ||||
| #  elif defined(__APPLE__) | ||||
| #    define PLATFORM_APPLE      1 | ||||
| #    define PLATFORM_LIB_EXT    "dylib" | ||||
| #  endif | ||||
| #  ifndef PLATFORM_POSIX | ||||
| #    define PLATFORM_POSIX      1 | ||||
| #  endif | ||||
| #  include <stdio.h> | ||||
| #  include <sys/types.h> | ||||
| #  include <sys/stat.h> | ||||
| #  include <errno.h> | ||||
| #  include <unistd.h> | ||||
| #  include <dirent.h> | ||||
| #  include <dlfcn.h> | ||||
| #  if defined(PLATFORM_APPLE) | ||||
| #    include <sys/syslimits.h> | ||||
| #  endif | ||||
| #  define PLATFORM_SEP_CHAR     '/' | ||||
| #  define PLATFORM_SEP_ALTCHAR  '\\' | ||||
| #  define PLATFORM_EXTERN_C     extern "C" __attribute__((visibility("default"))) | ||||
| #  define WINAPI | ||||
| #endif | ||||
|  | ||||
| #define PLATFORM_MAX_PATH 260 | ||||
|  | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 	typedef HMODULE  LibraryHandle; | ||||
| 	typedef HANDLE   DirHandle; | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 	typedef void*    LibraryHandle; | ||||
| 	typedef DIR*     DirHandle; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| enum FileTimeType | ||||
| { | ||||
| 	FileTime_LastAccess = 0,  /* Last access (not available on FAT) */ | ||||
| 	FileTime_Created    = 1,  /* Creation (not available on FAT) */ | ||||
| 	FileTime_LastChange = 2,  /* Last modification */ | ||||
| }; | ||||
|  | ||||
| class CDirectory | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		CDirectory(const char* path); | ||||
| 		~CDirectory(); | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		bool MoreFiles(); | ||||
| 		void NextEntry(); | ||||
| 		const char* GetEntryName(); | ||||
| 		bool IsEntryDirectory(); | ||||
| 		bool IsEntryFile(); | ||||
| 		bool IsEntryValid(); | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		bool IsValid(); | ||||
| 		DirHandle GetHandle(); | ||||
|  | ||||
| 	private: | ||||
|  | ||||
| #if defined PLATFORM_WINDOWS | ||||
|  | ||||
| 		HANDLE           m_dir; | ||||
| 		WIN32_FIND_DATAA m_fd; | ||||
|  | ||||
| #elif defined PLATFORM_POSIX | ||||
|  | ||||
| 		DIR*             m_dir; | ||||
| 		struct dirent*   m_ep; | ||||
| 		char             m_origpath[PLATFORM_MAX_PATH]; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| class CLibrary | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		CLibrary(LibraryHandle me); | ||||
| 		~CLibrary(); | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		void CloseLibrary(); | ||||
| 		void *GetSymbolAddress(const char* symname); | ||||
|  | ||||
| 	private: | ||||
|  | ||||
| 		LibraryHandle m_lib; | ||||
| }; | ||||
|  | ||||
| class LibrarySystem | ||||
| { | ||||
| 	public: | ||||
|  | ||||
| 		CLibrary* OpenLibrary(const char* path, char* error = nullptr, size_t maxlength = 0); | ||||
| 		CDirectory* OpenDirectory(const char* path); | ||||
| 		void CloseDirectory(CDirectory *dir); | ||||
|  | ||||
| 		bool PathExists(const char* path); | ||||
| 		bool IsPathFile(const char* path); | ||||
| 		bool IsPathDirectory(const char* path); | ||||
|  | ||||
| 		void GetPlatformError(char* error, size_t maxlength); | ||||
| 		void GetPlatformErrorEx(int code, char* error, size_t maxlength); | ||||
|  | ||||
| 		size_t PathFormat(char* buffer, size_t len, const char* fmt, ...); | ||||
| 		char*  PathFormat(const char* fmt, ...); | ||||
|  | ||||
| 		const char* GetFileExtension(const char* filename); | ||||
| 		bool CreateFolder(const char* path); | ||||
| 		size_t GetFileFromPath(char* buffer, size_t maxlength, const char* path); | ||||
|  | ||||
| 		bool FileTime(const char* path, FileTimeType type, time_t* pTime); | ||||
| 		void GetLoaderError(char* buffer, size_t maxlength); | ||||
| }; | ||||
|  | ||||
| extern LibrarySystem g_LibSys; | ||||
|  | ||||
| template <typename T> | ||||
| bool GET_IFACE(const char* library, T*& var, const char* version) | ||||
| { | ||||
| 	const char* path = g_LibSys.PathFormat("%s.%s", library, PLATFORM_LIB_EXT); | ||||
|  | ||||
| 	ke::AutoPtr<CLibrary> lib(g_LibSys.OpenLibrary(path)); | ||||
|  | ||||
| 	if (lib) | ||||
| 	{ | ||||
| 		CreateInterfaceFn factory = reinterpret_cast<CreateInterfaceFn>(lib->GetSymbolAddress(CREATEINTERFACE_PROCNAME)); | ||||
|  | ||||
| 		if (factory) | ||||
| 		{ | ||||
| 			var = reinterpret_cast<T*>(factory(version, nullptr)); | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var = nullptr; | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| #endif // _INCLUDE_LIBRARY_SYS_H_ | ||||
| @@ -152,6 +152,11 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) | ||||
| 			{ | ||||
| 				*get_amxaddr(plugin->getAMX(), addr) = gpGlobals->maxClients; | ||||
| 			} | ||||
|  | ||||
| 			if (amx_FindPubVar(plugin->getAMX(), "NULL_STRING", &addr) != AMX_ERR_NOTFOUND) | ||||
| 			{ | ||||
| 				plugin->m_pNullStringOfs = get_amxaddr(plugin->getAMX(), addr); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -256,7 +261,7 @@ const char* CPluginMngr::CPlugin::getStatus() const | ||||
| 	return "error"; | ||||
| } | ||||
|  | ||||
| CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d) : name(n), title(n) | ||||
| CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d) : name(n), title(n), m_pNullStringOfs(nullptr) | ||||
| { | ||||
| 	const char* unk = "unknown"; | ||||
| 	 | ||||
|   | ||||
| @@ -61,6 +61,7 @@ public: | ||||
| 		~CPlugin(); | ||||
| 		 | ||||
| 		bool m_Debug; | ||||
| 		cell* m_pNullStringOfs; | ||||
| 	public: | ||||
| 		inline const char* getName() { return name.c_str();} | ||||
| 		inline const char* getVersion() { return version.c_str();} | ||||
| @@ -90,6 +91,7 @@ public: | ||||
| 		 | ||||
| 		const char* getStatus() const; | ||||
| 		inline bool isDebug() const { return m_Debug; } | ||||
| 		inline cell* getNullStringOfs() const { return m_pNullStringOfs; } | ||||
| 	};  | ||||
| 	 | ||||
| private:	 | ||||
|   | ||||
| @@ -29,7 +29,7 @@ static cell AMX_NATIVE_CALL get_xvar_id(AMX *amx, cell *params) | ||||
| 	char* sName = get_amxstring(amx, params[1], 0, len); | ||||
| 	cell ptr; | ||||
|  | ||||
| 	if (!strcmp(sName, "MaxClients")) | ||||
| 	if (!strcmp(sName, "MaxClients") || !strcmp(sName, "NULL_STRING")) | ||||
| 	{ | ||||
| 		return -1; | ||||
| 	} | ||||
| @@ -3784,19 +3784,6 @@ cell AMX_NATIVE_CALL require_module(AMX *amx, cell *params) | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static cell AMX_NATIVE_CALL amx_mkdir(AMX *amx, cell *params) | ||||
| { | ||||
| 	int len = 0; | ||||
| 	char *path = get_amxstring(amx, params[1], 0, len); | ||||
| 	char *realpath = build_pathname("%s", path); | ||||
|  | ||||
| #if defined(__linux__) || defined(__APPLE__) | ||||
| 	return mkdir(realpath, 0700); | ||||
| #else | ||||
| 	return mkdir(realpath); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static cell AMX_NATIVE_CALL find_plugin_byfile(AMX *amx, cell *params) | ||||
| { | ||||
| 	typedef int (*STRCOMPARE)(const char*, const char*); | ||||
| @@ -4561,7 +4548,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] = | ||||
| 	{"hash_string",				amx_hash_string}, | ||||
| 	{"hash_file",				amx_hash_file}, | ||||
| 	{"module_exists",			module_exists}, | ||||
| 	{"mkdir",					amx_mkdir}, | ||||
| 	{"next_hudchannel",			next_hudchannel}, | ||||
| 	{"num_to_word",				num_to_word}, | ||||
| 	{"parse_loguser",			parse_loguser}, | ||||
|   | ||||
| @@ -276,6 +276,7 @@ char* format_amxstring(AMX *amx, cell *params, int parm, int& len); | ||||
| AMX* get_amxscript(int, void**, const char**); | ||||
| const char* get_amxscriptname(AMX* amx); | ||||
| char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len); | ||||
| char *get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len); | ||||
| extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, int maxlen); | ||||
|  | ||||
| int amxstring_len(cell* cstr); | ||||
|   | ||||
							
								
								
									
										1584
									
								
								amxmodx/file.cpp
									
									
									
									
									
								
							
							
						
						
									
										1584
									
								
								amxmodx/file.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -8,13 +8,6 @@ | ||||
| //     https://alliedmods.net/amxmodx-license | ||||
|  | ||||
| #include <time.h> | ||||
|  | ||||
| #if defined WIN32 | ||||
| #include <direct.h> | ||||
| #else | ||||
| #include <dirent.h> | ||||
| #endif | ||||
|  | ||||
| #include "amxmodx.h" | ||||
| #include "fakemeta.h" | ||||
| #include "CMenu.h" | ||||
| @@ -32,6 +25,8 @@ | ||||
| #include "CDataPack.h" | ||||
| #include "textparse.h" | ||||
| #include "CvarManager.h" | ||||
| #include "CLibrarySys.h" | ||||
| #include "CFileSystem.h" | ||||
|  | ||||
| plugin_info_t Plugin_info =  | ||||
| { | ||||
| @@ -143,6 +138,8 @@ int FF_InconsistentFile = -1; | ||||
| int FF_ClientAuthorized = -1; | ||||
| int FF_ChangeLevel = -1; | ||||
|  | ||||
| IFileSystem* g_FileSystem; | ||||
|  | ||||
| bool ColoredMenus(String & ModName) | ||||
| { | ||||
| 	const char * pModNames[] = { "cstrike", "czero", "dmc", "dod", "tfc", "valve" }; | ||||
| @@ -1493,7 +1490,9 @@ C_DLLEXPORT	int	Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m | ||||
| 	FlagMan.SetFile("cmdaccess.ini"); | ||||
|  | ||||
| 	g_CvarManager.CreateCvarHook(); | ||||
| 	 | ||||
|  | ||||
| 	GET_IFACE<IFileSystem>("filesystem_stdio", g_FileSystem, FILESYSTEM_INTERFACE_VERSION); | ||||
|  | ||||
| 	return (TRUE); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -43,30 +43,6 @@ ModuleCallReason g_ModuleCallReason; | ||||
|  | ||||
| extern const char* no_function;				// stupid work around | ||||
|  | ||||
| bool DirExists(const char *dir) | ||||
| { | ||||
| #if defined WIN32 || defined _WIN32 | ||||
| 	DWORD attr = GetFileAttributes(dir); | ||||
| 	 | ||||
| 	if (attr == INVALID_FILE_ATTRIBUTES) | ||||
| 		return false; | ||||
| 	 | ||||
| 	if (attr & FILE_ATTRIBUTE_DIRECTORY) | ||||
| 		return true; | ||||
| 	 | ||||
| #else | ||||
| 	struct stat s; | ||||
| 	 | ||||
| 	if (stat(dir, &s) != 0) | ||||
| 		return false; | ||||
| 	 | ||||
| 	if (S_ISDIR(s.st_mode)) | ||||
| 		return true; | ||||
| #endif | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void report_error(int code, const char* fmt, ...) | ||||
| { | ||||
| 	va_list argptr; | ||||
|   | ||||
| @@ -57,7 +57,6 @@ class Debugger; | ||||
| Debugger *DisableDebugHandler(AMX *amx); | ||||
| void EnableDebugHandler(AMX *amx, Debugger *pd); | ||||
|  | ||||
| bool DirExists(const char *dir); | ||||
| const char* GetFileName(AMX *amx); | ||||
|  | ||||
| inline cell FloatToCell(float input) | ||||
|   | ||||
| @@ -256,6 +256,7 @@ | ||||
|     <ClCompile Include="..\CFlagManager.cpp" /> | ||||
|     <ClCompile Include="..\CForward.cpp" /> | ||||
|     <ClCompile Include="..\CLang.cpp" /> | ||||
|     <ClCompile Include="..\CLibrarySys.cpp" /> | ||||
|     <ClCompile Include="..\CLogEvent.cpp" /> | ||||
|     <ClCompile Include="..\CMenu.cpp" /> | ||||
|     <ClCompile Include="..\CMisc.cpp" /> | ||||
| @@ -334,9 +335,11 @@ | ||||
|     <ClInclude Include="..\CDataPack.h" /> | ||||
|     <ClInclude Include="..\CEvent.h" /> | ||||
|     <ClInclude Include="..\CFile.h" /> | ||||
|     <ClInclude Include="..\CFileSystem.h" /> | ||||
|     <ClInclude Include="..\CFlagManager.h" /> | ||||
|     <ClInclude Include="..\CForward.h" /> | ||||
|     <ClInclude Include="..\CLang.h" /> | ||||
|     <ClInclude Include="..\CLibrarySys.h" /> | ||||
|     <ClInclude Include="..\CList.h" /> | ||||
|     <ClInclude Include="..\CLogEvent.h" /> | ||||
|     <ClInclude Include="..\CMenu.h" /> | ||||
|   | ||||
| @@ -277,6 +277,9 @@ | ||||
|       <Filter>Third Party\Hashing\hashers</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\CPlugin.cpp"> | ||||
|     	<Filter>Source Files</Filter> | ||||
| 	</ClCompile> | ||||
|     <ClCompile Include="..\CLibrarySys.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| @@ -475,6 +478,12 @@ | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\third_party\hashing\hashers\sha256.h"> | ||||
|       <Filter>Third Party\Hashing\hashers</Filter> | ||||
| 	</ClInclude> | ||||
|     <ClInclude Include="..\CFileSystem.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\CLibrarySys.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|   | ||||
| @@ -176,6 +176,16 @@ char *get_amxstring(AMX *amx, cell amx_addr, int id, int& len) | ||||
| 	return buffer[id]; | ||||
| } | ||||
|  | ||||
| char *get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len) | ||||
| { | ||||
| 	if (get_amxaddr(amx, amx_addr) == g_plugins.findPluginFast(amx)->getNullStringOfs()) | ||||
| 	{ | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	return get_amxstring(amx, amx_addr, id, len); | ||||
| } | ||||
|  | ||||
| void copy_amxmemory(cell* dest, cell* src, int len) | ||||
| { | ||||
| 	while (len--) | ||||
|   | ||||
| @@ -1895,8 +1895,10 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst | ||||
|         if (size > INT_MAX) | ||||
|           error(105);                   /* overflow, exceeding capacity */ | ||||
|       #endif | ||||
| #if 0	/* We don't actually care */ | ||||
|       if (ispublic) | ||||
|         error(56,name);                 /* arrays cannot be public */ | ||||
| #endif | ||||
|       dim[numdim++]=(int)size; | ||||
|     } /* while */ | ||||
|     /* if this variable is never used (which can be detected only in the | ||||
| @@ -1936,7 +1938,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst | ||||
|       sym->usage|=uDEFINE; | ||||
|     } /* if */ | ||||
|     if (ispublic) | ||||
|       sym->usage|=uPUBLIC; | ||||
|       sym->usage|=uPUBLIC|uREAD; | ||||
|     if (fconst) | ||||
|       sym->usage|=uCONST; | ||||
|     if (fstock) | ||||
|   | ||||
| @@ -619,7 +619,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) | ||||
|         assert(sym->vclass==sGLOBAL); | ||||
|         mainaddr=sym->addr; | ||||
|       } /* if */ | ||||
|     } else if (sym->ident==iVARIABLE) { | ||||
|     } else if (sym->ident==iVARIABLE || sym->ident == iARRAY || sym->ident == iREFARRAY) { | ||||
|       if ((sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) | ||||
|         match=++numpubvars; | ||||
|     } /* if */ | ||||
| @@ -794,7 +794,8 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) | ||||
|   /* write the public variables table */ | ||||
|   count=0; | ||||
|   for (sym=glbtab.next; sym!=NULL; sym=sym->next) { | ||||
|     if (sym->ident==iVARIABLE && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) { | ||||
|     if ((sym->ident==iVARIABLE || sym->ident==iARRAY || sym->ident==iREFARRAY)  | ||||
|         && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) { | ||||
|       assert((sym->usage & uDEFINE)!=0); | ||||
|       assert(sym->vclass==sGLOBAL); | ||||
|       func.address=sym->addr; | ||||
|   | ||||
| @@ -39,7 +39,15 @@ | ||||
|  */ | ||||
| #define MAX_PLAYERS 32 /* Maximum number of players AMX Mod X supports */ | ||||
|  | ||||
| public stock const MaxClients; /* Maximum number of players the server supports */ | ||||
| /** | ||||
|  * Maximum number of players the server supports  | ||||
|  */ | ||||
| public stock const MaxClients;  | ||||
|  | ||||
| /** | ||||
|  * Pass this into certain functions to act as a C++ NULL  | ||||
|  */ | ||||
| public stock const NULL_STRING[1]; | ||||
|  | ||||
| /** | ||||
|  * The maximum buffer size required to store a clients name. | ||||
|   | ||||
| @@ -12,140 +12,36 @@ | ||||
| // | ||||
|  | ||||
| #if defined _file_included | ||||
|   #endinput | ||||
| 	#endinput | ||||
| #endif | ||||
| #define _file_included | ||||
|  | ||||
| /* Reads content from directory. | ||||
| * Returns index of next element or 0 when end of dir. is reached. */ | ||||
| native read_dir(const dirname[],pos,output[],len,&outlen); | ||||
|  | ||||
| /* Reads line from file. Returns index of next line or 0 when end of file is reached. */ | ||||
| native read_file(const file[],line,text[],len,&txtlen); | ||||
|  | ||||
| /* Writes text to file. Function returns 0 on failure. | ||||
| * When line is set to -1, the text is added at the end of file. */ | ||||
| native write_file(const file[],const text[],line = -1); | ||||
|  | ||||
| /* Deletes file. Function returns 1 on success, 0 on failure. */ | ||||
| native delete_file(const file[]); | ||||
|  | ||||
| /* Checks for file. If file exists function returns 1, in other case 0. */ | ||||
| native file_exists(const file[]); | ||||
|  | ||||
| /* renames a file.  returns 0 on failure, 1 on success. | ||||
|  * if relative true, rename_file will act like other natives which  | ||||
|  * use the moddir as a base directory.  otherwise, the current directory is  | ||||
|  * undefined (but assumed to be hlds). | ||||
| /** | ||||
|  * @note All paths in AMX Mod X natives are relative to the mod folder | ||||
|  * unless otherwise noted. | ||||
|  * | ||||
|  * Most functions in AMX Mod X (at least, ones that deal with direct  | ||||
|  * file manipulation) will support an alternate path specification. | ||||
|  */ | ||||
| native rename_file(const oldname[], const newname[], relative=0); | ||||
|  | ||||
| /* Checks if a directory exists */ | ||||
| native dir_exists(const dir[]); | ||||
|  | ||||
| /* Returns a file size in bytes if flag is set to 0. | ||||
| * When flag is set to 1 returns number of lines in the file, | ||||
| * and when flags is 2, function returns 1 if the file ends | ||||
| * with line feed. If file doesn't exist returns -1. */ | ||||
| native file_size(const file[], flag=0); | ||||
|  | ||||
| #define SEEK_SET 0 | ||||
| #define SEEK_CUR 1 | ||||
| #define SEEK_END 2 | ||||
|  | ||||
| //Open a file, returns a handle or 0 on failure | ||||
| native fopen(const filename[],const mode[]); | ||||
|  | ||||
| //Closes a file handle | ||||
| native fclose(file); | ||||
|  | ||||
| #define BLOCK_INT	4 | ||||
| #define BLOCK_SHORT	2 | ||||
| #define BLOCK_CHAR	1 | ||||
| #define BLOCK_BYTE	1 | ||||
|  | ||||
| //The following functions work as such: | ||||
| // RAW - means the array you pass is a raw bytestream, for experts only | ||||
| // BLOCK - means you are passing in an array where each element will be written | ||||
| // NORMAL - means you are writing only one element | ||||
| // RAW and BLOCK return the number of blocks acted upon successfully | ||||
| // NORMAL returns 1 on success | ||||
|  | ||||
| native fread(file, &data, mode); | ||||
| native fread_blocks(file, data[], blocks, mode); | ||||
| native fread_raw(file, stream[], blocksize, blocks); | ||||
| native fwrite(file, data, mode); | ||||
| native fwrite_blocks(file, const data[], blocks, mode); | ||||
| native fwrite_raw(file, const stream[], blocksize, mode); | ||||
|  | ||||
| //Returns 1 if the file is ended, 0 otherwise | ||||
| native feof(file); | ||||
|  | ||||
| //Reads a line from a text file -- includes newline! | ||||
| native fgets(file, buffer[], maxlength); | ||||
|  | ||||
| //Writes a line to a text file.  Returns # of characters written. | ||||
| native fputs(file, const text[]); | ||||
|  | ||||
| //Writes a line to the file | ||||
| native fprintf(file, const fmt[], any:...); | ||||
|  | ||||
| //Sets the current position in a file (see SEEK_ values above) | ||||
| native fseek(file, position, start); | ||||
|  | ||||
| //Returns the current position in a file | ||||
| native ftell(file); | ||||
|  | ||||
| //These are straight from the C standard. | ||||
| native fgetc(file); | ||||
| native fputc(file, data); | ||||
| native fungetc(file, data); | ||||
|  | ||||
| //Return the size of a file | ||||
| native filesize(const filename[], any:...); | ||||
|  | ||||
| //Attempts to remove a directory. | ||||
| //Note that you cannot remove a directory that has files on most | ||||
| // operating systems. | ||||
| native rmdir(const path[]); | ||||
|  | ||||
| /* Returns 0 on success, like the POSIX specification */ | ||||
| native mkdir(const dirname[]); | ||||
|  | ||||
|  | ||||
| //Delete a file (delete_file macro) | ||||
| native unlink(const filename[]); | ||||
|  | ||||
| //Returns a handle to a directory | ||||
| native open_dir(dir[], firstfile[], length); | ||||
| native next_file(dirh, buffer[], length); | ||||
| native close_dir(dirh); | ||||
|   | ||||
| /** | ||||
|  * Maximum path length. | ||||
|  */ | ||||
| #define PLATFORM_MAX_PATH  256 | ||||
|  | ||||
| /** | ||||
|  * Loads a file using the LoadFileForMe engine function. | ||||
|  * | ||||
|  * The data is truncated if there is not enough space.  No null-terminator  | ||||
|  * is applied; the data is the raw contents of the file. | ||||
|  * | ||||
|  * @param file			File to load (may be a file from the GCF). | ||||
|  * @param buffer		Buffer to store file contents. | ||||
|  * @param maxlength		Maximum size of the file buffer. | ||||
|  * @param length		Variable to store the file length.  This may return  | ||||
|  *						a number larger than the buffer size. | ||||
|  * @return				-1 if the file could not be loaded.  Otherwise,  | ||||
|  *						the number of cells actually written to the buffer  | ||||
|  *						are returned. | ||||
|  * File inode types for use with open_dir() and next_file(). | ||||
|  */ | ||||
| native LoadFileForMe(const file[], buffer[], maxlength, &length=0); | ||||
| enum FileType | ||||
| { | ||||
| 	FileType_Unknown,       /* Unknown file type (device/socket) */ | ||||
| 	FileType_Directory,     /* File is a directory */ | ||||
| 	FileType_File,          /* File is a file */ | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Flushes a buffered output stream. | ||||
|  * | ||||
|  * @param file			File handle, or 0 for all open streams. | ||||
|  * @return				0 on success, -1 on failure. | ||||
|  * File time modes for use with GetFileTime(). | ||||
|  */ | ||||
| native fflush(file); | ||||
|  | ||||
| enum FileTimeType | ||||
| { | ||||
| 	FileTime_LastAccess,    /* Last access (not available on FAT) */ | ||||
| @@ -153,11 +49,618 @@ enum FileTimeType | ||||
| 	FileTime_LastChange,    /* Last modification */ | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * File position modes for use with fseek(). | ||||
|  */ | ||||
| #define SEEK_SET 0          /* Seek from start */ | ||||
| #define SEEK_CUR 1          /* Seek from current position */ | ||||
| #define SEEK_END 2          /* Seek from end position */ | ||||
|  | ||||
| /** | ||||
|  * Options for use with file_size() flag parameter. | ||||
|  */ | ||||
| #define FSOPT_BYTES_COUNT  0  /* Returns the file size in number of bytes */ | ||||
| #define FSOPT_LINES_COUNT  1  /* Returns how many lines there are in this file */ | ||||
| #define FSOPT_END_WITH_LF  2  /* Returns whether the last line is '\n' */ | ||||
|  | ||||
| /** | ||||
|  * Data block modes for use with fread*() and fwrite*(). | ||||
|  */ | ||||
| #define BLOCK_INT   4 | ||||
| #define BLOCK_SHORT 2 | ||||
| #define BLOCK_CHAR  1 | ||||
| #define BLOCK_BYTE  1 | ||||
|  | ||||
| /** | ||||
|  * File permissions flags for use with mkdir() and SetFilePermissions(). | ||||
|  */ | ||||
| #define FPERM_U_READ       0x0100   /* User can read.    */ | ||||
| #define FPERM_U_WRITE      0x0080   /* User can write.   */ | ||||
| #define FPERM_U_EXEC       0x0040   /* User can exec.    */ | ||||
| #define FPERM_U_RWX        FPERM_U_READ | FPERM_U_WRITE | FPERM_U_EXEC | ||||
|  | ||||
| #define FPERM_G_READ       0x0020   /* Group can read.   */ | ||||
| #define FPERM_G_WRITE      0x0010   /* Group can write.  */ | ||||
| #define FPERM_G_EXEC       0x0008   /* Group can exec.   */ | ||||
| #define FPERM_G_RWX        FPERM_G_READ | FPERM_G_WRITE | FPERM_G_EXEC | ||||
|  | ||||
| #define FPERM_O_READ       0x0004   /* Anyone can read.  */ | ||||
| #define FPERM_O_WRITE      0x0002   /* Anyone can write. */ | ||||
| #define FPERM_O_EXEC       0x0001   /* Anyone can exec.  */ | ||||
| #define FPERM_O_RWX        FPERM_O_READ | FPERM_O_WRITE | FPERM_O_EXEC | ||||
|  | ||||
| #define FPERM_DIR_DEFAULT  FPERM_U_RWX | FPERM_G_RWX | FPERM_O_RWX /* rwx r-x r-x (0755) */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Reads content from directory | ||||
|  * | ||||
|  * @note This native is expensive. Consider the use of open_dir(), next_file() and close_dir() instead. | ||||
|  * @note Both the '.' and '..' automatic directory entries will be retrieved for Windows and Linux. | ||||
|  * | ||||
|  * @param dirname      Path to open | ||||
|  * @param pos          Index the element | ||||
|  * @param output       String buffer to hold content | ||||
|  * @param len          Maximum size of string buffer | ||||
|  * @param outlen       Number of characters written to the buffer | ||||
|  * | ||||
|  * @return             Returns index of next element, otherwiwe 0 when end of dir is reached | ||||
|  */ | ||||
| native read_dir(const dirname[], pos, output[], len, &outlen = 0); | ||||
|  | ||||
| /** | ||||
|  * Reads line from file. | ||||
|  * | ||||
|  * @note This native is expensive. Consider the use of new file natives (fopen(), fgets(), etc.) | ||||
|  *       if purpose is to read several lines of a file. | ||||
|  * | ||||
|  * @param file         Path to open | ||||
|  * @param line         Index of the line, starting to 0 | ||||
|  * @param text         String buffer to hold line read | ||||
|  * @param len          Maximum size of string buffer | ||||
|  * @param txtlen       Number of characters written to the buffer | ||||
|  * | ||||
|  * @return             Returns index of next line, otherwise 0 when end of file is reached | ||||
|  * @error              Unable to read the file | ||||
|  */ | ||||
| native read_file(const file[], line, text[], len, &txtlen = 0); | ||||
|  | ||||
| /** | ||||
|  * Writes text to file. | ||||
|  * | ||||
|  * @note This native is expensive. Consider the use of new file natives (fopen(), fputs(), etc.) | ||||
|  *       if purpose is to write several lines of a file. | ||||
|  * | ||||
|  * @param file         Path to open | ||||
|  * @param text         String to write to | ||||
|  * @param line         Index of the line, starting to 0 | ||||
|  *                     If < 0, content will be appended | ||||
|  * | ||||
|  * @noreturn | ||||
|  * @error              Unable to write [temporary] file | ||||
|  */ | ||||
| native write_file(const file[], const text[], line = -1); | ||||
|  | ||||
| /** | ||||
|  * Deletes a file. | ||||
|  * | ||||
|  * @param file          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 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              1 on success, 0 on failure or if file not immediately removed. | ||||
|  */ | ||||
| native delete_file(const file[], bool:use_valve_fs = false, const valve_path_id[] = "GAMECONFIG"); | ||||
|  | ||||
| /** | ||||
|  * Checks if a file exists. | ||||
|  * | ||||
|  * @param file          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 Valve search paths, rather than solely files | ||||
|  *                      existing directly in the gamedir. | ||||
|  * | ||||
|  * @return              1 if the file exists, 0 otherwise | ||||
|  */ | ||||
| native file_exists(const file[], bool:use_valve_fs = false); | ||||
|  | ||||
|  /** | ||||
|   * Renames a file. | ||||
|   * | ||||
|   * @param oldname      New path to the file | ||||
|   * @param newname      Path to the existing file | ||||
|   * @param relative     If true, native  will act like other natives which | ||||
|   *                     use the moddir as a base directory. Otherwise, the | ||||
|   *                     current directory is undefined (but assumed to be hlds). | ||||
|   * | ||||
|   * @return             1 on success, 0 otherwise | ||||
|   */ | ||||
| native rename_file(const oldname[], const newname[], relative = 0); | ||||
|  | ||||
| /** | ||||
|  * Checks if a directory exists. | ||||
|  * | ||||
|  * @param dir           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 Valve search paths, rather than solely files | ||||
|  *                      existing directly in the gamedir. | ||||
|  * | ||||
|  * @return              1 if the directory exists, 0 otherwise | ||||
|  */ | ||||
| native dir_exists(const dir[], bool:use_valve_fs = false); | ||||
|  | ||||
| /** | ||||
|  * Get the file size in bytes. | ||||
|  * | ||||
|  * @param file          Path to the file | ||||
|  * @param flag          Flag options, see FSOPT_* constants | ||||
|  * @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 Valve search paths, rather than solely files | ||||
|  *                      existing directly in the gamedir. | ||||
|  *                      If used, flag option is ignored. | ||||
|  * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths | ||||
|  * | ||||
|  * @return              If flag is FSOPT_BYTES_COUNT or use_valve_fs to true, the file size in bytes | ||||
|  *                      If flag is FSOPT_LINES_COUNT, the number of lines in the file | ||||
|  *                      If flag is FSOPT_END_WITH_LF, 1 is returned if file ends with line feed | ||||
|  *                      If file doesn't exist, -1 | ||||
|  */ | ||||
| native file_size(const file[], flag = FSOPT_BYTES_COUNT, bool:use_valve_fs = false, const valve_path_id[] = "GAME"); | ||||
|  | ||||
| /** | ||||
|  * Opens or creates a file, returning a file handle on success. File handles | ||||
|  * should be closed with fclose(). | ||||
|  * | ||||
|  * @note The open mode may be one of the following strings: | ||||
|  *         "r": Open an existing file for reading. | ||||
|  *         "w": Create a file for writing, or truncate (delete the contents of) an | ||||
|  *              existing file and then open it for writing. | ||||
|  *         "a": Create a file for writing, or open an existing file such that writes | ||||
|  *              will be appended to the end. | ||||
|  *        "r+": Open an existing file for both reading and writing. | ||||
|  *        "w+": Create a file for reading and writing, or truncate an existing file | ||||
|  *              and then open it for reading and writing. | ||||
|  *        "a+": Create a file for both reading and writing, or open an existing file | ||||
|  *              such that writes will be appended to the end. | ||||
|  * | ||||
|  * @note The open mode may also contain an additional character after "r", "w", or "a", | ||||
|  *       but before any "+" sign. This character may be "b" (indicating binary mode) or | ||||
|  *       "t" (indicating text mode). By default, "text" mode is implied. On Linux and | ||||
|  *       Mac, this has no distinction from binary mode. On Windows, it causes the '\n' | ||||
|  *       character (0xA) to be written as "\r\n" (0xD, 0xA). | ||||
|  * | ||||
|  *       Example: "rb" opens a binary file for writing; "at" opens a text file for | ||||
|  *       appending. | ||||
|  * | ||||
|  * @note Registered paths ID are (in priority order) : | ||||
|  *         GAME           All paths related to current mod, including fallback | ||||
|  *                        Depending settings, it includes: <gamedir>_lv/_addon/_<language>/_hd | ||||
|  *                        and <gamedir> itself | ||||
|  *         GAMECONFIG     The default writable directory (<gamedir>) | ||||
|  *         GAMEDOWNLOAD   The download directory (<gamedir>_download) | ||||
|  *         GAME_FALLBACK  All paths related to fallback game, same as GAME | ||||
|  *         DEFAULTGAME    All paths related to the default game which is "valve", same as GAME | ||||
|  *         BASE           The base path where server is installed | ||||
|  * | ||||
|  *         Note that some paths are non-writable. It includes all <gamedir>_* (expect _download) | ||||
|  *         and DEFAULTGAME. Any file inside a non-writable path will be ignored if you try to open | ||||
|  *         it in writing mode. | ||||
|  * | ||||
|  * @param filename      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 finred 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 file handle, or null if the file could not be opened. | ||||
|  */ | ||||
| native fopen(const filename[], const mode[], bool:use_valve_fs = false, const valve_path_id[] = "GAME"); | ||||
|  | ||||
| /** | ||||
|  * Closes a file handle. | ||||
|  * | ||||
|  * @param file          File handle | ||||
|  */ | ||||
| native fclose(file); | ||||
|  | ||||
| /** | ||||
|  * Reads a single binary data from a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Variable to store item read | ||||
|  * @param mode          Size of each element, in bytes, to be read | ||||
|  *                      See BLOCK_* constants | ||||
|  * | ||||
|  * @return              Number of elements read | ||||
|  */ | ||||
| native fread(file, &any:data, mode); | ||||
|  | ||||
| /** | ||||
|  * Reads binary data from a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Array to store each item read | ||||
|  * @param blocks        Number of items to read into the array | ||||
|  * @param mode          Size of each element, in bytes, to be read | ||||
|  *                      Valid sizes are 1, 2, or 4. See BLOCK_* constants. | ||||
|  * | ||||
|  * @return              Number of elements read | ||||
|  */ | ||||
| native fread_blocks(file, any:data[], blocks, mode); | ||||
|  | ||||
| /** | ||||
|  * Reads raw binary data from a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param stream        Array to store each item read | ||||
|  * @param blocksize     Number of items to read into the array | ||||
|  * @param blocks        Size of each element, in bytes. The data is read directly. | ||||
|  *                      That is, in 1 or 2-byte mode, the lower byte(s) in | ||||
|  *                      each cell are used directly, rather than performing | ||||
|  *                      any casts from a 4-byte number to a smaller number. | ||||
|  * | ||||
|  * @return              Number of elements read | ||||
|  */ | ||||
| native fread_raw(file, any:stream[], blocksize, blocks); | ||||
|  | ||||
| /** | ||||
|  * Writes a single binary data to a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Item to write | ||||
|  * @param mode          Size of each item in the array in bytes | ||||
|  *                      Valid sizes are 1, 2, or 4. See BLOCK_* constants | ||||
|  * | ||||
|  * @return              Number of elements written | ||||
|  */ | ||||
| native fwrite(file, any:data, mode); | ||||
|  | ||||
| /** | ||||
|  * Writes binary data to a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Array of items to write | ||||
|  * @param blocks        Number of items in the array | ||||
|  * @param mode          Size of each item in the array in bytes | ||||
|  *                      Valid sizes are 1, 2, or 4. See BLOCK_* constants | ||||
|  * | ||||
|  * @return              Number of elements written | ||||
|  */ | ||||
| native fwrite_blocks(file, const any:data[], blocks, mode); | ||||
|  | ||||
| /** | ||||
|  * Writes raw binary data to a file. | ||||
|  * | ||||
|  * @param file          Handle to the file. | ||||
|  * @param stream        Array of items to write.  The data is written directly. | ||||
|  *                      That is, in 1 or 2-byte mode, the lower byte(s) in | ||||
|  *                      each cell are used directly, rather than performing | ||||
|  *                      any casts from a 4-byte number to a smaller number. | ||||
|  * @param blocks        Size of each item in the array in bytes. | ||||
|  * @param mode          Number of items in the array. | ||||
|  * | ||||
|  * @return              Number of elements written | ||||
|  */ | ||||
| native fwrite_raw(file, const any:stream[], blocks, mode); | ||||
|  | ||||
| /** | ||||
|  * Tests if the end of file has been reached. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * | ||||
|  * @return              1 if end of file has been reached, 0 otherwise. | ||||
|  */ | ||||
| native feof(file); | ||||
|  | ||||
| /** | ||||
|  * Reads a line from a text file. | ||||
|  * | ||||
|  * @param file          Handle to the file. | ||||
|  * @param buffer        String buffer to hold the line | ||||
|  * @param maxlength     Maximum size of string buffer | ||||
|  * | ||||
|  * @return              Total number of characters written on success, 0 otherwise | ||||
|  */ | ||||
| native fgets(file, buffer[], maxlength); | ||||
|  | ||||
| /** | ||||
|  * Writes a line of text to a text file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param text          String to write | ||||
|  * @param null_term     True to append NULL terminator, false otherwise | ||||
|  * | ||||
|  * @return              0 on success, -1 otherwise | ||||
|  */ | ||||
| native fputs(file, const text[], bool:null_term = false); | ||||
|  | ||||
| /** | ||||
|  * Writes a line of formatted text to a text file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param format        Formatting rules | ||||
|  * @param ...           Variable number of format parameters | ||||
|  * | ||||
|  * @return              Total number of characters written on success, 0 otherwise | ||||
|  */ | ||||
| native fprintf(file, const fmt[], any:...); | ||||
|  | ||||
| /** | ||||
|  * Sets the file position indicator. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param position      Position relative to what is specified in whence | ||||
|  * @param start         SEEK_ constant value of where to see from | ||||
|  * | ||||
|  * @return              0 on success, a non-zero value otherwise | ||||
|  */ | ||||
| native fseek(file, position, start); | ||||
|  | ||||
| /** | ||||
|  * Gets current position in the file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * | ||||
|  * @return              Value for the file position indicator | ||||
|  */ | ||||
| native ftell(file); | ||||
|  | ||||
| /** | ||||
|  * Gets character from file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * | ||||
|  * @return              Character read on success, -1 otherwise | ||||
|  */ | ||||
| native fgetc(file); | ||||
|  | ||||
| /** | ||||
|  * Writes character to file | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Character to put | ||||
|  * | ||||
|  * @return              Character written on success, -1 otherwise | ||||
|  */ | ||||
| native fputc(file, data); | ||||
|  | ||||
| /** | ||||
|  * Ungets character from file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Character to unget | ||||
|  * | ||||
|  * @return              On success, the character put back is returned, -1 otherwise | ||||
|  */ | ||||
| native fungetc(file, data); | ||||
|  | ||||
| /** | ||||
|  * Flushes a buffered output stream. | ||||
|  * | ||||
|  * @param file          File handle, or 0 for all open streams | ||||
|  * | ||||
|  * @return              0 on success, -1 on failure | ||||
|  */ | ||||
| native fflush(file); | ||||
|  | ||||
| /** | ||||
|  * Gets the formatted file size in bytes. | ||||
|  * | ||||
|  * @param filename      Path to the file | ||||
|  * @param ...           Variable number of format parameters | ||||
|  * | ||||
|  * @return              File size in bytes, otherwise -1 if file not found | ||||
|  */ | ||||
| native filesize(const filename[], any:...); | ||||
|  | ||||
| /** | ||||
|  * Removes a directory. | ||||
|  * | ||||
|  * @note On most Operating Systems you cannot remove a directory which has files inside it. | ||||
|  * | ||||
|  * @param path          Path to the directory | ||||
|  * | ||||
|  * @return              1 on success, 0 otherwise | ||||
|  */ | ||||
| native rmdir(const path[]); | ||||
|  | ||||
| /** | ||||
|  * Creates a directory. | ||||
|  * | ||||
|  * @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 | ||||
|  *                      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 | ||||
|  * | ||||
|  * @return              0 on success, -1 otherwise | ||||
|  */ | ||||
| native mkdir(const dirname[], mode = FPERM_DIR_DEFAULT, bool:use_valve_fs = false, const valve_path_id[] = "GAMECONFIG"); | ||||
|  | ||||
| /** | ||||
|  * Deletes a file (delete_file macro) | ||||
|  * | ||||
|  * @param filename      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 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              1 on success, 0 on failure or if file not immediately removed | ||||
|  */ | ||||
| native unlink(const filename[], bool:use_valve_fs = false, const valve_path_id[] = "GAMECONFIG"); | ||||
|  | ||||
| /** | ||||
|  * Opens a directory/folder for contents enumeration. | ||||
|  * | ||||
|  * @note Directories are closed with close_dir(). | ||||
|  * | ||||
|  * @param dir           Path to open. | ||||
|  * @param firstfile     String buffer to hold first file name | ||||
|  * @param length        Maximum size of the string buffer | ||||
|  * @param type          Optional variable to store the file type | ||||
|  * @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 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              Handle to the directory, 0 otherwise | ||||
|  */ | ||||
| native open_dir(dir[], firstfile[], length, &FileType:type = FileType_Unknown, bool:use_valve_fs = false, const valve_path_id[] = "GAME"); | ||||
|  | ||||
| /** | ||||
|  * Reads the next directory entry as a local filename. | ||||
|  * | ||||
|  * @note Contents of buffers are undefined when returning false. | ||||
|  * @note Both the '.' and '..' automatic directory entries will be retrieved for Windows and Linux. | ||||
|  * | ||||
|  * @param dirh          Handle to a directory | ||||
|  * @param buffer        String buffer to hold directory name | ||||
|  * @param length        Maximum size of string buffer | ||||
|  * @param type          Optional variable to store the file type. FileType_* constants | ||||
|  * | ||||
|  * @return              1 on success, 0 if there are no more files to read. | ||||
|  */ | ||||
| native next_file(dirh, buffer[], length, &FileType:type = FileType_Unknown); | ||||
|  | ||||
| /** | ||||
|  * Closes the directory. | ||||
|  * | ||||
|  * @param dirh          Handle to a directory | ||||
|  */ | ||||
| native close_dir(dirh); | ||||
|  | ||||
| /** | ||||
|  * Loads a file using the LoadFileForMe engine function. | ||||
|  * | ||||
|  * The data is truncated if there is not enough space.  No null-terminator | ||||
|  * is applied; the data is the raw contents of the file. | ||||
|  * | ||||
|  * @param file          File to load (may be a file from the GCF) | ||||
|  * @param buffer        Buffer to store file contents | ||||
|  * @param maxlength     Maximum size of the file buffer | ||||
|  * @param length        Variable to store the file length.  This may return | ||||
|  *                      a number larger than the buffer size | ||||
|  * @return              -1 if the file could not be loaded.  Otherwise, | ||||
|  *                      the number of cells actually written to the buffer | ||||
|  *                      are returned. | ||||
|  */ | ||||
| native LoadFileForMe(const file[], buffer[], maxlength, &length = 0); | ||||
|  | ||||
| /** | ||||
|  * Returns a file timestamp as a unix timestamp. | ||||
|  * | ||||
|  * @param file          File name. | ||||
|  * @param tmode         Time mode. See FileTime_* constants. | ||||
|  * @return              Returns a file timestamp as a unix timestamp. | ||||
|  * @param file          File name | ||||
|  * @param tmode         Time mode, see FileTime_* constants | ||||
|  * | ||||
|  * @return              Returns a file timestamp as a unix timestamp | ||||
|  */ | ||||
| native GetFileTime( const file[], FileTimeType:tmode ); | ||||
| native GetFileTime(const file[], FileTimeType:tmode); | ||||
|  | ||||
| /** | ||||
|  * Changes a file or directories permissions. | ||||
|  * | ||||
|  * @param path          Path to the file | ||||
|  * @param mode          Permissions to set, see FPERM_* constants | ||||
|  * | ||||
|  * @return              True on success, false otherwise | ||||
|  */ | ||||
| native bool:SetFilePermissions(const path[], mode); | ||||
|  | ||||
| /** | ||||
|  * Reads a single int8 (byte) from a file. The returned value is sign- | ||||
|  * extended to an int32. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Variable to store the data read | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileReadInt8(file, &any:data); | ||||
|  | ||||
| /** | ||||
|  * Reads a single uint8 (unsigned byte) from a file. The returned value is | ||||
|  * zero-extended to an int32. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Variable to store the data read | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileReadUint8(file, &any:data); | ||||
|  | ||||
| /** | ||||
|  * Reads a single int16 (short) from a file. The value is sign-extended to | ||||
|  * an int32. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Variable to store the data read | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileReadInt16(file, &any:data); | ||||
|  | ||||
| /** | ||||
|  * Reads a single unt16 (unsigned short) from a file. The value is zero- | ||||
|  * extended to an int32. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Variable to store the data read | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileReadUint16(file, &any:data); | ||||
|  | ||||
| /** | ||||
|  * Reads a single int32 (int/cell) from a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Variable to store the data read | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileReadInt32(file, &any:data); | ||||
|  | ||||
| /** | ||||
|  * Writes a single int8 (byte) to a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Data to write (truncated to an int8) | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileWriteInt8(file, any:data); | ||||
|  | ||||
| /** | ||||
|  * Writes a single int16 (short) to a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Data to write (truncated to an int16) | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileWriteInt16(file, any:data); | ||||
|  | ||||
| /** | ||||
|  * Writes a single int32 (int/cell) to a file. | ||||
|  * | ||||
|  * @param file          Handle to the file | ||||
|  * @param data          Data to write | ||||
|  * | ||||
|  * @return              True on success, false on failure | ||||
|  */ | ||||
| native bool:FileWriteInt32(file, any:data); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user