core/smn_filesystem.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sat Feb 23 20:18:49 2008 +0000 (2008-02-23)
changeset 1894 e6efc8ffa47a
parent 1854 91f2e0437e12
child 1914 0751a6430f15
permissions -rw-r--r--
Executable memory is now provided by MM:S's allocator, this should reduce virtual memory usage.
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 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@252
    33
#include "sm_globals.h"
dvander@252
    34
#include "HandleSys.h"
dvander@252
    35
#include "LibrarySys.h"
faluco@274
    36
#include "sm_stringutil.h"
dvander@592
    37
#include "Logger.h"
dvander@347
    38
#include "PluginSys.h"
dvander@347
    39
#include "sourcemm_api.h"
dvander@252
    40
dvander@252
    41
HandleType_t g_FileType;
dvander@252
    42
HandleType_t g_DirType;
dvander@252
    43
dvander@252
    44
class FileNatives : 
dvander@252
    45
	public SMGlobalClass,
dvander@252
    46
	public IHandleTypeDispatch
dvander@252
    47
{
dvander@252
    48
public:
dvander@252
    49
	virtual void OnSourceModAllInitialized()
dvander@252
    50
	{
dvander@262
    51
		g_FileType = g_HandleSys.CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@262
    52
		g_DirType = g_HandleSys.CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
dvander@252
    53
	}
dvander@252
    54
	virtual void OnSourceModShutdown()
dvander@252
    55
	{
dvander@252
    56
		g_HandleSys.RemoveType(g_DirType, g_pCoreIdent);
dvander@252
    57
		g_HandleSys.RemoveType(g_FileType, g_pCoreIdent);
dvander@252
    58
		g_DirType = 0;
dvander@252
    59
		g_FileType = 0;
dvander@252
    60
	}
dvander@252
    61
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@252
    62
	{
dvander@252
    63
		if (type == g_FileType)
dvander@252
    64
		{
dvander@252
    65
			FILE *fp = (FILE *)object;
dvander@252
    66
			fclose(fp);
dvander@252
    67
		} else if (type == g_DirType) {
dvander@252
    68
			IDirectory *pDir = (IDirectory *)object;
dvander@252
    69
			g_LibSys.CloseDirectory(pDir);
dvander@252
    70
		}
dvander@252
    71
	}
dvander@1378
    72
} s_FileNatives;
dvander@252
    73
faluco@274
    74
static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
dvander@252
    75
{
dvander@252
    76
	char *path;
dvander@252
    77
	int err;
dvander@252
    78
	if ((err=pContext->LocalToString(params[1], &path)) != SP_ERROR_NONE)
dvander@252
    79
	{
dvander@252
    80
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@252
    81
		return 0;
dvander@252
    82
	}
dvander@252
    83
ds@652
    84
	char realpath[PLATFORM_MAX_PATH];
dvander@317
    85
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
dvander@255
    86
dvander@255
    87
	IDirectory *pDir = g_LibSys.OpenDirectory(realpath);
dvander@252
    88
	if (!pDir)
dvander@252
    89
	{
dvander@252
    90
		return 0;
dvander@252
    91
	}
dvander@252
    92
dvander@262
    93
	return g_HandleSys.CreateHandle(g_DirType, pDir, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@252
    94
}
dvander@252
    95
faluco@274
    96
static cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params)
dvander@252
    97
{
dvander@252
    98
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@252
    99
	IDirectory *pDir;
dvander@252
   100
	HandleError herr;
dvander@262
   101
	HandleSecurity sec;
dvander@252
   102
	int err;
dvander@262
   103
dvander@262
   104
	sec.pOwner = NULL;
dvander@262
   105
	sec.pIdentity = g_pCoreIdent;
dvander@262
   106
dvander@262
   107
	if ((herr=g_HandleSys.ReadHandle(hndl, g_DirType, &sec, (void **)&pDir))
dvander@252
   108
		!= HandleError_None)
dvander@252
   109
	{
dvander@252
   110
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@252
   111
	}
dvander@252
   112
dvander@252
   113
	if (!pDir->MoreFiles())
dvander@252
   114
	{
dvander@252
   115
		return false;
dvander@252
   116
	}
dvander@252
   117
dvander@252
   118
	cell_t *filetype;
dvander@252
   119
	if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE)
dvander@252
   120
	{
dvander@252
   121
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@252
   122
		return 0;
dvander@252
   123
	}
dvander@252
   124
dvander@252
   125
	if (pDir->IsEntryDirectory())
