core/systems/LibrarySys.cpp
author Scott Ehlert <ds@alliedmods.net>
Tue May 22 03:39:18 2007 +0000 (2007-05-22)
changeset 829 3746e673414e
parent 794 5947b0ee60bb
child 978 54782a83a1ef
permissions -rw-r--r--
Wow, how did this go unnoticed:
Fixed ILibrarySys::GetFileExtension() and loading plugins without the "smx" extension.
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@141
    19
#include "LibrarySys.h"
dvander@141
    20
dvander@141
    21
LibrarySystem g_LibSys;
dvander@141
    22
dvander@141
    23
CLibrary::~CLibrary()
dvander@141
    24
{
dvander@141
    25
	if (m_lib)
dvander@141
    26
	{
dvander@141
    27
#if defined PLATFORM_WINDOWS
dvander@141
    28
		FreeLibrary(m_lib);
dvander@351
    29
#elif defined PLATFORM_POSIX
dvander@141
    30
		dlclose(m_lib);
dvander@141
    31
#endif
dvander@141
    32
		m_lib = NULL;
dvander@141
    33
	}
dvander@141
    34
}
dvander@141
    35
dvander@141
    36
CLibrary::CLibrary(LibraryHandle me)
dvander@141
    37
{
dvander@141
    38
	m_lib = me;
dvander@141
    39
}
dvander@141
    40
dvander@141
    41
void CLibrary::CloseLibrary()
dvander@141
    42
{
dvander@141
    43
	delete this;
dvander@141
    44
}
dvander@141
    45
dvander@141
    46
void *CLibrary::GetSymbolAddress(const char *symname)
dvander@141
    47
{
dvander@141
    48
#if defined PLATFORM_WINDOWS
dvander@141
    49
	return GetProcAddress(m_lib, symname);
dvander@351
    50
#elif defined PLATFORM_POSIX
dvander@141
    51
	return dlsym(m_lib, symname);
dvander@141
    52
#endif
dvander@141
    53
}
dvander@141
    54
dvander@141
    55
dvander@141
    56
/********************
dvander@141
    57
 ** Directory Code **
dvander@141
    58
 ********************/
dvander@141
    59
dvander@141
    60
dvander@141
    61
CDirectory::CDirectory(const char *path)
dvander@141
    62
{
dvander@141
    63
#if defined PLATFORM_WINDOWS
dvander@141
    64
	char newpath[PLATFORM_MAX_PATH];
dvander@141
    65
	snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
dvander@141
    66
	m_dir = FindFirstFileA(newpath, &m_fd);
dvander@141
    67
	if (!IsValid())
dvander@141
    68
	{
dvander@141
    69
		m_fd.cFileName[0] = '\0';
dvander@141
    70
	}
dvander@351
    71
#elif defined PLATFORM_POSIX
dvander@141
    72
	m_dir = opendir(path);
dvander@141
    73
	if (IsValid())
dvander@141
    74
	{
dvander@141
    75
		/* :TODO: we need to read past "." and ".."! */
dvander@351
    76
		ep = readdir(m_dir);
dvander@141
    77
		snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
dvander@141
    78
	} else {
dvander@141
    79
		ep = NULL;
dvander@141
    80
	}
dvander@141
    81
#endif
dvander@141
    82
}
dvander@141
    83
dvander@141
    84
CDirectory::~CDirectory()
dvander@141
    85
{
dvander@141
    86
	if (IsValid())
dvander@141
    87
	{
dvander@141
    88
#if defined PLATFORM_WINDOWS
dvander@141
    89
		FindClose(m_dir);
dvander@351
    90
#elif defined PLATFORM_POSIX
dvander@141
    91
		closedir(m_dir);
dvander@141
    92
#endif
dvander@141
    93
	}
dvander@141
    94
}
dvander@141
    95
dvander@141
    96
void CDirectory::NextEntry()
dvander@141
    97
{
dvander@141
    98
#if defined PLATFORM_WINDOWS
dvander@141
    99
	if (FindNextFile(m_dir, &m_fd) == 0)
dvander@141
   100
	{
dvander@141
   101
		FindClose(m_dir);
dvander@141
   102
		m_dir = INVALID_HANDLE_VALUE;
dvander@141
   103
	}
dvander@351
   104
#elif defined PLATFORM_POSIX
dvander@351
   105
	if ((ep=readdir(m_dir)) == NULL)
dvander@141
   106
	{
dvander@141
   107
		closedir(m_dir);
dvander@141
   108
		m_dir = NULL;
dvander@141
   109
	}
dvander@141
   110
#endif
dvander@141
   111
}
dvander@141
   112
dvander@252
   113
bool CDirectory::IsEntryValid()
dvander@252
   114
{
dvander@252
   115
	return IsValid();
dvander@252
   116
}
dvander@252
   117
dvander@141
   118
