From 201a65635055cb5a2987dc23819ba0fcb18e4e14 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 17 Oct 2014 21:46:08 +0200 Subject: win32: get rid of mp_stat in the normal source code mp_stat() instead of stat() was used in the normal code (i.e. even on Unix), because MinGW-w64 has an unbelievable macro-mess in place, which prevents solving this elegantly. Add some dirty workarounds to hide mp_stat() from the normal code properly. This now requires replacing all functions that use the struct stat type. This includes fstat, lstat, fstatat, and possibly others. (mpv currently uses stat and fstat only.) --- options/path.c | 4 ++-- osdep/io.c | 29 +++++++++++++++++++++++++++-- osdep/io.h | 32 +++++++++++++++++++++++++++----- player/lua.c | 2 +- player/scripting.c | 2 +- video/out/vo_image.c | 2 +- 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/options/path.c b/options/path.c index 7e5495f844..8a7873ded2 100644 --- a/options/path.c +++ b/options/path.c @@ -271,13 +271,13 @@ char *mp_getcwd(void *talloc_ctx) bool mp_path_exists(const char *path) { struct stat st; - return path && mp_stat(path, &st) == 0; + return path && stat(path, &st) == 0; } bool mp_path_isdir(const char *path) { struct stat st; - return mp_stat(path, &st) == 0 && S_ISDIR(st.st_mode); + return stat(path, &st) == 0 && S_ISDIR(st.st_mode); } // Return false if it's considered a normal local filesystem path. diff --git a/osdep/io.c b/osdep/io.c index b93618400c..a78dd78c2c 100644 --- a/osdep/io.c +++ b/osdep/io.c @@ -132,11 +132,36 @@ void mp_get_converted_argv(int *argc, char ***argv) *argv = win32_argv_utf8; } -int mp_stat(const char *path, struct stat *buf) +static void copy_stat(struct mp_stat *dst, struct _stat64 *src) { + dst->st_dev = src->st_dev; + dst->st_ino = src->st_ino; + dst->st_mode = src->st_mode; + dst->st_nlink = src->st_nlink; + dst->st_uid = src->st_uid; + dst->st_gid = src->st_gid; + dst->st_rdev = src->st_rdev; + dst->st_size = src->st_size; + dst->st_atime = src->st_atime; + dst->st_mtime = src->st_mtime; + dst->st_ctime = src->st_ctime; +} + +int mp_stat(const char *path, struct mp_stat *buf) +{ + struct _stat64 buf_; wchar_t *wpath = mp_from_utf8(NULL, path); - int res = _wstati64(wpath, buf); + int res = _wstat64(wpath, &buf_); talloc_free(wpath); + copy_stat(buf, &buf_); + return res; +} + +int mp_fstat(int fd, struct mp_stat *buf) +{ + struct _stat64 buf_; + int res = _fstat64(fd, &buf_); + copy_stat(buf, &buf_); return res; } diff --git a/osdep/io.h b/osdep/io.h index a24ad7c231..b56953aedf 100644 --- a/osdep/io.h +++ b/osdep/io.h @@ -22,6 +22,7 @@ #include "config.h" #include +#include #include #include #include @@ -65,7 +66,6 @@ char *mp_to_utf8(void *talloc_ctx, const wchar_t *s); void mp_get_converted_argv(int *argc, char ***argv); -int mp_stat(const char *path, struct stat *buf); int mp_printf(const char *format, ...); int mp_fprintf(FILE *stream, const char *format, ...); int mp_open(const char *filename, int oflag, ...); @@ -79,6 +79,27 @@ FILE *mp_tmpfile(void); char *mp_getenv(const char *name); off_t mp_lseek(int fd, off_t offset, int whence); +// MinGW-w64 will define "stat" to something useless. Since this affects both +// the type (struct stat) and the stat() function, it makes us harder to +// override these separately. +// Corresponds to struct _stat64 (copy & pasted, but using public types). +struct mp_stat { + dev_t st_dev; + ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + dev_t st_rdev; + int64_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + +int mp_stat(const char *path, struct mp_stat *buf); +int mp_fstat(int fd, struct mp_stat *buf); + typedef struct { size_t gl_pathc; char **gl_pathv; @@ -113,6 +134,11 @@ void mp_globfree(mp_glob_t *pglob); #define lseek(...) mp_lseek(__VA_ARGS__) #endif +#undef stat +#define stat mp_stat +#undef fstat +#define fstat(...) mp_fstat(__VA_ARGS__) + #ifndef GLOB_NOMATCH #define GLOB_NOMATCH 3 #endif @@ -121,10 +147,6 @@ void mp_globfree(mp_glob_t *pglob); #define glob(...) mp_glob(__VA_ARGS__) #define globfree(...) mp_globfree(__VA_ARGS__) -#else /* __MINGW32__ */ - -#define mp_stat(...) stat(__VA_ARGS__) - #endif /* __MINGW32__ */ #endif diff --git a/player/lua.c b/player/lua.c index ef8dc1ca7d..73b5a2991c 100644 --- a/player/lua.c +++ b/player/lua.c @@ -1090,7 +1090,7 @@ static int script_readdir(lua_State *L) fullpath[0] = '\0'; fullpath = talloc_asprintf_append(fullpath, "%s/%s", path, name); struct stat st; - if (mp_stat(fullpath, &st)) + if (stat(fullpath, &st)) continue; if (!(((t & 1) && S_ISREG(st.st_mode)) || ((t & 2) && S_ISDIR(st.st_mode)))) diff --git a/player/scripting.c b/player/scripting.c index 6e2a5a4e2d..5bc9a915f3 100644 --- a/player/scripting.c +++ b/player/scripting.c @@ -157,7 +157,7 @@ static char **list_script_files(void *talloc_ctx, char *path) while ((ep = readdir(dp))) { char *fname = mp_path_join(talloc_ctx, bstr0(path), bstr0(ep->d_name)); struct stat s; - if (!mp_stat(fname, &s) && S_ISREG(s.st_mode)) + if (!stat(fname, &s) && S_ISREG(s.st_mode)) MP_TARRAY_APPEND(talloc_ctx, files, count, fname); } closedir(dp); diff --git a/video/out/vo_image.c b/video/out/vo_image.c index 991265da23..a130048e54 100644 --- a/video/out/vo_image.c +++ b/video/out/vo_image.c @@ -55,7 +55,7 @@ static bool checked_mkdir(struct vo *vo, const char *buf) char *errstr = strerror(errno); if (errno == EEXIST) { struct stat stat_p; - if (mp_stat(buf, &stat_p ) == 0 && S_ISDIR(stat_p.st_mode)) + if (stat(buf, &stat_p ) == 0 && S_ISDIR(stat_p.st_mode)) return true; } MP_ERR(vo, "Error creating output directory: %s\n", errstr); -- cgit v1.2.3