dvander@370: /**
ds@653: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
dvander@1231: * Copyright (C) 2004-2007 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@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@141: FORMAT_MESSAGE_FROM_SYSTEM,
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: }