bool CDirectory::IsEntryDirectory()
dvander@141
   119
{
dvander@141
   120
#if defined PLATFORM_WINDOWS
dvander@141
   121
	return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
dvander@351
   122
#elif defined PLATFORM_LINUX
dvander@141
   123
	char temppath[PLATFORM_MAX_PATH];
dvander@141
   124
	snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
dvander@351
   125
	return g_LibSys.IsPathDirectory(temppath);
dvander@141
   126
#endif
dvander@141
   127
}
dvander@141
   128
dvander@141
   129
bool CDirectory::IsEntryFile()
dvander@141
   130
{
dvander@141
   131
#if defined PLATFORM_WINDOWS
dvander@141
   132
	return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
dvander@351
   133
#elif defined PLATFORM_POSIX
dvander@141
   134
	char temppath[PLATFORM_MAX_PATH];
dvander@141
   135
	snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
dvander@351
   136
	return g_LibSys.IsPathFile(temppath);
dvander@141
   137
#endif
dvander@141
   138
}
dvander@141
   139
dvander@141
   140
const char *CDirectory::GetEntryName()
dvander@141
   141
{
dvander@141
   142
#if defined PLATFORM_WINDOWS
dvander@141
   143
	return m_fd.cFileName;
dvander@351
   144
#elif defined PLATFORM_LINUX
dvander@141
   145
	return ep ? ep->d_name : "";
dvander@141
   146
#endif
dvander@141
   147
}
dvander@141
   148
dvander@141
   149
bool CDirectory::MoreFiles()
dvander@141
   150
{
dvander@141
   151
	return IsValid();
dvander@141
   152
}
dvander@141
   153
dvander@141
   154
bool CDirectory::IsValid()
dvander@141
   155
{
dvander@141
   156
#if defined PLATFORM_WINDOWS
dvander@141
   157
	return (m_dir != INVALID_HANDLE_VALUE);
dvander@351
   158
#elif defined PLATFORM_LINUX
dvander@141
   159
	return (m_dir != NULL);
dvander@141
   160
#endif
dvander@141
   161
}
dvander@141
   162
dvander@141
   163
dvander@141
   164
/*************************
dvander@141
   165
 ** Library System Code **
dvander@141
   166
 *************************/
dvander@141
   167
dvander@141
   168
dvander@141
   169
bool LibrarySystem::PathExists(const char *path)
dvander@141
   170
{
dvander@141
   171
#if defined PLATFORM_WINDOWS
dvander@141
   172
	DWORD attr = GetFileAttributesA(path);
dvander@141
   173
dvander@141
   174
	return (attr != INVALID_FILE_ATTRIBUTES);
dvander@351
   175
#elif defined PLATFORM_POSIX
dvander@141
   176
	struct stat s;
dvander@141
   177
dvander@141
   178
	return (stat(path, &s) == 0);
dvander@141
   179
#endif
dvander@141
   180
}
dvander@141
   181
dvander@141
   182
