Some platforms don't provide DT_REG/DT_LNK/DT_DIR. Create wrapper functions
which test the presence of those symbols and fall back to stat(2).

---
Not sure if I got the handling of DT_UNKNOWN correct in all cases. Someone
please double-check that.

 notmuch-new.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/notmuch-new.c b/notmuch-new.c
index 44b50aa..95ddddb 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -140,6 +140,62 @@ dirent_sort_strcmp_name (const struct dirent **a, const 
struct dirent **b)
     return strcmp ((*a)->d_name, (*b)->d_name);
 }
 
+/* Helper functions to test if a given dirent is of a certain type
+ */
+static int
+_is_reg(const char *path, struct dirent *entry)
+{
+#ifdef DT_REG
+    if (entry->d_type == DT_REG)
+        return 1;
+#endif
+
+    char buffer[PATH_MAX];
+    snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name);
+
+    struct stat sbuf;
+    if (!stat(buffer, &sbuf))
+        return S_ISREG(sbuf.st_mode);
+
+    return 0;
+}
+
+static int
+_is_dir(const char *path, struct dirent *entry)
+{
+#ifdef DT_DIR
+    if (entry->d_type == DT_DIR)
+        return 1;
+#endif
+
+    char buffer[PATH_MAX];
+    snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name);
+
+    struct stat sbuf;
+    if (!stat(buffer, &sbuf))
+        return S_ISDIR(sbuf.st_mode);
+
+    return 0;
+}
+
+static int
+_is_lnk(const char *path, struct dirent *entry)
+{
+#ifdef DT_LNK
+    if (entry->d_type == DT_LNK)
+        return 1;
+#endif
+
+    char buffer[PATH_MAX];
+    snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name);
+
+    struct stat sbuf;
+    if (!stat(buffer, &sbuf))
+        return S_ISLNK(sbuf.st_mode);
+
+    return 0;
+}
+
 /* Test if the directory looks like a Maildir directory.
  *
  * Search through the array of directory entries to see if we can find all
@@ -148,12 +204,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const 
struct dirent **b)
  * Return 1 if the directory looks like a Maildir and 0 otherwise.
  */
 static int
-_entries_resemble_maildir (struct dirent **entries, int count)
+_entries_resemble_maildir (const char *path, struct dirent **entries, int 
count)
 {
     int i, found = 0;
 
     for (i = 0; i < count; i++) {
-       if (entries[i]->d_type != DT_DIR && entries[i]->d_type != DT_UNKNOWN)
+       if (!_is_dir(path, entries[i]))
            continue;
 
        if (strcmp(entries[i]->d_name, "new") == 0 ||
@@ -265,7 +321,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     }
 
     /* Pass 1: Recurse into all sub-directories. */
-    is_maildir = _entries_resemble_maildir (fs_entries, num_fs_entries);
+    is_maildir = _entries_resemble_maildir (path, fs_entries, num_fs_entries);
 
     for (i = 0; i < num_fs_entries; i++) {
        if (interrupted)
@@ -280,9 +336,7 @@ add_files_recursive (notmuch_database_t *notmuch,
         * scandir results, then it might be a directory (and if not,
         * then we'll stat and return immediately in the next level of
         * recursion). */
-       if (entry->d_type != DT_DIR &&
-           entry->d_type != DT_LNK &&
-           entry->d_type != DT_UNKNOWN)
+       if (!_is_dir(path, entry) && !_is_lnk(path, entry))
        {
            continue;
        }
@@ -360,7 +414,7 @@ add_files_recursive (notmuch_database_t *notmuch,
         *
         * In either case, a stat does the trick.
         */
-       if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) {
+       if (_is_lnk(path, entry)) {
            int err;
 
            next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);
@@ -376,7 +430,7 @@ add_files_recursive (notmuch_database_t *notmuch,
 
            if (! S_ISREG (st.st_mode))
                continue;
-       } else if (entry->d_type != DT_REG) {
+       } else if (!_is_reg(path, entry)) {
            continue;
        }
 
-- 
1.7.0.5

_______________________________________________
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch

Reply via email to