core/logic/smn_filesystem.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Thu Jul 04 11:28:32 2013 -0400 (2013-07-04)
changeset 3931 576fa42454dc
parent 3794 b15d5b65fcda
child 4198 d6f90552ca85
permissions -rw-r--r--
Fixed build for real.
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
faluco@274
    32
#include <sys/stat.h>
dvander@3794
    33
#include <string.h>
dvander@3791
    34
#include <IHandleSys.h>
dvander@3791
    35
#include <ILibrarySys.h>
dvander@3791
    36
#include <IPluginSys.h>
dvander@3791
    37
#include <IForwardSys.h>
dvander@3791
    38
#include <ISourceMod.h>
dvander@3791
    39
#include <ITranslator.h>
dvander@3791
    40
#include "common_logic.h"
dvander@252
    41
dvander@252
    42
HandleType_t g_FileType;
dvander@252
    43
HandleType_t g_DirType;
dvander@1914
    44
IChangeableForward *g_pLogHook = NULL;
dvander@252
    45
dvander@252
    46
class FileNatives : 
dvander@252
    47
	public SMGlobalClass,
dvander@1914
    48
	public IHandleTypeDispatch,
dvander@1914
    49
	public IPluginsListener
dvander@252
    50
{
dvander@252
    51
public:
dvander@1914
    52
	FileNatives()
dvander@1914
    53
	{
dvander@1914
    54
	}
dvander@252
    55
	virtual void OnSourceModAllInitialized()
dvander@252
    56
	{
dvander@3791
    57
		g_FileType = handlesys->CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@3791
    58
		g_DirType = handlesys->CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@3791
    59
		g_pLogHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 1, NULL, Param_String);
dvander@3791
    60
		pluginsys->AddPluginsListener(this);
dvander@252
    61
	}
dvander@252
    62
	virtual void OnSourceModShutdown()
dvander@252
    63
	{
dvander@3791
    64
		pluginsys->RemovePluginsListener(this);
dvander@3791
    65
		forwardsys->ReleaseForward(g_pLogHook);
dvander@3791
    66
		handlesys->RemoveType(g_DirType, g_pCoreIdent);
dvander@3791
    67
		handlesys->RemoveType(g_FileType, g_pCoreIdent);
dvander@252
    68
		g_DirType = 0;
dvander@252
    69
		g_FileType = 0;
dvander@252
    70
	}
dvander@252
    71
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@252
    72
	{
dvander@252
    73
		if (type == g_FileType)
dvander@252
    74
		{
dvander@252
    75
			FILE *fp = (FILE *)object;
dvander@252
    76
			fclose(fp);
dvander@1914
    77
		}
dvander@1914
    78
		else if (type == g_DirType)
dvander@1914
    79
		{
dvander@252
    80
			IDirectory *pDir = (IDirectory *)object;
dvander@3791
    81
			libsys->CloseDirectory(pDir);
dvander@1914
    82
		}
dvander@1914
    83
	}
dvander@1914
    84
	virtual void AddLogHook(IPluginFunction *pFunc)
dvander@1914
    85
	{
dvander@1914
    86
		g_pLogHook->AddFunction(pFunc);
dvander@1914
    87
	}
dvander@1914
    88
	virtual void RemoveLogHook(IPluginFunction *pFunc)
dvander@1914
    89
	{
dvander@1914
    90
		g_pLogHook->RemoveFunction(pFunc);
dvander@1914
    91
	}
dvander@3791
    92
	virtual bool LogPrint(const char *msg)
dvander@1914
    93
	{
dvander@3791
    94
		cell_t result = 0;
dvander@1914
    95
		g_pLogHook->PushString(msg);
dvander@1914
    96
		g_pLogHook->Execute(&result);
dvander@3791
    97
		return result >= Pl_Handled;
dvander@3791
    98
	}
dvander@3791
    99
} s_FileNatives;
dvander@1914
   100
dvander@3791
   101
bool OnLogPrint(const char *msg)
dvander@3791
   102
{
dvander@3791
   103
	return s_FileNatives.LogPrint(msg);
dvander@3791
   104
}
dvander@252
   105
faluco@274
   106
static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
dvander@252
   107
{
dvander@252
   108
	char *path;
dvander@252
   109
	int err;
dvander@252
   110
	if ((err=pContext->LocalToString(params[1], &path)) != SP_ERROR_NONE)
dvander@252
   111
	{
dvander@252
   112
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@252
   113
		return 0;
dvander@252
   114
	}
dvander@252
   115
ds@652
   116
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   117
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
dvander@255
   118
dvander@3791
   119
	IDirectory *pDir = libsys->OpenDirectory(realpath);
dvander@252
   120
	if (!pDir)
dvander@252
   121
	{
dvander@252
   122
		return 0;
dvander@252
   123
	}
dvander@252
   124
dvander@3791
   125
	return handlesys->CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@252
   126
}
dvander@252
   127
