summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoroy <tom_adams@web.de>2021-12-10 15:50:33 +0100
committerGitHub <noreply@github.com>2021-12-10 15:50:33 +0100
commit1e1672fe4ef8582c754375e7d9f3dbaad07179c1 (patch)
tree1fdfe29f3831b37c024a9ac6ce67b5301c956079
parentd3f390821bb9fea1c7998b76ce1025e280eb0f3a (diff)
parent4f28113abd56ccb47c432078948b402cd31fe0ab (diff)
Merge pull request #2936 from Robyt3/windows-filesystem-unicode
Fix filesystem/IO with unicode filenames on windows
-rw-r--r--CMakeLists.txt4
-rw-r--r--bam.lua4
-rw-r--r--src/base/system.c256
-rw-r--r--src/base/system.h42
-rw-r--r--src/engine/client/client.cpp2
-rw-r--r--src/engine/client/graphics_threaded.cpp52
-rw-r--r--src/engine/server/server.cpp2
-rw-r--r--src/mastersrv/mastersrv.cpp17
-rw-r--r--src/test/test.cpp9
-rw-r--r--src/tools/crapnet.cpp2
-rw-r--r--src/tools/fake_server.cpp5
-rw-r--r--src/tools/map_resave.cpp40
-rw-r--r--src/tools/map_version.cpp5
-rw-r--r--src/tools/packetgen.cpp2
-rw-r--r--src/versionsrv/versionsrv.cpp7
15 files changed, 293 insertions, 156 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d68db960..fc898417d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2120,6 +2120,10 @@ foreach(target ${TARGETS_OWN})
target_compile_options(${target} PRIVATE /wd4267) # Possible loss of data (size_t - int on win64).
target_compile_options(${target} PRIVATE /wd4800) # Implicit conversion of int to bool.
endif()
+ if(TARGET_OS STREQUAL "windows")
+ target_compile_definitions(${target} PRIVATE UNICODE) # Windows headers
+ target_compile_definitions(${target} PRIVATE _UNICODE) # C-runtime
+ endif()
if(OUR_FLAGS_OWN)
target_compile_options(${target} PRIVATE ${OUR_FLAGS_OWN})
endif()
diff --git a/bam.lua b/bam.lua
index ec87f9395..e22669bd1 100644
--- a/bam.lua
+++ b/bam.lua
@@ -240,6 +240,10 @@ function GenerateWindowsSettings(settings, conf, target_arch, compiler)
settings.cc.defines:Add("_WIN32_WINNT=0x0501")
end
+ -- Unicode support
+ settings.cc.defines:Add("UNICODE") -- Windows headers
+ settings.cc.defines:Add("_UNICODE") -- C-runtime
+
local icons = SharedIcons(compiler)
local manifests = SharedManifests(compiler)
diff --git a/src/base/system.c b/src/base/system.c
index f77760507..8857c5b0f 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -42,6 +42,8 @@
#include <errno.h>
#include <process.h>
#include <wincrypt.h>
+ #include <share.h>
+ #include <shellapi.h>
#else
#error NOT IMPLEMENTED
#endif
@@ -209,14 +211,15 @@ static void logger_stdout(const char *line)
fflush(stdout);
}
-static void logger_debugger(const char *line)
-{
#if defined(CONF_FAMILY_WINDOWS)
- OutputDebugString(line);
- OutputDebugString("\n");
-#endif
+static void logger_win_debugger(const char *line)
+{
+ WCHAR wBuffer[512];
+ MultiByteToWideChar(CP_UTF8, 0, line, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ OutputDebugStringW(wBuffer);
+ OutputDebugStringW(L"\n");
}
-
+#endif
static IOHANDLE logfile = 0;
static void logger_file(const char *line)
@@ -238,7 +241,13 @@ void dbg_logger_stdout()
dbg_logger(logger_stdout);
}
-void dbg_logger_debugger() { dbg_logger(logger_debugger); }
+void dbg_logger_debugger()
+{
+#if defined(CONF_FAMILY_WINDOWS)
+ dbg_logger(logger_win_debugger);
+#endif
+}
+
void dbg_logger_file(const char *filename)
{
IOHANDLE handle = io_open(filename, IOFLAG_WRITE);
@@ -302,32 +311,52 @@ void mem_zero(void *block,unsigned size)
IOHANDLE io_open(const char *filename, int flags)
{
+ dbg_assert(flags == IOFLAG_READ || flags == IOFLAG_WRITE || flags == IOFLAG_APPEND, "flags must be read, write or append");
+#if defined(CONF_FAMILY_WINDOWS)
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
if(flags == IOFLAG_READ)
{
- #if defined(CONF_FAMILY_WINDOWS)
// check for filename case sensitive
- WIN32_FIND_DATA finddata;
+ WIN32_FIND_DATAW finddata;
HANDLE handle;
- int length;
+ char buffer[IO_MAX_PATH_LENGTH];
- length = str_length(filename);
+ int length = str_length(filename);
if(!filename || !length || filename[length-1] == '\\')
return 0x0;
- handle = FindFirstFile(filename, &finddata);
+ MultiByteToWideChar(CP_UTF8, 0, filename, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ handle = FindFirstFileW(wBuffer, &finddata);
if(handle == INVALID_HANDLE_VALUE)
return 0x0;
- else if(str_comp(filename+length-str_length(finddata.cFileName), finddata.cFileName) != 0)
+ WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer, sizeof(buffer), NULL, NULL);
+ if(str_comp(filename+length-str_length(buffer), buffer) != 0)
{
FindClose(handle);
return 0x0;
}
FindClose(handle);
- #endif
- return (IOHANDLE)fopen(filename, "rb");
+ return (IOHANDLE)_wfsopen(wBuffer, L"rb", _SH_DENYNO);
}
if(flags == IOFLAG_WRITE)
+ {
+ MultiByteToWideChar(CP_UTF8, 0, filename, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ return (IOHANDLE)_wfsopen(wBuffer, L"wb", _SH_DENYNO);
+ }
+ if(flags == IOFLAG_APPEND)
+ {
+ MultiByteToWideChar(CP_UTF8, 0, filename, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ return (IOHANDLE)_wfsopen(wBuffer, L"ab", _SH_DENYNO);
+ }
+ return 0x0;
+#else
+ if(flags == IOFLAG_READ)
+ return (IOHANDLE)fopen(filename, "rb");
+ if(flags == IOFLAG_WRITE)
return (IOHANDLE)fopen(filename, "wb");
+ if(flags == IOFLAG_APPEND)
+ return (IOHANDLE)fopen(filename, "ab");
return 0x0;
+#endif
}
unsigned io_read(IOHANDLE io, void *buffer, unsigned size)
@@ -898,7 +927,7 @@ int net_addr_from_str(NETADDR *addr, const char *string)
int size;
sa6.sin6_family = AF_INET6;
size = (int)sizeof(sa6);
- if(WSAStringToAddress(buf, AF_INET6, NULL, (struct sockaddr *)&sa6, &size) != 0)
+ if(WSAStringToAddressA(buf, AF_INET6, NULL, (struct sockaddr *)&sa6, &size) != 0)
return -1;
}
#else
@@ -985,9 +1014,11 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
{
#if defined(CONF_FAMILY_WINDOWS)
char buf[128];
+ WCHAR wBuffer[128];
int error = WSAGetLastError();
- if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
- buf[0] = 0;
+ if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
+ wBuffer[0] = 0;
+ WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buf, sizeof(buf), NULL, NULL);
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
#else
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
@@ -1024,11 +1055,13 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
{
#if defined(CONF_FAMILY_WINDOWS)
char buf[128];
+ WCHAR wBuffer[128];
int error = WSAGetLastError();
if(error == WSAEADDRINUSE && use_random_port)
continue;
- if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
- buf[0] = 0;
+ if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
+ wBuffer[0] = 0;
+ WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buf, sizeof(buf), NULL, NULL);
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
#else
if(errno == EADDRINUSE && use_random_port)
@@ -1480,15 +1513,18 @@ static inline time_t filetime_to_unixtime(LPFILETIME filetime)
void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
{
#if defined(CONF_FAMILY_WINDOWS)
- WIN32_FIND_DATA finddata;
+ WIN32_FIND_DATAW finddata;
HANDLE handle;
- char buffer[1024*2];
+ char buffer[IO_MAX_PATH_LENGTH];
+ char buffer2[IO_MAX_PATH_LENGTH];
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
int length;
- str_format(buffer, sizeof(buffer), "%s/*", dir);
- handle = FindFirstFileA(buffer, &finddata);
+ str_format(buffer, sizeof(buffer), "%s/*", dir);
+ MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
- if (handle == INVALID_HANDLE_VALUE)
+ handle = FindFirstFileW(wBuffer, &finddata);
+ if(handle == INVALID_HANDLE_VALUE)
return;
str_format(buffer, sizeof(buffer), "%s/", dir);
@@ -1497,17 +1533,17 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
/* add all the entries */
do
{
- str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length);
- if(cb(finddata.cFileName, fs_is_dir(buffer), type, user))
+ WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
+ str_copy(buffer+length, buffer2, (int)sizeof(buffer)-length);
+ if(cb(buffer2, fs_is_dir(buffer), type, user))
break;
}
- while (FindNextFileA(handle, &finddata));
+ while(FindNextFileW(handle, &finddata));
FindClose(handle);
- return;
#else
struct dirent *entry;
- char buffer[1024*2];
+ char buffer[IO_MAX_PATH_LENGTH];
int length;
DIR *d = opendir(dir);
@@ -1526,22 +1562,24 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
/* close the directory and return */
closedir(d);
- return;
#endif
}
-void fs_listdir_fileinfo(const char* dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void* user)
+void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void *user)
{
#if defined(CONF_FAMILY_WINDOWS)
- WIN32_FIND_DATA finddata;
+ WIN32_FIND_DATAW finddata;
HANDLE handle;
- char buffer[1024*2];
+ char buffer[IO_MAX_PATH_LENGTH];
+ char buffer2[IO_MAX_PATH_LENGTH];
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
int length;
- str_format(buffer, sizeof(buffer), "%s/*", dir);
- handle = FindFirstFileA(buffer, &finddata);
+ str_format(buffer, sizeof(buffer), "%s/*", dir);
+ MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
- if (handle == INVALID_HANDLE_VALUE)
+ handle = FindFirstFileW(wBuffer, &finddata);
+ if(handle == INVALID_HANDLE_VALUE)
return;
str_format(buffer, sizeof(buffer), "%s/", dir);
@@ -1550,24 +1588,24 @@ void fs_listdir_fileinfo(const char* dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
/* add all the entries */
do
{
- str_copy(buffer+length, finddata.cFileName, (int)sizeof(buffer)-length);
+ WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
+ str_copy(buffer+length, buffer2, (int)sizeof(buffer)-length);
CFsFileInfo info;
- info.m_pName = finddata.cFileName;
+ info.m_pName = buffer2;
info.m_TimeCreated = filetime_to_unixtime(&finddata.ftCreationTime);
info.m_TimeModified = filetime_to_unixtime(&finddata.ftLastWriteTime);
if(cb(&info, fs_is_dir(buffer), type, user))
break;
}
- while (FindNextFileA(handle, &finddata));
+ while(FindNextFileW(handle, &finddata));
FindClose(handle);
- return;
#else
struct dirent *entry;
time_t created = -1, modified = -1;
- char buffer[1024*2];
+ char buffer[IO_MAX_PATH_LENGTH];
int length;
DIR *d = opendir(dir);
@@ -1594,17 +1632,18 @@ void fs_listdir_fileinfo(const char* dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
/* close the directory and return */
closedir(d);
- return;
#endif
}
int fs_storage_path(const char *appname, char *path, int max)
{
#if defined(CONF_FAMILY_WINDOWS)
- char *home = getenv("APPDATA");
+ WCHAR *home = _wgetenv(L"APPDATA");
+ char buffer[IO_MAX_PATH_LENGTH];
if(!home)
return -1;
- str_format(path, max, "%s/%s", home, appname);
+ WideCharToMultiByte(CP_UTF8, 0, home, -1, buffer, sizeof(buffer), NULL, NULL);
+ str_format(path, max, "%s/%s", buffer, appname);
return 0;
#else
char *home = getenv("HOME");
@@ -1656,8 +1695,10 @@ int fs_storage_path(const char *appname, char *path, int max)
int fs_makedir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
- if(_mkdir(path) == 0)
- return 0;
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
+ MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ if(_wmkdir(wBuffer) == 0)
+ return 0;
if(errno == EEXIST)
return 0;
return -1;
@@ -1698,46 +1739,35 @@ int fs_makedir_recursive(const char *path)
int fs_is_dir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
- /* TODO: do this smarter */
- WIN32_FIND_DATA finddata;
- HANDLE handle;
- char buffer[1024*2];
- str_format(buffer, sizeof(buffer), "%s/*", path);
-
- if ((handle = FindFirstFileA(buffer, &finddata)) == INVALID_HANDLE_VALUE)
- return 0;
-
- FindClose(handle);
- return 1;
+ WCHAR wPath[IO_MAX_PATH_LENGTH];
+ MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, sizeof(wPath) / sizeof(WCHAR));
+ DWORD attributes = GetFileAttributesW(wPath);
+ return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
#else
struct stat sb;
- if (stat(path, &sb) == -1)
- return 0;
-
- if (S_ISDIR(sb.st_mode))
- return 1;
- else
- return 0;
-#endif
-}
-
-time_t fs_getmtime(const char *path)
-{
- struct stat sb;
if(stat(path, &sb) == -1)
return 0;
-
- return sb.st_mtime;
+ return S_ISDIR(sb.st_mode) ? 1 : 0;
+#endif
}
int fs_chdir(const char *path)
{
if(fs_is_dir(path))
{
+#if defined(CONF_FAMILY_WINDOWS)
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
+ MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ if(_wchdir(wBuffer))
+ return 1;
+ else
+ return 0;
+#else
if(chdir(path))
return 1;
else
return 0;
+#endif
}
else
return 1;
@@ -1748,7 +1778,11 @@ char *fs_getcwd(char *buffer, int buffer_size)
if(buffer == 0)
return 0;
#if defined(CONF_FAMILY_WINDOWS)
- return _getcwd(buffer, buffer_size);
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
+ if(_wgetcwd(wBuffer, buffer_size) == 0)
+ return 0;
+ WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buffer, buffer_size, NULL, NULL);
+ return buffer;
#else
return getcwd(buffer, buffer_size);
#endif
@@ -1773,16 +1807,34 @@ int fs_parent_dir(char *path)
int fs_remove(const char *filename)
{
- if(remove(filename) != 0)
+#if defined(CONF_FAMILY_WINDOWS)
+ WCHAR wFilename[IO_MAX_PATH_LENGTH];
+ MultiByteToWideChar(CP_UTF8, 0, filename, -1, wFilename, sizeof(wFilename) / sizeof(WCHAR));
+ if(DeleteFileW(wFilename) == 0)
+ return 1;
+ return 0;
+#else
+ if(remove(filename))
return 1;
return 0;
+#endif
}
int fs_rename(const char *oldname, const char *newname)
{
- if(rename(oldname, newname) != 0)
+#if defined(CONF_FAMILY_WINDOWS)
+ WCHAR wOldname[IO_MAX_PATH_LENGTH];
+ WCHAR wNewname[IO_MAX_PATH_LENGTH];
+ MultiByteToWideChar(CP_UTF8, 0, oldname, -1, wOldname, sizeof(wOldname) / sizeof(WCHAR));
+ MultiByteToWideChar(CP_UTF8, 0, newname, -1, wNewname, sizeof(wNewname) / sizeof(WCHAR));
+ if(MoveFileExW(wOldname, wNewname, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) == 0)
return 1;
return 0;
+#else
+ if(rename(oldname, newname))
+ return 1;
+ return 0;
+#endif
}
int fs_read(const char *name, void **result, unsigned *result_len)
@@ -1815,8 +1867,12 @@ char *fs_read_str(const char *name)
int fs_file_time(const char *name, time_t *created, time_t *modified)
{
#if defined(CONF_FAMILY_WINDOWS)
- WIN32_FIND_DATA finddata;
- HANDLE handle = FindFirstFile(name, &finddata);
+ WIN32_FIND_DATAW finddata;
+ HANDLE handle;
+ WCHAR wBuffer[IO_MAX_PATH_LENGTH];
+
+ MultiByteToWideChar(CP_UTF8, 0, name, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
+ handle = FindFirstFileW(wBuffer, &finddata);
if(handle == INVALID_HANDLE_VALUE)
return 1;
@@ -2800,6 +2856,50 @@ int pid()
#endif
}
+void cmdline_fix(int *argc, const char ***argv)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+ int wide_argc = 0;
+ WCHAR **wide_argv = CommandLineToArgvW(GetCommandLineW(), &wide_argc);
+ dbg_assert(wide_argv != NULL, "CommandLineToArgvW failure");
+
+ int total_size = 0;
+
+ for(int i = 0; i < wide_argc; i++)
+ {
+ int size = WideCharToMultiByte(CP_UTF8, 0, wide_argv[i], -1, NULL, 0, NULL, NULL);
+ dbg_assert(size != 0, "WideCharToMultiByte failure");
+ total_size += size;
+ }
+
+ char **new_argv = (char **)malloc((wide_argc + 1) * sizeof(*new_argv));
+ new_argv[0] = (char *)malloc(total_size);
+ mem_zero(new_argv[0], total_size);
+
+ int remaining_size = total_size;
+ for(int i = 0; i < wide_argc; i++)
+ {
+ int size = WideCharToMultiByte(CP_UTF8, 0, wide_argv[i], -1, new_argv[i], remaining_size, NULL, NULL);
+ dbg_assert(size != 0, "WideCharToMultiByte failure");
+
+ remaining_size -= size;
+ new_argv[i + 1] = new_argv[i] + size;
+ }
+
+ new_argv[wide_argc] = 0;
+ *argc = wide_argc;
+ *argv = (const char **)new_argv;
+#endif
+}
+
+void cmdline_free(int argc, const char **argv)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+ free((void *)*argv);
+ free((char **)argv);
+#endif
+}
+
unsigned bytes_be_to_uint(const unsigned char *bytes)
{
return (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<<8) | bytes[3];
diff --git a/src/base/system.h b/src/base/system.h
index 0a4cc4764..b8af722fe 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -179,7 +179,7 @@ int mem_has_null(const void *block, unsigned size);
enum {
IOFLAG_READ = 1,
IOFLAG_WRITE = 2,
- IOFLAG_RANDOM = 4,
+ IOFLAG_APPEND = 4,
IOSEEK_START = 0,
IOSEEK_CUR = 1,
@@ -196,7 +196,7 @@ typedef struct IOINTERNAL *IOHANDLE;
Parameters:
filename - File to open.
- flags - A set of flags. IOFLAG_READ, IOFLAG_WRITE, IOFLAG_RANDOM.
+ flags - A set of flags. IOFLAG_READ, IOFLAG_WRITE, IOFLAG_APPEND.
Returns:
Returns a handle to the file on success and 0 on failure.
@@ -1336,13 +1336,11 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user);
typedef struct
{
- const char* m_pName;
+ const char *m_pName;
time_t m_TimeCreated; // seconds since UNIX Epoch
time_t m_TimeModified; // seconds since UNIX Epoch
} CFsFileInfo;
-/* Group: Filesystem */
-
/*
Function: fs_listdir_fileinfo
Lists the files in a directory and gets additional file information
@@ -1353,7 +1351,7 @@ typedef struct
type - Type of the directory
user - Pointer to give to the callback
*/
-typedef int (*FS_LISTDIR_CALLBACK_FILEINFO)(const CFsFileInfo* info, int is_dir, int dir_type, void *user);
+typedef int (*FS_LISTDIR_CALLBACK_FILEINFO)(const CFsFileInfo *info, int is_dir, int dir_type, void *user);
void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void *user);
/*
@@ -1409,12 +1407,6 @@ int fs_storage_path(const char *appname, char *path, int max);
int fs_is_dir(const char *path);
/*
- Function: fs_getmtime
- Gets the modification time of a file
-*/
-time_t fs_getmtime(const char *path);
-
-/*
Function: fs_chdir
Changes current working directory
@@ -1794,6 +1786,32 @@ void secure_random_fill(void *bytes, unsigned length);
int pid();
/*
+ Function: cmdline_fix
+ Fixes the command line arguments to be encoded in UTF-8 on all
+ systems.
+
+ Parameters:
+ argc - A pointer to the argc parameter that was passed to the main function.
+ argv - A pointer to the argv parameter that was passed to the main function.
+
+ Remarks:
+ - You need to call cmdline_free once you're no longer using the
+ results.
+*/
+void cmdline_fix(int *argc, const char ***argv);
+
+/*
+ Function: cmdline_free
+ Frees memory that was allocated by cmdline_fix.
+
+ Parameters:
+ argc - The argc obtained from cmdline_fix.
+ argv - The argv obtained from cmdline_fix.
+
+*/
+void cmdline_free(int argc, const char **argv);
+
+/*
Function: bytes_be_to_uint
Packs 4 big endian bytes into an unsigned
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index b9a2e0142..ad046c184 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -2559,6 +2559,7 @@ extern "C" int TWMain(int argc, const char **argv) // ignore_convention
int main(int argc, const char **argv) // ignore_convention
#endif
{
+ cmdline_fix(&argc, &argv);
#if defined(CONF_FAMILY_WINDOWS)
bool QuickEditMode = false;
for(int i = 1; i < argc; i++) // ignore_convention
@@ -2723,5 +2724,6 @@ int main(int argc, const char **argv) // ignore_convention
delete pEngineMap;
delete pEngineMasterServer;
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp
index 9cc5b3288..796f7de92 100644
--- a/src/engine/client/graphics_threaded.cpp
+++ b/src/engine/client/graphics_threaded.cpp
@@ -408,41 +408,35 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTexture(const char *pFilename,
int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType)
{
- char aCompleteFilename[IO_MAX_PATH_LENGTH];
- unsigned char *pBuffer;
- png_t Png; // ignore_convention
-
// open file for reading
- png_init(0,0); // ignore_convention
-
+ char aCompleteFilename[IO_MAX_PATH_LENGTH];
IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType, aCompleteFilename, sizeof(aCompleteFilename));
- if(File)
- io_close(File);
- else
+ if(!File)
{
dbg_msg("game/png", "failed to open file. filename='%s'", pFilename);
return 0;
}
- int Error = png_open_file(&Png, aCompleteFilename); // ignore_convention
+ png_init(0, 0); // ignore_convention
+ png_t Png; // ignore_convention
+ int Error = png_open_read(&Png, 0, File); // ignore_convention
if(Error != PNG_NO_ERROR)
{
- dbg_msg("game/png", "failed to open file. filename='%s'", aCompleteFilename);
- if(Error != PNG_FILE_ERROR)
- png_close_file(&Png); // ignore_convention
+ dbg_msg("game/png", "failed to read file. filename='%s'", aCompleteFilename);
+ io_close(File);
return 0;
}
if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA) || Png.width > (2<<12) || Png.height > (2<<12)) // ignore_convention
{
dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename);
- png_close_file(&Png); // ignore_convention
+ io_close(File);
return 0;
}
- pBuffer = (unsigned char *)mem_alloc(Png.width * Png.height * Png.bpp); // ignore_convention
+ unsigned char *pBuffer = (unsigned char *)mem_alloc(Png.width * Png.height * Png.bpp); // ignore_convention
png_get_data(&Png, pBuffer); // ignore_convention
- png_close_file(&Png); // ignore_convention
+ io_close(File);
pImg->m_Width = Png.width; // ignore_convention
pImg->m_Height = Png.height; // ignore_convention
@@ -483,21 +477,23 @@ void CGraphics_Threaded::ScreenshotDirect(const char *pFilename)
if(Image.m_pData)
{
// find filename
- char aWholePath[1024];
- png_t Png; // ignore_convention
-
+ char aWholePath[IO_MAX_PATH_LENGTH];
+ char aBuf[IO_MAX_PATH_LENGTH+32];
IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath));
if(File)
+ {
+ // save png
+ png_t Png; // ignore_convention
+ png_open_write(&Png, 0, File); // ignore_convention
+ png_set_data(&Png, Image.m_Width, Image.m_Height, 8, PNG_TRUECOLOR, (unsigned char *)Image.m_pData); // ignore_convention
io_close(File);
-
- // save png
- char aBuf[256];
- str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
- m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
- png_open_file_write(&Png, aWholePath); // ignore_convention
- png_set_data(&Png, Image.m_Width, Image.m_Height, 8, PNG_TRUECOLOR, (unsigned char *)Image.m_pData); // ignore_convention
- png_close_file(&Png); // ignore_convention
-
+ str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath);
+ }
+ else
+ {
+ str_format(aBuf, sizeof(aBuf), "failed to open file '%s'", pFilename);
+ }
+ m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client/screenshot", aBuf);
mem_free(Image.m_pData);
}
}
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index d3375782e..2f170fc9c 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -1819,6 +1819,7 @@ void HandleSigInt(int Param)
int main(int argc, const char **argv) // ignore_convention
{
+ cmdline_fix(&argc, &argv);
#if defined(CONF_FAMILY_WINDOWS)
for(int i = 1; i < argc; i++) // ignore_convention
{
@@ -1923,5 +1924,6 @@ int main(int argc, const char **argv) // ignore_convention
delete pStorage;
delete pConfigManager;
+ cmdline_free(argc, argv);
return Ret;
}
diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp
index 624a9f3fe..e19672313 100644
--- a/src/mastersrv/mastersrv.cpp
+++ b/src/mastersrv/mastersrv.cpp
@@ -280,14 +280,11 @@ void ReloadBans()
m_pConsole->ExecuteFile("master.cfg");
}
-int main(int argc, const char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
- int64 LastBuild = 0, LastBanReload = 0;
- ServerType Type = SERVERTYPE_INVALID;
- NETADDR BindAddr;
-
dbg_logger_stdout();
-
+ cmdline_fix(&argc, &argv);
+
mem_copy(m_CountData.m_Header, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT));
int FlagMask = CFGFLAG_MASTER;
@@ -307,9 +304,10 @@ int main(int argc, const char **argv) // ignore_convention
pConfigManager->Init(FlagMask);
m_pConsole->Init();
m_NetBan.Init(m_pConsole, pStorage);
- if(argc > 1) // ignore_convention
- m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
+ if(argc > 1)
+ m_pConsole->ParseArguments(argc-1, &argv[1]);
+ NETADDR BindAddr;
if(pConfig->m_Bindaddr[0] && net_host_lookup(pConfig->m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
{
// got bindaddr
@@ -345,6 +343,8 @@ int main(int argc, const char **argv) // ignore_convention
dbg_msg("mastersrv", "started");
+ int64 LastBuild = 0, LastBanReload = 0;
+ ServerType Type = SERVERTYPE_INVALID;
while(1)
{
m_NetOp.Update();
@@ -460,5 +460,6 @@ int main(int argc, const char **argv) // ignore_convention
thread_sleep(1);
}
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/test/test.cpp b/src/test/test.cpp
index c14df1dd3..ccef77b33 100644
--- a/src/test/test.cpp
+++ b/src/test/test.cpp
@@ -17,9 +17,12 @@ void CTestInfo::Filename(char *pBuffer, int BufferLength, const char *pSuffix)
str_format(pBuffer, BufferLength, "%s%s", m_aFilenamePrefix, pSuffix);
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
- ::testing::InitGoogleTest(&argc, argv);
+ cmdline_fix(&argc, &argv);
+ ::testing::InitGoogleTest(&argc, const_cast<char **>(argv));
net_init();
- return RUN_ALL_TESTS();
+ int Result = RUN_ALL_TESTS();
+ cmdline_free(argc, argv);
+ return Result;
}
diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp
index 20cea2bde..146f1fb48 100644
--- a/src/tools/crapnet.cpp
+++ b/src/tools/crapnet.cpp
@@ -206,7 +206,7 @@ void Run(unsigned short Port, NETADDR Dest)
}
}
-int main(int argc, char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
NETADDR Addr = {NETTYPE_IPV4, {127,0,0,1},8303};
dbg_logger_stdout();
diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp
index 81bb1cebb..0e1e481a8 100644
--- a/src/tools/fake_server.cpp
+++ b/src/tools/fake_server.cpp
@@ -148,8 +148,10 @@ static int Run()
}
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
+ cmdline_fix(&argc, &argv);
+
pNet = new CNetServer;
while(argc)
@@ -214,6 +216,7 @@ int main(int argc, char **argv)
int RunReturn = Run();
delete pNet;
+ cmdline_free(argc, argv);
return RunReturn;
}
diff --git a/src/tools/map_resave.cpp b/src/tools/map_resave.cpp
index 0a624b0f4..45d025e39 100644
--- a/src/tools/map_resave.cpp
+++ b/src/tools/map_resave.cpp
@@ -6,40 +6,40 @@
int main(int argc, const char **argv)
{
- IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
- int Index, ID = 0, Type = 0, Size;
- void *pPtr;
- char aFileName[1024];
- CDataFileReader DataFile;
- CDataFileWriter df;
+ cmdline_fix(&argc, &argv);
+ IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
if(!pStorage || argc != 3)
return -1;
- str_format(aFileName, sizeof(aFileName), "%s", argv[2]);
-
- if(!DataFile.Open(pStorage, argv[1], IStorage::TYPE_ALL))
+ CDataFileReader Reader;
+ if(!Reader.Open(pStorage, argv[1], IStorage::TYPE_ALL))
return -1;
- if(!df.Open(pStorage, aFileName))
+
+ CDataFileWriter Writer;
+ if(!Writer.Open(pStorage, argv[2]))
return -1;
// add all items
- for(Index = 0; Index < DataFile.NumItems(); Index++)
+ for(int Index = 0; Index < Reader.NumItems(); Index++)
{
- pPtr = DataFile.GetItem(Index, &Type, &ID);
- Size = DataFile.GetItemSize(Index);
- df.AddItem(Type, ID, Size, pPtr);
+ int Type, ID;
+ void *pPtr = Reader.GetItem(Index, &Type, &ID);
+ int Size = Reader.GetItemSize(Index);
+ Writer.AddItem(Type, ID, Size, pPtr);
}
// add all data
- for(Index = 0; Index < DataFile.NumData(); Index++)
+ for(int Index = 0; Index < Reader.NumData(); Index++)
{
- pPtr = DataFile.GetData(Index);
- Size = DataFile.GetDataSize(Index);
- df.AddData(Size, pPtr);
+ void *pPtr = Reader.GetData(Index);
+ int Size = Reader.GetDataSize(Index);
+ Writer.AddData(Size, pPtr);
}
- DataFile.Close();
- df.Finish();
+ Reader.Close();
+ Writer.Finish();
+
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/tools/map_version.cpp b/src/tools/map_version.cpp
index fbeb27d74..55b28c3a4 100644
--- a/src/tools/map_version.cpp
+++ b/src/tools/map_version.cpp
@@ -46,8 +46,10 @@ io_write(s_File, aBuf, str_length(aBuf));
return 0;
}
-int main(int argc, const char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
+ cmdline_fix(&argc, &argv);
+
IKernel *pKernel = IKernel::Create();
s_pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_BASIC, argc, argv);
s_pEngineMap = CreateEngineMap();
@@ -67,5 +69,6 @@ int main(int argc, const char **argv) // ignore_convention
io_close(s_File);
}
+ cmdline_free(argc, argv);
return 0;
}
diff --git a/src/tools/packetgen.cpp b/src/tools/packetgen.cpp
index 0d3f5c0e2..25fa7ebf8 100644
--- a/src/tools/packetgen.cpp
+++ b/src/tools/packetgen.cpp
@@ -28,7 +28,7 @@ void Run(NETADDR Dest)
}
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
NETADDR Dest = {NETTYPE_IPV4, {127,0,0,1}, 8303};
Run(Dest);
diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp
index 698251060..1413d8baa 100644
--- a/src/versionsrv/versionsrv.cpp
+++ b/src/versionsrv/versionsrv.cpp
@@ -79,11 +79,10 @@ void SendVer(NETADDR *pAddr, TOKEN ResponseToken)
g_NetOp.Send(&p, ResponseToken);
}
-int main(int argc, const char **argv) // ignore_convention
+int main(int argc, const char **argv)
{
- NETADDR BindAddr;
-
dbg_logger_stdout();
+ cmdline_fix(&argc, &argv);
int FlagMask = 0;
IKernel *pKernel = IKernel::Create();
@@ -100,6 +99,7 @@ int main(int argc, const char **argv) // ignore_convention
pConfigManager->Init(FlagMask);
pConsole->Init();
+ NETADDR BindAddr;
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
BindAddr.port = VERSIONSRV_PORT;
@@ -155,5 +155,6 @@ int main(int argc, const char **argv) // ignore_convention
thread_sleep(1);
}
+ cmdline_free(argc, argv);
return 0;
}