First phase of redesigning GetExePath to work with full unicode

This means the game will successfully set current directory now even if it's got say a Ӛ character in it
This commit is contained in:
UnknownShadow200 2019-08-15 21:09:41 +10:00
parent 18e780ae2e
commit c3f9110778
4 changed files with 97 additions and 94 deletions

View File

@ -34,7 +34,9 @@
#include <wincrypt.h> #include <wincrypt.h>
#define Socket__Error() WSAGetLastError() #define Socket__Error() WSAGetLastError()
#define NATIVE_STR_LEN 300
static HANDLE heap; static HANDLE heap;
const ReturnCode ReturnCode_FileShareViolation = ERROR_SHARING_VIOLATION; const ReturnCode ReturnCode_FileShareViolation = ERROR_SHARING_VIOLATION;
const ReturnCode ReturnCode_FileNotFound = ERROR_FILE_NOT_FOUND; const ReturnCode ReturnCode_FileNotFound = ERROR_FILE_NOT_FOUND;
const ReturnCode ReturnCode_SocketInProgess = WSAEINPROGRESS; const ReturnCode ReturnCode_SocketInProgess = WSAEINPROGRESS;
@ -62,6 +64,8 @@ const ReturnCode ReturnCode_SocketWouldBlock = WSAEWOULDBLOCK;
#define Platform_DecodeString(dst, src, len) String_AppendUtf8(dst, (uint8_t*)(src), len) #define Platform_DecodeString(dst, src, len) String_AppendUtf8(dst, (uint8_t*)(src), len)
#define Socket__Error() errno #define Socket__Error() errno
#define NATIVE_STR_LEN 600
const ReturnCode ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ const ReturnCode ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */
const ReturnCode ReturnCode_FileNotFound = ENOENT; const ReturnCode ReturnCode_FileNotFound = ENOENT;
const ReturnCode ReturnCode_SocketInProgess = EINPROGRESS; const ReturnCode ReturnCode_SocketInProgess = EINPROGRESS;
@ -91,24 +95,6 @@ const ReturnCode ReturnCode_SocketWouldBlock = EWOULDBLOCK;
#undef CC_BUILD_FREETYPE #undef CC_BUILD_FREETYPE
#endif #endif
/* Attempts to set current/working directory to the directory exe file is in */
static void SetCurrentToExeDirectory(void) {
String path; char pathBuffer[FILENAME_SIZE];
int i;
ReturnCode res;
String_InitArray(path, pathBuffer);
res = Process_GetExePath(&path);
if (res) { Logger_Warn(res, "getting exe path"); return; }
/* get rid of filename at end of directory */
for (i = path.length - 1; i >= 0; i--, path.length--) {
if (path.buffer[i] == '/' || path.buffer[i] == '\\') break;
}
res = Directory_SetCurrent(&path);
if (res) { Logger_Warn(res, "setting current directory"); return; }
}
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Memory----------------------------------------------------------* *---------------------------------------------------------Memory----------------------------------------------------------*
@ -431,12 +417,6 @@ ReturnCode Directory_Enum(const String* dirPath, void* obj, Directory_EnumCallba
return res == ERROR_NO_MORE_FILES ? 0 : GetLastError(); return res == ERROR_NO_MORE_FILES ? 0 : GetLastError();
} }
ReturnCode Directory_SetCurrent(const String* path) {
TCHAR str[300];
Platform_ConvertString(str, path);
return SetCurrentDirectory(str) ? 0 : GetLastError();
}
ReturnCode File_GetModifiedTime(const String* path, TimeMS* time) { ReturnCode File_GetModifiedTime(const String* path, TimeMS* time) {
FileHandle file; FileHandle file;
FILETIME ft; FILETIME ft;
@ -589,12 +569,6 @@ ReturnCode Directory_Enum(const String* dirPath, void* obj, Directory_EnumCallba
return res; return res;
} }
ReturnCode Directory_SetCurrent(const String* path) {
char str[600];
Platform_ConvertString(str, path);
return chdir(str) == -1 ? errno : 0;
}
ReturnCode File_GetModifiedTime(const String* path, TimeMS* time) { ReturnCode File_GetModifiedTime(const String* path, TimeMS* time) {
char str[600]; char str[600];
struct stat sb; struct stat sb;
@ -1598,12 +1572,18 @@ ReturnCode Process_StartShell(void) {
return Process_RawStart(NULL, str); return Process_RawStart(NULL, str);
} }
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(TCHAR* path, int* len) {
TCHAR chars[FILENAME_SIZE + 1]; *len = GetModuleFileName(NULL, path, NATIVE_STR_LEN);
DWORD len = GetModuleFileName(NULL, chars, FILENAME_SIZE); return *len ? 0 : GetLastError();
if (!len) return GetLastError(); }
Platform_DecodeString(path, chars, len); ReturnCode Process_GetExePath(String* path) {
TCHAR raw[NATIVE_STR_LEN];
int len;
ReturnCode res = Process_GetRawExePath(raw, &len);
if (res) return res;
Platform_DecodeString(path, raw, len);
return 0; return 0;
} }
#elif defined CC_BUILD_WEB #elif defined CC_BUILD_WEB
@ -1672,6 +1652,17 @@ ReturnCode Process_Start(const String* path, const String* args) {
} }
void Process_Exit(ReturnCode code) { exit(code); } void Process_Exit(ReturnCode code) { exit(code); }
static ReturnCode Process_GetRawExePath(char* path, int* len);
ReturnCode Process_GetExePath(String* path) {
char str[NATIVE_STR_LEN];
int len = 0;
ReturnCode res = Process_GetRawExePath(str, &len);
if (res) return res;
Platform_DecodeString(path, str, len);
return 0;
}
#endif #endif
/* Opening browser and starting shell is not really standardised */ /* Opening browser and starting shell is not really standardised */
#if defined CC_BUILD_OSX #if defined CC_BUILD_OSX
@ -1700,37 +1691,30 @@ ReturnCode Process_StartShell(void) {
#endif #endif
/* Retrieving exe path is completely OS dependant */ /* Retrieving exe path is completely OS dependant */
#if defined CC_BUILD_OSX #if defined CC_BUILD_OSX
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(char* path, int* len) {
char str[600] = { 0 }; Mem_Set(path, '\0', NATIVE_STR_LEN);
uint32_t len = 600; uint32_t size = 600;
if (_NSGetExecutablePath(str, &len)) return ERR_INVALID_ARGUMENT; if (_NSGetExecutablePath(str, &size)) return ERR_INVALID_ARGUMENT;
len = String_CalcLen(str, 600); *len = String_CalcLen(path, NATIVE_STR_LEN);
Platform_DecodeString(path, str, len);
return 0; return 0;
} }
#elif defined CC_BUILD_LINUX #elif defined CC_BUILD_LINUX
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(char* path, int* len) {
char str[600]; *len = readlink("/proc/self/exe", path, NATIVE_STR_LEN);
int len = readlink("/proc/self/exe", str, 600); return *len == -1 ? errno : 0;
if (len == -1) return errno;
Platform_DecodeString(path, str, len);
return 0;
} }
#elif defined CC_BUILD_FREEBSD #elif defined CC_BUILD_FREEBSD
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(char* path, int* len) {
static int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; static int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
char str[600]; size_t size = NATIVE_STR_LEN;
size_t size = 600;
if (sysctl(mib, 4, str, &size, NULL, 0) == -1) return errno;
size = String_CalcLen(str, 600); if (sysctl(mib, 4, str, &size, NULL, 0) == -1) return errno;
Platform_DecodeString(path, str, size); *len = String_CalcLen(path, NATIVE_STR_LEN);
return 0; return 0;
} }
#elif defined CC_BUILD_OPENBSD #elif defined CC_BUILD_OPENBSD
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(char* path, int* len) {
static int mib[4] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV }; static int mib[4] = { CTL_KERN, KERN_PROC_ARGS, 0, KERN_PROC_ARGV };
char tmp[600]; char tmp[600];
size_t size; size_t size;
@ -1751,29 +1735,23 @@ ReturnCode Process_GetExePath(String* path) {
str = tmp; str = tmp;
} }
size = String_CalcLen(str, 600); *len = String_CalcLen(str, 600);
Platform_DecodeString(path, str, size); Mem_Copy(path, str, *len);
return 0; return 0;
} }
#elif defined CC_BUILD_NETBSD #elif defined CC_BUILD_NETBSD
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(char* path, int* len) {
static int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; static int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
char str[600]; size_t size = NATIVE_STR_LEN;
size_t size = 600;
if (sysctl(mib, 4, str, &size, NULL, 0) == -1) return errno;
size = String_CalcLen(str, 600); if (sysctl(mib, 4, path, &size, NULL, 0) == -1) return errno;
Platform_DecodeString(path, str, size); *len = String_CalcLen(path, NATIVE_STR_LEN);
return 0; return 0;
} }
#elif defined CC_BUILD_SOLARIS #elif defined CC_BUILD_SOLARIS
ReturnCode Process_GetExePath(String* path) { static ReturnCode Process_GetRawExePath(char* path, int* len) {
char str[600]; *len = readlink("/proc/self/path/a.out", path, NATIVE_STR_LEN);
int len = readlink("/proc/self/path/a.out", str, 600); return *len == -1 ? errno : 0;
if (len == -1) return errno;
Platform_DecodeString(path, str, len);
return 0;
} }
#endif #endif
@ -1898,7 +1876,21 @@ void Platform_Free(void) {
WSACleanup(); WSACleanup();
HeapDestroy(heap); HeapDestroy(heap);
} }
void Platform_SetDefaultCurrentDirectory(void) { SetCurrentToExeDirectory(); }
ReturnCode Platform_SetDefaultCurrentDirectory(void) {
TCHAR path[NATIVE_STR_LEN + 1];
int i, len;
ReturnCode res = Process_GetRawExePath(path, &len);
if (res) return res;
/* Get rid of filename at end of directory */
for (i = len - 1; i >= 0; i--, len--) {
if (path[i] == '/' || path[i] == '\\') break;
}
path[len] = '\0';
return SetCurrentDirectory(path) ? 0 : GetLastError();
}
static String Platform_NextArg(STRING_REF String* args) { static String Platform_NextArg(STRING_REF String* args) {
String arg; String arg;
@ -2004,7 +1996,7 @@ int Platform_ConvertUniString(void* data, const UniString* src) {
return len; return len;
} }
static void Platform_InitCommon(void) { static void Platform_InitPosix(void) {
signal(SIGCHLD, SIG_IGN); signal(SIGCHLD, SIG_IGN);
/* So writing to closed socket doesn't raise SIGPIPE */ /* So writing to closed socket doesn't raise SIGPIPE */
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
@ -2034,6 +2026,23 @@ ReturnCode Platform_Decrypt(const void* data, int len, uint8_t** dec, int* decLe
return ERR_NOT_SUPPORTED; return ERR_NOT_SUPPORTED;
} }
#if !defined CC_BUILD_WEB && !defined CC_BUILD_ANDROID
ReturnCode Platform_SetDefaultCurrentDirectory(void) {
char path[NATIVE_STR_LEN];
int i, len = 0;
ReturnCode res = Process_GetRawExePath(path, &len);
if (res) return res;
/* get rid of filename at end of directory */
for (i = len - 1; i >= 0; i--, len--) {
if (path[i] == '\\') break;
}
path[len] = '\0';
return chdir(path) == -1 ? errno : 0;
}
#endif
bool Platform_DescribeError(ReturnCode res, String* dst) { bool Platform_DescribeError(ReturnCode res, String* dst) {
char chars[600]; char chars[600];
int len; int len;
@ -2045,10 +2054,10 @@ bool Platform_DescribeError(ReturnCode res, String* dst) {
Platform_DecodeString(dst, chars, len); Platform_DecodeString(dst, chars, len);
return true; return true;
} }
#endif #endif
#if defined CC_BUILD_UNIX #if defined CC_BUILD_UNIX
void Platform_Init(void) { Platform_InitCommon(); } void Platform_Init(void) { Platform_InitPosix(); }
void Platform_SetDefaultCurrentDirectory(void) { SetCurrentToExeDirectory(); }
#elif defined CC_BUILD_OSX #elif defined CC_BUILD_OSX
static void Platform_InitStopwatch(void) { static void Platform_InitStopwatch(void) {
mach_timebase_info_data_t tb = { 0 }; mach_timebase_info_data_t tb = { 0 };
@ -2062,7 +2071,7 @@ static void Platform_InitStopwatch(void) {
void Platform_Init(void) { void Platform_Init(void) {
ProcessSerialNumber psn; /* TODO: kCurrentProcess */ ProcessSerialNumber psn; /* TODO: kCurrentProcess */
Platform_InitCommon(); Platform_InitPosix();
Platform_InitStopwatch(); Platform_InitStopwatch();
/* NOTE: Call as soon as possible, otherwise can't click on dialog boxes. */ /* NOTE: Call as soon as possible, otherwise can't click on dialog boxes. */
@ -2070,7 +2079,6 @@ void Platform_Init(void) {
/* NOTE: TransformProcessType is OSX 10.3 or later */ /* NOTE: TransformProcessType is OSX 10.3 or later */
TransformProcessType(&psn, kProcessTransformToForegroundApplication); TransformProcessType(&psn, kProcessTransformToForegroundApplication);
} }
void Platform_SetDefaultCurrentDirectory(void) { SetCurrentToExeDirectory(); }
#elif defined CC_BUILD_WEB #elif defined CC_BUILD_WEB
void Platform_Init(void) { void Platform_Init(void) {
EM_ASM( Module['websocket']['subprotocol'] = 'ClassiCube'; ); EM_ASM( Module['websocket']['subprotocol'] = 'ClassiCube'; );
@ -2095,32 +2103,28 @@ void Platform_Init(void) {
*/ */
} }
void Platform_SetDefaultCurrentDirectory(void) { ReturnCode Platform_SetDefaultCurrentDirectory(void) {
static const String path = String_FromConst("/classicube"); return chdir("/classicube") == -1 ? errno : 0;
ReturnCode res = Directory_SetCurrent(&path);
if (res) Logger_Warn(res, "setting current directory");
} }
#elif defined CC_BUILD_ANDROID #elif defined CC_BUILD_ANDROID
jclass App_Class; jclass App_Class;
jobject App_Instance; jobject App_Instance;
JavaVM* VM_Ptr; JavaVM* VM_Ptr;
void Platform_Init(void) { Platform_InitCommon(); } void Platform_Init(void) { Platform_InitPosix(); }
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, String* args) { int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, String* args) {
if (!gameArgs.length) return 0; if (!gameArgs.length) return 0;
return String_UNSAFE_Split(&gameArgs, ' ', args, GAME_MAX_CMDARGS); return String_UNSAFE_Split(&gameArgs, ' ', args, GAME_MAX_CMDARGS);
} }
void Platform_SetDefaultCurrentDirectory(void) { ReturnCode Platform_SetDefaultCurrentDirectory(void) {
String dir; char dirBuffer[FILENAME_SIZE + 1]; String dir; char dirBuffer[FILENAME_SIZE + 1];
String_InitArray_NT(dir, dirBuffer); String_InitArray_NT(dir, dirBuffer);
JavaCall_Void_String("getExternalAppDir", &dir); JavaCall_Void_String("getExternalAppDir", &dir);
dir.buffer[dir.length] = '\0'; dir.buffer[dir.length] = '\0';
Platform_Log1("EXTERNAL DIR: %s|", &dir); Platform_Log1("EXTERNAL DIR: %s|", &dir);
return chdir(dir.buffer) == -1 ? errno : 0;
ReturnCode res = chdir(dir.buffer) == -1 ? errno : 0;
if (res) Logger_Warn(res, "setting current directory");
} }
/* JNI helpers */ /* JNI helpers */

View File

@ -46,7 +46,7 @@ void Platform_Init(void);
/* Frees the platform specific state. */ /* Frees the platform specific state. */
void Platform_Free(void); void Platform_Free(void);
/* Sets the appropriate default current/working directory. */ /* Sets the appropriate default current/working directory. */
void Platform_SetDefaultCurrentDirectory(void); ReturnCode Platform_SetDefaultCurrentDirectory(void);
/* Gets the command line arguments passed to the program. */ /* Gets the command line arguments passed to the program. */
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, String* args); int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, String* args);
@ -132,9 +132,6 @@ CC_API ReturnCode Directory_Create(const String* path);
typedef void Directory_EnumCallback(const String* filename, void* obj); typedef void Directory_EnumCallback(const String* filename, void* obj);
/* Invokes a callback function on all filenames in the given directory (and its sub-directories) */ /* Invokes a callback function on all filenames in the given directory (and its sub-directories) */
CC_API ReturnCode Directory_Enum(const String* path, void* obj, Directory_EnumCallback callback); CC_API ReturnCode Directory_Enum(const String* path, void* obj, Directory_EnumCallback callback);
/* Sets current/working directory to the given directory. */
/* This is the 'base directory' relative paths are relative to. */
CC_API ReturnCode Directory_SetCurrent(const String* path);
/* Returns whether the given file exists. */ /* Returns whether the given file exists. */
CC_API bool File_Exists(const String* path); CC_API bool File_Exists(const String* path);

View File

@ -162,10 +162,13 @@ int main_real(int argc, char** argv) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
#endif #endif
static char ipBuffer[STRING_SIZE]; static char ipBuffer[STRING_SIZE];
ReturnCode res;
Logger_Hook(); Logger_Hook();
Platform_Init(); Platform_Init();
Window_Init(); Window_Init();
Platform_SetDefaultCurrentDirectory();
res = Platform_SetDefaultCurrentDirectory();
if (res) Logger_Warn(res, "setting current directory");
#ifdef CC_TEST_VORBIS #ifdef CC_TEST_VORBIS
main_imdct(); main_imdct();
#endif #endif

View File

@ -671,8 +671,8 @@ void TexturePack_ExtractZip_File(const String* filename) {
/* should be read from memory. I don't know how to do that, */ /* should be read from memory. I don't know how to do that, */
/* since mounting /classicube/texpacks to memory doesn't work.. */ /* since mounting /classicube/texpacks to memory doesn't work.. */
#ifdef CC_BUILD_WEB #ifdef CC_BUILD_WEB
static const String memPath = String_FromConst("/"); extern int chdir(const char* path);
Directory_SetCurrent(&memPath); chdir("/");
#endif #endif
String_InitArray(path, pathBuffer); String_InitArray(path, pathBuffer);
@ -688,8 +688,7 @@ void TexturePack_ExtractZip_File(const String* filename) {
if (res) { Logger_Warn2(res, "closing", &path); } if (res) { Logger_Warn2(res, "closing", &path); }
#ifdef CC_BUILD_WEB #ifdef CC_BUILD_WEB
static const String idbPath = String_FromConst("/classicube"); Platform_SetDefaultCurrentDirectory();
Directory_SetCurrent(&idbPath);
#endif #endif
} }