faluco@274
   128
static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
dvander@252
   129
{
dvander@252
   130
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@252
   131
	IDirectory *pDir;
dvander@252
   132
	HandleError herr;
dvander@262
   133
	HandleSecurity sec;
dvander@252
   134
	int err;
dvander@262
   135
dvander@262
   136
	sec.pOwner = NULL;
dvander@262
   137
	sec.pIdentity = g_pCoreIdent;
dvander@262
   138
dvander@3791
   139
	if ((herr=handlesys->ReadHandle(hndl, g_DirType, &sec, (void **)&pDir))
dvander@252
   140
		!= HandleError_None)
dvander@252
   141
	{
dvander@252
   142
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@252
   143
	}
dvander@252
   144
dvander@252
   145
	if (!pDir->MoreFiles())
dvander@252
   146
	{
dvander@252
   147
		return false;
dvander@252
   148
	}
dvander@252
   149
dvander@252
   150
	cell_t *filetype;
dvander@252
   151
	if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE)
dvander@252
   152
	{
dvander@252
   153
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@252
   154
		return 0;
dvander@252
   155
	}
dvander@252
   156
dvander@252
   157
	if (pDir->IsEntryDirectory())
dvander@252
   158
	{
dvander@252
   159
		*filetype = 1;
dvander@252
   160
	} else if (pDir->IsEntryFile()) {
dvander@252
   161
		*filetype = 2;
dvander@252
   162
	} else {
dvander@252
   163
		*filetype = 0;
dvander@252
   164
	}
dvander@252
   165
dvander@252
   166
	const char *path = pDir->GetEntryName();
dvander@255
   167
	if ((err=pContext->StringToLocalUTF8(params[2], params[3], path, NULL))
dvander@252
   168
		!= SP_ERROR_NONE)
dvander@252
   169
	{
dvander@252
   170
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@252
   171
		return 0;
dvander@252
   172
	}
dvander@252
   173
dvander@255
   174
	pDir->NextEntry();
dvander@255
   175
dvander@252
   176
	return true;
dvander@252
   177
}
dvander@252
   178
faluco@274
   179
static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   180
{
faluco@274
   181
	char *name, *mode;
faluco@274
   182
	int err;
faluco@274
   183
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   184
	{
faluco@274
   185
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   186
		return 0;
faluco@274
   187
	}
faluco@274
   188
	if ((err=pContext->LocalToString(params[2], &mode)) != SP_ERROR_NONE)
faluco@274
   189
	{
faluco@274
   190
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   191
		return 0;
faluco@274
   192
	}
faluco@274
   193
ds@652
   194
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   195
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   196
faluco@274
   197
	FILE *pFile = fopen(realpath, mode);
faluco@274
   198
	if (!pFile)
faluco@274
   199
	{
faluco@274
   200
		return 0;
faluco@274
   201
	}
faluco@274
   202
dvander@3791
   203
	return handlesys->CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL);
faluco@274
   204
}
faluco@274
   205
faluco@274
   206
static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   207
{
faluco@274
   208
	char *name;
faluco@274
   209
	int err;
faluco@274
   210
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   211
	{
faluco@274
   212
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   213
		return 0;
faluco@274
   214
	}
faluco@274
   215
ds@652
   216
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   217
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   218
faluco@274
   219
	return (unlink(realpath)) ? 0 : 1;
faluco@274
   220
}
faluco@274
   221
faluco@274
   222
static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params)
faluco@274
   223
{
faluco@274
   224
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   225
	HandleError herr;
faluco@274
   226
	HandleSecurity sec;
faluco@274
   227
	FILE *pFile;
faluco@274
   228
	int err;
faluco@274
   229
faluco@274
   230
	sec.pOwner = NULL;
faluco@274
   231
	sec.pIdentity = g_pCoreIdent;
faluco@274
   232
dvander@3791
   233
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   234
		!= HandleError_None)
faluco@274
   235
	{
faluco@274
   236
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   237
	}
faluco@274
   238
faluco@274
   239
	char *buf;
faluco@274
   240
	if ((err=pContext->LocalToString(params[2], &buf)) != SP_ERROR_NONE)
faluco@274
   241
	{
faluco@274
   242
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   243
		return 0;
faluco@274
   244
	}
faluco@274
   245
dvander@638
   246
	if (fgets(buf, params[3], pFile) == NULL)
dvander@638
   247
	{
dvander@638
   248
		return 0;
dvander@638
   249
	}
faluco@274
   250
faluco@274
   251
	return 1;
faluco@274
   252
}
faluco@274
   253
faluco@274
   254
static cell_t sm_IsEndOfFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   255
{
faluco@274
   256
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   257
	HandleError herr;
faluco@274
   258
	HandleSecurity sec;
faluco@274
   259
	FILE *pFile;
faluco@274
   260
faluco@274
   261
	sec.pOwner = NULL;
faluco@274
   262
	sec.pIdentity = g_pCoreIdent;
faluco@274
   263
dvander@3791
   264
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   265
		!= HandleError_None)
