]> git.sesse.net Git - vlc/blobdiff - src/win32/filesystem.c
Contribs: put WinCE higher than mingw, because mingw* can match mingwce
[vlc] / src / win32 / filesystem.c
index d6a84c4b06e1c6eba822f4917cdb2f63524ed6d7..dfcaee8032cca02f2aed547ab113eaa5921c114d 100644 (file)
@@ -108,18 +108,90 @@ int vlc_mkdir( const char *dirname, mode_t mode )
 #endif
 }
 
-DIR *vlc_opendir( const char *dirname )
+/* Under Windows, these wrappers return the list of drive letters
+ * when called with an empty argument or just '\'. */
+typedef struct vlc_DIR
+{
+    _WDIR *wdir; /* MUST be first, see <vlc_fs.h> */
+    union
+    {
+        DWORD drives;
+        bool insert_dot_dot;
+    } u;
+} vlc_DIR;
+
+
+DIR *vlc_opendir (const char *dirname)
 {
     CONVERT_PATH (dirname, wpath, NULL);
-    return (DIR *)vlc_wopendir (wpath);
+
+    vlc_DIR *p_dir = malloc (sizeof (*p_dir));
+    if (unlikely(p_dir == NULL))
+        return NULL;
+
+    if (wpath == NULL || wpath[0] == '\0'
+     || (wcscmp (wpath, L"\\") == 0))
+    {
+        /* Special mode to list drive letters */
+        p_dir->wdir = NULL;
+#ifdef UNDER_CE
+        p_dir->u.drives = 1;
+#else
+        p_dir->u.drives = GetLogicalDrives ();
+#endif
+        return (void *)p_dir;
+    }
+
+    _WDIR *wdir = _wopendir (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;
 }
 
-char *vlc_readdir( DIR *dir )
+char *vlc_readdir (DIR *dir)
 {
-    struct _wdirent *ent = vlc_wreaddir (dir);
+    vlc_DIR *p_dir = (vlc_DIR *)dir;
+
+    if (p_dir->wdir == NULL)
+    {
+        /* Drive letters mode */
+        DWORD drives = p_dir->u.drives;
+        if (drives == 0)
+            return NULL; /* end */
+#ifdef UNDER_CE
+        p_dir->u.drives = 0;
+        return strdup ("\\");
+#else
+        unsigned int i;
+        for (i = 0; !(drives & 1); i++)
+            drives >>= 1;
+        p_dir->u.drives &= ~(1UL << i);
+        assert (i < 26);
+
+        char *ret;
+        if (asprintf (&ret, "%c:\\", 'A' + i) == -1)
+            return NULL;
+        return ret;
+#endif
+    }
+
+    if (p_dir->u.insert_dot_dot)
+    {
+        /* Adds "..", gruik! */
+        p_dir->u.insert_dot_dot = false;
+        return strdup ("..");
+    }
+
+    struct _wdirent *ent = _wreaddir (p_dir->wdir);
     if (ent == NULL)
         return NULL;
-
     return FromWide (ent->d_name);
 }
 
@@ -158,7 +230,7 @@ int vlc_rename (const char *oldpath, const char *newpath)
     /* FIXME: errno support */
     return MoveFileW (wold, wnew) ? 0 : -1;
 #else
-    if (_wrename (wold, wnew) && errno == EACCES)
+    if (_wrename (wold, wnew) && (errno == EACCES || errno == EEXIST))
     {   /* Windows does not allow atomic file replacement */
         if (_wremove (wnew))
         {
@@ -183,6 +255,17 @@ int vlc_dup (int oldfd)
 #endif
 }
 
+int vlc_pipe (int fds[2])
+{
+#ifdef UNDER_CE
+    (void) fds;
+    errno = ENOSYS;
+    return -1;
+#else
+    return _pipe (fds, 32768, O_BINARY);
+#endif
+}
+
 #include <vlc_network.h>
 
 int vlc_socket (int pf, int type, int proto, bool nonblock)