core/systems/LibrarySys.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sun Jul 15 01:04:34 2007 +0000 (2007-07-15)
changeset 1112 152ceef17866
parent 978 54782a83a1ef
child 1192 94ee3f012044
permissions -rw-r--r--
added amb292, optional natives
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@370
     3
 * ===============================================================
dvander@370
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@370
     5
 * ===============================================================
dvander@370
     6
 *
dvander@370
     7
 * This file is not open source and may not be copied without explicit
dvander@370
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@370
     9
 * in whole or significant part.
dvander@370
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@370
    11
 *
dvander@370
    12
 * Version: $Id$
dvander@370
    13
 */
dvander@370
    14
dvander@141
    15
#include <stdio.h>
dvander@351
    16
#include <stdarg.h>
dvander@351
    17
#include <string.h>
dvander@351
    18
#include <sm_platform.h>
dvander@978
    19
#include "sm_stringutil.h"
dvander@141
    20
#include "LibrarySys.h"
dvander@141
    21
dvander@141
    22
LibrarySystem g_LibSys;
dvander@141
    23
dvander@141
    24
CLibrary::~CLibrary()
dvander@141
    25
{
dvander@141
    26
	if (m_lib)
dvander@141
    27
	{
dvander@141
    28
#if defined PLATFORM_WINDOWS
dvander@141
    29
		FreeLibrary(m_lib);
dvander@351
    30
#elif defined PLATFORM_POSIX
dvander@141
    31
		dlclose(m_lib);
dvander@141
    32
#endif
dvander@141
    33
		m_lib = NULL;
dvander@141
    34
	}
dvander@141
    35
}
dvander@141
    36
dvander@141
    37
CLibrary::CLibrary(LibraryHandle me)
dvander@141
    38
{
dvander@141
    39
	m_lib = me;
dvander@141
    40
}
dvander@141
    41
dvander@141
    42
void CLibrary::CloseLibrary()
dvander@141
    43
{
dvander@141
    44
	delete this;
dvander@141
    45
}
dvander@141
    46
dvander@141
    47
void *CLibrary::GetSymbolAddress(const char *symname)
dvander@141
    48
{
dvander@141
    49
#if defined PLATFORM_WINDOWS
dvander@141
    50
	return GetProcAddress(m_lib, symname);
dvander@351
    51
#elif defined PLATFORM_POSIX
dvander@141
    52
	return dlsym(m_lib, symname);
dvander@141
    53
#endif
dvander@141
    54
}
dvander@141
    55
dvander@141
    56
dvander@141
    57
/********************
dvander@141
    58
 ** Directory Code **
dvander@141
    59
 ********************/
dvander@141
    60
dvander@141
    61
dvander@141
    62
CDirectory::CDirectory(const char *path)
dvander@141
    63
{
dvander@141
    64
#if defined PLATFORM_WINDOWS
dvander@141
    65
	char newpath[PLATFORM_MAX_PATH];
dvander@141
    66
	snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
dvander@141
    67
	m_dir = FindFirstFileA(newpath, &m_fd);
dvander@141
    68
	if (!IsValid())
dvander@141
    69
	{
dvander@141
    70
		m_fd.cFileName[0] = '\0';
dvander@141
    71
	}
dvander@351
    72
#elif defined PLATFORM_POSIX
dvander@141
    73
	m_dir = opendir(path);
dvander@141
    74
	if (IsValid())
dvander@141
    75
	{
dvander@141
    76
		/* :TODO: we need to read past "." and ".."! */
dvander@351
    77
		ep = readdir(m_dir);
dvander@141
    78
		snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
dvander@141
    79
	} else {
dvander@141
    80
		ep = NULL;
dvander@141
    81
	}
dvander@141
    82
#endif
dvander@141
    83
}
dvander@141
    84
dvander@141
    85
CDirectory::~CDirectory()
dvander@141
    86
{
dvander@141
    87
	if (IsValid())
dvander@141
    88
	{
dvander@141
    89
#if defined PLATFORM_WINDOWS
dvander@141
    90
		FindClose(m_dir);
dvander@351
    91
#elif defined PLATFORM_POSIX
dvander@141
    92
		closedir(m_dir);
dvander@141
    93
#endif
dvander@141
    94
	}
dvander@141
    95
}
dvander@141
    96