faluco@274
   266
	{
faluco@274
   267
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   268
	}
faluco@274
   269
faluco@274
   270
	return (feof(pFile)) ? 1 : 0;
faluco@274
   271
}
faluco@274
   272
faluco@274
   273
static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params)
faluco@274
   274
{
faluco@274
   275
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   276
	HandleError herr;
faluco@274
   277
	HandleSecurity sec;
faluco@274
   278
	FILE *pFile;
faluco@274
   279
faluco@274
   280
	sec.pOwner = NULL;
faluco@274
   281
	sec.pIdentity = g_pCoreIdent;
faluco@274
   282
dvander@3791
   283
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   284
		!= HandleError_None)
faluco@274
   285
	{
faluco@274
   286
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   287
	}
faluco@274
   288
faluco@274
   289
	fseek(pFile, params[2], params[3]);
faluco@274
   290
	
faluco@274
   291
	return 1;
faluco@274
   292
}
faluco@274
   293
faluco@274
   294
static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params)
faluco@274
   295
{
faluco@274
   296
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   297
	HandleError herr;
faluco@274
   298
	HandleSecurity sec;
faluco@274
   299
	FILE *pFile;
faluco@274
   300
faluco@274
   301
	sec.pOwner = NULL;
faluco@274
   302
	sec.pIdentity = g_pCoreIdent;
faluco@274
   303
dvander@3791
   304
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   305
		!= HandleError_None)
faluco@274
   306
	{
faluco@274
   307
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   308
	}
faluco@274
   309
faluco@274
   310
	return ftell(pFile);
faluco@274
   311
}
faluco@274
   312
faluco@274
   313
static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params)
faluco@274
   314
{
faluco@274
   315
	char *name;
faluco@274
   316
	int err;
faluco@274
   317
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   318
	{
faluco@274
   319
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   320
		return 0;
faluco@274
   321
	}
faluco@274
   322
dvander@1854
   323
	if (params[0] >= 2 && params[2] == 1)
dvander@1854
   324
	{
dvander@3791
   325
		return smcore.FileExists(name) ? 1 : 0;
dvander@1854
   326
	}
dvander@1854
   327
ds@652
   328
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   329
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   330
#ifdef PLATFORM_WINDOWS
faluco@274
   331
	struct _stat s;
faluco@274
   332
	if (_stat(realpath, &s) != 0)
faluco@274
   333
	{
faluco@274
   334
		return 0;
faluco@274
   335
	}
faluco@274
   336
	if (s.st_mode & S_IFREG)
faluco@274
   337
	{
faluco@274
   338
		return 1;
faluco@274
   339
	}
faluco@274
   340
	return 0;
dvander@351
   341
#elif defined PLATFORM_POSIX
faluco@274
   342
	struct stat s;
faluco@274
   343
	if (stat(realpath, &s) != 0)
faluco@274
   344
	{
faluco@274
   345
		return 0;
faluco@274
   346
	}
faluco@274
   347
	if (S_ISREG(s.st_mode))
faluco@274
   348
	{
faluco@274
   349
		return 1;
faluco@274
   350
	}
faluco@274
   351
	return 0;
faluco@274
   352
#endif
faluco@274
   353
}
faluco@274
   354
faluco@274
   355
static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   356
{
faluco@274
   357
	char *newpath, *oldpath;
faluco@274
   358
	int err;
faluco@274
   359
	if ((err=pContext->LocalToString(params[1], &newpath)) != SP_ERROR_NONE)
faluco@274
   360
	{
faluco@274
   361
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   362
		return 0;
faluco@274
   363
	}
faluco@274
   364
	if ((err=pContext->LocalToString(params[2], &oldpath)) != SP_ERROR_NONE)
faluco@274
   365
	{
faluco@274
   366
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   367
		return 0;
faluco@274
   368
	}
faluco@274
   369
ds@652
   370
	char new_realpath[PLATFORM_MAX_PATH];
dvander@3791
   371
	g_pSM->BuildPath(Path_Game, new_realpath, sizeof(new_realpath), "%s", newpath);
ds@652
   372
	char old_realpath[PLATFORM_MAX_PATH];
dvander@3791
   373
	g_pSM->BuildPath(Path_Game, old_realpath, sizeof(old_realpath), "%s", oldpath);
faluco@274
   374
faluco@274
   375
#ifdef PLATFORM_WINDOWS
faluco@274
   376
	return (MoveFileA(old_realpath, new_realpath)) ? 1 : 0;
dvander@351
   377
#elif defined PLATFORM_POSIX
faluco@274
   378
	return (rename(old_realpath, new_realpath)) ? 0 : 1;
faluco@274
   379
#endif
faluco@274
   380
}
faluco@274
   381
faluco@274
   382
static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params)
faluco@274
   383
{
faluco@274
   384
	char *name;
faluco@274
   385
	int err;
faluco@274
   386
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   387
	{
faluco@274
   388
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   389
		return 0;
faluco@274
   390
	}
faluco@274
   391
ds@652
   392
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   393
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   394
#ifdef PLATFORM_WINDOWS
faluco@274
   395
	struct _stat s;
faluco@274
   396
	if (_stat(realpath, &s) != 0)
faluco@274
   397
	{
faluco@274
   398
		return 0;
faluco@274
   399
	}
faluco@274
   400
	if (s.st_mode & S_IFDIR)
faluco@274
   401
	{
faluco@274
   402
		return 1;
faluco@274
   403
	}
faluco@274
   404
	return 0;
dvander@351
   405
#elif defined PLATFORM_POSIX
faluco@274
   406
	struct stat s;
faluco@274
   407
	if (stat(realpath, &s) != 0)
faluco@274
   408
	{
faluco@274
   409
		return 0;
faluco@274
   410
	}
faluco@274
   411
	if (S_ISDIR(s.st_mode))
faluco@274
   412
	{
faluco@274
   413
		return 1;
faluco@274
   414
	}
faluco@274
   415
	return 0;
faluco@274
   416
#endif
faluco@274
   417
}
faluco@274
   418
faluco@274
   419
static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params)
faluco@274
   420
{
faluco@274
   421
	char *name;
faluco@274
   422
	int err;
faluco@274
   423
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   424
	{
faluco@274
   425
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   426
		return -1;
faluco@274
   427
	}
faluco@274
   428
ds@652
   429
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   430
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   431
#ifdef PLATFORM_WINDOWS
faluco@274
   432
	struct _stat s;
faluco@274
   433
	if (_stat(realpath, &s) != 0)
faluco@274
   434
	{
faluco@274
   435
		return -1;
faluco@274
   436
	}
faluco@274
   437
	if (s.st_mode & S_IFREG)
faluco@274
   438
	{
faluco@274
   439
		return static_cast<cell_t>(s.st_size);
faluco@274
   440
	}
faluco@274
   441
	return -1;
dvander@351
   442
#elif defined PLATFORM_POSIX
faluco@274
   443
	struct stat s;
faluco@274
   444
	if (stat(realpath, &s) != 0)
faluco@274
   445
	{
faluco@274
   446
		return -1;
faluco@274
   447
	}
faluco@274
   448
	if (S_ISREG(s.st_mode))
faluco@274
   449
	{
faluco@274
   450
		return static_cast<cell_t>(s.st_size);
faluco@274
   451
	}
faluco@274
   452
	return -1;
faluco@274
   453
#endif
faluco@274
   454
}
faluco@274
   455
dvander@2307
   456
static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params)
dvander@2307
   457
{
dvander@2307
   458
	char *name;
dvander@2307
   459
	char realpath[PLATFORM_MAX_PATH];
dvander@2307
   460
dvander@2307
   461
	pContext->LocalToString(params[1], &name);
dvander@3791
   462
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
dvander@2307
   463
dvander@2307
   464
#if defined PLATFORM_WINDOWS
dvander@2307
   465
	return mkdir(realpath) == 0;
dvander@2307
   466
#else
dvander@2307
   467
	return mkdir(realpath, params[2]) == 0;
dvander@2307
   468
#endif
dvander@2307
   469
}
dvander@2307
   470
faluco@274
   471
static cell_t sm_RemoveDir(IPluginContext *pContext, const cell_t *params)
faluco@274
   472
{
faluco@274
   473
	char *name;
faluco@274
   474
	int err;
faluco@274
   475
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   476
	{
faluco@274
   477
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   478
		return 0;
faluco@274
   479
	}
faluco@274
   480
ds@652
   481
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   482
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   483
faluco@274
   484
	return (rmdir(realpath)) ? 0 : 1;
faluco@274
   485
}
faluco@274
   486
faluco@274
   487
static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params)
faluco@274
   488
{
faluco@274
   489
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   490
	HandleError herr;
faluco@274
   491
	HandleSecurity sec;
faluco@274
   492
	FILE *pFile;
faluco@274
   493
faluco@274
   494
	sec.pOwner = NULL;
faluco@274
   495
	sec.pIdentity = g_pCoreIdent;
faluco@274
   496
dvander@3791
   497
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   498
		!= HandleError_None)
faluco@274
   499
	{
faluco@274
   500
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   501
	}
faluco@274
   502
faluco@274
   503
	char *fmt;
faluco@274
   504
	int err;
faluco@274
   505
	if ((err=pContext->LocalToString(params[2], &fmt)) != SP_ERROR_NONE)
faluco@274
   506
	{
faluco@274
   507
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   508
		return 0;
faluco@274
   509
	}
faluco@274
   510