dvander@252
   126
	{
dvander@252
   127
		*filetype = 1;
dvander@252
   128
	} else if (pDir->IsEntryFile()) {
dvander@252
   129
		*filetype = 2;
dvander@252
   130
	} else {
dvander@252
   131
		*filetype = 0;
dvander@252
   132
	}
dvander@252
   133
dvander@252
   134
	const char *path = pDir->GetEntryName();
dvander@255
   135
	if ((err=pContext->StringToLocalUTF8(params[2], params[3], path, NULL))
dvander@252
   136
		!= SP_ERROR_NONE)
dvander@252
   137
	{
dvander@252
   138
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@252
   139
		return 0;
dvander@252
   140
	}
dvander@252
   141
dvander@255
   142
	pDir->NextEntry();
dvander@255
   143
dvander@252
   144
	return true;
dvander@252
   145
}
dvander@252
   146
faluco@274
   147
static cell_t sm_OpenFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   148
{
faluco@274
   149
	char *name, *mode;
faluco@274
   150
	int err;
faluco@274
   151
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   152
	{
faluco@274
   153
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   154
		return 0;
faluco@274
   155
	}
faluco@274
   156
	if ((err=pContext->LocalToString(params[2], &mode)) != SP_ERROR_NONE)
faluco@274
   157
	{
faluco@274
   158
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   159
		return 0;
faluco@274
   160
	}
faluco@274
   161
ds@652
   162
	char realpath[PLATFORM_MAX_PATH];
dvander@636
   163
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   164
faluco@274
   165
	FILE *pFile = fopen(realpath, mode);
faluco@274
   166
	if (!pFile)
faluco@274
   167
	{
faluco@274
   168
		return 0;
faluco@274
   169
	}
faluco@274
   170
faluco@274
   171
	return g_HandleSys.CreateHandle(g_FileType, pFile, pContext->GetIdentity(), g_pCoreIdent, NULL);
faluco@274
   172
}
faluco@274
   173
faluco@274
   174
static cell_t sm_DeleteFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   175
{
faluco@274
   176
	char *name;
faluco@274
   177
	int err;
faluco@274
   178
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   179
	{
faluco@274
   180
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   181
		return 0;
faluco@274
   182
	}
faluco@274
   183
ds@652
   184
	char realpath[PLATFORM_MAX_PATH];
dvander@636
   185
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   186
faluco@274
   187
	return (unlink(realpath)) ? 0 : 1;
faluco@274
   188
}
faluco@274
   189
faluco@274
   190
static cell_t sm_ReadFileLine(IPluginContext *pContext, const cell_t *params)
faluco@274
   191
{
faluco@274
   192
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   193
	HandleError herr;
faluco@274
   194
	HandleSecurity sec;
faluco@274
   195
	FILE *pFile;
faluco@274
   196
	int err;
faluco@274
   197
faluco@274
   198
	sec.pOwner = NULL;
faluco@274
   199
	sec.pIdentity = g_pCoreIdent;
faluco@274
   200
faluco@274
   201
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   202
		!= HandleError_None)
faluco@274
   203
	{
faluco@274
   204
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   205
	}
faluco@274
   206
faluco@274
   207
	char *buf;
faluco@274
   208
	if ((err=pContext->LocalToString(params[2], &buf)) != SP_ERROR_NONE)
faluco@274
   209
	{
faluco@274
   210
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   211
		return 0;
faluco@274
   212
	}
faluco@274
   213
dvander@638
   214
	if (fgets(buf, params[3], pFile) == NULL)
dvander@638
   215
	{
dvander@638
   216
		return 0;
dvander@638
   217
	}
faluco@274
   218
faluco@274
   219
	return 1;
faluco@274
   220
}
faluco@274
   221
faluco@274
   222
static cell_t sm_IsEndOfFile(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
faluco@274
   229
	sec.pOwner = NULL;
faluco@274
   230
	sec.pIdentity = g_pCoreIdent;
faluco@274
   231
faluco@274
   232
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   233
		!= HandleError_None)
faluco@274
   234
	{
faluco@274
   235
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   236
	}
faluco@274
   237
faluco@274
   238
	return (feof(pFile)) ? 1 : 0;
faluco@274
   239
}
faluco@274
   240
faluco@274
   241
static cell_t sm_FileSeek(IPluginContext *pContext, const cell_t *params)
faluco@274
   242
{
faluco@274
   243
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   244
	HandleError herr;
faluco@274
   245
	HandleSecurity sec;
faluco@274
   246
	FILE *pFile;
faluco@274
   247
faluco@274
   248
	sec.pOwner = NULL;
faluco@274
   249
	sec.pIdentity = g_pCoreIdent;
faluco@274
   250
faluco@274
   251
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   252
		!= HandleError_None)
faluco@274
   253
	{
faluco@274
   254
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   255
	}
faluco@274
   256
faluco@274
   257
	fseek(pFile, params[2], params[3]);
faluco@274
   258
	
faluco@274
   259
	return 1;
faluco@274
   260
}
faluco@274
   261
faluco@274
   262
static cell_t sm_FilePosition(IPluginContext *pContext, const cell_t *params)
faluco@274
   263
{
faluco@274
   264
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   265
	HandleError herr;
faluco@274
   266
	HandleSecurity sec;
faluco@274
   267
	FILE *pFile;
faluco@274
   268
faluco@274
   269
	sec.pOwner = NULL;
faluco@274
   270
	sec.pIdentity = g_pCoreIdent;
faluco@274
   271
faluco@274
   272
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   273
		!= HandleError_None)
faluco@274
   274
	{
faluco@274
   275
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   276
	}
faluco@274
   277
faluco@274
   278
	return ftell(pFile);
faluco@274
   279
}
faluco@274
   280
faluco@274
   281
static cell_t sm_FileExists(IPluginContext *pContext, const cell_t *params)
faluco@274
   282
{
faluco@274
   283
	char *name;
faluco@274
   284
	int err;
faluco@274
   285
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   286
	{
faluco@274
   287
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   288
		return 0;
faluco@274
   289
	}
faluco@274
   290
dvander@1854
   291
	if (params[0] >= 2 && params[2] == 1)
dvander@1854
   292
	{
dvander@1854
   293
		return basefilesystem->FileExists(name) ? 1 : 0;
dvander@1854
   294
	}
dvander@1854
   295
ds@652
   296
	char realpath[PLATFORM_MAX_PATH];
dvander@636
   297
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   298
#ifdef PLATFORM_WINDOWS
faluco@274
   299
	struct _stat s;
faluco@274
   300
	if (_stat(realpath, &s) != 0)
faluco@274
   301
	{
faluco@274
   302
		return 0;
faluco@274
   303
	}
faluco@274
   304
	if (s.st_mode & S_IFREG)
faluco@274
   305
	{
faluco@274
   306
		return 1;
faluco@274
   307
	}
faluco@274
   308
	return 0;
dvander@351
   309
#elif defined PLATFORM_POSIX
faluco@274
   310
	struct stat s;
faluco@274
   311
	if (stat(realpath, &s) != 0)
faluco@274
   312
	{
faluco@274
   313
		return 0;
faluco@274
   314
	}
faluco@274
   315
	if (S_ISREG(s.st_mode))
faluco@274
   316
	{
faluco@274
   317
		return 1;
faluco@274
   318
	}
faluco@274
   319
	return 0;
faluco@274
   320
#endif
faluco@274
   321
}
faluco@274
   322
faluco@274
   323
static cell_t sm_RenameFile(IPluginContext *pContext, const cell_t *params)
faluco@274
   324
{
faluco@274
   325
	char *newpath, *oldpath;
faluco@274
   326
	int err;
faluco@274
   327
	if ((err=pContext->LocalToString(params[1], &newpath)) != SP_ERROR_NONE)
faluco@274
   328
	{
faluco@274
   329
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   330
		return 0;
faluco@274
   331
	}
faluco@274
   332
	if ((err=pContext->LocalToString(params[2], &oldpath)) != SP_ERROR_NONE)
faluco@274
   333
	{
faluco@274
   334
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   335
		return 0;
faluco@274
   336
	}
faluco@274
   337
ds@652
   338
	char new_realpath[PLATFORM_MAX_PATH];
dvander@636
   339
	g_SourceMod.BuildPath(Path_Game, new_realpath, sizeof(new_realpath), "%s", newpath);
ds@652
   340
	char old_realpath[PLATFORM_MAX_PATH];
dvander@636
   341
	g_SourceMod.BuildPath(Path_Game, old_realpath, sizeof(old_realpath), "%s", oldpath);
faluco@274
   342
faluco@274
   343
#ifdef PLATFORM_WINDOWS
faluco@274
   344
	return (MoveFileA(old_realpath, new_realpath)) ? 1 : 0;
dvander@351
   345
#elif defined PLATFORM_POSIX
faluco@274
   346
	return (rename(old_realpath, new_realpath)) ? 0 : 1;
faluco@274
   347
#endif
faluco@274
   348
}
faluco@274
   349
