Merge pull request #5552 from bparker06/win32_file_encoding

win32: support local multibyte encoding for file paths
This commit is contained in:
Twinaphex 2017-10-15 13:07:18 +02:00 committed by GitHub
commit e86e237ed7
11 changed files with 175 additions and 13 deletions

View File

@ -3701,15 +3701,15 @@ bool config_save_file(const char *path)
if (settings->bools.ssh_enable)
fclose(fopen(LAKKA_SSH_PATH, "w"));
else
remove(LAKKA_SSH_PATH);
path_file_remove(LAKKA_SSH_PATH);
if (settings->bools.samba_enable)
fclose(fopen(LAKKA_SAMBA_PATH, "w"));
else
remove(LAKKA_SAMBA_PATH);
path_file_remove(LAKKA_SAMBA_PATH);
if (settings->bools.bluetooth_enable)
fclose(fopen(LAKKA_BLUETOOTH_PATH, "w"));
else
remove(LAKKA_BLUETOOTH_PATH);
path_file_remove(LAKKA_BLUETOOTH_PATH);
#endif
for (i = 0; i < MAX_USERS; i++)

View File

@ -241,7 +241,7 @@ bool input_remapping_remove_file(const char *path)
fill_pathname_noext(remap_file, buf, ".rmp", path_size);
ret = remove(remap_file) == 0 ? true : false;;
ret = path_file_remove(remap_file) == 0 ? true : false;;
free(buf);
free(remap_file);
return ret;

View File

@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
@ -31,6 +32,15 @@
#include <encodings/utf.h>
#if defined(_WIN32) && !defined(_XBOX)
#include <windows.h>
/* Starting with Windows 8: MultiByteToWideChar is declared in stringapiset.h. Before Windows 8, it was declared in winnls.h (which windows.h includes for us). */
#ifndef MultiByteToWideChar
#include <stringapiset.h>
#endif
#endif
static INLINE unsigned leading_ones(uint8_t c)
{
unsigned ones = 0;
@ -267,3 +277,81 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
return ret;
}
/* Returned pointer MUST be freed by the caller if non-NULL. */
static char* mb_to_mb_string_alloc(const char *str, enum CodePage cp_in, enum CodePage cp_out)
{
char *path_buf = NULL;
wchar_t *path_buf_wide = NULL;
int path_buf_len = 0;
int path_buf_wide_len = 0;
if (!str || !*str)
return NULL;
#if !defined(_WIN32) || defined(_XBOX)
/* assume string needs no modification if not on Windows */
return strdup(str);
#else
#ifdef UNICODE
/* TODO/FIXME: Not implemented. */
return strdup(str);
#else
path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
if (path_buf_wide_len)
{
path_buf_wide = (wchar_t*)calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
if (path_buf_wide)
{
MultiByteToWideChar(cp_in, 0, str, -1, path_buf_wide, path_buf_wide_len);
if (*path_buf_wide)
{
path_buf_len = WideCharToMultiByte(cp_out, 0, path_buf_wide, -1, NULL, 0, NULL, NULL);
if (path_buf_len)
{
path_buf = (char*)calloc(path_buf_len + sizeof(char), sizeof(char));
if (path_buf)
{
WideCharToMultiByte(cp_out, 0, path_buf_wide, -1, path_buf, path_buf_len, NULL, NULL);
free(path_buf_wide);
if (*path_buf)
return path_buf;
else
{
free(path_buf);
return NULL;
}
}
}
}
}
}
#endif
#endif
if (path_buf_wide)
free(path_buf_wide);
return NULL;
}
/* Returned pointer MUST be freed by the caller if non-NULL. */
char* utf8_to_local_string_alloc(const char *str)
{
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
}
/* Returned pointer MUST be freed by the caller if non-NULL. */
char* local_to_utf8_string_alloc(const char *str)
{
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
}

View File

