From 8204dfad6ab9ebac2d5dae09edb1ca50220ad18d Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Fri, 18 Jan 2013 00:15:55 +0100 Subject: [PATCH] Doesn't apply file filter rules to directory. In Windows uses the information reported by FindFirstFile instead of calling lstat(). --- HISTORY | 5 +++-- elem.h | 4 ++-- mingw.c | 21 ++++++++++++++------- mingw.h | 17 +++++++++++++---- portable.h | 3 +-- scan.c | 38 ++++++++++++++++++++++---------------- 6 files changed, 55 insertions(+), 33 deletions(-) diff --git a/HISTORY b/HISTORY index aff62972..54df803f 100644 --- a/HISTORY +++ b/HISTORY @@ -1,9 +1,10 @@ SnapRAID HISTORY ================ -2.1 2012/12 -=========== +2.1 2013/1 +========== * Checks for wrong empty fields in the configuration file. + * Filter rules for files are not anymore applied to directories. 2.0 2012/12 =========== diff --git a/elem.h b/elem.h index c0983f93..114c0b6f 100644 --- a/elem.h +++ b/elem.h @@ -234,9 +234,9 @@ void filter_free(struct snapraid_filter* filter); * Filter hidden files. * Return !=0 if it matches and it should be excluded. */ -static inline int filter_hidden(int enable, struct dirent* dd, struct stat* st) +static inline int filter_hidden(int enable, struct dirent* dd) { - if (enable && stat_hidden(dd, st)) { + if (enable && dirent_hidden(dd)) { return 1; /* filter out */ } diff --git a/mingw.c b/mingw.c index c0d00e98..cbbd111c 100644 --- a/mingw.c +++ b/mingw.c @@ -401,6 +401,9 @@ static void windows_finddata2dirent(const WIN32_FIND_DATAW* info, struct windows } memcpy(dirent->d_name, name, len + 1); + + /* Store the HIDDEN attribute in a separate field */ + dirent->d_hidden = (info->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0; } /** @@ -479,6 +482,11 @@ int windows_lstat(const char* file, struct windows_stat* st) return 0; } +void windows_dirent_lstat(const struct windows_dirent* dd, struct windows_stat* st) +{ + windows_finddata2stat(&dd->d_data, st); +} + int windows_access(const char* file, int mode) { return _waccess(convert(file), mode); @@ -709,7 +717,7 @@ windows_dir* windows_opendir(const char* dir) wdir[len++] = L'*'; wdir[len++] = 0; - dirstream->h = FindFirstFileW(wdir, &dirstream->data); + dirstream->h = FindFirstFileW(wdir, &dirstream->buffer.d_data); if (dirstream->h == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); @@ -725,7 +733,7 @@ windows_dir* windows_opendir(const char* dir) dirstream->flags = 1; - windows_finddata2dirent(&dirstream->data, &dirstream->buffer); + windows_finddata2dirent(&dirstream->buffer.d_data, &dirstream->buffer); return dirstream; } @@ -742,7 +750,7 @@ struct windows_dirent* windows_readdir(windows_dir* dirstream) return &dirstream->buffer; } - if (!FindNextFileW(dirstream->h, &dirstream->data)) { + if (!FindNextFileW(dirstream->h, &dirstream->buffer.d_data)) { DWORD error = GetLastError(); if (error == ERROR_NO_MORE_FILES) { @@ -754,7 +762,7 @@ struct windows_dirent* windows_readdir(windows_dir* dirstream) return 0; } - windows_finddata2dirent(&dirstream->data, &dirstream->buffer); + windows_finddata2dirent(&dirstream->buffer.d_data, &dirstream->buffer); return &dirstream->buffer; } @@ -776,10 +784,9 @@ int windows_closedir(windows_dir* dirstream) return 0; } -int windows_stat_hidden(struct dirent* dd, struct windows_stat* st) +int windows_dirent_hidden(struct dirent* dd) { - (void)dd; - return st->st_hidden; + return dd->d_hidden; } const char* windows_stat_desc(struct stat* st) diff --git a/mingw.h b/mingw.h index ebb734d5..f4026786 100644 --- a/mingw.h +++ b/mingw.h @@ -53,7 +53,9 @@ #define HAVE_FUTIMENS 1 #define futimens windows_futimens #define O_NOFOLLOW 0 -#define stat_hidden windows_stat_hidden +#define dirent_hidden windows_dirent_hidden +#define HAVE_DIRENT_LSTAT 1 +#define dirent_lstat windows_dirent_lstat #define stat_desc windows_stat_desc #define sleep windows_sleep /* In Windows symbolic links are not supported */ @@ -173,13 +175,14 @@ int windows_open(const char* file, int flags, ...); */ struct windows_dirent { char d_name[PATH_MAX]; + int d_hidden; + WIN32_FIND_DATAW d_data; }; /** * Like the C DIR. */ struct windows_dir_struct { - WIN32_FIND_DATAW data; HANDLE h; struct windows_dirent buffer; int flags; @@ -202,9 +205,15 @@ struct windows_dirent* windows_readdir(windows_dir* dirstream); int windows_closedir(windows_dir* dirstream); /** - * Like stat_hidden(). + * Convert a dirent record to a lstat record. + * Just like the one obtained calling lstat(). */ -int windows_stat_hidden(struct dirent* dd, struct windows_stat* st); +void windows_dirent_lstat(const struct windows_dirent* dd, struct windows_stat* st); + +/** + * Like dirent_hidden(). + */ +int windows_dirent_hidden(struct dirent* dd); /** * Like stat_desc(). diff --git a/portable.h b/portable.h index 46cd4ce3..1db7e0c3 100644 --- a/portable.h +++ b/portable.h @@ -155,9 +155,8 @@ static inline int open_noatime(const char* file, int flags) /** * Check if the specified file is hidden. */ -static inline int stat_hidden(struct dirent* dd, struct stat* st) +static inline int dirent_hidden(struct dirent* dd) { - (void)st; return dd->d_name[0] == '.'; } diff --git a/scan.c b/scan.c index 40948e09..a364e61c 100644 --- a/scan.c +++ b/scan.c @@ -480,24 +480,35 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, i exit(EXIT_FAILURE); } - /* exclude files before doing any check on them */ - if (filter_path(&state->filterlist, disk->name, sub_next) != 0) { + /* exclude hidden stuff even beforer calling lstat() */ + if (filter_hidden(state->filter_hidden, dd) != 0) { if (state->verbose) { - printf("Excluding file '%s'\n", path_next); + printf("Excluding hidden '%s'\n", path_next); } continue; } - /* get info about the file */ + /* exclude content files even beforer calling lstat() */ + if (filter_content(&state->contentlist, path_next) != 0) { + if (state->verbose) { + printf("Excluding content '%s'\n", path_next); + } + continue; + } + +#if HAVE_DIRENT_LSTAT + /* convert dirent to lstat result */ + dirent_lstat(dd, &st); +#else + /* get lstat info about the file */ if (lstat(path_next, &st) != 0) { fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); exit(EXIT_FAILURE); } +#endif if (S_ISREG(st.st_mode)) { - if (filter_hidden(state->filter_hidden, dd, &st) == 0 - && filter_content(&state->contentlist, path_next) == 0 - ) { + if (filter_path(&state->filterlist, disk->name, sub_next) == 0) { /* check for read permission */ if (access(path_next, R_OK) != 0) { fprintf(stderr, "warning: Ignoring, for missing read permission, file '%s'\n", path_next); @@ -520,8 +531,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, i } } } else if (S_ISLNK(st.st_mode)) { - if (filter_hidden(state->filter_hidden, dd, &st) == 0 - ) { + if (filter_path(&state->filterlist, disk->name, sub_next) == 0) { char subnew[PATH_MAX]; int ret; @@ -541,13 +551,11 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, i scan_link(scan, state, output, disk, sub_next, subnew); } else { if (state->verbose) { - printf("Excluding file '%s'\n", path_next); + printf("Excluding link '%s'\n", path_next); } } } else if (S_ISDIR(st.st_mode)) { - if (filter_hidden(state->filter_hidden, dd, &st) == 0 - && filter_dir(&state->filterlist, disk->name, sub_next) == 0 - ) { + if (filter_dir(&state->filterlist, disk->name, sub_next) == 0) { pathslash(path_next, sizeof(path_next)); pathslash(sub_next, sizeof(sub_next)); scan_dir(scan, state, output, disk, path_next, sub_next); @@ -557,9 +565,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, i } } } else { - if (filter_hidden(state->filter_hidden, dd, &st) == 0 - && filter_content(&state->contentlist, path_next) == 0 - ) { + if (filter_path(&state->filterlist, disk->name, sub_next) == 0) { fprintf(stderr, "warning: Ignoring special '%s' file '%s'\n", stat_desc(&st), path_next); } else { if (state->verbose) {