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>
#define Socket__Error() WSAGetLastError()
#define NATIVE_STR_LEN 300
static HANDLE heap;
const ReturnCode ReturnCode_FileShareViolation = ERROR_SHARING_VIOLATION;
const ReturnCode ReturnCode_FileNotFound = ERROR_FILE_NOT_FOUND;
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 Socket__Error() errno
#define NATIVE_STR_LEN 600
const ReturnCode ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */
const ReturnCode ReturnCode_FileNotFound = ENOENT;
const ReturnCode ReturnCode_SocketInProgess = EINPROGRESS;
@ -91,24 +95,6 @@ const ReturnCode ReturnCode_SocketWouldBlock = EWOULDBLOCK;
#undef CC_BUILD_FREETYPE
#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----------------------------------------------------------*
@ -431,12 +417,6 @@ ReturnCode Directory_Enum(const String* dirPath, void* obj, Directory_EnumCallba
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) {
FileHandle file;
FILETIME ft;
@ -589,12 +569,6 @@ ReturnCode Directory_Enum(const String* dirPath, void* obj, Directory_EnumCallba
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) {
char str[600];
struct stat sb;
@ -1598,12 +1572,18 @@ ReturnCode Process_StartShell(void) {
return Process_RawStart(NULL, str);
}
ReturnCode Process_GetExePath(String* path) {
TCHAR chars[FILENAME_SIZE + 1];
DWORD len = GetModuleFileName(NULL, chars, FILENAME_SIZE);
if (!len) return GetLastError();
static ReturnCode Process_GetRawExePath(TCHAR* path, int* len) {
*len = GetModuleFileName(NULL, path, NATIVE_STR_LEN);
return *len ? 0 : 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;
}
#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); }
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
/* Opening browser and starting shell is not really standardised */
#if defined CC_BUILD_OSX
@ -1700,37 +1691,30 @@ ReturnCode Process_StartShell(void) {
#endif
/* Retrieving exe path is completely OS dependant */
#if defined CC_BUILD_OSX
ReturnCode Process_GetExePath(String* path) {
char str[600] = { 0 };
uint32_t len = 600;
if (_NSGetExecutablePath(str, &len)) return ERR_INVALID_ARGUMENT;
static ReturnCode Process_GetRawExePath(char* path, int* len) {
Mem_Set(path, '\0', NATIVE_STR_LEN);
uint32_t size = 600;
if (_NSGetExecutablePath(str, &size)) return ERR_INVALID_ARGUMENT;
len = String_CalcLen(str, 600);
Platform_DecodeString(path, str, len);
*len = String_CalcLen(path, NATIVE_STR_LEN);
return 0;
}
#elif defined CC_BUILD_LINUX
ReturnCode Process_GetExePath(String* path) {
char str[600];
int len = readlink("/proc/self/exe", str, 600);
if (len == -1) return errno;
Platform_DecodeString(path, str, len);
return 0;
static ReturnCode Process_GetRawExePath(char* path, int* len) {
*len = readlink("/proc/self/exe", path, NATIVE_STR_LEN);
return *len == -1 ? errno : 0;
}
#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 };
char str[600];
size_t size = 600;
if (sysctl(mib, 4, str, &size, NULL, 0) == -1) return errno;
size_t size = NATIVE_STR_LEN;
size = String_CalcLen(str, 600);
Platform_DecodeString(path, str, size);
if (sysctl(mib, 4, str, &size, NULL, 0) == -1) return errno;
*len = String_CalcLen(path, NATIVE_STR_LEN);
return 0;
}
#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 };
char tmp[600];
size_t size;
@ -1751,29 +1735,23 @@ ReturnCode Process_GetExePath(String* path) {
str = tmp;
}
size = String_CalcLen(str, 600);
Platform_DecodeString(path, str, size);
*len = String_CalcLen(str, 600);
Mem_Copy(path, str, *len);
return 0;
}
#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 };
char str[600];
size_t size = 600;
if (sysctl(mib, 4, str, &size, NULL, 0) == -1) return errno;
size_t size = NATIVE_STR_LEN;
size = String_CalcLen(str, 600);
Platform_DecodeString(path, str, size);
if (sysctl(mib, 4, path, &size, NULL, 0) == -1) return errno;
*len = String_CalcLen(path, NATIVE_STR_LEN);
return 0;
}
#elif defined CC_BUILD_SOLARIS
ReturnCode Process_GetExePath(String* path) {
char str[600];
int len = readlink("/proc/self/path/a.out", str, 600);
if (len == -1) return errno;
Platform_DecodeString(path, str, len);
return 0;
static ReturnCode Process_GetRawExePath(char* path, int* len) {
*len = readlink("/proc/self/path/a.out", path, NATIVE_STR_LEN);
return *len == -1 ? errno : 0;
}
#endif
@ -1898,7 +1876,21 @@ void Platform_Free(void) {
WSACleanup();
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) {
String arg;
@ -2004,7 +1996,7 @@ int Platform_ConvertUniString(void* data, const UniString* src) {
return len;
}
static void Platform_InitCommon(void) {
static void Platform_InitPosix(void) {
signal(SIGCHLD, SIG_IGN);
/* So writing to closed socket doesn't raise SIGPIPE */
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;
}
#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) {
char chars[600];
int len;
@ -2045,10 +2054,10 @@ bool Platform_DescribeError(ReturnCode res, String* dst) {
Platform_DecodeString(dst, chars, len);
return true;
}
#endif
#if defined CC_BUILD_UNIX
void Platform_Init(void) { Platform_InitCommon(); }
void Platform_SetDefaultCurrentDirectory(void) { SetCurrentToExeDirectory(); }
void Platform_Init(void) { Platform_InitPosix(); }
#elif defined CC_BUILD_OSX
static void Platform_InitStopwatch(void) {
mach_timebase_info_data_t tb = { 0 };
@ -2062,7 +2071,7 @@ static void Platform_InitStopwatch(void) {
void Platform_Init(void) {
ProcessSerialNumber psn; /* TODO: kCurrentProcess */
Platform_InitCommon();
Platform_InitPosix();
Platform_InitStopwatch();
/* 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 */
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
}
void Platform_SetDefaultCurrentDirectory(void) { SetCurrentToExeDirectory(); }
#elif defined CC_BUILD_WEB
void Platform_Init(void) {
EM_ASM( Module['websocket']['subprotocol'] = 'ClassiCube'; );
@ -2095,32 +2103,28 @@ void Platform_Init(void) {
*/
}
void Platform_SetDefaultCurrentDirectory(void) {
static const String path = String_FromConst("/classicube");
ReturnCode res = Directory_SetCurrent(&path);
if (res) Logger_Warn(res, "setting current directory");
ReturnCode Platform_SetDefaultCurrentDirectory(void) {
return chdir("/classicube") == -1 ? errno : 0;
}
#elif defined CC_BUILD_ANDROID
jclass App_Class;
jobject App_Instance;
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) {
if (!gameArgs.length) return 0;
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_InitArray_NT(dir, dirBuffer);
JavaCall_Void_String("getExternalAppDir", &dir);
dir.buffer[dir.length] = '\0';
Platform_Log1("EXTERNAL DIR: %s|", &dir);
ReturnCode res = chdir(dir.buffer) == -1 ? errno : 0;
if (res) Logger_Warn(res, "setting current directory");
return chdir(dir.buffer) == -1 ? errno : 0;
}
/* JNI helpers */

View File

@ -46,7 +46,7 @@ void Platform_Init(void);
/* Frees the platform specific state. */
void Platform_Free(void);
/* Sets the appropriate default current/working directory. */
void Platform_SetDefaultCurrentDirectory(void);
ReturnCode Platform_SetDefaultCurrentDirectory(void);
/* Gets the command line arguments passed to the program. */
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);
/* 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);
/* 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. */
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) {
#endif
static char ipBuffer[STRING_SIZE];
ReturnCode res;
Logger_Hook();
Platform_Init();
Window_Init();
Platform_SetDefaultCurrentDirectory();
res = Platform_SetDefaultCurrentDirectory();
if (res) Logger_Warn(res, "setting current directory");
#ifdef CC_TEST_VORBIS
main_imdct();
#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, */
/* since mounting /classicube/texpacks to memory doesn't work.. */
#ifdef CC_BUILD_WEB
static const String memPath = String_FromConst("/");
Directory_SetCurrent(&memPath);
extern int chdir(const char* path);
chdir("/");
#endif
String_InitArray(path, pathBuffer);
@ -688,8 +688,7 @@ void TexturePack_ExtractZip_File(const String* filename) {
if (res) { Logger_Warn2(res, "closing", &path); }
#ifdef CC_BUILD_WEB
static const String idbPath = String_FromConst("/classicube");
Directory_SetCurrent(&idbPath);
Platform_SetDefaultCurrentDirectory();
#endif
}