faluco@274
   350
static cell_t sm_DirExists(IPluginContext *pContext, const cell_t *params)
faluco@274
   351
{
faluco@274
   352
	char *name;
faluco@274
   353
	int err;
faluco@274
   354
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   355
	{
faluco@274
   356
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   357
		return 0;
faluco@274
   358
	}
faluco@274
   359
ds@652
   360
	char realpath[PLATFORM_MAX_PATH];
dvander@636
   361
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   362
#ifdef PLATFORM_WINDOWS
faluco@274
   363
	struct _stat s;
faluco@274
   364
	if (_stat(realpath, &s) != 0)
faluco@274
   365
	{
faluco@274
   366
		return 0;
faluco@274
   367
	}
faluco@274
   368
	if (s.st_mode & S_IFDIR)
faluco@274
   369
	{
faluco@274
   370
		return 1;
faluco@274
   371
	}
faluco@274
   372
	return 0;
dvander@351
   373
#elif defined PLATFORM_POSIX
faluco@274
   374
	struct stat s;
faluco@274
   375
	if (stat(realpath, &s) != 0)
faluco@274
   376
	{
faluco@274
   377
		return 0;
faluco@274
   378
	}
faluco@274
   379
	if (S_ISDIR(s.st_mode))
faluco@274
   380
	{
faluco@274
   381
		return 1;
faluco@274
   382
	}
faluco@274
   383
	return 0;
faluco@274
   384
#endif
faluco@274
   385
}
faluco@274
   386
faluco@274
   387
static cell_t sm_FileSize(IPluginContext *pContext, const cell_t *params)
faluco@274
   388
{
faluco@274
   389
	char *name;
faluco@274
   390
	int err;
faluco@274
   391
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   392
	{
faluco@274
   393
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   394
		return -1;
faluco@274
   395
	}
faluco@274
   396
ds@652
   397
	char realpath[PLATFORM_MAX_PATH];
dvander@636
   398
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   399
#ifdef PLATFORM_WINDOWS
faluco@274
   400
	struct _stat s;
faluco@274
   401
	if (_stat(realpath, &s) != 0)
faluco@274
   402
	{
faluco@274
   403
		return -1;
faluco@274
   404
	}
faluco@274
   405
	if (s.st_mode & S_IFREG)
faluco@274
   406
	{
faluco@274
   407
		return static_cast<cell_t>(s.st_size);
faluco@274
   408
	}
faluco@274
   409
	return -1;
dvander@351
   410
#elif defined PLATFORM_POSIX
faluco@274
   411
	struct stat s;
faluco@274
   412
	if (stat(realpath, &s) != 0)
faluco@274
   413
	{
faluco@274
   414
		return -1;
faluco@274
   415
	}
faluco@274
   416
	if (S_ISREG(s.st_mode))
faluco@274
   417
	{
faluco@274
   418
		return static_cast<cell_t>(s.st_size);
faluco@274
   419
	}
faluco@274
   420
	return -1;
faluco@274
   421
#endif
faluco@274
   422
}
faluco@274
   423
faluco@274
   424
static cell_t sm_RemoveDir(IPluginContext *pContext, const cell_t *params)
faluco@274
   425
{
faluco@274
   426
	char *name;
faluco@274
   427
	int err;
faluco@274
   428
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
faluco@274
   429
	{
faluco@274
   430
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   431
		return 0;
faluco@274
   432
	}
faluco@274
   433
ds@652
   434
	char realpath[PLATFORM_MAX_PATH];
dvander@636
   435
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
faluco@274
   436
faluco@274
   437
	return (rmdir(realpath)) ? 0 : 1;
faluco@274
   438
}
faluco@274
   439
faluco@274
   440
static cell_t sm_WriteFileLine(IPluginContext *pContext, const cell_t *params)
faluco@274
   441
{
faluco@274
   442
	Handle_t hndl = static_cast<Handle_t>(params[1]);
faluco@274
   443
	HandleError herr;
faluco@274
   444
	HandleSecurity sec;
faluco@274
   445
	FILE *pFile;
faluco@274
   446
faluco@274
   447
	sec.pOwner = NULL;
faluco@274
   448
	sec.pIdentity = g_pCoreIdent;
faluco@274
   449
faluco@274
   450
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
faluco@274
   451
		!= HandleError_None)
faluco@274
   452
	{
faluco@274
   453
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
faluco@274
   454
	}
