dvander@370: /**
ds@653: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@370: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1231: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1231: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1231: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@370: *
dvander@370: * Version: $Id$
dvander@370: */
dvander@370:
dvander@1738: #include
dvander@141: #include
dvander@351: #include
dvander@351: #include
dvander@351: #include
dvander@978: #include "sm_stringutil.h"
dvander@141: #include "LibrarySys.h"
dvander@141:
dvander@141: LibrarySystem g_LibSys;
dvander@141:
dvander@141: CLibrary::~CLibrary()
dvander@141: {
dvander@141: if (m_lib)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: FreeLibrary(m_lib);
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: dlclose(m_lib);
dvander@141: #endif
dvander@141: m_lib = NULL;
dvander@141: }
dvander@141: }
dvander@141:
dvander@141: CLibrary::CLibrary(LibraryHandle me)
dvander@141: {
dvander@141: m_lib = me;
dvander@141: }
dvander@141:
dvander@141: void CLibrary::CloseLibrary()
dvander@141: {
dvander@141: delete this;
dvander@141: }
dvander@141:
dvander@141: void *CLibrary::GetSymbolAddress(const char *symname)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: return GetProcAddress(m_lib, symname);
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: return dlsym(m_lib, symname);
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141:
dvander@141: /********************
dvander@141: ** Directory Code **
dvander@141: ********************/
dvander@141:
dvander@141:
dvander@141: CDirectory::CDirectory(const char *path)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: char newpath[PLATFORM_MAX_PATH];
dvander@141: snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
dvander@141: m_dir = FindFirstFileA(newpath, &m_fd);
dvander@141: if (!IsValid())
dvander@141: {
dvander@141: m_fd.cFileName[0] = '\0';
dvander@141: }
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: m_dir = opendir(path);
dvander@141: if (IsValid())
dvander@141: {
dvander@141: /* :TODO: we need to read past "." and ".."! */
dvander@351: ep = readdir(m_dir);
dvander@141: snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
dvander@141: } else {
dvander@141: ep = NULL;
dvander@141: }
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141: CDirectory::~CDirectory()
dvander@141: {
dvander@141: if (IsValid())
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: FindClose(m_dir);
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: closedir(m_dir);
dvander@141: #endif
dvander@141: }
dvander@141: }
dvander@141:
dvander@141: void CDirectory::NextEntry()
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: if (FindNextFile(m_dir, &m_fd) == 0)
dvander@141: {
dvander@141: FindClose(m_dir);
dvander@141: m_dir = INVALID_HANDLE_VALUE;
dvander@141: }
dvander@351: #elif defined PLATFORM_POSIX
dvander@351: if ((ep=readdir(m_dir)) == NULL)
dvander@141: {
dvander@141: closedir(m_dir);
dvander@141: m_dir = NULL;
dvander@141: }
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@252: bool CDirectory::IsEntryValid()
dvander@252: {
dvander@252: return IsValid();
dvander@252: }
dvander@252:
dvander@141: bool CDirectory::IsEntryDirectory()
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
dvander@2471: #elif defined PLATFORM_POSIX
dvander@141: char temppath[PLATFORM_MAX_PATH];
dvander@141: snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
dvander@351: return g_LibSys.IsPathDirectory(temppath);
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141: bool CDirectory::IsEntryFile()
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: char temppath[PLATFORM_MAX_PATH];
dvander@141: snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
dvander@351: return g_LibSys.IsPathFile(temppath);
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141: const char *CDirectory::GetEntryName()
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: return m_fd.cFileName;
dvander@2471: #elif defined PLATFORM_POSIX
dvander@141: return ep ? ep->d_name : "";
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141: bool CDirectory::MoreFiles()
dvander@141: {
dvander@141: return IsValid();
dvander@141: }
dvander@141:
dvander@141: bool CDirectory::IsValid()
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: return (m_dir != INVALID_HANDLE_VALUE);
dvander@2471: #elif defined PLATFORM_POSIX
dvander@141: return (m_dir != NULL);
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141:
dvander@141: /*************************
dvander@141: ** Library System Code **
dvander@141: *************************/
dvander@141:
dvander@141:
dvander@141: bool LibrarySystem::PathExists(const char *path)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: DWORD attr = GetFileAttributesA(path);
dvander@141:
dvander@141: return (attr != INVALID_FILE_ATTRIBUTES);
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: struct stat s;
dvander@141:
dvander@141: return (stat(path, &s) == 0);
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141: bool LibrarySystem::IsPathFile(const char *path)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: DWORD attr = GetFileAttributes(path);
dvander@141:
dvander@141: if (attr == INVALID_FILE_ATTRIBUTES)
dvander@141: {
dvander@141: return false;
dvander@141: }
dvander@141:
dvander@141: if (attr & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
dvander@141: {
dvander@141: return false;
dvander@141: }
dvander@141:
dvander@141: return true;
dvander@2471: #elif defined PLATFORM_POSIX
dvander@141: struct stat s;
dvander@141:
dvander@141: if (stat(path, &s) != 0)
dvander@141: {
dvander@141: return false;
dvander@141: }
dvander@141:
dvander@141: return S_ISREG(s.st_mode) ? true : false;
dvander@141: #endif
dvander@141: }
dvander@141:
dvander@141: bool LibrarySystem::IsPathDirectory(const char *path)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: DWORD attr = GetFileAttributes(path);
dvander@141:
dvander@141: if (attr == INVALID_FILE_ATTRIBUTES)
dvander@141: {
dvander@141: return false;
dvander@141: }
dvander@141:
dvander@141: if (attr & FILE_ATTRIBUTE_DIRECTORY)
dvander@141: {
dvander@141: return true;
dvander@141: }
dvander@141:
ds@3027: #elif defined PLATFORM_POSIX
dvander@141: struct stat s;
dvander@141:
dvander@141: if (stat(path, &s) != 0)
dvander@141: {
dvander@141: return false;
dvander@141: }
dvander@141:
dvander@141: if (S_ISDIR(s.st_mode))
dvander@141: {
dvander@141: return true;
dvander@141: }
dvander@141: #endif
dvander@141:
dvander@141: return false;
dvander@141: }
dvander@141:
dvander@141: IDirectory *LibrarySystem::OpenDirectory(const char *path)
dvander@141: {
dvander@141: CDirectory *dir = new CDirectory(path);
dvander@141:
dvander@141: if (!dir->IsValid())
dvander@141: {
dvander@141: delete dir;
dvander@141: return NULL;
dvander@141: }
dvander@141:
dvander@141: return dir;
dvander@141: }
dvander@141:
ds@755: void LibrarySystem::GetPlatformError(char *error, size_t maxlength)
dvander@141: {
dvander@2474: #if defined PLATFORM_WINDOWS
dvander@2474: return GetPlatformErrorEx(GetLastError(), error, maxlength);
dvander@2474: #elif defined PLATFORM_POSIX
dvander@2474: return GetPlatformErrorEx(errno, error, maxlength);
dvander@2474: #endif
dvander@2474: }
dvander@2474:
dvander@2474: void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
dvander@2474: {
ds@755: if (error && maxlength)
dvander@141: {
dvander@141: #if defined PLATFORM_WINDOWS
dvander@2685: if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
dvander@2685: NULL,
dvander@2685: (DWORD)code,
dvander@2685: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
dvander@2685: (LPSTR)error,
dvander@2685: maxlength,
dvander@2685: NULL) == 0)
dvander@2685: {
dvander@2685: UTIL_Format(error, maxlength, "error code %08x", code);
dvander@2685: }
dvander@2474: #elif defined PLATFORM_LINUX
dvander@2474: const char *ae = strerror_r(code, error, maxlength);
dvander@2474: if (ae != error)
dvander@2474: {
dvander@2474: UTIL_Format(error, maxlength, "%s", ae);
dvander@2474: }
dvander@351: #elif defined PLATFORM_POSIX
dvander@2474: strerror_r(code, error, maxlength);
dvander@141: #endif
dvander@141: }
dvander@141: }
dvander@141:
dvander@1974: void LibrarySystem::GetLoaderError(char *buffer, size_t maxlength)
dvander@1974: {
dvander@1974: #if defined PLATFORM_WINDOWS
dvander@1974: GetPlatformError(buffer, maxlength);
dvander@1974: #elif defined PLATFORM_POSIX
dvander@1974: if (buffer != NULL && maxlength)
dvander@1974: {
dvander@1974: strncopy(buffer, dlerror(), maxlength);
dvander@1974: }
dvander@1974: #endif
dvander@1974: }
dvander@1974:
dvander@141: void LibrarySystem::CloseDirectory(IDirectory *dir)
dvander@141: {
dvander@141: delete dir;
dvander@141: }
dvander@141:
ds@755: ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
dvander@141: {
dvander@141: LibraryHandle lib;
dvander@141: #if defined PLATFORM_WINDOWS
dvander@141: lib = LoadLibraryA(path);
dvander@351: #elif defined PLATFORM_POSIX
dvander@141: lib = dlopen(path, RTLD_NOW);
dvander@1974: #endif
dvander@1974:
dvander@1974: if (lib == NULL)
dvander@141: {
dvander@1974: GetLoaderError(error, maxlength);
dvander@1974: return NULL;
dvander@141: }
dvander@141:
dvander@141: return new CLibrary(lib);
dvander@141: }
dvander@206:
dvander@317: size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
dvander@206: {
dvander@206: va_list ap;
ds@652: va_start(ap, fmt);
dvander@206: size_t mylen = vsnprintf(buffer, len, fmt, ap);
dvander@206: va_end(ap);
dvander@206:
ds@652: if (mylen >= len)
ds@652: {
ds@652: mylen = len - 1;
ds@652: buffer[mylen] = '\0';
ds@652: }
faluco@274:
dvander@206: for (size_t i=0; i