core/smn_filesystem.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 16 20:36:09 2007 +0000 (2007-01-16)
changeset 300 186b2f7bf277
parent 283 c3d54680969a
child 317 e5342c8a0cf4
permissions -rw-r--r--
fixed up bad includes
     1 #include <sys/stat.h>
     2 #include "sm_globals.h"
     3 #include "HandleSys.h"
     4 #include "LibrarySys.h"
     5 #include "sm_stringutil.h"
     6 
     7 HandleType_t g_FileType;
     8 HandleType_t g_DirType;
     9 
    10 class FileNatives : 
    11 	public SMGlobalClass,
    12 	public IHandleTypeDispatch
    13 {
    14 public:
    15 	virtual void OnSourceModAllInitialized()
    16 	{
    17 		g_FileType = g_HandleSys.CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    18 		g_DirType = g_HandleSys.CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    19 	}
    20 	virtual void OnSourceModShutdown()
    21 	{
    22 		g_HandleSys.RemoveType(g_DirType, g_pCoreIdent);
    23 		g_HandleSys.RemoveType(g_FileType, g_pCoreIdent);
    24 		g_DirType = 0;
    25 		g_FileType = 0;
    26 	}
    27 	virtual void OnHandleDestroy(HandleType_t type, void *object)
    28 	{
    29 		if (type == g_FileType)
    30 		{
    31 			FILE *fp = (FILE *)object;
    32 			fclose(fp);
    33 		} else if (type == g_DirType) {
    34 			IDirectory *pDir = (IDirectory *)object;
    35 			g_LibSys.CloseDirectory(pDir);
    36 		}
    37 	}
    38 };
    39 
    40 
    41 static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
    42 {
    43 	char *path;
    44 	int err;
    45 	if ((err=pContext->LocalToString(params[1], &path)) != SP_ERROR_NONE)
    46 	{
    47 		pContext->ThrowNativeErrorEx(err, NULL);
    48 		return 0;
    49 	}
    50 
    51 	char realpath[PLATFORM_MAX_PATH+1];
    52 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), path);
    53 
    54 	IDirectory *pDir = g_LibSys.OpenDirectory(realpath);
    55 	if (!pDir)
    56 	{
    57 		return 0;
    58 	}
    59 
    60 	return g_HandleSys.CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL);
    61 }
    62 
    63 static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
    64 {
    65 	Handle_t hndl = static_cast<Handle_t>(params[1]);
    66 	IDirectory *pDir;
    67 	HandleError herr;
    68 	HandleSecurity sec;
    69 	int err;
    70 
    71 	sec.pOwner = NULL;
    72 	sec.pIdentity = g_pCoreIdent;
    73 
    74 	if ((herr=g_HandleSys.ReadHandle(hndl, g_DirType, &sec, (void **)&pDir))
    75 		!= HandleError_None)
    76 	{
    77 		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
    78 	}
    79 
    80 	if (!pDir->MoreFiles())
    81 	{
    82 		return false;
    83 	}
    84 
    85 	cell_t *filetype;
    86 	if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE)
    87 	{
    88 		pContext->ThrowNativeErrorEx(err, NULL);
    89 		return 0;
    90 	}
    91 
    92 	if (pDir->IsEntryDirectory())
    93 	{
    94 		*filetype = 1;
    95 	} else if (pDir->IsEntryFile()) {
    96 		*filetype = 2;
    97 	} else {
    98 		*filetype = 0;
    99 	}
   100 
   101 	const char *path = pDir->GetEntryName();
   102 	if ((err=pContext->StringToLocalUTF8(params[2], params[3], path, NULL))
   103 		!= SP_ERROR_NONE)
   104 	{
   105 		pContext->ThrowNativeErrorEx(err, NULL);
   106 		return 0;
   107 	}
   108 
   109 	pDir->NextEntry();
   110 
   111 	return true;
   112 }
   113 
   114 static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params)
   115 {
   116 	char *name, *mode;
   117 	int err;
   118 	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
   119 	{
   120 		pContext->ThrowNativeErrorEx(err, NULL);
   121 		return 0;
   122 	}
   123 	if ((err=pContext->LocalToString(params[2], &mode)) != SP_ERROR_NONE)
   124 	{
   125 		pContext->ThrowNativeErrorEx(err, NULL);
   126 		return 0;
   127 	}
   128 
   129 	char realpath[PLATFORM_MAX_PATH+1];
   130 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
   131 
   132 	FILE *pFile = fopen(realpath, mode);
   133 	if (!pFile)
   134 	{
   135 		return 0;
   136 	}
   137 
   138 	return g_HandleSys.CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL);
   139 }
   140 
   141 static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params)
   142 {
   143 	char *name;
   144 	int err;
   145 	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
   146 	{
   147 		pContext->ThrowNativeErrorEx(err, NULL);
   148 		return 0;
   149 	}
   150 
   151 	char realpath[PLATFORM_MAX_PATH+1];
   152 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
   153 
   154 	return (unlink(realpath)) ? 0 : 1;
   155 }
   156 
   157 static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params)
   158 {
   159 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   160 	HandleError herr;
   161 	HandleSecurity sec;
   162 	FILE *pFile;
   163 	int err;
   164 
   165 	sec.pOwner = NULL;
   166 	sec.pIdentity = g_pCoreIdent;
   167 
   168 	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
   169 		!= HandleError_None)
   170 	{
   171 		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
   172 	}
   173 
   174 	char *buf;
   175 	if ((err=pContext->LocalToString(params[2], &buf)) != SP_ERROR_NONE)
   176 	{
   177 		pContext->ThrowNativeErrorEx(err, NULL);
   178 		return 0;
   179 	}
   180 
   181 	fgets(buf, params[3], pFile);
   182 
   183 	return 1;
   184 }
   185 
   186 static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params)
   187 {
   188 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   189 	HandleError herr;
   190 	HandleSecurity sec;
   191 	FILE *pFile;
   192 
   193 	sec.pOwner = NULL;
   194 	sec.pIdentity = g_pCoreIdent;
   195 
   196 	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
   197 		!= HandleError_None)
   198 	{
   199 		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
   200 	}
   201 
   202 	return (feof(pFile)) ? 1 : 0;
   203 }
   204 
   205 static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params)
   206 {
   207 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   208 	HandleError herr;
   209 	HandleSecurity sec;
   210 	FILE *pFile;
   211 
   212 	sec.pOwner = NULL;
   213 	sec.pIdentity = g_pCoreIdent;
   214 
   215 	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
   216 		!= HandleError_None)
   217 	{
   218 		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
   219 	}
   220 
   221 	fseek(pFile, params[2], params[3]);
   222 	
   223 	return 1;
   224 }
   225 
   226 static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params)
   227 {
   228 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   229 	HandleError herr;
   230 	HandleSecurity sec;
   231 	FILE *pFile;
   232 
   233 	sec.pOwner = NULL;
   234 	sec.pIdentity = g_pCoreIdent;
   235 
   236 	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
   237 		!= HandleError_None)
   238 	{
   239 		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
   240 	}
   241 
   242 	return ftell(pFile);
   243 }
   244 
   245 static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params)
   246 {
   247 	char *name;
   248 	int err;
   249 	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
   250 	{
   251 		pContext->ThrowNativeErrorEx(err, NULL);
   252 		return 0;
   253 	}
   254 
   255 	char realpath[PLATFORM_MAX_PATH+1];
   256 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
   257 #ifdef PLATFORM_WINDOWS
   258 	struct _stat s;
   259 	if (_stat(realpath, &s) != 0)
   260 	{
   261 		return 0;
   262 	}
   263 	if (s.st_mode & S_IFREG)
   264 	{
   265 		return 1;
   266 	}
   267 	return 0;
   268 #else if defined PLATFORM_POSIX
   269 	struct stat s;
   270 	if (stat(realpath, &s) != 0)
   271 	{
   272 		return 0;
   273 	}
   274 	if (S_ISREG(s.st_mode))
   275 	{
   276 		return 1;
   277 	}
   278 	return 0;
   279 #endif
   280 }
   281 
   282 static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params)
   283 {
   284 	char *newpath, *oldpath;
   285 	int err;
   286 	if ((err=pContext->LocalToString(params[1], &newpath)) != SP_ERROR_NONE)
   287 	{
   288 		pContext->ThrowNativeErrorEx(err, NULL);
   289 		return 0;
   290 	}
   291 	if ((err=pContext->LocalToString(params[2], &oldpath)) != SP_ERROR_NONE)
   292 	{
   293 		pContext->ThrowNativeErrorEx(err, NULL);
   294 		return 0;
   295 	}
   296 
   297 	char new_realpath[PLATFORM_MAX_PATH+1];
   298 	g_LibSys.PathFormat(new_realpath, sizeof(new_realpath), "%s/%s", g_SourceMod.GetBaseDir(), newpath);
   299 	char old_realpath[PLATFORM_MAX_PATH+1];
   300 	g_LibSys.PathFormat(old_realpath, sizeof(old_realpath), "%s/%s", g_SourceMod.GetBaseDir(), oldpath);
   301 
   302 #ifdef PLATFORM_WINDOWS
   303 	return (MoveFileA(old_realpath, new_realpath)) ? 1 : 0;
   304 #else if defined PLATFORM_POSIX
   305 	return (rename(old_realpath, new_realpath)) ? 0 : 1;
   306 #endif
   307 }
   308 
   309 static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params)
   310 {
   311 	char *name;
   312 	int err;
   313 	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
   314 	{
   315 		pContext->ThrowNativeErrorEx(err, NULL);
   316 		return 0;
   317 	}
   318 
   319 	char realpath[PLATFORM_MAX_PATH+1];
   320 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
   321 #ifdef PLATFORM_WINDOWS
   322 	struct _stat s;
   323 	if (_stat(realpath, &s) != 0)
   324 	{
   325 		return 0;
   326 	}
   327 	if (s.st_mode & S_IFDIR)
   328 	{
   329 		return 1;
   330 	}
   331 	return 0;
   332 #else if defined PLATFORM_POSIX
   333 	struct stat s;
   334 	if (stat(realpath, &s) != 0)
   335 	{
   336 		return 0;
   337 	}
   338 	if (S_ISDIR(s.st_mode))
   339 	{
   340 		return 1;
   341 	}
   342 	return 0;
   343 #endif
   344 }
   345 
   346 static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params)
   347 {
   348 	char *name;
   349 	int err;
   350 	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
   351 	{
   352 		pContext->ThrowNativeErrorEx(err, NULL);
   353 		return -1;
   354 	}
   355 
   356 	char realpath[PLATFORM_MAX_PATH+1];
   357 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
   358 #ifdef PLATFORM_WINDOWS
   359 	struct _stat s;
   360 	if (_stat(realpath, &s) != 0)
   361 	{
   362 		return -1;
   363 	}
   364 	if (s.st_mode & S_IFREG)
   365 	{
   366 		return static_cast<cell_t>(s.st_size);
   367 	}
   368 	return -1;
   369 #else if defined PLATFORM_POSIX
   370 	struct stat s;
   371 	if (stat(realpath, &s) != 0)
   372 	{
   373 		return -1;
   374 	}
   375 	if (S_ISREG(s.st_mode))
   376 	{
   377 		return static_cast<cell_t>(s.st_size);
   378 	}
   379 	return -1;
   380 #endif
   381 }
   382 
   383 static cell_t sm_RemoveDir(IPluginContext *pContext, const cell_t *params)
   384 {
   385 	char *name;
   386 	int err;
   387 	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
   388 	{
   389 		pContext->ThrowNativeErrorEx(err, NULL);
   390 		return 0;
   391 	}
   392 
   393 	char realpath[PLATFORM_MAX_PATH+1];
   394 	g_LibSys.PathFormat(realpath, sizeof(realpath), "%s/%s", g_SourceMod.GetBaseDir(), name);
   395 
   396 	return (rmdir(realpath)) ? 0 : 1;
   397 }
   398 
   399 static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params)
   400 {
   401 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   402 	HandleError herr;
   403 	HandleSecurity sec;
   404 	FILE *pFile;
   405 
   406 	sec.pOwner = NULL;
   407 	sec.pIdentity = g_pCoreIdent;
   408 
   409 	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
   410 		!= HandleError_None)
   411 	{
   412 		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
   413 	}
   414 
   415 	char *fmt;
   416 	int err;
   417 	if ((err=pContext->LocalToString(params[2], &fmt)) != SP_ERROR_NONE)
   418 	{
   419 		pContext->ThrowNativeErrorEx(err, NULL);
   420 		return 0;
   421 	}
   422 
   423 	char buffer[2048];
   424 	int arg = 3;
   425 	atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
   426 	fprintf(pFile, "%s\n", buffer);
   427 
   428 	return 1;
   429 }
   430 
   431 static FileNatives s_FileNatives;
   432 
   433 REGISTER_NATIVES(filesystem)
   434 {
   435 	{"OpenDirectory",			sm_OpenDirectory},
   436 	{"ReadDirEntry",			sm_ReadDirEntry},
   437 	{"OpenFile",				sm_OpenFile},
   438 	{"DeleteFile",				sm_DeleteFile},
   439 	{"ReadFileLine",			sm_ReadFileLine},
   440 	{"IsEndOfFile",				sm_IsEndOfFile},
   441 	{"FileSeek",				sm_FileSeek},
   442 	{"FilePosition",			sm_FilePosition},
   443 	{"FileExists",				sm_FileExists},
   444 	{"RenameFile",				sm_RenameFile},
   445 	{"DirExists",				sm_DirExists},
   446 	{"FileSize",				sm_FileSize},
   447 	{"RemoveDir",				sm_RemoveDir},
   448 	{"WriteFileLine",			sm_WriteFileLine},
   449 	{NULL,						NULL},
   450 };