faluco@274
   455
faluco@274
   456
	char *fmt;
faluco@274
   457
	int err;
faluco@274
   458
	if ((err=pContext->LocalToString(params[2], &fmt)) != SP_ERROR_NONE)
faluco@274
   459
	{
faluco@274
   460
		pContext->ThrowNativeErrorEx(err, NULL);
faluco@274
   461
		return 0;
faluco@274
   462
	}
faluco@274
   463
faluco@274
   464
	char buffer[2048];
faluco@274
   465
	int arg = 3;
faluco@274
   466
	atcprintf(buffer, sizeof(buffer), fmt, pContext, params, &arg);
faluco@274
   467
	fprintf(pFile, "%s\n", buffer);
faluco@274
   468
faluco@274
   469
	return 1;
faluco@274
   470
}
faluco@274
   471
dvander@821
   472
static cell_t sm_FlushFile(IPluginContext *pContext, const cell_t *params)
dvander@821
   473
{
dvander@821
   474
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@821
   475
	HandleError herr;
dvander@821
   476
	HandleSecurity sec;
dvander@821
   477
	FILE *pFile;
dvander@821
   478
dvander@821
   479
	sec.pOwner = NULL;
dvander@821
   480
	sec.pIdentity = g_pCoreIdent;
dvander@821
   481
dvander@821
   482
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@821
   483
		!= HandleError_None)
dvander@821
   484
	{
dvander@821
   485
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@821
   486
	}
dvander@821
   487
dvander@821
   488
	return (fflush(pFile) == 0) ? 1 : 0;
dvander@821
   489
}
dvander@821
   490
dvander@345
   491
static cell_t sm_BuildPath(IPluginContext *pContext, const cell_t *params)
dvander@345
   492
{
dvander@345
   493
	char path[PLATFORM_MAX_PATH], *fmt, *buffer;
ds@711
   494
	int arg = 5;
dvander@345
   495
	pContext->LocalToString(params[2], &buffer);
dvander@345
   496
	pContext->LocalToString(params[4], &fmt);
dvander@345
   497
dvander@345
   498
	atcprintf(path, sizeof(path), fmt, pContext, params, &arg);
dvander@345
   499
dvander@345
   500
	return g_SourceMod.BuildPath(Path_SM_Rel, buffer, params[3], "%s", path);
dvander@345
   501
}
dvander@345
   502
dvander@347
   503
static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
dvander@347
   504
{
dvander@1011
   505
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   506
dvander@347
   507
	char buffer[1024];
dvander@347
   508
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
dvander@347
   509
dvander@1378
   510
	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
dvander@1378
   511
	{
dvander@1378
   512
		return 0;
dvander@1378
   513
	}
dvander@1378
   514
dvander@347
   515
	if (len >= sizeof(buffer)-2)
dvander@347
   516
	{
dvander@347
   517
		buffer[1022] = '\n';
dvander@347
   518
		buffer[1023] = '\0';
dvander@347
   519
	} else {
dvander@347
   520
		buffer[len++] = '\n';
dvander@347
   521
		buffer[len] = '\0';
dvander@347
   522
	}
dvander@347
   523
dvander@347
   524
	engine->LogPrint(buffer);
dvander@347
   525
dvander@347
   526
	return 1;
dvander@347
   527
}
dvander@347
   528
dvander@347
   529
static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
dvander@347
   530
{
dvander@1011
   531
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   532
dvander@347
   533
	char buffer[1024];
dvander@351
   534
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
dvander@347
   535
dvander@1378
   536
	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
dvander@1378
   537
	{
dvander@1378
   538
		return 0;
dvander@1378
   539
	}
dvander@1378
   540
dvander@1378
   541
	CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
dvander@347
   542
	g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer);
dvander@347
   543
dvander@347
   544
	return 1;
dvander@347
   545
}
dvander@347
   546
dvander@347
   547
static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
dvander@347
   548
{
dvander@1011
   549
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1011
   550
dvander@347
   551
	char buffer[1024];
dvander@351
   552
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
dvander@347
   553
dvander@1378
   554
	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
dvander@1378
   555
	{
dvander@1378
   556
		return 0;
dvander@1378
   557
	}
dvander@1378
   558
dvander@1378
   559
	CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
dvander@347
   560
	g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
dvander@347
   561
dvander@347
   562
	return 1;
dvander@347
   563
}
dvander@347
   564
dvander@1370
   565
