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@351: #elif defined PLATFORM_LINUX 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@351: #elif defined PLATFORM_LINUX 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@351: #elif defined PLATFORM_LINUX 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@351: #elif defined PLATFORM_LINUX 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: dvander@351: #elif defined PLATFORM_LINUX 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: { ds@755: if (error && maxlength) dvander@141: { dvander@141: #if defined PLATFORM_WINDOWS dvander@141: DWORD dw = GetLastError(); dvander@141: FormatMessageA( dvander@1814: FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, dvander@141: NULL, dvander@141: dw, dvander@141: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), dvander@141: (LPSTR)error, ds@755: maxlength, dvander@141: NULL); dvander@351: #elif defined PLATFORM_POSIX ds@755: snprintf(error, maxlength, "%s", strerror(errno)); dvander@141: #endif dvander@141: } dvander@141: } dvander@141: 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@141: if (!lib) dvander@141: { ds@755: GetPlatformError(error, maxlength); dvander@141: return false; dvander@141: } dvander@351: #elif defined PLATFORM_POSIX dvander@141: lib = dlopen(path, RTLD_NOW); dvander@141: if (!lib) dvander@141: { ds@755: GetPlatformError(error, maxlength); dvander@141: return false; dvander@141: } dvander@141: #endif 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= 0; i--) ds@794: { ds@829: if (i > end) ds@829: { ds@829: break; ds@829: } ds@829: ds@794: if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR) ds@794: { ds@829: break; ds@794: } ds@794: ds@829: if (filename[i] == '.' && i != end) ds@794: { ds@794: return &filename[++i]; ds@794: } ds@794: } ds@794: ds@794: return NULL; ds@794: } dvander@978: dvander@1192: bool LibrarySystem::CreateFolder(const char *path) dvander@978: { dvander@978: #if defined PLATFORM_WINDOWS dvander@978: return (mkdir(path) != -1); dvander@978: #elif defined PLATFORM_POSIX dvander@978: return (mkdir(path, 0775) != -1); dvander@978: #endif dvander@978: } dvander@978: dvander@978: size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char *path) dvander@978: { dvander@978: size_t length = strlen(path); dvander@978: dvander@978: for (size_t i = length - 1; dvander@978: i >= 0 && i <= length - 1; dvander@1508: i--) dvander@978: { dvander@978: if (path[i] == '/' dvander@978: #if defined PLATFORM_WINDOWS dvander@978: || path[i] == '\\' dvander@978: #endif dvander@978: ) dvander@978: { dvander@978: return UTIL_Format(buffer, maxlength, "%s", &path[i+1]); dvander@978: } dvander@978: } dvander@978: dvander@978: /* We scanned and found no path separator */ dvander@978: return UTIL_Format(buffer, maxlength, "%s", path); dvander@978: } dvander@1738: dvander@1738: bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime) dvander@1738: { dvander@1738: #ifdef PLATFORM_WINDOWS dvander@1738: struct _stat s; dvander@1738: if (_stat(path, &s) != 0) dvander@1738: #elif defined PLATFORM_POSIX dvander@1738: struct stat s; dvander@1738: if (stat(path, &s) != 0) dvander@1738: #endif dvander@1738: { dvander@1738: return false; dvander@1738: } dvander@1738: dvander@1738: if (type == FileTime_LastAccess) dvander@1738: { dvander@1738: *pTime = s.st_atime; dvander@1738: } dvander@1738: else if (type == FileTime_Created) dvander@1738: { dvander@1738: *pTime = s.st_ctime; dvander@1738: } dvander@1738: else if (type == FileTime_LastChange) dvander@1738: { dvander@1738: *pTime = s.st_mtime; dvander@1738: } dvander@1738: dvander@1738: return true; dvander@1738: }