2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-03-26 04:09:14 +03:00

254 lines
6.3 KiB
C
Raw Normal View History

2016-07-26 23:31:47 +07:00
#pragma once
2016-07-04 12:07:29 +06:00
// Various differences between WIN32 and Linux.
2016-07-30 02:03:01 +03:00
#include "types_meta.h" // bool
2016-07-26 23:31:47 +07:00
#include "mreg.h" // REG_CMD_FN, etc
2016-07-04 12:07:29 +06:00
#include "log_meta.h" // LOG_ERROR, etc
// String describing platform/DLL-type, for matching lines in plugins.ini.
2016-07-26 07:22:47 +07:00
#ifdef _WIN32
2016-07-26 23:31:47 +07:00
#define UNUSED /**/
2016-07-26 23:31:47 +07:00
#define PLATFORM "mswin"
#define PLATFORM_SPC "win32"
#define PLATFORM_DLEXT ".dll"
#else
#define UNUSED __attribute__((unused))
2016-07-26 23:31:47 +07:00
#define PLATFORM "linux"
#define PLATFORM_SPC "lin32"
#define PLATFORM_DLEXT ".so"
#endif
2016-07-30 02:03:01 +03:00
extern bool dlclose_handle_invalid;
2016-07-04 12:07:29 +06:00
// Functions & types for DLL open/close/etc operations.
2016-07-26 23:31:47 +07:00
#ifdef _WIN32
typedef HINSTANCE DLHANDLE;
typedef FARPROC DLFUNC;
inline DLHANDLE DLOPEN(const char *filename)
{
return LoadLibraryA(filename);
}
2016-07-26 23:31:47 +07:00
inline DLFUNC DLSYM(DLHANDLE handle, const char *string)
{
return GetProcAddress(handle, string);
}
2016-07-26 23:31:47 +07:00
inline int DLCLOSE(DLHANDLE handle)
{
if (!handle)
{
2016-07-30 02:03:01 +03:00
dlclose_handle_invalid = true;
2016-07-26 23:31:47 +07:00
return 1;
}
2016-07-26 23:31:47 +07:00
2016-07-30 02:03:01 +03:00
dlclose_handle_invalid = false;
2016-07-26 23:31:47 +07:00
// NOTE: Windows FreeLibrary returns success=nonzero, fail=zero,
// which is the opposite of the unix convention, thus the '!'.
return !FreeLibrary(handle);
}
2016-07-26 23:31:47 +07:00
// Windows doesn't provide a function corresponding to dlerror(), so
// we make our own.
const char *str_GetLastError();
inline const char *DLERROR()
{
if (dlclose_handle_invalid)
2016-07-26 23:31:47 +07:00
return "Invalid handle.";
return str_GetLastError();
}
2016-07-26 23:31:47 +07:00
#else
typedef void *DLHANDLE;
typedef void *DLFUNC;
inline DLHANDLE DLOPEN(const char *filename)
{
return dlopen(filename, RTLD_NOW);
}
2016-07-26 23:31:47 +07:00
inline DLFUNC DLSYM(DLHANDLE handle, const char *string)
{
return dlsym(handle, string);
}
2016-07-26 23:31:47 +07:00
// dlclose crashes if handle is null.
inline int DLCLOSE(DLHANDLE handle)
{
if (!handle)
{
2016-07-30 02:03:01 +03:00
dlclose_handle_invalid = true;
2016-07-26 23:31:47 +07:00
return 1;
2016-07-04 12:07:29 +06:00
}
2016-07-30 02:03:01 +03:00
dlclose_handle_invalid = false;
2016-07-26 23:31:47 +07:00
return dlclose(handle);
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
inline const char *DLERROR()
{
2016-07-26 07:22:47 +07:00
if (dlclose_handle_invalid)
2016-07-26 23:31:47 +07:00
return "Invalid handle.";
return dlerror();
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
#endif
2016-07-26 07:22:47 +07:00
const char *DLFNAME(void *memptr);
2016-07-30 02:03:01 +03:00
bool IS_VALID_PTR(void *memptr);
2016-07-04 12:07:29 +06:00
// Attempt to call the given function pointer, without segfaulting.
2016-07-30 02:03:01 +03:00
bool os_safe_call(REG_CMD_FN pfn);
2016-07-04 12:07:29 +06:00
// Windows doesn't have an strtok_r() routine, so we write our own.
#ifdef _WIN32
#define strtok_r(s, delim, ptrptr) my_strtok_r(s, delim, ptrptr)
2016-07-26 07:22:47 +07:00
char *my_strtok_r(char *s, const char *delim, char **ptrptr);
2016-07-26 23:31:47 +07:00
#else
// Linux doesn't have an strlwr() routine, so we write our own.
#define strlwr(s) my_strlwr(s)
char *my_strlwr(char *s);
#endif // _WIN32
2016-07-04 12:07:29 +06:00
// Set filename and pathname maximum lengths. Note some windows compilers
// provide a <limits.h> which is incomplete and/or causes problems; see
// doc/windows_notes.txt for more information.
//
// Note that both OS's include room for null-termination:
// linux: "# chars in a path name including nul"
// win32: "note that the sizes include space for 0-terminator"
#if defined(__linux) || defined(__APPLE__)
2016-07-04 12:07:29 +06:00
#include <limits.h>
#elif defined(_WIN32)
#include <stdlib.h>
#define NAME_MAX _MAX_FNAME
#define PATH_MAX _MAX_PATH
2016-07-26 23:31:47 +07:00
#endif // _WIN32
2016-07-04 12:07:29 +06:00
// Various other windows routine differences.
#if defined(__linux) || defined(__APPLE__)
2016-07-04 12:07:29 +06:00
#include <unistd.h> // sleep
#ifndef O_BINARY
#define O_BINARY 0
2016-07-26 23:31:47 +07:00
#endif
2016-07-04 12:07:29 +06:00
#elif defined(_WIN32)
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define sleep(x) Sleep(x*1000)
#include <io.h>
#define open _open
#define read _read
#define write _write
#define close _close
2016-07-26 23:31:47 +07:00
#endif // _WIN32
#ifdef __GNUC__
#include <unistd.h> // _getcwd
#elif defined(_MSC_VER)
#include <direct.h> // _getcwd
#endif /* _MSC_VER */
2016-07-04 12:07:29 +06:00
#include <sys/stat.h>
#ifndef S_ISREG
// Linux gcc defines this; earlier mingw didn't, later mingw does;
// MSVC doesn't seem to.
#define S_ISREG(m) ((m) & S_IFREG)
#endif /* not S_ISREG */
#ifdef _WIN32
// The following two are defined in mingw but not in MSVC
#ifndef S_IRUSR
#define S_IRUSR _S_IREAD
#endif
#ifndef S_IWUSR
#define S_IWUSR _S_IWRITE
#endif
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
// The following two are defined neither in mingw nor in MSVC
#ifndef S_IRGRP
#define S_IRGRP S_IRUSR
#endif
#ifndef S_IWGRP
#define S_IWGRP S_IWUSR
#endif
2016-07-26 23:31:47 +07:00
#endif // _WIN32
2016-07-04 12:07:29 +06:00
// Normalize/standardize a pathname.
// - For win32, this involves:
// - Turning backslashes (\) into slashes (/), so that config files and
// Metamod internal code can be simpler and just use slashes (/).
// - Turning upper/mixed case into lowercase, since windows is
// non-case-sensitive.
// - For linux, this requires no work, as paths uses slashes (/) natively,
// and pathnames are case-sensitive.
#if defined(__linux) || defined(__APPLE__)
2016-07-04 12:07:29 +06:00
#define normalize_pathname(a)
#elif defined(_WIN32)
2016-07-26 23:31:47 +07:00
inline void normalize_pathname(char *path)
{
char *cp;
META_DEBUG(8, ("normalize: %s", path));
2016-07-26 23:31:47 +07:00
for (cp = path; *cp; cp++)
{
if (isupper(*cp)) *cp = tolower(*cp);
if (*cp == '\\') *cp = '/';
}
2016-07-26 23:31:47 +07:00
META_DEBUG(8, ("normalized: %s", path));
}
2016-07-26 23:31:47 +07:00
#endif // _WIN32
2016-07-04 12:07:29 +06:00
// Indicate if pathname appears to be an absolute-path. Under linux this
// is a leading slash (/). Under win32, this can be:
// - a drive-letter path (ie "D:blah" or "C:\blah")
// - a toplevel path (ie "\blah")
// - a UNC network address (ie "\\srv1\blah").
// Also, handle both native and normalized pathnames.
2016-07-26 23:31:47 +07:00
inline int is_absolute_path(const char *path)
{
if (path[0] == '/') return TRUE;
2016-07-04 12:07:29 +06:00
#ifdef _WIN32
2016-07-26 23:31:47 +07:00
if (path[1] == ':') return TRUE;
if (path[0] == '\\') return TRUE;
#endif // _WIN32
return FALSE;
2016-07-04 12:07:29 +06:00
}
#ifdef _WIN32
// Buffer pointed to by resolved_name is assumed to be able to store a
// string of PATH_MAX length.
2016-07-26 23:31:47 +07:00
inline char *realpath(const char *file_name, char *resolved_name)
{
int ret;
2016-07-26 23:31:47 +07:00
ret = GetFullPathName(file_name, PATH_MAX, resolved_name, NULL);
if (ret > PATH_MAX)
{
errno = ENAMETOOLONG;
return NULL;
}
2016-07-26 23:31:47 +07:00
else if (ret > 0)
{
HANDLE handle;
WIN32_FIND_DATA find_data;
2016-07-26 23:31:47 +07:00
handle = FindFirstFile(resolved_name, &find_data);
if (INVALID_HANDLE_VALUE == handle)
{
errno = ENOENT;
return NULL;
}
2016-07-26 23:31:47 +07:00
FindClose(handle);
normalize_pathname(resolved_name);
2016-07-26 23:31:47 +07:00
return resolved_name;
}
2016-07-26 23:31:47 +07:00
return NULL;
}
2016-07-26 23:31:47 +07:00
#endif // _WIN32
2016-07-04 12:07:29 +06:00
// Generic "error string" from a recent OS call. For linux, this is based
// on errno. For win32, it's based on GetLastError.
2016-07-26 23:31:47 +07:00
inline const char *str_os_error()
{
#ifdef _WIN32
return str_GetLastError();
#else
return strerror(errno);
#endif
2016-07-26 07:22:47 +07:00
}