aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorMartin Storsjö <martin@martin.st>2014-11-17 23:08:15 +0200
committerMartin Storsjö <martin@martin.st>2014-11-24 23:36:29 +0200
commit960aff379da46dcaff61504a57714d4d4e758e41 (patch)
treebc7789d4d4435845a5bb99e94c7e8933c397a2e9 /libavformat
parentb9d08c77a44390b0848c06f20bc0e9e951ba6a3c (diff)
downloadffmpeg-960aff379da46dcaff61504a57714d4d4e758e41.tar.gz
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>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/internal.h1
-rw-r--r--libavformat/os_support.h100
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 */