bool LibrarySystem::IsPathFile(const char *path)
dvander@141
   183
{
dvander@141
   184
#if defined PLATFORM_WINDOWS
dvander@141
   185
	DWORD attr = GetFileAttributes(path);
dvander@141
   186
dvander@141
   187
	if (attr == INVALID_FILE_ATTRIBUTES)
dvander@141
   188
	{
dvander@141
   189
		return false;
dvander@141
   190
	}
dvander@141
   191
dvander@141
   192
	if (attr & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
dvander@141
   193
	{
dvander@141
   194
		return false;
dvander@141
   195
	}
dvander@141
   196
dvander@141
   197
	return true;
dvander@351
   198
#elif defined PLATFORM_LINUX
dvander@141
   199
	struct stat s;
dvander@141
   200
dvander@141
   201
	if (stat(path, &s) != 0)
dvander@141
   202
	{
dvander@141
   203
		return false;
dvander@141
   204
	}
dvander@141
   205
dvander@141
   206
	return S_ISREG(s.st_mode) ? true : false;
dvander@141
   207
#endif
dvander@141
   208
}
dvander@141
   209
dvander@141
   210
bool LibrarySystem::IsPathDirectory(const char *path)
dvander@141
   211
{
dvander@141
   212
#if defined PLATFORM_WINDOWS
dvander@141
   213
	DWORD attr = GetFileAttributes(path);
dvander@141
   214
dvander@141
   215
	if (attr == INVALID_FILE_ATTRIBUTES)
dvander@141
   216
	{
dvander@141
   217
		return false;
dvander@141
   218
	}
dvander@141
   219
dvander@141
   220
	if (attr & FILE_ATTRIBUTE_DIRECTORY)
dvander@141
   221
	{
dvander@141
   222
		return true;
dvander@141
   223
	}
dvander@141
   224
dvander@351
   225
#elif defined PLATFORM_LINUX
dvander@141
   226
	struct stat s;
dvander@141
   227
dvander@141
   228
	if (stat(path, &s) != 0)
dvander@141
   229
	{
dvander@141
   230
		return false;
dvander@141
   231
	}
dvander@141
   232
dvander@141
   233
	if (S_ISDIR(s.st_mode))
dvander@141
   234
	{
dvander@141
   235
		return true;
dvander@141
   236
	}
dvander@141
   237
#endif
dvander@141
   238
dvander@141
   239
	return false;
dvander@141
   240
}
dvander@141
   241
dvander@141
   242
IDirectory *LibrarySystem::OpenDirectory(const char *path)
dvander@141
   243
{
dvander@141
   244
	CDirectory *dir = new CDirectory(path);
dvander@141
   245
dvander@141
   246
	if (!dir->IsValid())
dvander@141
   247
	{
dvander@141
   248
		delete dir;
dvander@141
   249
		return NULL;
dvander@141
   250
	}
dvander@141
   251
dvander@141
   252
	return dir;
dvander@141
   253
}
dvander@141
   254
ds@755
   255
void LibrarySystem::GetPlatformError(char *error, size_t maxlength)
dvander@141
   256
{
ds@755
   257
	if (error && maxlength)
dvander@141
   258
	{
dvander@141
   259
#if defined PLATFORM_WINDOWS
dvander@141
   260
		DWORD dw = GetLastError();
dvander@141
   261
		FormatMessageA(
dvander@141
   262
			FORMAT_MESSAGE_FROM_SYSTEM,
dvander@141
   263
			NULL,
dvander@141
   264
			dw,
dvander@141
   265
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
dvander@141
   266
			(LPSTR)error,
ds@755
   267
			maxlength,
dvander@141
   268
			NULL);
dvander@351
   269
#elif defined PLATFORM_POSIX
ds@755
   270
		snprintf(error, maxlength, "%s", strerror(errno));
dvander@141
   271
#endif
dvander@141
   272
	}
dvander@141
   273
}
dvander@141
   274
dvander@141
   275
void LibrarySystem::CloseDirectory(IDirectory *dir)
dvander@141
   276
{
dvander@141
   277
	delete dir;
dvander@141
   278
}
dvander@141
   279
ds@755
   280
ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
dvander@141
   281
{
dvander@141
   282
	LibraryHandle lib;
dvander@141
   283
#if defined PLATFORM_WINDOWS
dvander@141
   284
	lib = LoadLibraryA(path);
dvander@141
   285
	if (!lib)
dvander@141
   286
	{
ds@755
   287
		GetPlatformError(error, maxlength);
dvander@141
   288
		return false;
dvander@141
   289
	}
dvander@351
   290
#elif defined PLATFORM_POSIX
dvander@141
   291
	lib = dlopen(path, RTLD_NOW);
dvander@141
   292
	if (!lib)
dvander@141
   293
	{
ds@755
   294
		GetPlatformError(error, maxlength);
dvander@141
   295
		return false;
dvander@141
   296
	}
dvander@141
   297
#endif
dvander@141
   298
dvander@141
   299
	return new CLibrary(lib);
dvander@141
   300
}
dvander@206
   301
dvander@317
   302
size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
dvander@206
   303
{
dvander@206
   304
	va_list ap;
ds@652
   305
	va_start(ap, fmt);
dvander@206
   306
	size_t mylen = vsnprintf(buffer, len, fmt, ap);
dvander@206
   307
	va_end(ap);
dvander@206
   308
ds@652
   309
	if (mylen >= len)
ds@652
   310
	{
ds@652
   311
		mylen = len - 1;
ds@652
   312
		buffer[mylen] = '\0';
ds@652
   313
	}
faluco@274
   314
dvander@206
   315
	for (size_t i=0; i<mylen; i++)
dvander@206
   316
	{
dvander@206
   317
		if (buffer[i] == PLATFORM_SEP_ALTCHAR)
dvander@206
   318
		{
dvander@206
   319
			buffer[i] = PLATFORM_SEP_CHAR;
dvander@206
   320
		}
dvander@206
   321
	}
dvander@317
   322
dvander@317
   323
	return mylen;
dvander@206
   324
}
ds@794
   325
ds@794
   326
const char *LibrarySystem::GetFileExtension(const char *filename)
ds@794
   327
{
ds@829
   328
	size_t end = strlen(filename) - 1;
ds@794
   329
ds@829
   330
	for (size_t i = end; i >= 0; i--)
ds@794
   331
	{
ds@829
   332
		if (i > end)
ds@829
   333
		{
ds@829
   334
			break;
ds@829
   335
		}
ds@829
   336
ds@794
   337
		if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
ds@794
   338
		{
ds@829
   339
			break;
ds@794
   340
		}
ds@794
   341
ds@829
   342
		if (filename[i] == '.' && i != end)
ds@794
   343
		{
ds@794
   344
			return &filename[++i];
ds@794
   345
		}
ds@794
   346
	}
ds@794
   347
ds@794
   348
	return NULL;
ds@794
   349
}