VFS: Fix various things

- The "ALL" fake pathID is replaced by what does SM, having a public var NULL_STRING which will acts as NULL when needed.
  To make compiler accepting public array, this patch was needed: https://hg.alliedmods.net/sourcemod-central/rev/b12f329def09
- The offset thing in read_dir: considering that's something very specific to this native and that implementation in CDirectory doesn't make sense because of the offset compatibility for windows, all code is now in the native.
This commit is contained in:
Arkshine 2015-03-25 13:50:07 +01:00
parent 8f6b8588c1
commit 52c73126e1
12 changed files with 101 additions and 97 deletions

View File

@ -61,28 +61,16 @@ CDirectory::~CDirectory()
}
}
void CDirectory::NextEntry(cell* offset)
DirHandle CDirectory::GetHandle()
{
return m_dir;
}
void CDirectory::NextEntry()
{
#if defined PLATFORM_WINDOWS
if (offset)
{
// Should be declared after loop so entry starts to '.' and not '..'
// But old code did that, so keep this for compatibility.
++*offset;
for (cell i = 0; i < *offset; ++i)
{
if (FindNextFile(m_dir, &m_fd) == 0)
{
*offset = 0;
FindClose(m_dir);
m_dir = INVALID_HANDLE_VALUE;
return;
}
}
}
else if (FindNextFile(m_dir, &m_fd) == 0)
if (FindNextFile(m_dir, &m_fd) == 0)
{
FindClose(m_dir);
m_dir = INVALID_HANDLE_VALUE;
@ -90,22 +78,7 @@ void CDirectory::NextEntry(cell* offset)
#elif defined PLATFORM_POSIX
if (offset)
{
seekdir(m_dir, *offset);
if (!(m_ep = readdir(m_dir)))
{
*offset = 0;
closedir(m_dir);
m_dir = nullptr;
}
else
{
*offset = telldir(m_dir);
}
}
else if (!(m_ep = readdir(m_dir)))
if (!(m_ep = readdir(m_dir)))
{
closedir(m_dir);
m_dir = nullptr;

View File

@ -58,9 +58,15 @@
#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
@ -80,7 +86,7 @@ class CDirectory
public:
bool MoreFiles();
void NextEntry(cell* offset = nullptr);
void NextEntry();
const char* GetEntryName();
bool IsEntryDirectory();
bool IsEntryFile();
@ -89,6 +95,7 @@ class CDirectory
public:
bool IsValid();
DirHandle GetHandle();
private:

View File

@ -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";

View File

@ -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:

View File

@ -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;
}

View File

@ -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);

View File

@ -29,7 +29,30 @@ static cell AMX_NATIVE_CALL read_dir(AMX *amx, cell *params)
cell offset = Max(0, params[2]);
dir->NextEntry(&offset);
if (offset >= 0)
{
#if defined PLATFORM_WINDOWS
// Should be declared after so entry starts to '.' and not '..'
// But old code did that, so keep this for compatibility.
++offset;
for (cell i = 0; i < offset && dir->MoreFiles(); ++i)
{
dir->NextEntry();
}
#elif defined PLATFORM_POSIX
seekdir(dir->GetHandle(), offset);
dir->NextEntry();
if (dir->IsValid())
{
offset = telldir(dir->GetHandle());
}
#endif
}
if (!dir->IsValid())
{
@ -190,12 +213,7 @@ static cell AMX_NATIVE_CALL delete_file(AMX *amx, cell *params)
if (*params / sizeof(cell) >= 2 && params[2] > 0)
{
const char* pathID = get_amxstring(amx, params[3], 1, length);
if (!strcmp(pathID, "ALL"))
{
pathID = nullptr;
}
const char* pathID = get_amxstring_null(amx, params[3], 1, length);
return ValveFile::Delete(file, pathID);
}
@ -240,7 +258,7 @@ static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params)
{
int length;
const char* path = get_amxstring(amx, params[1], 0, length);
int flag = params[2];
int flag = FSOPT_BYTES_COUNT;
AutoPtr<FileObject> fp;
@ -248,12 +266,7 @@ static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params)
if (numParams >= 3 && params[3] > 0)
{
const char* pathID = get_amxstring(amx, params[4], 1, length);
if (!strcmp(pathID, "ALL"))
{
pathID = nullptr;
}
const char* pathID = get_amxstring_null(amx, params[4], 1, length);
fp = ValveFile::Open(path, "r", pathID);
}
@ -267,9 +280,13 @@ static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params)
return -1;
}
if (numParams >= 2)
{
flag = params[2];
}
switch (flag)
{
default:
case FSOPT_BYTES_COUNT:
{
fp->Seek(0, SEEK_END);
@ -314,12 +331,7 @@ static cell AMX_NATIVE_CALL amx_fopen(AMX *amx, cell *params)
if (*params / sizeof(cell) >= 3 && params[3] > 0)
{
const char* pathID = get_amxstring(amx, params[4], 2, length);
if (!strcmp(pathID, "ALL"))
{
pathID = nullptr;
}
const char* pathID = get_amxstring_null(amx, params[4], 2, length);
fp = ValveFile::Open(file, flags, pathID);
}
@ -388,16 +400,14 @@ static cell AMX_NATIVE_CALL amx_fwrite_blocks(AMX *amx, cell *params)
}
break;
}
default:
{
if (size != BLOCK_INT)
{
size = BLOCK_INT;
}
}
case BLOCK_INT:
{
read = fp->Write(data, sizeof(cell) * blocks);
break;
}
default:
{
return 0;
}
}
@ -429,7 +439,6 @@ static cell AMX_NATIVE_CALL amx_fwrite(AMX *amx, cell *params)
short value = static_cast<short>(data);
return fp->Write(&value, sizeof(value));
}
default:
case BLOCK_INT:
{
int value = static_cast<int>(data);
@ -499,7 +508,6 @@ static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params)
return res;
}
case BLOCK_INT:
default:
{
int value;
size_t res = fp->Read(&value, sizeof(value));
@ -561,18 +569,15 @@ static cell AMX_NATIVE_CALL amx_fread_blocks(AMX *amx, cell *params)
}
break;
}
default:
{
if (size != BLOCK_INT)
{
size = BLOCK_INT;
}
}
case BLOCK_INT:
{
read = fp->Read(data, sizeof(cell) * blocks);
break;
}
default:
{
return 0;
}
}
return read / size;
@ -764,12 +769,7 @@ static cell AMX_NATIVE_CALL amx_open_dir(AMX *amx, cell *params)
if (numParams >= 4 && params[5] > 0)
{
const char* wildcardedPath = g_LibSys.PathFormat("%s%s*", path, (path[length - 1] != '/' && path[length - 1] != '\\') ? "/" : "");
const char* pathID = get_amxstring(amx, params[6], 1, length);
if (!strcmp(pathID, "ALL"))
{
pathID = nullptr;
}
const char* pathID = get_amxstring_null(amx, params[6], 1, length);
static FileFindHandle_t handle;
const char* pFirst = g_FileSystem->FindFirst(wildcardedPath, &handle, pathID);
@ -976,18 +976,13 @@ static cell AMX_NATIVE_CALL amx_mkdir(AMX *amx, cell *params)
if (numParams >= 3 && params[3] > 0)
{
const char* pathID = get_amxstring(amx, params[4], 1, length);
const char* pathID = get_amxstring_null(amx, params[4], 1, length);
if (g_FileSystem->IsDirectory(path))
{
return -1;
}
if (!strcmp(pathID, "ALL"))
{
pathID = nullptr;
}
g_FileSystem->CreateDirHierarchy(path, pathID);
if (g_FileSystem->IsDirectory(path))

View File

@ -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--)

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -149,7 +149,7 @@ native write_file(const file[], const text[], line = -1);
* 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 "ALL" for all search paths.
* @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.
*/
@ -204,7 +204,7 @@ native dir_exists(const dir[], bool:use_valve_fs = false);
* 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 "ALL" for all search paths
* @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
@ -258,7 +258,7 @@ native file_size(const file[], flag = FSOPT_BYTES_COUNT, bool:use_valve_fs = fal
* 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 "ALL" for all search paths
* @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.
*/
@ -481,7 +481,7 @@ native rmdir(const path[]);
* @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 "ALL" for default
* @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
@ -496,7 +496,7 @@ native mkdir(const dirname[], mode = FPERM_DIR_DEFAULT, bool:use_valve_fs = fals
* 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 "ALL" for all search paths
* @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
*/
@ -515,7 +515,7 @@ native unlink(const filename[], bool:use_valve_fs = false, const valve_path_id[]
* 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 "ALL" for all search paths.
* @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
*/