2 * ===============================================================
3 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
4 * ===============================================================
6 * This file is not open source and may not be copied without explicit
7 * written permission of AlliedModders LLC. This file may not be redistributed
8 * in whole or significant part.
9 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
15 #include "sm_globals.h"
16 #include "HandleSys.h"
17 #include "LibrarySys.h"
18 #include "sm_stringutil.h"
20 #include "PluginSys.h"
21 #include "sourcemm_api.h"
23 HandleType_t g_FileType;
24 HandleType_t g_DirType;
28 public IHandleTypeDispatch
31 virtual void OnSourceModAllInitialized()
33 g_FileType = g_HandleSys.CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
34 g_DirType = g_HandleSys.CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
36 virtual void OnSourceModShutdown()
38 g_HandleSys.RemoveType(g_DirType, g_pCoreIdent);
39 g_HandleSys.RemoveType(g_FileType, g_pCoreIdent);
43 virtual void OnHandleDestroy(HandleType_t type, void *object)
45 if (type == g_FileType)
47 FILE *fp = (FILE *)object;
49 } else if (type == g_DirType) {
50 IDirectory *pDir = (IDirectory *)object;
51 g_LibSys.CloseDirectory(pDir);
57 static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
61 if ((err=pContext->LocalToString(params[1], &path)) != SP_ERROR_NONE)
63 pContext->ThrowNativeErrorEx(err, NULL);
67 char realpath[PLATFORM_MAX_PATH+1];
68 g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
70 IDirectory *pDir = g_LibSys.OpenDirectory(realpath);
76 return g_HandleSys.CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL);
79 static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
81 Handle_t hndl = static_cast<Handle_t>(params[1]);
88 sec.pIdentity = g_pCoreIdent;
90 if ((herr=g_HandleSys.ReadHandle(hndl, g_DirType, &sec, (void **)&pDir))
93 return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
96 if (!pDir->MoreFiles())
102 if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE)
104 pContext->ThrowNativeErrorEx(err, NULL);
108 if (pDir->IsEntryDirectory())
111 } else if (pDir->IsEntryFile()) {
117 const char *path = pDir->GetEntryName();
118 if ((err=pContext->StringToLocalUTF8(params[2], params[3], path, NULL))
121 pContext->ThrowNativeErrorEx(err, NULL);
130 static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params)
134 if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
136 pContext->ThrowNativeErrorEx(err, NULL);
139 if ((err=pContext->LocalToString(params[2], &mode)) != SP_ERROR_NONE)
141 pContext->ThrowNativeErrorEx(err, NULL);
145 char realpath[PLATFORM_MAX_PATH+1];
146 g_SourceMod.BuildPath(Path_SM, realpath, sizeof(realpath), "%s", name);
148 FILE *pFile = fopen(realpath, mode);
154 return g_HandleSys.CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL);
157 static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params)
161 if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
163 pContext->ThrowNativeErrorEx(err, NULL);
167 char realpath[PLATFORM_MAX_PATH+1];
168 g_SourceMod.BuildPath(Path_SM, realpath, sizeof(realpath), "%s", name);
170 return (unlink(realpath)) ? 0 : 1;
173 static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params)
175 Handle_t hndl = static_cast<Handle_t>(params[1]);
182 sec.pIdentity = g_pCoreIdent;
184 if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
187 return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
191 if ((err=pContext->LocalToString(params[2], &buf)) != SP_ERROR_NONE)
193 pContext->ThrowNativeErrorEx(err, NULL);
197 fgets(buf, params[3], pFile);
202 static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params)
204 Handle_t hndl = static_cast<Handle_t>(params[1]);
210 sec.pIdentity = g_pCoreIdent;
212 if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
215 return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
218 return (feof(pFile)) ? 1 : 0;
221 static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params)
223 Handle_t hndl = static_cast<Handle_t>(params[1]);
229 sec.pIdentity = g_pCoreIdent;
231 if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
234 return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
237 fseek(pFile, params[2], params[3]);
242 static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params)
244 Handle_t hndl = static_cast<Handle_t>(params[1]);
250 sec.pIdentity = g_pCoreIdent;
252 if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
255 return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
261 static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params)
265 if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
267 pContext->ThrowNativeErrorEx(err, NULL);
271 char realpath[PLATFORM_MAX_PATH+1];
272 g_SourceMod.BuildPath(Path_SM, realpath, sizeof(realpath), "%s", name);
273 #ifdef PLATFORM_WINDOWS
275 if (_stat(realpath, &s) != 0)
279 if (s.st_mode & S_IFREG)
284 #elif defined PLATFORM_POSIX
286 if (stat(realpath, &s) != 0)
290 if (S_ISREG(s.st_mode))
298 static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params)
300 char *newpath, *oldpath;
302 if ((err=pContext->LocalToString(params[1], &newpath)) != SP_ERROR_NONE)
304 pContext->ThrowNativeErrorEx(err, NULL);
307 if ((err=pContext->LocalToString(params[2], &oldpath)) != SP_ERROR_NONE)
309 pContext->ThrowNativeErrorEx(err, NULL);
313 char new_realpath[PLATFORM_MAX_PATH+1];
314 g_SourceMod.BuildPath(Path_SM, new_realpath, sizeof(new_realpath), "%s", newpath);
315 char old_realpath[PLATFORM_MAX_PATH+1];
316 g_SourceMod.BuildPath(Path_SM, old_realpath, sizeof(old_realpath), "%s", oldpath);
318 #ifdef PLATFORM_WINDOWS
319 return (MoveFileA(old_realpath, new_realpath)) ? 1 : 0;
320 #elif defined PLATFORM_POSIX
321 return (rename(old_realpath, new_realpath)) ? 0 : 1;
325 static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params)
329 if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
331 pContext->ThrowNativeErrorEx(err, NULL);
335 char realpath[PLATFORM_MAX_PATH+1];
336 g_SourceMod.BuildPath(Path_SM, realpath, sizeof(realpath), "%s", name);
337 #ifdef PLATFORM_WINDOWS
339 if (_stat(realpath, &s) != 0)
343 if (s.st_mode & S_IFDIR)
348 #elif defined PLATFORM_POSIX
350 if (stat(realpath, &s) != 0)
354 if (S_ISDIR(s.st_mode))
362 static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params)
366 if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
368 pContext->ThrowNativeErrorEx(err, NULL);
372 char realpath[PLATFORM_MAX_PATH+1];
373 g_SourceMod.BuildPath(Path_SM, realpath, sizeof(realpath), "%s", name);
374 #ifdef PLATFORM_WINDOWS
376 if (_stat(realpath, &s) != 0)
380 if (s.st_mode & S_IFREG)
382 return static_cast<cell_t>(s.st_size);
385 #elif defined PLATFORM_POSIX
387 if (stat(realpath, &s) != 0)
391 if (S_ISREG(s.st_mode))
393 return static_cast<cell_t>(s.st_size);
399 static cell_t sm_RemoveDir(IPluginContext *pContext, const cell_t *params)
403 if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
405 pContext->ThrowNativeErrorEx(err, NULL);
409 char realpath[PLATFORM_MAX_PATH+1];
410 g_SourceMod.BuildPath(Path_SM, realpath, sizeof(realpath), "%s", name);
412 return (rmdir(realpath)) ? 0 : 1;
415 static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params)
417 Handle_t hndl = static_cast<Handle_t>(params[1]);
423 sec.pIdentity = g_pCoreIdent;
425 if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
428 return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
433 if ((err=pContext->LocalToString(params[2], &fmt)) != SP_ERROR_NONE)
435 pContext->ThrowNativeErrorEx(err, NULL);
441 atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
442 fprintf(pFile, "%s\n", buffer);
447 static cell_t sm_BuildPath(IPluginContext *pContext, const cell_t *params)
449 char path[PLATFORM_MAX_PATH], *fmt, *buffer;
451 pContext->LocalToString(params[2], &buffer);
452 pContext->LocalToString(params[4], &fmt);
454 atcprintf(path, sizeof(path), fmt, pContext, params, &arg);
456 return g_SourceMod.BuildPath(Path_SM_Rel, buffer, params[3], "%s", path);
459 static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
462 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
464 if (len >= sizeof(buffer)-2)
469 buffer[len++] = '\n';
473 engine->LogPrint(buffer);
478 static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
481 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
483 IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
484 g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer);
489 static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
492 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
494 IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
495 g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
500 static FileNatives s_FileNatives;
502 REGISTER_NATIVES(filesystem)
504 {"OpenDirectory", sm_OpenDirectory},
505 {"ReadDirEntry", sm_ReadDirEntry},
506 {"OpenFile", sm_OpenFile},
507 {"DeleteFile", sm_DeleteFile},
508 {"ReadFileLine", sm_ReadFileLine},
509 {"IsEndOfFile", sm_IsEndOfFile},
510 {"FileSeek", sm_FileSeek},
511 {"FilePosition", sm_FilePosition},
512 {"FileExists", sm_FileExists},
513 {"RenameFile", sm_RenameFile},
514 {"DirExists", sm_DirExists},
515 {"FileSize", sm_FileSize},
516 {"RemoveDir", sm_RemoveDir},
517 {"WriteFileLine", sm_WriteFileLine},
518 {"BuildPath", sm_BuildPath},
519 {"LogToGame", sm_LogToGame},
520 {"LogMessage", sm_LogMessage},
521 {"LogError", sm_LogError},