LGPL
[vlc.git] / src / win32 / filesystem.c
index dfcaee8..3819437 100644 (file)
@@ -1,24 +1,24 @@
 /*****************************************************************************
  * filesystem.c: Windows file system helpers
  *****************************************************************************
- * Copyright (C) 2005-2006 the VideoLAN team
+ * Copyright (C) 2005-2006 VLC authors and VideoLAN
  * Copyright © 2005-2008 Rémi Denis-Courmont
  *
  * Authors: Rémi Denis-Courmont <rem # videolan.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 # include <tchar.h>
 #endif
 
-static int convert_path (const char *restrict path, wchar_t *restrict wpath)
+static wchar_t *widen_path (const char *path)
 {
-    if (!MultiByteToWideChar (CP_UTF8, 0, path, -1, wpath, MAX_PATH))
+    wchar_t *wpath;
+
+    errno = 0;
+    wpath = ToWide (path);
+    if (wpath == NULL)
     {
-        errno = ENOENT;
-        return -1;
+        if (errno == 0)
+            errno = ENOENT;
+        return NULL;
     }
-    wpath[MAX_PATH] = L'\0';
-    return 0;
+    return wpath;
 }
+
 #define CONVERT_PATH(path, wpath, err) \
-  wchar_t wpath[MAX_PATH+1]; \
-  if (convert_path (path, wpath)) \
-      return (err)
+    wchar_t *wpath = wide_path(path); \
+    if (wpath == NULL) return (err)
+
 
 int vlc_open (const char *filename, int flags, ...)
 {
@@ -73,6 +78,10 @@ int vlc_open (const char *filename, int flags, ...)
         mode = va_arg (ap, unsigned int);
     va_end (ap);
 
+    /* Defaults to binary mode */
+    if ((flags & O_TEXT) == 0)
+        flags |= O_BINARY;
+
 #ifdef UNDER_CE
     /*_open translates to wchar internally on WinCE*/
     return _open (filename, flags, mode);
@@ -81,9 +90,13 @@ int vlc_open (const char *filename, int flags, ...)
      * open() cannot open files with non-“ANSI” characters on Windows.
      * We use _wopen() instead. Same thing for mkdir() and stat().
      */
-    CONVERT_PATH(filename, wpath, -1);
-    return _wopen (wpath, flags, mode);
+    wchar_t *wpath = widen_path (filename);
+    if (wpath == NULL)
+        return -1;
 
+    int fd = _wopen (wpath, flags, mode);
+    free (wpath);
+    return fd;
 #endif
 }
 
@@ -101,10 +114,29 @@ int vlc_mkdir( const char *dirname, mode_t mode )
     /* mkdir converts internally to wchar */
     return _mkdir(dirname);
 #else
+    wchar_t *wpath = widen_path (dirname);
+    if (wpath == NULL)
+        return -1;
+
+    int ret = _wmkdir (wpath);
+    free (wpath);
     (void) mode;
-    CONVERT_PATH (dirname, wpath, -1);
-    return _wmkdir (wpath);
+    return ret;
+#endif
+}
+
+char *vlc_getcwd (void)
+{
+#ifndef UNDER_CE
+    wchar_t *wdir = _wgetcwd (NULL, 0);
+    if (wdir == NULL)
+        return NULL;
 
+    char *dir = FromWide (wdir);
+    free (wdir);
+    return dir;
+#else
+    return NULL;
 #endif
 }
 
@@ -123,15 +155,20 @@ typedef struct vlc_DIR
 
 DIR *vlc_opendir (const char *dirname)
 {
-    CONVERT_PATH (dirname, wpath, NULL);
+    wchar_t *wpath = widen_path (dirname);
+    if (wpath == NULL)
+        return NULL;
 
     vlc_DIR *p_dir = malloc (sizeof (*p_dir));
     if (unlikely(p_dir == NULL))
+    {
+        free(wpath);
         return NULL;
+    }
 
-    if (wpath == NULL || wpath[0] == '\0'
-     || (wcscmp (wpath, L"\\") == 0))
+    if (wpath[0] == L'\0' || (wcscmp (wpath, L"\\") == 0))
     {
+        free (wpath);
         /* Special mode to list drive letters */
         p_dir->wdir = NULL;
 #ifdef UNDER_CE
@@ -142,16 +179,17 @@ DIR *vlc_opendir (const char *dirname)
         return (void *)p_dir;
     }
 
+    assert (wpath[0]); // wpath[1] is defined
+    p_dir->u.insert_dot_dot = !wcscmp (wpath + 1, L":\\");
+
     _WDIR *wdir = _wopendir (wpath);
+    free (wpath);
     if (wdir == NULL)
     {
         free (p_dir);
         return NULL;
     }
-
     p_dir->wdir = wdir;
-    assert (wpath[0]); // wpath[1] is defined
-    p_dir->u.insert_dot_dot = !wcscmp (wpath + 1, L":\\");
     return (void *)p_dir;
 }
 
@@ -201,8 +239,13 @@ int vlc_stat (const char *filename, struct stat *buf)
     /* _stat translates to wchar internally on WinCE */
     return _stat (filename, buf);
 #else
-    CONVERT_PATH (filename, wpath, -1);
-    return _wstati64 (wpath, buf);
+    wchar_t *wpath = widen_path (filename);
+    if (wpath == NULL)
+        return -1;
+
+    int ret = _wstati64 (wpath, buf);
+    free (wpath);
+    return ret;
 #endif
 }
 
@@ -217,31 +260,45 @@ int vlc_unlink (const char *filename)
     /*_open translates to wchar internally on WinCE*/
     return _unlink( filename );
 #else
-    CONVERT_PATH (filename, wpath, -1);
-    return _wunlink (wpath);
+    wchar_t *wpath = widen_path (filename);
+    if (wpath == NULL)
+        return -1;
+
+    int ret = _wunlink (wpath);
+    free (wpath);
+    return ret;
 #endif
 }
 
 int vlc_rename (const char *oldpath, const char *newpath)
 {
-    CONVERT_PATH (oldpath, wold, -1);
-    CONVERT_PATH (newpath, wnew, -1);
+    int ret = -1;
+
+    wchar_t *wold = widen_path (oldpath), *wnew = widen_path (newpath);
+    if (wold == NULL || wnew == NULL)
+        goto out;
+
 # ifdef UNDER_CE
     /* FIXME: errno support */
-    return MoveFileW (wold, wnew) ? 0 : -1;
+    if (MoveFileW (wold, wnew))
+        ret = 0;
 #else
     if (_wrename (wold, wnew) && (errno == EACCES || errno == EEXIST))
     {   /* Windows does not allow atomic file replacement */
         if (_wremove (wnew))
         {
             errno = EACCES; /* restore errno */
-            return -1;
+            goto out;
         }
         if (_wrename (wold, wnew))
-            return -1;
+            goto out;
     }
-    return 0;
+    ret = 0;
 #endif
+out:
+    free (wnew);
+    free (wold);
+    return ret;
 }
 
 int vlc_dup (int oldfd)