diff options
author | Martin Storsjö <martin@martin.st> | 2014-11-18 00:08:15 +0300 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2014-11-25 00:36:29 +0300 |
commit | 960aff379da46dcaff61504a57714d4d4e758e41 (patch) | |
tree | bc7789d4d4435845a5bb99e94c7e8933c397a2e9 | |
parent | b9d08c77a44390b0848c06f20bc0e9e951ba6a3c (diff) |
lavf: Use wchar functions for filenames on windows for mkdir/rmdir/rename/unlink
This makes sure that the internal utf8 path names are handled
properly - the normal file handling functions assume path names
are in the native codepage, which isn't utf8.
This assumes that the tools outside of lavf don't use the mkdir
definition. (The tools don't do the same reading of command line
parameters as wchar either - they probably won't handle all possible
unicode file parameters properly, but at least work more predictably
if no utf8/wchar conversion is involved.)
This is moved further down in os_support.h, since windows.h shouldn't
be included before winsock2.h, while io.h needs to be included before
the manual defines for lseek functions.
Signed-off-by: Martin Storsjö <martin@martin.st>
-rw-r--r-- | libavformat/internal.h | 1 | ||||
-rw-r--r-- | libavformat/os_support.h | 100 |
2 files changed, 92 insertions, 9 deletions
diff --git a/libavformat/internal.h b/libavformat/internal.h index 5feb0f8434..d69ce492fa 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -23,6 +23,7 @@ #include <stdint.h> #include "avformat.h" +#include "os_support.h" #define MAX_URL_SIZE 4096 diff --git a/libavformat/os_support.h b/libavformat/os_support.h index 068abdfa33..50846d0f41 100644 --- a/libavformat/os_support.h +++ b/libavformat/os_support.h @@ -31,6 +31,15 @@ #include <sys/stat.h> +#ifdef _WIN32 +#if HAVE_DIRECT_H +#include <direct.h> +#endif +#if HAVE_IO_H +#include <io.h> +#endif +#endif + #if defined(_WIN32) && !defined(__MINGW32CE__) # include <fcntl.h> # undef lseek @@ -41,15 +50,6 @@ # define fstat(f,s) _fstati64((f), (s)) #endif /* defined(_WIN32) && !defined(__MINGW32CE__) */ -#ifdef _WIN32 -#if HAVE_DIRECT_H -#include <direct.h> -#elif HAVE_IO_H -#include <io.h> -#endif -#define mkdir(a, b) _mkdir(a) -#endif - static inline int is_dos_path(const char *path) { #if HAVE_DOS_PATHS @@ -122,4 +122,86 @@ int ff_poll(struct pollfd *fds, nfds_t numfds, int timeout); #endif /* HAVE_POLL_H */ #endif /* CONFIG_NETWORK */ +#if defined(__MINGW32CE__) +#define mkdir(a, b) _mkdir(a) +#elif defined(_WIN32) +#include <stdio.h> +#include <windows.h> +#include "libavutil/mem.h" + +static inline int utf8towchar(const char *filename_utf8, wchar_t **filename_w) +{ + int num_chars; + num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0); + if (num_chars <= 0) { + *filename_w = NULL; + return 0; + } + *filename_w = av_mallocz(sizeof(wchar_t) * num_chars); + if (!*filename_w) { + errno = ENOMEM; + return -1; + } + MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars); + return 0; +} + +#define DEF_FS_FUNCTION(name, wfunc, afunc) \ +static inline int win32_##name(const char *filename_utf8) \ +{ \ + wchar_t *filename_w; \ + int ret; \ + \ + if (utf8towchar(filename_utf8, &filename_w)) \ + return -1; \ + if (!filename_w) \ + goto fallback; \ + \ + ret = wfunc(filename_w); \ + av_free(filename_w); \ + return ret; \ + \ +fallback: \ + /* filename may be be in CP_ACP */ \ + return afunc(filename_utf8); \ +} + +DEF_FS_FUNCTION(unlink, _wunlink, _unlink) +DEF_FS_FUNCTION(mkdir, _wmkdir, _mkdir) +DEF_FS_FUNCTION(rmdir, _wrmdir , _rmdir) + +static inline int win32_rename(const char *src_utf8, const char *dest_utf8) +{ + wchar_t *src_w, *dest_w; + int ret; + + if (utf8towchar(src_utf8, &src_w)) + return -1; + if (utf8towchar(dest_utf8, &dest_w)) { + av_free(src_w); + return -1; + } + if (!src_w || !dest_w) { + av_free(src_w); + av_free(dest_w); + goto fallback; + } + + ret = _wrename(src_w, dest_w); + av_free(src_w); + av_free(dest_w); + return ret; + +fallback: + /* filename may be be in CP_ACP */ + return rename(src_utf8, dest_utf8); +} + +#define mkdir(a, b) win32_mkdir(a) +#define rename win32_rename +#define rmdir win32_rmdir +#define unlink win32_unlink + +#endif + #endif /* AVFORMAT_OS_SUPPORT_H */ |