From 49f09958df22f80e4058b6f2892f6224a80c3d6d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 6 Jan 2010 10:09:17 -0800 Subject: [PATCH] notmuch new: Fix regression preventing recursion through symlinks. In commit 3df737bc4addfce71c647792ee668725e5221a98 we switched from using stat() to using the d_type field in the result of scandir() to determine whether a filename is a regular file or a directory. This change introduced a regression in that the recursion would no longer traverse through a symlink to a directory. (Since stat() would resolve the symlink but with scandir() we see a distinct DT_LNK value in d_type). We fix this for directories by allowing both DT_DIR and DT_LNK values to recurse, and then downgrading the existing not-a-directory check within the recursion to not be an error. We also add a new not-a-directory check outside the recursion that is an error. --- notmuch-new.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index c15f6837..e2b5878f 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -229,10 +229,11 @@ add_files_recursive (notmuch_database_t *notmuch, return NOTMUCH_STATUS_FILE_ERROR; } - if (! S_ISDIR (st.st_mode)) { - fprintf (stderr, "Error: %s is not a directory.\n", path); - return NOTMUCH_STATUS_FILE_ERROR; - } + /* This is not an error since we may have recursed based on a + * symlink to a regular file, not a directory, and we don't know + * that until this stat. */ + if (! S_ISDIR (st.st_mode)) + return NOTMUCH_STATUS_SUCCESS; fs_mtime = st.st_mtime; @@ -262,7 +263,7 @@ add_files_recursive (notmuch_database_t *notmuch, entry = fs_entries[i]; - if (entry->d_type != DT_DIR) + if (entry->d_type != DT_DIR && entry->d_type != DT_LNK) continue; /* Ignore special directories to avoid infinite recursion. @@ -447,6 +448,7 @@ add_files (notmuch_database_t *notmuch, struct sigaction action; struct itimerval timerval; notmuch_bool_t timer_is_active = FALSE; + struct stat st; if (state->output_is_a_tty && ! debugger_is_active () && ! state->verbose) { /* Setup our handler for SIGALRM */ @@ -466,6 +468,17 @@ add_files (notmuch_database_t *notmuch, timer_is_active = TRUE; } + if (stat (path, &st)) { + fprintf (stderr, "Error reading directory %s: %s\n", + path, strerror (errno)); + return NOTMUCH_STATUS_FILE_ERROR; + } + + if (! S_ISDIR (st.st_mode)) { + fprintf (stderr, "Error: %s is not a directory.\n", path); + return NOTMUCH_STATUS_FILE_ERROR; + } + status = add_files_recursive (notmuch, path, state); if (timer_is_active) {