core/systems/LibrarySys.cpp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1231 17badaf66ce4
child 1508 398538bce59b
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

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