# 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, ...)
{
* 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
}
/* 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
}
-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
{
- CONVERT_PATH (dirname, wpath, NULL);
- return (DIR *)vlc_wopendir (wpath);
+ _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)
+{
+ 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[0] == L'\0' || (wcscmp (wpath, L"\\") == 0))
+ {
+ free (wpath);
+ /* 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;
+ }
+
+ 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;
+ 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);
}
/* _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
}
/*_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)
+ 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)
#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)