dvander@141
    97
void CDirectory::NextEntry()
dvander@141
    98
{
dvander@141
    99
#if defined PLATFORM_WINDOWS
dvander@141
   100
	if (FindNextFile(m_dir, &m_fd) == 0)
dvander@141
   101
	{
dvander@141
   102
		FindClose(m_dir);
dvander@141
   103
		m_dir = INVALID_HANDLE_VALUE;
dvander@141
   104
	}
dvander@351
   105
#elif defined PLATFORM_POSIX
dvander@351
   106
	if ((ep=readdir(m_dir)) == NULL)
dvander@141
   107
	{
dvander@141
   108
		closedir(m_dir);
dvander@141
   109
		m_dir = NULL;
dvander@141
   110
	}
dvander@141
   111
#endif
dvander@141
   112
}
dvander@141
   113
dvander@252
   114
bool CDirectory::IsEntryValid()
dvander@252
   115
{
dvander@252
   116
	return IsValid();
dvander@252
   117
}
dvander@252
   118
dvander@141
   119
bool CDirectory::IsEntryDirectory()
dvander@141
   120
{
dvander@141
   121
#if defined PLATFORM_WINDOWS
dvander@141
   122
	return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
dvander@351
   123
#elif defined PLATFORM_LINUX
dvander@141
   124
	char temppath[PLATFORM_MAX_PATH];
dvander@141
   125
	snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
dvander@351
   126
	return g_LibSys.IsPathDirectory(temppath);
dvander@141
   127
#endif
dvander@141
   128
}
dvander@141
   129
dvander@141
   130
bool CDirectory::IsEntryFile()
dvander@141
   131
{
dvander@141
   132
#if defined PLATFORM_WINDOWS
dvander@141
   133
	return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
dvander@351
   134
#elif defined PLATFORM_POSIX
dvander@141
   135
	char temppath[PLATFORM_MAX_PATH];
dvander@141
   136
	snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
dvander@351
   137
	return g_LibSys.IsPathFile(temppath);
dvander@141
   138
#endif
dvander@141
   139
}
dvander@141
   140
dvander@141
   141
const char *CDirectory::GetEntryName()
dvander@141
   142
{
dvander@141
   143
#if defined PLATFORM_WINDOWS
dvander@141
   144
	return m_fd.cFileName;
dvander@351
   145
#elif defined PLATFORM_LINUX
dvander@141
   146
	return ep ? ep->d_name : "";
dvander@141
   147
#endif
dvander@141
   148
}
dvander@141
   149
dvander@141
   150
bool CDirectory::MoreFiles()
dvander@141
   151
{
dvander@141
   152
	return IsValid();
dvander@141
   153
}
dvander@141
   154
dvander@141
   155
bool CDirectory::IsValid()
dvander@141
   156
{
dvander@141
   157
#if defined PLATFORM_WINDOWS
dvander@141
   158
	return (m_dir != INVALID_HANDLE_VALUE);
dvander@351
   159
#elif defined PLATFORM_LINUX
dvander@141
   160
	return (m_dir != NULL);
dvander@141
   161
#endif
dvander@141
   162
}
dvander@141
   163
dvander@141
   164
dvander@141
   165
/*************************
dvander@141
   166
 ** Library System Code **
dvander@141
   167
 *************************/
dvander@141
   168
dvander@141
   169
dvander@141
   170
bool LibrarySystem::PathExists(const char *path)
dvander@141
   171
{
dvander@141
   172
#if defined PLATFORM_WINDOWS
dvander@141
   173
	DWORD attr = GetFileAttributesA(path);
dvander@141
   174
dvander@141
   175
	return (attr != INVALID_FILE_ATTRIBUTES);
dvander@351
   176
#elif defined PLATFORM_POSIX
dvander@141
   177
	struct stat s;
dvander@141
   178
dvander@141
   179
	return (stat(path, &s) == 0);
dvander@141
   180
#endif
dvander@141
   181
}
dvander@141
   182
dvander@141
   183
