foxygit / doom Log in
commit 67d4033dabed2e864944c8359b8cff1e66339143
Author:     Fabian Greffrath <fabian@greffrath.com>
AuthorDate: Mon Oct 29 09:57:24 2018 +0100
Commit:     Fabian Greffrath <fabian@greffrath.com>
CommitDate: Mon Oct 29 09:57:24 2018 +0100

    glob: repair for systems without d_type field in struct dirent

    The d_type field in struct dirent is not mandated by POSIX and is missing
    e.g. on MinGW where this leads to a failing build. Fall back to using
    stat() here.
---
 src/i_glob.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/i_glob.c b/src/i_glob.c
index d47a60b5..bb7c7f85 100644
--- a/src/i_glob.c
+++ b/src/i_glob.c
@@ -36,6 +36,39 @@

 #ifndef NO_DIRENT_IMPLEMENTATION

+// Only the fields d_name and (as an XSI extension) d_ino are specified
+// in POSIX.1.  Other than Linux, the d_type field is available mainly
+// only on BSD systems.  The remaining fields are available on many, but
+// not all systems.
+#if defined(_DIRENT_HAVE_D_TYPE)
+static boolean IsDirectory(char *dir, struct dirent *de)
+{
+    return de->d_type == DT_DIR;
+}
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+static boolean IsDirectory(char *dir, struct dirent *de)
+{
+    char *filename;
+    struct stat sb;
+    int result;
+
+    filename = M_StringJoin(dir, DIR_SEPARATOR_S, de->d_name, NULL);
+    result = stat(filename, &sb);
+    free(filename);
+
+    if (result != 0)
+    {
+        return false;
+    }
+
+    return S_ISDIR(sb.st_mode);
+}
+#endif
+
 struct glob_s
 {
     char *glob;
@@ -126,7 +159,7 @@ const char *I_NextGlob(glob_t *glob)
         {
             return NULL;
         }
-    } while (de->d_type == DT_DIR || !MatchesGlob(de->d_name, glob->glob));
+    } while (IsDirectory(glob->directory, de) || !MatchesGlob(de->d_name, glob->glob));

     // Return the fully-qualified path, not just the bare filename.
     free(glob->last_filename);