static cell_t sm_GetFileTime(IPluginContext *pContext, const cell_t *params)
dvander@1370
   566
{
dvander@1370
   567
	char *name;
dvander@1370
   568
	int err;
dvander@1370
   569
	if ((err=pContext->LocalToString(params[1], &name)) != SP_ERROR_NONE)
dvander@1370
   570
	{
dvander@1370
   571
		pContext->ThrowNativeErrorEx(err, NULL);
dvander@1370
   572
		return 0;
dvander@1370
   573
	}
dvander@1370
   574
dvander@1738
   575
	time_t time_val;
dvander@1370
   576
	char realpath[PLATFORM_MAX_PATH];
dvander@1370
   577
	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
dvander@1370
   578
dvander@1738
   579
	if (!g_LibSys.FileTime(realpath, (FileTimeType)params[2], &time_val))
dvander@1370
   580
	{
dvander@1370
   581
		return -1;
dvander@1370
   582
	}
dvander@1370
   583
dvander@1738
   584
	return (cell_t)time_val;
dvander@1370
   585
}
dvander@1370
   586
dvander@1378
   587
static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
dvander@1378
   588
{
dvander@1378
   589
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1378
   590
	HandleError herr;
dvander@1378
   591
	HandleSecurity sec;
dvander@1378
   592
	FILE *pFile;
dvander@1378
   593
dvander@1378
   594
	sec.pOwner = NULL;
dvander@1378
   595
	sec.pIdentity = g_pCoreIdent;
dvander@1378
   596
dvander@1378
   597
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1378
   598
		!= HandleError_None)
dvander@1378
   599
	{
dvander@1378
   600
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1378
   601
	}
dvander@1378
   602
dvander@1378
   603
	char buffer[2048];
dvander@1378
   604
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1378
   605
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@1378
   606
dvander@1378
   607
	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
dvander@1378
   608
	{
dvander@1378
   609
		return 0;
dvander@1378
   610
	}
dvander@1378
   611
dvander@1378
   612
	CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
dvander@1378
   613
	g_Logger.LogToOpenFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer);
dvander@1378
   614
dvander@1378
   615
	return 1;
dvander@1378
   616
}
dvander@1378
   617
dvander@1378
   618
static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
dvander@1378
   619
{
dvander@1378
   620
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1378
   621
	HandleError herr;
dvander@1378
   622
	HandleSecurity sec;
dvander@1378
   623
	FILE *pFile;
dvander@1378
   624
dvander@1378
   625
	sec.pOwner = NULL;
dvander@1378
   626
	sec.pIdentity = g_pCoreIdent;
dvander@1378
   627
dvander@1378
   628
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1378
   629
		!= HandleError_None)
dvander@1378
   630
	{
dvander@1378
   631
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1378
   632
	}
dvander@1378
   633
dvander@1378
   634
	char buffer[2048];
dvander@1378
   635
	g_SourceMod.SetGlobalTarget(LANG_SERVER);
dvander@1378
   636
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
dvander@1378
   637
dvander@1378
   638
	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
dvander@1378
   639
	{
dvander@1378
   640
		return 0;
dvander@1378
   641
	}
dvander@1378
   642
dvander@1378
   643
	g_Logger.LogToOpenFile(pFile, "%s", buffer);
dvander@1378
   644
dvander@1378
   645
	return 1;
dvander@1378
   646
}
dvander@252
   647
dvander@1796
   648
static cell_t sm_ReadFile(IPluginContext *pContext, const cell_t *params)
dvander@1796
   649
{
dvander@1796
   650
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   651
	HandleError herr;
dvander@1796
   652
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   653
	FILE *pFile;
dvander@1796
   654
	size_t read = 0;
dvander@1796
   655
dvander@1796
   656
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   657
		!= HandleError_None)
dvander@1796
   658
	{
dvander@1796
   659
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   660
	}
dvander@1796
   661
dvander@1796
   662
	if (params[4] != 1 && params[4] != 2 && params[4] != 4)
dvander@1796
   663
	{
dvander@1796
   664
		return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]);
dvander@1796
   665
	}
dvander@1796
   666
dvander@1796
   667
	cell_t *data;
dvander@1796
   668
	pContext->LocalToPhysAddr(params[2], &data);
dvander@1796
   669
dvander@1796
   670
	if (params[4] == 4)
dvander@1796
   671
	{
dvander@1796
   672
		read = fread(data, sizeof(cell_t), params[3], pFile);
dvander@1796
   673
	}
dvander@1796
   674
	else if (params[4] == 2)