faluco@274
   511
	char buffer[2048];
faluco@274
   512
	int arg = 3;
dvander@3791
   513
	smcore.atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
faluco@274
   514
	fprintf(pFile, "%s\n", buffer);
faluco@274
   515
faluco@274
   516
	return 1;
faluco@274
   517
}
faluco@274
   518
dvander@821
   519
static cell_t sm_FlushFile(IPluginContext *pContext, const cell_t *params)
dvander@821
   520
{
dvander@821
   521
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@821
   522
	HandleError herr;
dvander@821
   523
	HandleSecurity sec;
dvander@821
   524
	FILE *pFile;
dvander@821
   525
dvander@821
   526
	sec.pOwner = NULL;
dvander@821
   527
	sec.pIdentity = g_pCoreIdent;
dvander@821
   528
dvander@3791
   529
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@821
   530
		!= HandleError_None)
dvander@821
   531
	{
dvander@821
   532
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@821
   533
	}
dvander@821
   534
dvander@821
   535
	return (fflush(pFile) == 0) ? 1 : 0;
dvander@821
   536
}
dvander@821
   537
dvander@345
   538
static cell_t sm_BuildPath(IPluginContext *pContext, const cell_t *params)
dvander@345
   539
{
dvander@345
   540
	char path[PLATFORM_MAX_PATH], *fmt, *buffer;
ds@711
   541
	int arg = 5;
dvander@345
   542
	pContext->LocalToString(params[2], &buffer);
dvander@345
   543
	pContext->LocalToString(params[4], &fmt);
dvander@345
   544
dvander@3791
   545
	smcore.atcprintf(path, sizeof(path), fmt, pContext, params, &arg);
dvander@345
   546
dvander@3791
   547
	return g_pSM->BuildPath(Path_SM_Rel, buffer, params[3], "%s", path);
dvander@345
   548
}
dvander@345
   549
dvander@347
   550
static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
dvander@347
   551
{
dvander@3791
   552
	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
dvander@1011
   553
dvander@347
   554
	char buffer[1024];
dvander@3791
   555
	size_t len = g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
dvander@347
   556
dvander@2193
   557
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
dvander@1378
   558
	{
dvander@1378
   559
		return 0;
dvander@1378
   560
	}
dvander@1378
   561
dvander@347
   562
	if (len >= sizeof(buffer)-2)
dvander@347
   563
	{
dvander@347
   564
		buffer[1022] = '\n';
dvander@347
   565
		buffer[1023] = '\0';
dvander@347
   566
	} else {
dvander@347
   567
		buffer[len++] = '\n';
dvander@347
   568
		buffer[len] = '\0';
dvander@347
   569
	}
dvander@347
   570
dvander@3791
   571
	smcore.LogToGame(buffer);
dvander@347
   572
dvander@347
   573
	return 1;
dvander@347
   574
}
dvander@347
   575
dvander@347
   576
static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
dvander@347
   577
{
dvander@3791
   578
	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
dvander@1011
   579
dvander@347
   580
	char buffer[1024];
dvander@3791
   581
	g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
dvander@347
   582
dvander@2193
   583
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
dvander@1378
   584
	{
dvander@1378
   585
		return 0;
dvander@1378
   586
	}
dvander@1378
   587
dvander@3791
   588
	IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
dvander@3791
   589
	smcore.Log("[%s] %s", pPlugin->GetFilename(), buffer);
dvander@347
   590
dvander@347
   591
	return 1;
dvander@347
   592
}
dvander@347
   593
dvander@347
   594
static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
dvander@347
   595
{
dvander@3791
   596
	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
dvander@1011
   597
dvander@347
   598
	char buffer[1024];
dvander@3791
   599
	g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
dvander@347
   600
dvander@2193
   601
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
dvander@1378
   602
	{
dvander@1378
   603
		return 0;
dvander@1378
   604
	}
dvander@1378
   605
dvander@3791
   606
	IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
dvander@3791
   607
	smcore.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
dvander@347
   608
dvander@347
   609
	return 1;
dvander@347
   610
}
dvander@347
   611
dvander@1370
   612
static cell_t sm_GetFileTime(IPluginContext *pContext, const cell_t *params)
dvander@1370
   613
{
dvander@1370
   614
	char *name;
dvander@1370
   615
	int err;
dvander@1370
   616
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
dvander@1370
   617
	{
dvander@1370
   618
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@1370
   619
		return 0;
dvander@1370
   620
	}
dvander@1370
   621
dvander@1738
   622
	time_t time_val;
dvander@1370
   623
	char realpath[PLATFORM_MAX_PATH];
dvander@3791
   624
	g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
dvander@1370
   625
dvander@3791
   626
	if (!libsys->FileTime(realpath, (FileTimeType)params[2], &time_val))
dvander@1370
   627
	{
dvander@1370
   628
		return -1;
dvander@1370
   629
	}
dvander@1370
   630
dvander@1738
   631
	return (cell_t)time_val;
dvander@1370
   632
}
dvander@1370
   633