@ -37,6 +37,7 @@
#endif
#include <compat/strcasestr.h>
#include <retro_miscellaneous.h>
#include <encodings/utf.h>
#if defined(_WIN32)
#ifdef _MSC_VER
@ -115,9 +116,18 @@ static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
return false;
#elif defined(_WIN32)
struct _stat buf;
DWORD file_info = GetFileAttributes(path);
_stat(path, &buf);
if (!path || !*path)
return false;
char *path_local = utf8_to_local_string_alloc(path);
DWORD file_info = GetFileAttributes(path_local);
_stat(path_local, &buf);
if (path_local)
free(path_local);
if (file_info == INVALID_FILE_ATTRIBUTES)
return false;
@ -365,8 +375,8 @@ bool path_is_compressed_file(const char* path)
* Returns: true (1) if file already exists, otherwise false (0).
*/
bool path_file_exists(const char *path)
{
FILE *dummy;
{
FILE *dummy;
if (!path || !*path)
return false;
@ -884,3 +894,24 @@ void fill_short_pathname_representation_noext(char* out_rep,
fill_short_pathname_representation(out_rep, in_path, size);
path_remove_extension(out_rep);
}
int path_file_remove(const char *path)
{
if (!path || !*path)
return false;
#if defined(_WIN32) && !defined(_XBOX)
char *path_local = utf8_to_local_string_alloc(path);
if (path_local)
{
bool ret = remove(path_local);
free(path_local);
return ret;
}
#else
return remove(path);
#endif
return -1;
}

View File

@ -28,6 +28,8 @@
#include <boolean.h>
#include <retro_dirent.h>
#include <encodings/utf.h>
#include <compat/strl.h>
#if defined(_WIN32)
# ifdef _MSC_VER
@ -89,6 +91,7 @@ struct RDIR *retro_opendir(const char *name)
{
#if defined(_WIN32)
char path_buf[1024];
char *path_local = NULL;
#endif
struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir));
@ -98,7 +101,11 @@ struct RDIR *retro_opendir(const char *name)
#if defined(_WIN32)
path_buf[0] = '\0';
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
rdir->directory = FindFirstFile(path_buf, &rdir->entry);
path_local = utf8_to_local_string_alloc(path_buf);
rdir->directory = FindFirstFile(path_local, &rdir->entry);
if (path_local)
free(path_local);
#elif defined(VITA) || defined(PSP)
rdir->directory = sceIoDopen(name);
#elif defined(_3DS)
@ -149,6 +156,12 @@ int retro_readdir(struct RDIR *rdir)
const char *retro_dirent_get_name(struct RDIR *rdir)
{
#if defined(_WIN32)
char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName);
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName));
if (name_local)
free(name_local);
return rdir->entry.cFileName;
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
return rdir->entry.d_name;

View File

@ -32,6 +32,12 @@
RETRO_BEGIN_DECLS
enum CodePage
{
CODEPAGE_LOCAL = 0, /* CP_ACP */
CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
};
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
const char *in, size_t in_size);
@ -48,6 +54,10 @@ uint32_t utf8_walk(const char **string);
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len);
char* utf8_to_local_string_alloc(const char *str);
char* local_to_utf8_string_alloc(const char *str);
RETRO_END_DECLS
#endif

View File

@ -466,6 +466,8 @@ bool path_is_valid(const char *path);
int32_t path_get_size(const char *path);
int path_file_remove(const char *path);
RETRO_END_DECLS
#endif

View File

@ -65,6 +65,7 @@
#include <string/stdstring.h>
#include <memmap.h>
#include <retro_miscellaneous.h>
#include <encodings/utf.h>
struct RFILE
{
@ -140,6 +141,9 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
const char *mode_str = NULL;
#endif
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
#if defined(_WIN32) && !defined(_XBOX)
char *path_local = NULL;
#endif
if (!stream)
return NULL;
@ -228,7 +232,14 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0 && mode_str)
{
#if defined(_WIN32) && !defined(_XBOX)
path_local = utf8_to_local_string_alloc(path);
stream->fp = fopen(path_local, mode_str);
if (path_local)
free(path_local);
#else
stream->fp = fopen(path, mode_str);
#endif
if (!stream->fp)
goto error;
}
@ -236,7 +247,14 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
#endif
{
/* FIXME: HAVE_BUFFERED_IO is always 1, but if it is ever changed, open() needs to be changed to _wopen() for WIndows. */
#if defined(_WIN32) && !defined(_XBOX)
path_local = utf8_to_local_string_alloc(path);
stream->fd = open(path_local, flags, mode_int);
if (path_local)
free(path_local);
#else
stream->fd = open(path, flags, mode_int);
#endif
if (stream->fd == -1)
goto error;
#ifdef HAVE_MMAP

View File

@ -2643,7 +2643,7 @@ static void cb_decompressed(void *task_data, void *user_data, const char *err)
if (dec)
{
if (path_file_exists(dec->source_file))
remove(dec->source_file);
path_file_remove(dec->source_file);
free(dec->source_file);
free(dec);
@ -4242,7 +4242,7 @@ static int action_ok_core_delete(const char *path,
generic_action_ok_command(CMD_EVENT_UNLOAD_CORE);
menu_entries_flush_stack(0, 0);
if (remove(core_path) != 0) { }
if (path_file_remove(core_path) != 0) { }
free(core_path);

View File

@ -1860,7 +1860,7 @@ static void systemd_service_toggle(const char *path, char *unit, bool enable)
if (enable)
fclose(fopen(path, "w"));
else
remove(path);
path_file_remove(path);
if (pid == 0)
execvp(args[0], args);

View File

@ -1717,7 +1717,7 @@ void content_deinit(void)
RARCH_LOG("%s: %s.\n",
msg_hash_to_str(MSG_REMOVING_TEMPORARY_CONTENT_FILE), path);
if (remove(path) < 0)
if (path_file_remove(path) < 0)
RARCH_ERR("%s: %s.\n",
msg_hash_to_str(MSG_FAILED_TO_REMOVE_TEMPORARY_FILE),
path);