dvander@1796
   675
	{
dvander@1796
   676
		int16_t val;
dvander@1796
   677
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   678
		{
dvander@1796
   679
			if (fread(&val, sizeof(int16_t), 1, pFile) != 1)
dvander@1796
   680
			{
dvander@1796
   681
				break;
dvander@1796
   682
			}
dvander@1796
   683
			data[read++] = val;
dvander@1796
   684
		}
dvander@1796
   685
	}
dvander@1796
   686
	else if (params[4] == 1)
dvander@1796
   687
	{
dvander@1796
   688
		int8_t val;
dvander@1796
   689
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   690
		{
dvander@1796
   691
			if (fread(&val, sizeof(int8_t), 1, pFile) != 1)
dvander@1796
   692
			{
dvander@1796
   693
				break;
dvander@1796
   694
			}
dvander@1796
   695
			data[read++] = val;
dvander@1796
   696
		}
dvander@1796
   697
	}
dvander@1796
   698
dvander@1796
   699
	if (read != (size_t)params[3] && ferror(pFile) != 0)
dvander@1796
   700
	{
dvander@1796
   701
		return -1;
dvander@1796
   702
	}
dvander@1796
   703
dvander@1796
   704
	return read;
dvander@1796
   705
}
dvander@1796
   706
dvander@1796
   707
static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params)
dvander@1796
   708
{
dvander@1796
   709
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   710
	HandleError herr;
dvander@1796
   711
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   712
	FILE *pFile;
dvander@1796
   713
	cell_t num_read = 0;
dvander@1796
   714
dvander@1796
   715
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   716
		!= HandleError_None)
dvander@1796
   717
	{
dvander@1796
   718
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   719
	}
dvander@1796
   720
dvander@1796
   721
	char *buffer;
dvander@1796
   722
	pContext->LocalToString(params[2], &buffer);
dvander@1796
   723
dvander@1796
   724
	char val;
dvander@1796
   725
	while (1)
dvander@1796
   726
	{
dvander@1796
   727
		/* If we're in stop mode, break as soon as the buffer is full. */
dvander@1796
   728
		if (params[4] && (params[3] == 0 || num_read >= params[3] - 1))
dvander@1796
   729
		{
dvander@1796
   730
			break;
dvander@1796
   731
		}
dvander@1796
   732
		if (fread(&val, sizeof(val), 1, pFile) != 1)
dvander@1796
   733
		{
dvander@1796
   734
			if (ferror(pFile))
dvander@1796
   735
			{
dvander@1796
   736
				return -1;
dvander@1796
   737
			}
dvander@1796
   738
			break;
dvander@1796
   739
		}
dvander@1796
   740
		if (val == '\0')
dvander@1796
   741
		{
dvander@1796
   742
			break;
dvander@1796
   743
		}
dvander@1796
   744
		if (params[3] > 0 && num_read < params[3] - 1)
dvander@1796
   745
		{
dvander@1796
   746
			buffer[num_read++] = val;
dvander@1796
   747
		}
dvander@1796
   748
	}
dvander@1796
   749
dvander@1796
   750
	if (params[3] > 0)
dvander@1796
   751
	{
dvander@1796
   752
		buffer[num_read] = '\0';
dvander@1796
   753
	}
dvander@1796
   754
dvander@1796
   755
	return num_read;
dvander@1796
   756
}
dvander@1796
   757
dvander@1796
   758
static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params)
dvander@1796
   759
{
dvander@1796
   760
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   761
	HandleError herr;
dvander@1796
   762
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   763
	FILE *pFile;
dvander@1796
   764
dvander@1796
   765
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   766
		!= HandleError_None)
dvander@1796
   767
	{
dvander@1796
   768
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   769
	}
dvander@1796
   770
dvander@1796
   771
	cell_t *data;
dvander@1796
   772
	pContext->LocalToPhysAddr(params[2], &data);
dvander@1796
   773
dvander@1796
   774
	if (params[4] != 1 && params[4] != 2 && params[4] != 4)
dvander@1796
   775
	{
dvander@1796
   776
		return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]);
dvander@1796
   777
	}
dvander@1796
   778
dvander@1796
   779
	/* :NOTE: This really isn't compatible with big endian but we will never have to worry about that. */
dvander@1796
   780
dvander@1796
   781
	if (params[4] == 4)
dvander@1796
   782
	{
dvander@1796
   783
		if (fwrite(data, sizeof(cell_t), params[3], pFile) != (size_t)params[3])
dvander@1796
   784
		{
dvander@1796
   785
			return 0;
dvander@1796
   786
		}
dvander@1796
   787
	}