dvander@1378
   634
static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
dvander@1378
   635
{
dvander@1378
   636
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1378
   637
	HandleError herr;
dvander@1378
   638
	HandleSecurity sec;
dvander@1378
   639
	FILE *pFile;
dvander@1378
   640
dvander@1378
   641
	sec.pOwner = NULL;
dvander@1378
   642
	sec.pIdentity = g_pCoreIdent;
dvander@1378
   643
dvander@3791
   644
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1378
   645
		!= HandleError_None)
dvander@1378
   646
	{
dvander@1378
   647
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1378
   648
	}
dvander@1378
   649
dvander@1378
   650
	char buffer[2048];
dvander@3791
   651
	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
dvander@3791
   652
	g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@1378
   653
dvander@2193
   654
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
dvander@1378
   655
	{
dvander@1378
   656
		return 0;
dvander@1378
   657
	}
dvander@1378
   658
dvander@3791
   659
	IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
dvander@3791
   660
	smcore.LogToFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer);
dvander@1378
   661
dvander@1378
   662
	return 1;
dvander@1378
   663
}
dvander@1378
   664
dvander@1378
   665
static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
dvander@1378
   666
{
dvander@1378
   667
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1378
   668
	HandleError herr;
dvander@1378
   669
	HandleSecurity sec;
dvander@1378
   670
	FILE *pFile;
dvander@1378
   671
dvander@1378
   672
	sec.pOwner = NULL;
dvander@1378
   673
	sec.pIdentity = g_pCoreIdent;
dvander@1378
   674
dvander@3791
   675
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1378
   676
		!= HandleError_None)
dvander@1378
   677
	{
dvander@1378
   678
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1378
   679
	}
dvander@1378
   680
dvander@1378
   681
	char buffer[2048];
dvander@3791
   682
	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
dvander@3791
   683
	g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@1378
   684
dvander@2193
   685
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
dvander@1378
   686
	{
dvander@1378
   687
		return 0;
dvander@1378
   688
	}
dvander@1378
   689
dvander@3791
   690
	smcore.LogToFile(pFile, "%s", buffer);
dvander@1378
   691
dvander@1378
   692
	return 1;
dvander@1378
   693
}
dvander@252
   694
dvander@1796
   695
static cell_t sm_ReadFile(IPluginContext *pContext, const cell_t *params)
dvander@1796
   696
{
dvander@1796
   697
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   698
	HandleError herr;
dvander@1796
   699
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   700
	FILE *pFile;
dvander@1796
   701
	size_t read = 0;
dvander@1796
   702
dvander@3791
   703
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   704
		!= HandleError_None)
dvander@1796
   705
	{
dvander@1796
   706
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   707
	}
dvander@1796
   708
dvander@1796
   709
	if (params[4] != 1 && params[4] != 2 && params[4] != 4)
dvander@1796
   710
	{
dvander@1796
   711
		return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]);
dvander@1796
   712
	}
dvander@1796
   713
dvander@1796
   714
	cell_t *data;
dvander@1796
   715
	pContext->LocalToPhysAddr(params[2], &data);
dvander@1796
   716
dvander@1796
   717
	if (params[4] == 4)
dvander@1796
   718
	{
dvander@1796
   719
		read = fread(data, sizeof(cell_t), params[3], pFile);
dvander@1796
   720
	}
dvander@1796
   721
	else if (params[4] == 2)
dvander@1796
   722
	{
dvander@2431
   723
		uint16_t val;
dvander@1796
   724
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   725
		{
dvander@2431
   726
			if (fread(&val, sizeof(uint16_t), 1, pFile) != 1)
dvander@1796
   727
			{
dvander@1796
   728
				break;
dvander@1796
   729
			}
dvander@1796
   730
			data[read++] = val;
dvander@1796
   731
		}
dvander@1796
   732
	}
dvander@1796
   733
	else if (params[4] == 1)
dvander@1796
   734
	{
dvander@2431
   735
		uint8_t val;
dvander@1796
   736
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   737
		{
dvander@2431
   738
			if (fread(&val, sizeof(uint8_t), 1, pFile) != 1)
dvander@1796
   739
			{
dvander@1796
   740
				break;
dvander@1796
   741
			}
dvander@1796
   742
			data[read++] = val;
dvander@1796
   743
		}
dvander@1796
   744
	}
dvander@1796
   745
dvander@1796
   746
	if (read != (size_t)params[3] && ferror(pFile) != 0)
dvander@1796
   747
	{
dvander@1796
   748
		return -1;
dvander@1796
   749
	}
dvander@1796
   750
dvander@1796
   751
	return read;
dvander@1796
   752
}
dvander@1796
   753
dvander@1796
   754
