[libav-commits] lavf: Use wchar functions for filenames on windows for mkdir/rmdir/rename/ unlink

Martin Storsjö git at libav.org
Mon Nov 24 22:42:36 CET 2014


Module: libav
Branch: master
Commit: 960aff379da46dcaff61504a57714d4d4e758e41

Author:    Martin Storsjö <martin at martin.st>
Committer: Martin Storsjö <martin at martin.st>
Date:      Mon Nov 17 23:08:15 2014 +0200

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 at martin.st>

---

 libavformat/internal.h   |    1 +
 libavformat/os_support.h |  100 +++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 92 insertions(+), 9 deletions(-)

diff --git a/libavformat/internal.h b/libavformat/internal.h
index 5feb0f8..d69ce49 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 068abdf..50846d0 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 */



More information about the libav-commits mailing list