dvander@1796
   788
	else if (params[4] == 2)
dvander@1796
   789
	{
dvander@1796
   790
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   791
		{
dvander@1796
   792
			if (fwrite(&data[i], sizeof(int16_t), 1, pFile) != 1)
dvander@1796
   793
			{
dvander@1796
   794
				return 0;
dvander@1796
   795
			}
dvander@1796
   796
		}
dvander@1796
   797
	}
dvander@1796
   798
	else if (params[4] == 1)
dvander@1796
   799
	{
dvander@1796
   800
		for (cell_t i = 0; i < params[3]; i++)
dvander@1796
   801
		{
dvander@1796
   802
			if (fwrite(&data[i], sizeof(int8_t), 1, pFile) != 1)
dvander@1796
   803
			{
dvander@1796
   804
				return 0;
dvander@1796
   805
			}
dvander@1796
   806
		}
dvander@1796
   807
	}
dvander@1796
   808
dvander@1796
   809
	return 1;
dvander@1796
   810
}
dvander@1796
   811
dvander@1796
   812
static cell_t sm_WriteFileString(IPluginContext *pContext, const cell_t *params)
dvander@1796
   813
{
dvander@1796
   814
	Handle_t hndl = static_cast<Handle_t>(params[1]);
dvander@1796
   815
	HandleError herr;
dvander@1796
   816
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
dvander@1796
   817
	FILE *pFile;
dvander@1796
   818
dvander@1796
   819
	if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
dvander@1796
   820
		!= HandleError_None)
dvander@1796
   821
	{
dvander@1796
   822
		return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
dvander@1796
   823
	}
dvander@1796
   824
dvander@1796
   825
	char *buffer;
dvander@1796
   826
	pContext->LocalToString(params[2], &buffer);
dvander@1796
   827
dvander@1796
   828
	size_t len = strlen(buffer);
dvander@1796
   829
dvander@1796
   830
	if (params[3])
dvander@1796
   831
	{
dvander@1796
   832
		len++;
dvander@1796
   833
	}
dvander@1796
   834
dvander@1796
   835
	return (fwrite(buffer, sizeof(char), len, pFile) == len) ? 1 : 0;
dvander@1796
   836
}
dvander@1796
   837
dvander@252
   838
REGISTER_NATIVES(filesystem)
dvander@252
   839
{
dvander@252
   840
	{"OpenDirectory",			sm_OpenDirectory},
dvander@252
   841
	{"ReadDirEntry",			sm_ReadDirEntry},
faluco@274
   842
	{"OpenFile",				sm_OpenFile},
faluco@274
   843
	{"DeleteFile",				sm_DeleteFile},
faluco@274
   844
	{"ReadFileLine",			sm_ReadFileLine},
faluco@274
   845
	{"IsEndOfFile",				sm_IsEndOfFile},
faluco@274
   846
	{"FileSeek",				sm_FileSeek},
faluco@274
   847
	{"FilePosition",			sm_FilePosition},
faluco@274
   848
	{"FileExists",				sm_FileExists},
faluco@274
   849
	{"RenameFile",				sm_RenameFile},
faluco@274
   850
	{"DirExists",				sm_DirExists},
faluco@274
   851
	{"FileSize",				sm_FileSize},
faluco@274
   852
	{"RemoveDir",				sm_RemoveDir},
faluco@274
   853
	{"WriteFileLine",			sm_WriteFileLine},
dvander@345
   854
	{"BuildPath",				sm_BuildPath},
dvander@636
   855
	{"LogToGame",				sm_LogToGame},
dvander@636
   856
	{"LogMessage",				sm_LogMessage},
dvander@347
   857
	{"LogError",				sm_LogError},
dvander@821
   858
	{"FlushFile",				sm_FlushFile},
dvander@1370
   859
	{"GetFileTime",				sm_GetFileTime},
dvander@1378
   860
	{"LogToOpenFile",			sm_LogToOpenFile},
dvander@1379
   861
	{"LogToOpenFileEx",			sm_LogToOpenFileEx},
dvander@1796
   862
	{"ReadFile",				sm_ReadFile},
dvander@1796
   863
	{"ReadFileString",			sm_ReadFileString},
dvander@1796
   864
	{"WriteFile",				sm_WriteFile},
dvander@1796
   865
	{"WriteFileString",			sm_WriteFileString},
dvander@252
   866
	{NULL,						NULL},
dvander@252
   867
};