static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params)
dvander@1796
   755
{
dvander@1796
   756
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   757
	HandleError herr;
dvander@1796
   758
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   759
	FILE *pFile;
dvander@1796
   760
	cell_t num_read = 0;
dvander@1796
   761
dvander@3791
   762
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   763
		!= HandleError_None)
dvander@1796
   764
	{
dvander@1796
   765
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   766
	}
dvander@1796
   767
dvander@1796
   768
	char *buffer;
dvander@1796
   769
	pContext->LocalToString(params[2], &buffer);
dvander@1796
   770
dvander@2445
   771
	if (params[4] != -1)
dvander@2445
   772
	{
dvander@2445
   773
		if (size_t(params[4]) > size_t(params[3]))
dvander@2445
   774
		{
dvander@2445
   775
			return pContext->ThrowNativeError("read_count (%u) is greater than buffer size (%u)",
dvander@2445
   776
				params[4],
dvander@2445
   777
				params[3]);
dvander@2445
   778
		}
dvander@2445
   779
dvander@2445
   780
		num_read = (cell_t)fread(buffer, 1, params[4], pFile);
dvander@2445
   781
dvander@2445
   782
		if (num_read != params[4] && ferror(pFile))
dvander@2445
   783
		{
dvander@2445
   784
			return -1;
dvander@2445
   785
		}
dvander@2445
   786
dvander@2445
   787
		return num_read;
dvander@2445
   788
	}
dvander@2445
   789
dvander@1796
   790
	char val;
dvander@1796
   791
	while (1)
dvander@1796
   792
	{
dvander@2445
   793
		if (params[3] == 0 || num_read >= params[3] - 1)
dvander@1796
   794
		{
dvander@1796
   795
			break;
dvander@1796
   796
		}
dvander@1796
   797
		if (fread(&val, sizeof(val), 1, pFile) != 1)
dvander@1796
   798
		{
dvander@1796
   799
			if (ferror(pFile))
dvander@1796
   800
			{
dvander@1796
   801
				return -1;
dvander@1796
   802
			}
dvander@1796
   803
			break;
dvander@1796
   804
		}
dvander@1796
   805
		if (val == '\0')
dvander@1796
   806
		{
dvander@1796
   807
			break;
dvander@1796
   808
		}
dvander@1796
   809
		if (params[3] > 0 && num_read < params[3] - 1)
dvander@1796
   810
		{
dvander@1796
   811
			buffer[num_read++] = val;
dvander@1796
   812
		}
dvander@1796
   813
	}
dvander@1796
   814
dvander@1796
   815
	if (params[3] > 0)
dvander@1796
   816
	{
dvander@1796
   817
		buffer[num_read] = '\0';
dvander@1796
   818
	}
dvander@1796
   819
dvander@1796
   820
	return num_read;
dvander@1796
   821
}
dvander@1796
   822
dvander@1796
   823
static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params)
dvander@1796
   824
{
dvander@1796
   825
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   826
	HandleError herr;
dvander@1796
   827
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   828
	FILE *pFile;
dvander@1796
   829
dvander@3791
   830
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   831
		!= HandleError_None)
dvander@1796
   832
	{
dvander@1796
   833
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   834
	}
dvander@1796
   835
dvander@1796
   836
	cell_t *data;
dvander@1796
   837
	pContext->LocalToPhysAddr(params[2], &data);
dvander@1796
   838
dvander@1796
   839
	if (params[4] != 1 && params[4] != 2 && params[4] != 4)
dvander@1796
   840
	{
dvander@1796
   841
		return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]);
dvander@1796
   842
	}
dvander@1796
   843
dvander@1796
   844
	/* :NOTE: This really isn't compatible with big endian but we will never have to worry about that. */
dvander@1796
   845
dvander@1796
   846
	if (params[4] == 4)
dvander@1796
   847
	{
dvander@1796
   848
		if (fwrite(data, sizeof(cell_t), params[3], pFile) != (size_t)params[3])
dvander@1796
   849
		{
dvander@1796
   850
			return 0;
dvander@1796
   851
		}
dvander@1796
   852
	}
dvander@1796
   853
	else if (params[4] == 2)
dvander@1796
   854
	{
dvander@1796
   855
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   856
		{
dvander@1796
   857
			if (fwrite(&data[i], sizeof(int16_t), 1, pFile) != 1)
dvander@1796
   858
			{
dvander@1796
   859
				return 0;
dvander@1796
   860
			}
dvander@1796
   861
		}
dvander@1796
   862
	}
dvander@1796
   863
	else if (params[4] == 1)
dvander@1796
   864
	{
dvander@1796
   865
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   866
		{
dvander@1796
   867
			if (fwrite(&data[i], sizeof(int8_t), 1, pFile) != 1)
dvander@1796
   868
			{
dvander@1796
   869
				return 0;
dvander@1796
   870
			}
dvander@1796
   871
		}
dvander@1796
   872
	}
