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