summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
Diffstat (limited to 'osdep')
-rw-r--r--osdep/glob-win.c195
-rw-r--r--osdep/glob.h34
-rw-r--r--osdep/io.h25
3 files changed, 151 insertions, 103 deletions
diff --git a/osdep/glob-win.c b/osdep/glob-win.c
index d67d6ddf63..30dad4dfc5 100644
--- a/osdep/glob-win.c
+++ b/osdep/glob-win.c
@@ -1,98 +1,155 @@
/*
- * This file is part of MPlayer.
+ * This file is part of mpv.
*
- * MPlayer is free software; you can redistribute it and/or modify
+ * mpv 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
* (at your option) any later version.
*
- * MPlayer is distributed in the hope that it will be useful,
+ * mpv 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.
*
* You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <windows.h>
+#include <stdbool.h>
#include <string.h>
+#include "osdep/io.h"
+#include "talloc.h"
-#include "config.h"
+static wchar_t *talloc_wcsdup(void *ctx, const wchar_t *wcs)
+{
+ size_t len = (wcslen(wcs) + 1) * sizeof(wchar_t);
+ return talloc_memdup(ctx, (void*)wcs, len);
+}
-#include <windows.h>
-#include "glob.h"
+static int compare_wcscoll(const void *v1, const void *v2)
+{
+ wchar_t * const* p1 = v1;
+ wchar_t * const* p2 = v2;
+ return wcscoll(*p1, *p2);
+}
-int glob(const char *pattern, int flags,
- int (*errfunc)(const char *epath, int eerrno), glob_t *pglob)
+static bool exists(const char *filename)
{
- HANDLE searchhndl;
- WIN32_FIND_DATA found_file;
- if (errfunc)
- printf("glob():ERROR:Sorry errfunc not supported by this implementation\n");
- if (flags)
- printf("glob():ERROR:Sorry no flags supported by this globimplementation\n");
- //printf("PATTERN \"%s\"\n",pattern);
- pglob->gl_pathc = 0;
- searchhndl = FindFirstFile(pattern, &found_file);
- if (searchhndl == INVALID_HANDLE_VALUE) {
- if (GetLastError() == ERROR_FILE_NOT_FOUND) {
- pglob->gl_pathc = 0;
- //printf("could not find a file matching your search criteria\n");
- return 1;
- } else {
- //printf("glob():ERROR:FindFirstFile: %i\n",GetLastError());
- return 1;
+ wchar_t *wfilename = mp_from_utf8(NULL, filename);
+ bool result = GetFileAttributesW(wfilename) != INVALID_FILE_ATTRIBUTES;
+ talloc_free(wfilename);
+ return result;
+}
+
+int mp_glob(const char *restrict pattern, int flags,
+ int (*errfunc)(const char*, int), mp_glob_t *restrict pglob)
+{
+ // This glob implementation never calls errfunc and doesn't understand any
+ // flags. These features are currently unused in mpv, however if new code
+ // were to use these them, it would probably break on Windows.
+
+ unsigned dirlen = 0;
+ bool wildcards = false;
+
+ // Check for drive relative paths eg. "C:*.flac"
+ if (pattern[0] != '\0' && pattern[1] == ':')
+ dirlen = 2;
+
+ // Split the directory and filename. All files returned by FindFirstFile
+ // will be in this directory. Also check the filename for wildcards.
+ for (unsigned i = 0; pattern[i]; i ++) {
+ if (pattern[i] == '?' || pattern[i] == '*')
+ wildcards = true;
+
+ if (pattern[i] == '\\' || pattern[i] == '/') {
+ dirlen = i + 1;
+ wildcards = false;
}
}
- pglob->gl_pathv = malloc(sizeof(char *));
- pglob->gl_pathv[0] = strdup(found_file.cFileName);
- pglob->gl_pathc++;
- while (1) {
- if (!FindNextFile(searchhndl, &found_file)) {
- if (GetLastError() == ERROR_NO_MORE_FILES) {
- //printf("glob(): no more files found\n");
- break;
- } else {
- //printf("glob():ERROR:FindNextFile:%i\n",GetLastError());
- return 1;
- }
- } else {
- //printf("glob: found file %s\n",found_file.cFileName);
- pglob->gl_pathc++;
- pglob->gl_pathv = realloc(pglob->gl_pathv, pglob->gl_pathc * sizeof(char *));
- pglob->gl_pathv[pglob->gl_pathc - 1] = strdup(found_file.cFileName);
+
+ // FindFirstFile is unreliable with certain input (it returns weird results
+ // with paths like "." and "..", and presumably others.) If there are no
+ // wildcards in the filename, don't call it, just check if the file exists.
+ // The CRT globbing code does this too.
+ if (!wildcards) {
+ if (!exists(pattern)) {
+ pglob->gl_pathc = 0;
+ return GLOB_NOMATCH;
}
+
+ pglob->ctx = talloc_new(NULL);
+ pglob->gl_pathc = 1;
+ pglob->gl_pathv = talloc_array_ptrtype(pglob->ctx, pglob->gl_pathv, 2);
+ pglob->gl_pathv[0] = talloc_strdup(pglob->ctx, pattern);
+ pglob->gl_pathv[1] = NULL;
+ return 0;
}
- FindClose(searchhndl);
- return 0;
-}
-void globfree(glob_t *pglob)
-{
- int i;
- for (i = 0; i < pglob->gl_pathc; i++)
- free(pglob->gl_pathv[i]);
- free(pglob->gl_pathv);
-}
+ wchar_t *wpattern = mp_from_utf8(NULL, pattern);
+ WIN32_FIND_DATAW data;
+ HANDLE find = FindFirstFileW(wpattern, &data);
+ talloc_free(wpattern);
-#if 0
-int main(void)
-{
- glob_t gg;
- printf("globtest\n");
- glob("*.jpeg", 0, NULL, &gg);
- {
- int i;
- for (i = 0; i < gg.gl_pathc; i++)
- printf("GLOBED:%i %s\n", i, gg.gl_pathv[i]);
+ // Assume an error means there were no matches. mpv doesn't check for
+ // glob() errors, so this should be fine for now.
+ if (find == INVALID_HANDLE_VALUE) {
+ pglob->gl_pathc = 0;
+ return GLOB_NOMATCH;
}
- globfree(&gg);
+ size_t pathc = 0;
+ void *tmp = talloc_new(NULL);
+ wchar_t **wnamev = NULL;
+
+ // Read a list of filenames. Unlike glob(), FindFirstFile doesn't return
+ // the full path, since all files are relative to the directory specified
+ // in the pattern.
+ do {
+ if (!wcscmp(data.cFileName, L".") || !wcscmp(data.cFileName, L".."))
+ continue;
+
+ wchar_t *wname = talloc_wcsdup(tmp, data.cFileName);
+ MP_TARRAY_APPEND(tmp, wnamev, pathc, wname);
+ } while (FindNextFileW(find, &data));
+ FindClose(find);
+
+ if (!wnamev) {
+ talloc_free(tmp);
+ pglob->gl_pathc = 0;
+ return GLOB_NOMATCH;
+ }
+
+ // POSIX glob() is supposed to sort paths according to LC_COLLATE.
+ // FindFirstFile just returns paths in the order they are read from the
+ // directory, so sort them manually with wcscoll.
+ qsort(wnamev, pathc, sizeof(wchar_t*), compare_wcscoll);
+
+ pglob->ctx = talloc_new(NULL);
+ pglob->gl_pathc = pathc;
+ pglob->gl_pathv = talloc_array_ptrtype(pglob->ctx, pglob->gl_pathv,
+ pathc + 1);
+
+ // Now convert all filenames to UTF-8 (they had to be in UTF-16 for
+ // sorting) and prepend the directory
+ for (unsigned i = 0; i < pathc; i ++) {
+ int namelen = WideCharToMultiByte(CP_UTF8, 0, wnamev[i], -1, NULL, 0,
+ NULL, NULL);
+ char *path = talloc_array(pglob->ctx, char, namelen + dirlen);
+
+ memcpy(path, pattern, dirlen);
+ WideCharToMultiByte(CP_UTF8, 0, wnamev[i], -1, path + dirlen,
+ namelen, NULL, NULL);
+ pglob->gl_pathv[i] = path;
+ }
+
+ // gl_pathv must be null terminated
+ pglob->gl_pathv[pathc] = NULL;
+ talloc_free(tmp);
return 0;
}
-#endif
+void mp_globfree(mp_glob_t *pglob)
+{
+ talloc_free(pglob->ctx);
+}
diff --git a/osdep/glob.h b/osdep/glob.h
deleted file mode 100644
index f117725d63..0000000000
--- a/osdep/glob.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer 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
- * (at your option) any later version.
- *
- * MPlayer 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPLAYER_GLOB_H
-#define MPLAYER_GLOB_H
-
-#include <sys/types.h>
-
-typedef struct {
- size_t gl_pathc;
- char **gl_pathv;
- size_t gl_offs;
-} glob_t;
-
-void globfree(glob_t *pglob);
-
-int glob(const char *pattern, int flags, int (*errfunc)(const char *epath, int eerrno), glob_t *pglob);
-
-#endif /* MPLAYER_GLOB_H */
diff --git a/osdep/io.h b/osdep/io.h
index 4cb16677f2..53097a1b78 100644
--- a/osdep/io.h
+++ b/osdep/io.h
@@ -20,12 +20,17 @@
#ifndef MPLAYER_OSDEP_IO
#define MPLAYER_OSDEP_IO
+#include "config.h"
#include <stdbool.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#if HAVE_GLOB
+#include <glob.h>
+#endif
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -71,6 +76,18 @@ int mp_closedir(DIR *dir);
int mp_mkdir(const char *path, int mode);
char *mp_getenv(const char *name);
+typedef struct {
+ size_t gl_pathc;
+ char **gl_pathv;
+ size_t gl_offs;
+ void *ctx;
+} mp_glob_t;
+
+// glob-win.c
+int mp_glob(const char *restrict pattern, int flags,
+ int (*errfunc)(const char*, int), mp_glob_t *restrict pglob);
+void mp_globfree(mp_glob_t *pglob);
+
// NOTE: stat is not overridden with mp_stat, because MinGW-w64 defines it as
// macro.
@@ -85,6 +102,14 @@ char *mp_getenv(const char *name);
#define mkdir(...) mp_mkdir(__VA_ARGS__)
#define getenv(...) mp_getenv(__VA_ARGS__)
+#ifndef GLOB_NOMATCH
+#define GLOB_NOMATCH 3
+#endif
+
+#define glob_t mp_glob_t
+#define glob(...) mp_glob(__VA_ARGS__)
+#define globfree(...) mp_globfree(__VA_ARGS__)
+
#else /* __MINGW32__ */
#define mp_stat(...) stat(__VA_ARGS__)