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