Makes sense to use similar code in both places. --- notmuch-new.c | 97 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index 262895d466ae..966b89ca39a0 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -733,64 +733,83 @@ stop_progress_printing_timer (void) static void count_files (const char *path, int *count, add_files_state_t *state) { - struct dirent *entry = NULL; - char *next; - struct dirent **fs_entries = NULL; - int num_fs_entries = scandir (path, &fs_entries, 0, NULL); - int entry_type, i; + char **fs_files = NULL, **fs_subdirs = NULL; + int num_fs_files = 0, num_fs_subdirs = 0; + int i; + notmuch_bool_t is_maildir; + struct filter filter = { + .path = path, + .state = state, + }; - if (num_fs_entries == -1) { + filter.entry_type = S_IFDIR; + num_fs_subdirs = scandirx (path, &fs_subdirs, filter_fn, NULL, &filter); + if (num_fs_subdirs == -1) { fprintf (stderr, "Warning: failed to open directory %s: %s\n", path, strerror (errno)); goto DONE; } - for (i = 0; i < num_fs_entries && ! interrupted; i++) { - entry = fs_entries[i]; + is_maildir = _entries_resemble_maildir (fs_subdirs, num_fs_subdirs); + + /* Recurse to subdirs. */ + for (i = 0; i < num_fs_subdirs && !interrupted; i++) { + const char *name = fs_subdirs[i]; + char *next; - /* Ignore special directories to avoid infinite recursion. - * Also ignore the .notmuch directory and files/directories - * the user has configured to be ignored. + /* + * Ignore the .notmuch directory and any "tmp" directory that + * appears within a maildir. */ - if (strcmp (entry->d_name, ".") == 0 || - strcmp (entry->d_name, "..") == 0 || - strcmp (entry->d_name, ".notmuch") == 0 || - _entry_in_ignore_list (entry->d_name, state)) - { - if (state->debug && _entry_in_ignore_list (entry->d_name, state)) - printf ("(D) count_files: explicitly ignoring %s/%s\n", - path, - entry->d_name); + if ((is_maildir && strcmp (name, "tmp") == 0) || + strcmp (name, ".notmuch") == 0) continue; - } - if (asprintf (&next, "%s/%s", path, entry->d_name) == -1) { - next = NULL; + next = talloc_asprintf (NULL, "%s/%s", path, name); + if (!next) { fprintf (stderr, "Error descending from %s to %s: Out of memory\n", - path, entry->d_name); + path, name); continue; } + count_files (next, count, state); + talloc_free (next); + next = NULL; + } - entry_type = dirent_type (path, entry); - if (entry_type == S_IFREG) { - *count = *count + 1; - if (*count % 1000 == 0 && state->verbosity >= VERBOSITY_NORMAL) { - printf ("Found %d files so far.\r", *count); - fflush (stdout); - } - } else if (entry_type == S_IFDIR) { - count_files (next, count, state); - } + if (interrupted) + goto DONE; + + filter.entry_type = S_IFREG; + num_fs_files = scandirx (path, &fs_files, filter_fn, NULL, &filter); + if (num_fs_files == -1) { + fprintf (stderr, "Warning: failed to open directory %s: %s\n", + path, strerror (errno)); + goto DONE; + } + + if (state->verbosity >= VERBOSITY_NORMAL) { + int new_count = *count + num_fs_files; - free (next); + if (new_count / 1000 > *count / 1000) { + printf ("Found %d files so far.\r", new_count / 1000 * 1000); + fflush (stdout); + } } + *count += num_fs_files; + DONE: - if (fs_entries) { - for (i = 0; i < num_fs_entries; i++) - free (fs_entries[i]); + if (fs_subdirs) { + for (i = 0; i < num_fs_subdirs; i++) + free (fs_subdirs[i]); + + free (fs_subdirs); + } + if (fs_files) { + for (i = 0; i < num_fs_files; i++) + free (fs_files[i]); - free (fs_entries); + free (fs_files); } } -- 2.1.4