dvander@1796
   873
dvander@1796
   874
	return 1;
dvander@1796
   875
}
dvander@1796
   876
dvander@1796
   877
static cell_t sm_WriteFileString(IPluginContext *pContext, const cell_t *params)
dvander@1796
   878
{
dvander@1796
   879
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   880
	HandleError herr;
dvander@1796
   881
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   882
	FILE *pFile;
dvander@1796
   883
dvander@3791
   884
	if ((herr=handlesys->ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   885
		!= HandleError_None)
dvander@1796
   886
	{
dvander@1796
   887
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   888
	}
dvander@1796
   889
dvander@1796
   890
	char *buffer;
dvander@1796
   891
	pContext->LocalToString(params[2], &buffer);
dvander@1796
   892
dvander@1796
   893
	size_t len = strlen(buffer);
dvander@1796
   894
dvander@1796
   895
	if (params[3])
dvander@1796
   896
	{
dvander@1796
   897
		len++;
dvander@1796
   898
	}
dvander@1796
   899
dvander@1796
   900
	return (fwrite(buffer, sizeof(char), len, pFile) == len) ? 1 : 0;
dvander@1796
   901
}
dvander@1796
   902
dvander@1914
   903
static cell_t sm_AddGameLogHook(IPluginContext *pContext, const cell_t *params)
dvander@1914
   904
{
dvander@1914
   905
	IPluginFunction *pFunction;
dvander@1914
   906
dvander@1914
   907
	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
dvander@1914
   908
	{
dvander@1914
   909
		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
dvander@1914
   910
	}
dvander@1914
   911
dvander@1914
   912
	s_FileNatives.AddLogHook(pFunction);
dvander@1914
   913
	
dvander@1914
   914
	return 1;
dvander@1914
   915
}
dvander@1914
   916
dvander@1914
   917
static cell_t sm_RemoveGameLogHook(IPluginContext *pContext, const cell_t *params)
dvander@1914
   918
{
dvander@1914
   919
	IPluginFunction *pFunction;
dvander@1914
   920
dvander@1914
   921
	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
dvander@1914
   922
	{
dvander@1914
   923
		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
dvander@1914
   924
	}
dvander@1914
   925
dvander@1914
   926
	s_FileNatives.RemoveLogHook(pFunction);
dvander@1914
   927
dvander@1914
   928
	return 1;
dvander@1914
   929
}
dvander@1914
   930
dvander@252
   931
REGISTER_NATIVES(filesystem)
dvander@252
   932
{
dvander@252
   933
	{"OpenDirectory",			sm_OpenDirectory},
dvander@252
   934
	{"ReadDirEntry",			sm_ReadDirEntry},
faluco@274
   935
	{"OpenFile",				sm_OpenFile},
faluco@274
   936
	{"DeleteFile",				sm_DeleteFile},
faluco@274
   937
	{"ReadFileLine",			sm_ReadFileLine},
faluco@274
   938
	{"IsEndOfFile",				sm_IsEndOfFile},
faluco@274
   939
	{"FileSeek",				sm_FileSeek},
faluco@274
   940
	{"FilePosition",			sm_FilePosition},
faluco@274
   941
	{"FileExists",				sm_FileExists},
faluco@274
   942
	{"RenameFile",				sm_RenameFile},
faluco@274
   943
	{"DirExists",				sm_DirExists},
faluco@274
   944
	{"FileSize",				sm_FileSize},
faluco@274
   945
	{"RemoveDir",				sm_RemoveDir},
faluco@274
   946
	{"WriteFileLine",			sm_WriteFileLine},
dvander@345
   947
	{"BuildPath",				sm_BuildPath},
dvander@636
   948
	{"LogToGame",				sm_LogToGame},
dvander@636
   949
	{"LogMessage",				sm_LogMessage},
dvander@347
   950
	{"LogError",				sm_LogError},
dvander@821
   951
	{"FlushFile",				sm_FlushFile},
dvander@1370
   952
	{"GetFileTime",				sm_GetFileTime},
dvander@1378
   953
	{"LogToOpenFile",			sm_LogToOpenFile},
dvander@1379
   954
	{"LogToOpenFileEx",			sm_LogToOpenFileEx},
dvander@1796
   955
	{"ReadFile",				sm_ReadFile},
dvander@1796
   956
	{"ReadFileString",			sm_ReadFileString},
dvander@1796
   957
	{"WriteFile",				sm_WriteFile},
dvander@1796
   958
	{"WriteFileString",			sm_WriteFileString},
dvander@1914
   959
	{"AddGameLogHook",			sm_AddGameLogHook},
dvander@1914
   960
	{"RemoveGameLogHook",		sm_RemoveGameLogHook},
dvander@2307
   961
	{"CreateDirectory",			sm_CreateDirectory},
dvander@252
   962
	{NULL,						NULL},
dvander@252
   963
};