2016-07-26 07:22:47 +07:00
|
|
|
#pragma once
|
2016-07-04 12:07:29 +06:00
|
|
|
|
|
|
|
// Various differences between WIN32 and Linux.
|
|
|
|
#include "types_meta.h" // mBOOL
|
|
|
|
#include "mreg.h" // REG_CMD_FN, etc
|
|
|
|
#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 09:08:43 +07:00
|
|
|
#define UNUSED /**/
|
|
|
|
|
2016-07-04 12:07:29 +06:00
|
|
|
#define PLATFORM "mswin"
|
|
|
|
#define PLATFORM_SPC "win32"
|
|
|
|
#define PLATFORM_DLEXT ".dll"
|
2016-07-26 07:22:47 +07:00
|
|
|
#else
|
2016-07-26 09:08:43 +07:00
|
|
|
#define UNUSED __attribute__((unused))
|
|
|
|
|
2016-07-26 07:22:47 +07:00
|
|
|
#define PLATFORM "linux"
|
|
|
|
#define PLATFORM_SPC "lin32"
|
|
|
|
#define PLATFORM_DLEXT ".so"
|
|
|
|
#endif
|
2016-07-04 12:07:29 +06:00
|
|
|
|
|
|
|
// Special version that fixes vsnprintf bugs.
|
|
|
|
#ifndef DO_NOT_FIX_VARARG_ENGINE_API_WARPERS
|
2016-07-26 07:22:47 +07:00
|
|
|
int safe_vsnprintf(char* s, size_t n, const char *format, va_list ap);
|
|
|
|
int safe_snprintf(char* s, size_t n, const char* format, ...);
|
2016-07-04 12:07:29 +06:00
|
|
|
#endif
|
2016-07-26 07:22:47 +07:00
|
|
|
void safevoid_vsnprintf(char* s, size_t n, const char *format, va_list ap);
|
|
|
|
void safevoid_snprintf(char* s, size_t n, const char* format, ...);
|
2016-07-04 12:07:29 +06:00
|
|
|
|
|
|
|
// Functions & types for DLL open/close/etc operations.
|
2016-07-26 07:22:47 +07:00
|
|
|
extern mBOOL dlclose_handle_invalid;
|
|
|
|
#ifdef _WIN32
|
|
|
|
typedef HINSTANCE DLHANDLE;
|
|
|
|
typedef FARPROC DLFUNC;
|
|
|
|
inline DLHANDLE DLOPEN(const char *filename)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
return LoadLibraryA(filename);
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
inline DLFUNC DLSYM(DLHANDLE handle, const char *string)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
return GetProcAddress(handle, string);
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
inline int DLCLOSE(DLHANDLE handle)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
if (!handle)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-04 12:07:29 +06:00
|
|
|
dlclose_handle_invalid = mTRUE;
|
2016-07-26 07:22:47 +07:00
|
|
|
return 1;
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
|
2016-07-04 12:07:29 +06:00
|
|
|
dlclose_handle_invalid = mFALSE;
|
2016-07-26 07:22: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-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
// Windows doesn't provide a function corresponding to dlerror(), so
|
|
|
|
// we make our own.
|
|
|
|
char *str_GetLastError();
|
|
|
|
inline const char *DLERROR()
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
if (dlclose_handle_invalid)
|
|
|
|
return "Invalid handle.";
|
|
|
|
|
|
|
|
return str_GetLastError();
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
#else
|
|
|
|
typedef void *DLHANDLE;
|
|
|
|
typedef void *DLFUNC;
|
|
|
|
inline DLHANDLE DLOPEN(const char *filename)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
return dlopen(filename, RTLD_NOW);
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
inline DLFUNC DLSYM(DLHANDLE handle, const char *string)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
return dlsym(handle, string);
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
// dlclose crashes if handle is null.
|
|
|
|
inline int DLCLOSE(DLHANDLE handle)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
if (!handle)
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-04 12:07:29 +06:00
|
|
|
dlclose_handle_invalid = mTRUE;
|
2016-07-26 07:22:47 +07:00
|
|
|
return 1;
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
|
|
|
dlclose_handle_invalid = mFALSE;
|
2016-07-26 07:22:47 +07:00
|
|
|
return dlclose(handle);
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
inline const char *DLERROR()
|
|
|
|
{
|
|
|
|
if (dlclose_handle_invalid)
|
|
|
|
return "Invalid handle.";
|
|
|
|
|
|
|
|
return dlerror();
|
2016-07-04 12:07:29 +06:00
|
|
|
}
|
2016-07-26 07:22:47 +07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
const char *DLFNAME(void *memptr);
|
|
|
|
mBOOL IS_VALID_PTR(void *memptr);
|
2016-07-04 12:07:29 +06:00
|
|
|
|
|
|
|
// Attempt to call the given function pointer, without segfaulting.
|
2016-07-26 07:22:47 +07:00
|
|
|
mBOOL 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 09:08:43 +07:00
|
|
|
#else
|
2016-07-04 12:07:29 +06:00
|
|
|
// Linux doesn't have an strlwr() routine, so we write our own.
|
|
|
|
#define strlwr(s) my_strlwr(s)
|
2016-07-26 07:22:47 +07:00
|
|
|
char *my_strlwr(char *s);
|
2016-07-26 09:08:43 +07:00
|
|
|
#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"
|
|
|
|
#ifdef linux
|
|
|
|
#include <limits.h>
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define NAME_MAX _MAX_FNAME
|
|
|
|
#ifndef PATH_MAX
|
|
|
|
#define PATH_MAX _MAX_PATH
|
|
|
|
#endif
|
2016-07-26 09:08:43 +07:00
|
|
|
#endif // _WIN32
|
2016-07-04 12:07:29 +06:00
|
|
|
|
|
|
|
// Various other windows routine differences.
|
|
|
|
#ifdef linux
|
|
|
|
#include <unistd.h> // sleep
|
|
|
|
#ifndef O_BINARY
|
|
|
|
#define O_BINARY 0
|
2016-07-26 07:22:47 +07:00
|
|
|
#endif
|
2016-07-04 12:07:29 +06:00
|
|
|
#elif defined(_WIN32)
|
|
|
|
#include <io.h>
|
|
|
|
#include <direct.h>
|
2016-07-26 07:22:47 +07:00
|
|
|
|
2016-07-04 12:07:29 +06:00
|
|
|
#define sleep(x) Sleep(x*1000)
|
|
|
|
|
|
|
|
// Fixed MSVC compiling, by Nikolay "The Storm" Baklicharov.
|
|
|
|
#if defined(__GNUC__) || defined (_MSC_VER) && _MSC_VER >= 1400
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#define vsnprintf _vsnprintf
|
|
|
|
#define unlink _unlink
|
|
|
|
#define strlwr _strlwr
|
|
|
|
#define strdup _strdup
|
|
|
|
#define strcasecmp _stricmp
|
|
|
|
#define strncasecmp _strnicmp
|
|
|
|
#define getcwd _getcwd
|
|
|
|
#define open _open
|
|
|
|
#define read _read
|
|
|
|
#define write _write
|
|
|
|
#define close _close
|
|
|
|
#endif /* GCC or MSVC 8.0+ */
|
2016-07-26 09:08:43 +07:00
|
|
|
#endif // _WIN32
|
2016-07-04 12:07:29 +06:00
|
|
|
|
|
|
|
#if !defined WIN32 && !defined _MSC_VER
|
|
|
|
#include <unistd.h> // getcwd
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#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 07:22: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 09:08:43 +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.
|
|
|
|
#ifdef linux
|
|
|
|
#define normalize_pathname(a)
|
|
|
|
#elif defined(_WIN32)
|
2016-07-26 07:22:47 +07:00
|
|
|
void normalize_pathname(char *path);
|
2016-07-26 09:08:43 +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 07:22:47 +07:00
|
|
|
inline mBOOL is_absolute_path(const char *path) {
|
|
|
|
if (path[0]=='/') return mTRUE;
|
2016-07-04 12:07:29 +06:00
|
|
|
#ifdef _WIN32
|
2016-07-26 07:22:47 +07:00
|
|
|
if (path[1]==':') return mTRUE;
|
|
|
|
if (path[0]=='\\') return mTRUE;
|
2016-07-26 09:08:43 +07:00
|
|
|
#endif // _WIN32
|
2016-07-26 07:22:47 +07:00
|
|
|
return mFALSE;
|
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 07:22:47 +07:00
|
|
|
char *realpath(const char *file_name, char *resolved_name);
|
2016-07-26 09:08:43 +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 07:22:47 +07:00
|
|
|
inline const char *str_os_error()
|
2016-07-04 13:11:20 +06:00
|
|
|
{
|
2016-07-26 07:22:47 +07:00
|
|
|
#ifdef _WIN32
|
|
|
|
return str_GetLastError();
|
|
|
|
#else
|
|
|
|
return strerror(errno);
|
2016-07-04 13:11:20 +06:00
|
|
|
#endif
|
2016-07-26 07:22:47 +07:00
|
|
|
}
|