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: }