bool LibrarySystem::IsPathFile(const char *path)
dvander@141
   184
{
dvander@141
   185
#if defined PLATFORM_WINDOWS
dvander@141
   186
	DWORD attr = GetFileAttributes(path);
dvander@141
   187
dvander@141
   188
	if (attr == INVALID_FILE_ATTRIBUTES)
dvander@141
   189
	{
dvander@141
   190
		return false;
dvander@141
   191
	}
dvander@141
   192
dvander@141
   193
	if (attr & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
dvander@141
   194
	{
dvander@141
   195
		return false;
dvander@141
   196
	}
dvander@141
   197
dvander@141
   198
	return true;
dvander@351
   199
#elif defined PLATFORM_LINUX
dvander@141
   200
	struct stat s;
dvander@141
   201
dvander@141
   202
	if (stat(path, &s) != 0)
dvander@141
   203
	{
dvander@141
   204
		return false;
dvander@141
   205
	}
dvander@141
   206
dvander@141
   207
	return S_ISREG(s.st_mode) ? true : false;
dvander@141
   208
#endif
dvander@141
   209
}
dvander@141
   210
dvander@141
   211
bool LibrarySystem::IsPathDirectory(const char *path)
dvander@141
   212
{
dvander@141
   213
#if defined PLATFORM_WINDOWS
dvander@141
   214
	DWORD attr = GetFileAttributes(path);
dvander@141
   215
dvander@141
   216
	if (attr == INVALID_FILE_ATTRIBUTES)
dvander@141
   217
	{
dvander@141
   218
		return false;
dvander@141
   219
	}
dvander@141
   220
dvander@141
   221
	if (attr & FILE_ATTRIBUTE_DIRECTORY)
dvander@141
   222
	{
dvander@141
   223
		return true;
dvander@141
   224
	}
dvander@141
   225
dvander@351
   226
#elif defined PLATFORM_LINUX
dvander@141
   227
	struct stat s;
dvander@141
   228
dvander@141
   229
	if (stat(path, &s) != 0)
dvander@141
   230
	{
dvander@141
   231
		return false;
dvander@141
   232
	}
dvander@141
   233
dvander@141
   234
	if (S_ISDIR(s.st_mode))
dvander@141
   235
	{
dvander@141
   236
		return true;
dvander@141
   237
	}
dvander@141
   238
#endif
dvander@141
   239
dvander@141
   240
	return false;
dvander@141
   241
}
dvander@141
   242
dvander@141
   243
IDirectory *LibrarySystem::OpenDirectory(const char *path)
dvander@141
   244
{
dvander@141
   245
	CDirectory *dir = new CDirectory(path);
dvander@141
   246
dvander@141
   247
	if (!dir->IsValid())
dvander@141
   248
	{
dvander@141
   249
		delete dir;
dvander@141
   250
		return NULL;
dvander@141
   251
	}
dvander@141
   252
dvander@141
   253
	return dir;
dvander@141
   254
}
dvander@141
   255
ds@755
   256
void LibrarySystem::GetPlatformError(char *error, size_t maxlength)
dvander@141
   257
{
ds@755
   258
	if (error && maxlength)
dvander@141
   259
	{
dvander@141
   260
#if defined PLATFORM_WINDOWS
dvander@141
   261
		DWORD dw = GetLastError();
dvander@141
   262
		FormatMessageA(
dvander@141
   263
			FORMAT_MESSAGE_FROM_SYSTEM,
dvander@141
   264
			NULL,
dvander@141
   265
			dw,
dvander@141
   266
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
dvander@141
   267
			(LPSTR)error,
ds@755
   268
			maxlength,
dvander@141
   269
			NULL);
dvander@351
   270
#elif defined PLATFORM_POSIX
ds@755
   271
		snprintf(error, maxlength, "%s", strerror(errno));
dvander@141
   272
#endif
dvander@141
   273
	}
dvander@141
   274
}
dvander@141
   275
dvander@141
   276
void LibrarySystem::CloseDirectory(IDirectory *dir)
dvander@141
   277
{
dvander@141
   278
	delete dir;
dvander@141
   279
}
dvander@141
   280
ds@755
   281
ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
dvander@141
   282
{
dvander@141
   283
	LibraryHandle lib;
dvander@141
   284
#if defined PLATFORM_WINDOWS
dvander@141
   285
	lib = LoadLibraryA(path);
dvander@141
   286
	if (!lib)
dvander@141
   287
	{
ds@755
   288
		GetPlatformError(error, maxlength);
dvander@141
   289
		return false;
dvander@141
   290
	}
dvander@351
   291
#elif defined PLATFORM_POSIX
dvander@141
   292
	lib = dlopen(path, RTLD_NOW);
dvander@141
   293
	if (!lib)
dvander@141
   294
	{
ds@755
   295
		GetPlatformError(error, maxlength);
dvander@141
   296
		return false;
dvander@141
   297
	}
dvander@141
   298
#endif
dvander@141
   299
dvander@141
   300
	return new CLibrary(lib);
dvander@141
   301
}
dvander@206
   302
dvander@317
   303
size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
dvander@206
   304
{
dvander@206
   305
	va_list ap;
ds@652
   306
	va_start(ap, fmt);
dvander@206
   307
	size_t mylen = vsnprintf(buffer, len, fmt, ap);
dvander@206
   308
	va_end(ap);
dvander@206
   309
ds@652
   310
	if (mylen >= len)
ds@652
   311
	{
ds@652
   312
		mylen = len - 1;
ds@652
   313
		buffer[mylen] = '\0';
ds@652
   314
	}
faluco@274
   315
dvander@206
   316
	for (size_t i=0; i<mylen; i++)
dvander@206
   317
	{
dvander@206
   318
		if (buffer[i] == PLATFORM_SEP_ALTCHAR)
dvander@206
   319
		{
dvander@206
   320
			buffer[i] = PLATFORM_SEP_CHAR;
dvander@206
   321
		}
dvander@206
   322
	}
dvander@317
   323
dvander@317
   324
	return mylen;
dvander@206
   325
}
ds@794
   326
ds@794
   327
const char *LibrarySystem::GetFileExtension(const char *filename)
ds@794
   328
{
ds@829
   329
	size_t end = strlen(filename) - 1;
ds@794
   330
ds@829
   331
	for (size_t i = end; i >= 0; i--)
ds@794
   332
	{
ds@829
   333
		if (i > end)
ds@829
   334
		{
ds@829
   335
			break;
ds@829
   336
		}
ds@829
   337
ds@794
   338
		if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
ds@794
   339
		{
ds@829
   340
			break;
ds@794
   341
		}
ds@794
   342
ds@829
   343
		if (filename[i] == '.' && i != end)
ds@794
   344
		{
ds@794
   345
			return &filename[++i];
ds@794
   346
		}
ds@794
   347
	}
ds@794
   348
ds@794
   349
	return NULL;
ds@794
   350
}
dvander@978
   351
dvander@978
   352
bool LibrarySystem::CreateDirectory(const char *path)
dvander@978
   353
{
dvander@978
   354
#if defined PLATFORM_WINDOWS
dvander@978
   355
	return (mkdir(path) != -1);
dvander@978
   356
#elif defined PLATFORM_POSIX
dvander@978
   357
	return (mkdir(path, 0775) != -1);
dvander@978
   358
#endif
dvander@978
   359
}
dvander@978
   360
dvander@978
   361
size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char *path)
dvander@978
   362
{
dvander@978
   363
	size_t length = strlen(path);
dvander@978
   364
dvander@978
   365
	for (size_t i = length - 1;
dvander@978
   366
		 i >= 0 && i <= length - 1;
dvander@978
   367
		 i++)
dvander@978
   368
	{
dvander@978
   369
		if (path[i] == '/' 
dvander@978
   370
#if defined PLATFORM_WINDOWS
dvander@978
   371
			|| path[i] == '\\'
dvander@978
   372
#endif
dvander@978
   373
			)
dvander@978
   374
		{
dvander@978
   375
			return UTIL_Format(buffer, maxlength, "%s", &path[i+1]);
dvander@978
   376
		}
dvander@978
   377
	}
dvander@978
   378
dvander@978
   379
	/* We scanned and found no path separator */
dvander@978
   380
	return UTIL_Format(buffer, maxlength, "%s", path);
dvander@978
   381
}