Added a bunch of new file natives.

Fixed possible corruption in snprintf when input buffer was bigger than output buffer and relaying on its retval.
Fixed all cases when the above situation happened.
Fixed _PrintToHL2Log not taking va_list in.

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40279
This commit is contained in:
Borja Ferrer
2007-01-07 01:30:28 +00:00
parent 7bb52e67f3
commit 45baab94a6
9 changed files with 484 additions and 19 deletions
+13 -9
View File
@@ -35,6 +35,7 @@ void CLogger::_NewMapFile()
{
g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n");
m_Active = false;
return;
} else {
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
@@ -125,7 +126,10 @@ void CLogger::LogMessage(const char *vafmt, ...)
if (m_mode == LoggingMode_HL2)
{
_PrintToHL2Log(vafmt);
va_list ap;
va_start(ap, vafmt);
_PrintToHL2Log(vafmt, ap);
va_end(ap);
return;
}
@@ -135,7 +139,7 @@ void CLogger::LogMessage(const char *vafmt, ...)
_NewMapFile();
}
static char msg[3072];
char msg[3072];
va_list ap;
va_start(ap, vafmt);
vsnprintf(msg, sizeof(msg), vafmt, ap);
@@ -215,7 +219,7 @@ void CLogger::LogError(const char *vafmt, ...)
m_ErrMapStart = false;
}
static char msg[3072];
char msg[3072];
va_list ap;
va_start(ap, vafmt);
vsnprintf(msg, sizeof(msg), vafmt, ap);
@@ -235,6 +239,7 @@ void CLogger::LogError(const char *vafmt, ...)
} else {
g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n");
m_Active = false;
return;
}
g_SMAPI->ConPrintf("L %s: %s\n", date, msg);
@@ -265,17 +270,16 @@ void CLogger::MapChange(const char *mapname)
m_ErrMapStart = false;
}
void CLogger::_PrintToHL2Log(const char *fmt, ...)
void CLogger::_PrintToHL2Log(const char *fmt, va_list ap)
{
static char msg[3072];
char msg[3072];
size_t len;
va_list ap;
va_start(ap, fmt);
len = vsnprintf(msg, sizeof(msg)-1, fmt, ap);
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
msg[len++] = '\n';
msg[len] = '\0';
va_end(ap);
engine->LogPrint(msg);
}
+1 -1
View File
@@ -40,7 +40,7 @@ public:
private:
void _CloseFile();
void _NewMapFile();
void _PrintToHL2Log(const char *fmt, ...);
void _PrintToHL2Log(const char *fmt, va_list ap);
private:
String m_NrmFileName;
String m_ErrFileName;
+5 -4
View File
@@ -1,5 +1,6 @@
#include "sm_srvcmds.h"
#include "sm_version.h"
#include "sm_stringutil.h"
ConVarAccessor g_ConCmdAccessor;
@@ -70,15 +71,15 @@ CON_COMMAND(sm, "SourceMod Menu")
int len = 0;
const sm_plugininfo_t *info = pl->GetPublicInfo();
len += snprintf(&buffer[len], sizeof(buffer)-len, " %02d <%s>", id, StatusToStr(pl->GetStatus()));
len += snprintf(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, StatusToStr(pl->GetStatus()));
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
if (IS_STR_FILLED(info->version))
{
len += snprintf(&buffer[len], sizeof(buffer)-len, " (%s)", info->version);
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", info->version);
}
if (IS_STR_FILLED(info->author))
{
snprintf(&buffer[len], sizeof(buffer)-len, " by %s", info->author);
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", info->author);
}
META_CONPRINTF("%s\n", buffer);
}
+11
View File
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include "sm_stringutil.h"
#define ALT 0x00000001 /* alternate form */
@@ -471,3 +472,13 @@ unsigned int strncopy(char *dest, const char *src, size_t count)
return (dest - start);
}
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
va_end(ap);
return (len >= maxlength) ? (maxlength - 1) : len;
}
+1
View File
@@ -10,5 +10,6 @@ using namespace SourcePawn;
size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param);
const char *stristr(const char *str, const char *substr);
unsigned int strncopy(char *dest, const char *src, size_t count);
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
#endif // _INCLUDE_SOURCEMOD_STRINGUTIL_H_
+335 -3
View File
@@ -1,6 +1,8 @@
#include <sys/stat.h>
#include "sm_globals.h"
#include "HandleSys.h"
#include "LibrarySys.h"
#include "sm_stringutil.h"
HandleType_t g_FileType;
HandleType_t g_DirType;
@@ -36,7 +38,7 @@ public:
};
cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
{
char *path;
int err;
@@ -58,7 +60,7 @@ cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
return g_HandleSys.CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL);
}
cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
IDirectory *pDir;
@@ -109,6 +111,324 @@ cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
return true;
}
static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params)
{
char *name, *mode;
int err;
if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
if ((err=pContext->LocalToString(params[2], &mode)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
char realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
FILE *pFile = fopen(realpath, mode);
if (!pFile)
{
return 0;
}
return g_HandleSys.CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL);
}
static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params)
{
char *name;
int err;
if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
char realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
return (unlink(realpath)) ? 0 : 1;
}
static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
FILE *pFile;
int err;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_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)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
fgets(buf, params[3], pFile);
return 1;
}
static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
FILE *pFile;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
return (feof(pFile)) ? 1 : 0;
}
static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
FILE *pFile;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
fseek(pFile, params[2], params[3]);
return 1;
}
static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
FILE *pFile;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
return ftell(pFile);
}
static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params)
{
char *name;
int err;
if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
char realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
#ifdef PLATFORM_WINDOWS
struct _stat s;
if (_stat(realpath, &s) != 0)
{
return 0;
}
if (s.st_mode & S_IFREG)
{
return 1;
}
return 0;
#elif PLATFORM_LINUX
struct stat s;
if (stat(realpath, &s) != 0)
{
return 0;
}
if (S_ISREG(s.st_mode))
{
return 1;
}
return 0;
#endif
}
static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params)
{
char *newpath, *oldpath;
int err;
if ((err=pContext->LocalToString(params[1], &newpath)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
if ((err=pContext->LocalToString(params[2], &oldpath)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
char new_realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(new_realpath, sizeof(new_realpath), "%s/%s", g_SourceMod.GetBaseDir(), newpath);
char old_realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(old_realpath, sizeof(old_realpath), "%s/%s", g_SourceMod.GetBaseDir(), oldpath);
#ifdef PLATFORM_WINDOWS
return (MoveFileA(old_realpath, new_realpath)) ? 1 : 0;
#elif PLATFORM_LINUX
return (rename(old_realpath, new_realpath)) ? 0 : 1;
#endif
}
static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params)
{
char *name;
int err;
if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
char realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
#ifdef PLATFORM_WINDOWS
struct _stat s;
if (_stat(realpath, &s) != 0)
{
return 0;
}
if (s.st_mode & S_IFDIR)
{
return 1;
}
return 0;
#elif PLATFORM_LINUX
struct stat s;
if (stat(realpath, &s) != 0)
{
return 0;
}
if (S_ISDIR(s.st_mode))
{
return 1;
}
return 0;
#endif
}
static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params)
{
char *name;
int err;
if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return -1;
}
char realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
#ifdef PLATFORM_WINDOWS
struct _stat s;
if (_stat(realpath, &s) != 0)
{
return -1;
}
if (s.st_mode & S_IFREG)
{
return static_cast<cell_t>(s.st_size);
}
return -1;
#elif PLATFORM_LINUX
struct stat s;
if (stat(realpath, &s) != 0)
{
return -1;
}
if (S_ISREG(s.st_mode))
{
return static_cast<cell_t>(s.st_size);
}
return -1;
#endif
}
static cell_t sm_RemoveDir(IPluginContext *pContext, const cell_t *params)
{
char *name;
int err;
if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
char realpath[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
return (rmdir(realpath)) ? 0 : 1;
}
static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
FILE *pFile;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_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);
return 0;
}
char buffer[2048];
int arg = 3;
atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
fprintf(pFile, "%s\n", buffer);
return 1;
}
//:TODO: DEBUG CODE HERE
cell_t PrintStuff(IPluginContext *pContext, const cell_t *params)
{
char *stuff;
@@ -127,6 +447,18 @@ REGISTER_NATIVES(filesystem)
{
{"OpenDirectory", sm_OpenDirectory},
{"ReadDirEntry", sm_ReadDirEntry},
{"PrintStuff", PrintStuff},
{"PrintStuff", PrintStuff},//:TODO: remove this when no longer needed
{"OpenFile", sm_OpenFile},
{"DeleteFile", sm_DeleteFile},
{"ReadFileLine", sm_ReadFileLine},
{"IsEndOfFile", sm_IsEndOfFile},
{"FileSeek", sm_FileSeek},
{"FilePosition", sm_FilePosition},
{"FileExists", sm_FileExists},
{"RenameFile", sm_RenameFile},
{"DirExists", sm_DirExists},
{"FileSize", sm_FileSize},
{"RemoveDir", sm_RemoveDir},
{"WriteFileLine", sm_WriteFileLine},
{NULL, NULL},
};
+4 -2
View File
@@ -84,8 +84,9 @@ static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
{
char *str;
pCtx->LocalToString(params[2], &str);
size_t res = UTIL_Format(str, params[3], "%d", params[1]);
return snprintf(str, params[3], "%d", params[1]);
return static_cast<cell_t>(res);
}
static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
@@ -102,8 +103,9 @@ static cell_t sm_floattostr(IPluginContext *pCtx, const cell_t *params)
{
char *str;
pCtx->LocalToString(params[2], &str);
size_t res = UTIL_Format(str, params[3], "%f", sp_ctof(params[1]));
return snprintf(str, params[3], "%f", sp_ctof(params[1]));
return static_cast<cell_t>(res);
}
static cell_t sm_formatex(IPluginContext *pCtx, const cell_t *params)
+2
View File
@@ -289,6 +289,8 @@ void LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
size_t mylen = vsnprintf(buffer, len, fmt, ap);
va_end(ap);
mylen = (mylen >= len) ? (len - 1) : mylen;
for (size_t i=0; i<mylen; i++)
{
if (buffer[i] == PLATFORM_SEP_ALTCHAR)