diff --git a/cmdline/scan.c b/cmdline/scan.c index da027511..7f72aee6 100644 --- a/cmdline/scan.c +++ b/cmdline/scan.c @@ -1523,8 +1523,36 @@ static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* pa tommy_list_insert_tail(&list, &entry->node, entry); /* process ignore files */ - if (pathcmp(".snapraidignore", dd->d_name) == 0) - state_load_ignore_file(&scan->local_filter_list, path_next, sub_next); + if (pathcmp(".snapraidignore", dd->d_name) == 0) { + int d_type; +#if HAVE_STRUCT_DIRENT_D_TYPE + d_type = dd->d_type; +#else + d_type = DT_UNKNOWN; +#endif + + if (d_type == DT_UNKNOWN) { + struct stat st_ignore; + + if (lstat(path_next, &st_ignore) != 0) { + /* LCOV_EXCL_START */ + log_fatal(errno, "Error stating the ignore file '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (S_ISREG(st_ignore.st_mode)) + d_type = DT_REG; + } + + if (d_type != DT_REG) { + log_fatal(EUSER, "Ignore file '%s' is not a regular file.\n", path_next); + exit(EXIT_FAILURE); + } + + if (state_load_ignore_file(&scan->local_filter_list, path_next, sub_next) != 0) + exit(EXIT_FAILURE); + } } if (closedir(d) != 0) { diff --git a/cmdline/state.c b/cmdline/state.c index dfa33adb..649e447a 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -6695,16 +6695,17 @@ int state_write_barrier(struct snapraid_state* state, struct snapraid_io* io, st return 0; } -void state_load_ignore_file(tommy_list* filter_list, const char* path, const char* sub) +int state_load_ignore_file(tommy_list* filter_list, const char* path, const char* sub) { STREAM* f; int line; + int error = 0; - f = sopen_read(path, 0); + f = sopen_read(path, STREAM_FLAGS_NOFOLLOW); if (!f) { /* LCOV_EXCL_START */ - log_error(errno, "Error opening the ignore file '%s'. %s.\n", path, strerror(errno)); - return; + log_fatal(errno, "Error opening the ignore file '%s'. %s.\n", path, strerror(errno)); + return -1; /* LCOV_EXCL_STOP */ } @@ -6721,7 +6722,8 @@ void state_load_ignore_file(tommy_list* filter_list, const char* path, const cha ret = sgetline(f, buffer, sizeof(buffer)); if (ret < 0) { /* LCOV_EXCL_START */ - log_error(EUSER, "Too long line in '%s' at line %u\n", path, line); + log_fatal(EUSER, "Too long line in '%s' at line %u\n", path, line); + error = 1; break; /* LCOV_EXCL_STOP */ } @@ -6736,7 +6738,8 @@ void state_load_ignore_file(tommy_list* filter_list, const char* path, const cha filter = filter_alloc_file(-1, sub, buffer); if (!filter) { /* LCOV_EXCL_START */ - log_error(EUSER, "Invalid ignore specification '%s' in '%s' at line %u\n", buffer, path, line); + log_fatal(EUSER, "Invalid ignore specification '%s' in '%s' at line %u\n", buffer, path, line); + error = 1; break; /* LCOV_EXCL_STOP */ } @@ -6751,7 +6754,8 @@ void state_load_ignore_file(tommy_list* filter_list, const char* path, const cha } if (c != '\n') { /* LCOV_EXCL_START */ - log_error(EUSER, "Extra data in '%s' at line %u\n", path, line); + log_fatal(EUSER, "Extra data in '%s' at line %u\n", path, line); + error = 1; break; /* LCOV_EXCL_STOP */ } @@ -6760,11 +6764,19 @@ void state_load_ignore_file(tommy_list* filter_list, const char* path, const cha if (serror(f)) { /* LCOV_EXCL_START */ - log_error(errno, "Error reading the ignore file '%s' at line %u\n", path, line); + log_fatal(errno, "Error reading the ignore file '%s' at line %u. %s.\n", path, line, strerror(errno)); + error = 1; /* LCOV_EXCL_STOP */ } - sclose(f); + if (sclose(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal(errno, "Error closing the ignore file '%s'. %s.\n", path, strerror(errno)); + error = 1; + /* LCOV_EXCL_STOP */ + } + + return error ? -1 : 0; } static int state_snapshot_dir(struct fssnapshot_struct* fss, const char* name, struct snapraid_disk* disk) diff --git a/cmdline/state.h b/cmdline/state.h index 209df4ad..0c2ee353 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -438,7 +438,7 @@ int state_thermal_begin(struct snapraid_state* state, time_t now); /** * Load the ignore file .snapraidignore */ -void state_load_ignore_file(tommy_list* filter_list, const char* path, const char* sub); +int state_load_ignore_file(tommy_list* filter_list, const char* path, const char* sub); /** * Report attributes into the log diff --git a/cmdline/stream.c b/cmdline/stream.c index ff535e75..a7c49e33 100644 --- a/cmdline/stream.c +++ b/cmdline/stream.c @@ -25,6 +25,8 @@ STREAM* sopen_read(const char* file, int flags) advise_init(&s->advise[0], s->flags & STREAM_FLAGS_ADVISE_MASK); int open_flags = O_RDONLY | O_BINARY | advise_flags(&s->advise[0]); + if ((s->flags & STREAM_FLAGS_NOFOLLOW) != 0) + open_flags |= O_NOFOLLOW; pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file); s->handle[0].f = open(file, open_flags); diff --git a/cmdline/stream.h b/cmdline/stream.h index d432d878..ea9d52f6 100644 --- a/cmdline/stream.h +++ b/cmdline/stream.h @@ -12,6 +12,7 @@ #define STREAM_FLAGS_ADVISE_MASK 0xFF /**< Low bits containing one of ADVISE_*. */ #define STREAM_FLAGS_CRC 0x100 /**< Enable the CRC computation. */ +#define STREAM_FLAGS_NOFOLLOW 0x200 /**< Don't follow the final symbolic link on open. */ /** * Size of the buffer of the stream.