Commit 9197cdff authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Win32: handle file paths of arbitrary length (in file system code)

parent 058e5676
...@@ -48,20 +48,25 @@ ...@@ -48,20 +48,25 @@
# include <tchar.h> # include <tchar.h>
#endif #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; if (errno == 0)
return -1; errno = ENOENT;
return NULL;
} }
wpath[MAX_PATH] = L'\0'; return wpath;
return 0;
} }
#define CONVERT_PATH(path, wpath, err) \ #define CONVERT_PATH(path, wpath, err) \
wchar_t wpath[MAX_PATH+1]; \ wchar_t *wpath = wide_path(path); \
if (convert_path (path, wpath)) \ if (wpath == NULL) return (err)
return (err)
int vlc_open (const char *filename, int flags, ...) int vlc_open (const char *filename, int flags, ...)
{ {
...@@ -81,9 +86,13 @@ int vlc_open (const char *filename, int flags, ...) ...@@ -81,9 +86,13 @@ int vlc_open (const char *filename, int flags, ...)
* open() cannot open files with non-“ANSI” characters on Windows. * open() cannot open files with non-“ANSI” characters on Windows.
* We use _wopen() instead. Same thing for mkdir() and stat(). * We use _wopen() instead. Same thing for mkdir() and stat().
*/ */
CONVERT_PATH(filename, wpath, -1); wchar_t *wpath = widen_path (filename);
return _wopen (wpath, flags, mode); if (wpath == NULL)
return -1;
int fd = _wopen (wpath, flags, mode);
free (wpath);
return fd;
#endif #endif
} }
...@@ -101,10 +110,14 @@ int vlc_mkdir( const char *dirname, mode_t mode ) ...@@ -101,10 +110,14 @@ int vlc_mkdir( const char *dirname, mode_t mode )
/* mkdir converts internally to wchar */ /* mkdir converts internally to wchar */
return _mkdir(dirname); return _mkdir(dirname);
#else #else
(void) mode; wchar_t *wpath = widen_path (dirname);
CONVERT_PATH (dirname, wpath, -1); if (wpath == NULL)
return _wmkdir (wpath); return -1;
int ret = _wmkdir (wpath);
free (wpath);
(void) mode;
return ret;
#endif #endif
} }
...@@ -134,15 +147,20 @@ typedef struct vlc_DIR ...@@ -134,15 +147,20 @@ typedef struct vlc_DIR
DIR *vlc_opendir (const char *dirname) 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)); vlc_DIR *p_dir = malloc (sizeof (*p_dir));
if (unlikely(p_dir == NULL)) if (unlikely(p_dir == NULL))
{
free(wpath);
return NULL; return NULL;
}
if (wpath == NULL || wpath[0] == '\0' if (wpath[0] == L'\0' || (wcscmp (wpath, L"\\") == 0))
|| (wcscmp (wpath, L"\\") == 0))
{ {
free (wpath);
/* Special mode to list drive letters */ /* Special mode to list drive letters */
p_dir->wdir = NULL; p_dir->wdir = NULL;
#ifdef UNDER_CE #ifdef UNDER_CE
...@@ -153,16 +171,17 @@ DIR *vlc_opendir (const char *dirname) ...@@ -153,16 +171,17 @@ DIR *vlc_opendir (const char *dirname)
return (void *)p_dir; 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); _WDIR *wdir = _wopendir (wpath);
free (wpath);
if (wdir == NULL) if (wdir == NULL)
{ {
free (p_dir); free (p_dir);
return NULL; return NULL;
} }
p_dir->wdir = wdir; 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; return (void *)p_dir;
} }
...@@ -212,8 +231,13 @@ int vlc_stat (const char *filename, struct stat *buf) ...@@ -212,8 +231,13 @@ int vlc_stat (const char *filename, struct stat *buf)
/* _stat translates to wchar internally on WinCE */ /* _stat translates to wchar internally on WinCE */
return _stat (filename, buf); return _stat (filename, buf);
#else #else
CONVERT_PATH (filename, wpath, -1); wchar_t *wpath = widen_path (filename);
return _wstati64 (wpath, buf); if (wpath == NULL)
return -1;
int ret = _wstati64 (wpath, buf);
free (wpath);
return ret;
#endif #endif
} }
...@@ -228,31 +252,45 @@ int vlc_unlink (const char *filename) ...@@ -228,31 +252,45 @@ int vlc_unlink (const char *filename)
/*_open translates to wchar internally on WinCE*/ /*_open translates to wchar internally on WinCE*/
return _unlink( filename ); return _unlink( filename );
#else #else
CONVERT_PATH (filename, wpath, -1); wchar_t *wpath = widen_path (filename);
return _wunlink (wpath); if (wpath == NULL)
return -1;
int ret = _wunlink (wpath);
free (wpath);
return ret;
#endif #endif
} }
int vlc_rename (const char *oldpath, const char *newpath) int vlc_rename (const char *oldpath, const char *newpath)
{ {
CONVERT_PATH (oldpath, wold, -1); int ret = -1;
CONVERT_PATH (newpath, wnew, -1);
wchar_t *wold = widen_path (oldpath), *wnew = widen_path (newpath);
if (wold == NULL || wnew == NULL)
goto out;
# ifdef UNDER_CE # ifdef UNDER_CE
/* FIXME: errno support */ /* FIXME: errno support */
return MoveFileW (wold, wnew) ? 0 : -1; if (MoveFileW (wold, wnew))
ret = 0;
#else #else
if (_wrename (wold, wnew) && (errno == EACCES || errno == EEXIST)) if (_wrename (wold, wnew) && (errno == EACCES || errno == EEXIST))
{ /* Windows does not allow atomic file replacement */ { /* Windows does not allow atomic file replacement */
if (_wremove (wnew)) if (_wremove (wnew))
{ {
errno = EACCES; /* restore errno */ errno = EACCES; /* restore errno */
return -1; goto out;
} }
if (_wrename (wold, wnew)) if (_wrename (wold, wnew))
return -1; goto out;
} }
return 0; ret = 0;
#endif #endif
out:
free (wnew);
free (wold);
return ret;
} }
int vlc_dup (int oldfd) int vlc_dup (int oldfd)
......
...@@ -53,23 +53,23 @@ static char *GetWindowsError( void ) ...@@ -53,23 +53,23 @@ static char *GetWindowsError( void )
int module_Load( vlc_object_t *p_this, const char *psz_file, int module_Load( vlc_object_t *p_this, const char *psz_file,
module_handle_t *p_handle, bool lazy ) module_handle_t *p_handle, bool lazy )
{ {
module_handle_t handle; wchar_t *wfile = ToWide (psz_file);
if (wfile == NULL)
wchar_t psz_wfile[MAX_PATH]; return -1;
MultiByteToWideChar( CP_UTF8, 0, psz_file, -1, psz_wfile, MAX_PATH );
(void) lazy; module_handle_t handle;
#ifndef UNDER_CE #ifndef UNDER_CE
/* FIXME: this is not thread-safe -- Courmisch */ /* FIXME: this is not thread-safe -- Courmisch */
UINT mode = SetErrorMode (SEM_FAILCRITICALERRORS); UINT mode = SetErrorMode (SEM_FAILCRITICALERRORS);
SetErrorMode (mode|SEM_FAILCRITICALERRORS); SetErrorMode (mode|SEM_FAILCRITICALERRORS);
#endif #endif
handle = LoadLibraryW( psz_wfile ); handle = LoadLibraryW (wfile);
#ifndef UNDER_CE #ifndef UNDER_CE
SetErrorMode (mode); SetErrorMode (mode);
#endif #endif
free (wfile);
if( handle == NULL ) if( handle == NULL )
{ {
...@@ -80,6 +80,7 @@ int module_Load( vlc_object_t *p_this, const char *psz_file, ...@@ -80,6 +80,7 @@ int module_Load( vlc_object_t *p_this, const char *psz_file,
} }
*p_handle = handle; *p_handle = handle;
(void) lazy;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment