From f8d2c91a962fc80894f0f79957ba869148c852ce Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 11 Jun 2011 09:38:19 +0200 Subject: [PATCH] Changes the way files without read or write permission are handled. Now we try to continue processing returning a warning where possible. --- HISTORY | 9 +++++++++ check.c | 17 ++++++++++++++--- handle.c | 15 ++++++++++++++- handle.h | 4 +++- mingw.h | 1 + scan.c | 20 +++++++++++--------- 6 files changed, 52 insertions(+), 14 deletions(-) diff --git a/HISTORY b/HISTORY index 3530cee2..9c578a9b 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,15 @@ SnapRAID HISTORY ================ +1.4 2011/6 +========== +* Ignoring in sync System and Hidden files in Windows. +* Files without read permission are ignored in sync. +* If a file is ignored a warning message is printed. You have to exclude it + to remove the warning. +* In fixing, if a file cannot be written for missing permission, an error is + reported only if a write is effectively required. + 1.3 2011/5 ========== * Fixed the restore of directory with unicode chars in Windows. diff --git a/check.c b/check.c index 7bb9c9df..5428a781 100644 --- a/check.c +++ b/check.c @@ -291,9 +291,13 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (fix) { /* if fixing, create the file, open for writing and resize if required */ - ret = handle_create(&handle[j], block_file_get(block)); + ret = handle_create(&handle[j], block_file_get(block)); if (ret == -1) { - fprintf(stderr, "DANGER! Without a working data disk, it isn't possible to fix errors on it.\n"); + if (errno == EACCES) { + fprintf(stderr, "WARNING! Please give write permission to the file.\n"); + } else { + fprintf(stderr, "DANGER! Without a working data disk, it isn't possible to fix errors on it.\n"); + } fprintf(stderr, "Stopping at block %u\n", i); ++unrecoverable_error; goto bail; @@ -450,7 +454,12 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity ret = handle_write(failed[j].handle, failed[j].block, buffer[failed[j].index], state->block_size); if (ret == -1) { - fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + if (errno == EACCES) { + fprintf(stderr, "WARNING! Please give write permission to the file.\n"); + } else { + /* we do not use DANGER because for ENOSPC which is not always correctly reported */ + fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + } fprintf(stderr, "Stopping at block %u\n", i); ++unrecoverable_error; goto bail; @@ -468,6 +477,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (buffer_parity == 0 && parity_f != -1) { ret = parity_write(state->parity, parity_f, i, buffer[diskmax], state->block_size); if (ret == -1) { + /* we do not use DANGER because for ENOSPC which is not always correctly reported */ fprintf(stderr, "WARNING! Without a working Parity disk, it isn't possible to fix errors on it.\n"); fprintf(stderr, "Stopping at block %u\n", i); ++unrecoverable_error; @@ -483,6 +493,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (buffer_qarity == 0 && qarity_f != -1) { ret = parity_write(state->qarity, qarity_f, i, buffer[diskmax + 1], state->block_size); if (ret == -1) { + /* we do not use DANGER because for ENOSPC which is not always correctly reported */ fprintf(stderr, "WARNING! Without a working Q-Parity disk, it isn't possible to fix errors on it.\n"); fprintf(stderr, "Stopping at block %u\n", i); ++unrecoverable_error; diff --git a/handle.c b/handle.c index 68822eb8..801e386c 100644 --- a/handle.c +++ b/handle.c @@ -112,6 +112,13 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file) /* opening in sequential mode in Windows */ handle->f = open(handle->path, O_RDWR | O_CREAT | O_BINARY | O_SEQUENTIAL, 0600); + + /* if failed for missing permission */ + if (handle->f == -1 && errno == EACCES) { + /* retry without requesting write permission */ + handle->f = open(handle->path, O_RDONLY | O_BINARY | O_SEQUENTIAL); + } + if (handle->f == -1) { /* invalidate for error */ handle->file = 0; @@ -142,6 +149,8 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file) if (ret != 0) { if (errno == ENOSPC) { fprintf(stderr, "Failed to grow file '%s' due lack of space.\n", handle->path); + } else if (errno == EACCES) { + fprintf(stderr, "Failed to grow file '%s' for missing write permission.\n", handle->path); } else { fprintf(stderr, "Error growing file '%s'. %s.\n", handle->path, strerror(errno)); } @@ -150,7 +159,11 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file) } else if (handle->st.st_size > file->size) { ret = ftruncate(handle->f, file->size); if (ret != 0) { - fprintf(stderr, "Error truncating file '%s'. %s.\n", handle->path, strerror(errno)); + if (errno == EACCES) { + fprintf(stderr, "Failed to truncate file '%s' for missing write permission.\n", handle->path); + } else { + fprintf(stderr, "Error truncating file '%s'. %s.\n", handle->path, strerror(errno)); + } return -1; } } diff --git a/handle.h b/handle.h index e2ee0155..d4a60a9b 100644 --- a/handle.h +++ b/handle.h @@ -36,8 +36,10 @@ int handle_close_if_different(struct snapraid_handle* handle, struct snapraid_fi /** * Creates a file. - * The file is created if missing, and opening with write access. + * The file is created if missing, and opened with write access. * If the file is larger than expected, the value 1 is returned, and the file is truncated to the correct size. + * If the file cannot be opened for write access, it's opened with read-only access. + * The read-only access works only if the file has already the correct size and doesn't need to be modified. */ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file); diff --git a/mingw.h b/mingw.h index 8dce156b..bfb1cd32 100644 --- a/mingw.h +++ b/mingw.h @@ -82,6 +82,7 @@ int windows_mkdir(const char* file); /** * Like the C stat() with inode information. * It doesn't work for all kind of files and directories. For example "\System Volume Information" cannot be opened. + * Note that instead stat() works for all the files. */ #define HAVE_STAT_INODE 1 int stat_inode(const char* file, struct windows_stat* st); diff --git a/scan.c b/scan.c index 40639f84..1ae08f5a 100644 --- a/scan.c +++ b/scan.c @@ -206,7 +206,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s d = opendir(dir); if (!d) { fprintf(stderr, "Error opening directory '%s'. %s.\n", dir, strerror(errno)); - fprintf(stderr, "You can exclude it in the config file with:\n\texclude /%s\n", sub); + fprintf(stderr, "You can exclude it in the config file with:\n\texclude /%s/\n", sub); exit(EXIT_FAILURE); } @@ -222,7 +222,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s dd = readdir(d); if (dd == 0 && errno != 0) { fprintf(stderr, "Error reading directory '%s'. %s.\n", dir, strerror(errno)); - fprintf(stderr, "You can exclude it in the config file with:\n\texclude /%s\n", sub); + fprintf(stderr, "You can exclude it in the config file with:\n\texclude /%s/\n", sub); exit(EXIT_FAILURE); } if (dd == 0 && errno == 0) { @@ -254,13 +254,11 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s /* check for read permission */ if (access(path_next, R_OK) != 0) { - fprintf(stderr, "You do not have read permissions for file '%s'.\n", path_next); - fprintf(stderr, "Fix the permissions or exclude it in the configuration with:\n\texclude /%s\n", sub_next); - fprintf(stderr, "or exclude the whole directory with:\n\texclude /%s\n", sub); - exit(EXIT_FAILURE); + fprintf(stderr, "warning: Ignoring, for missing read permission, file '%s'\n", path_next); + continue; } -#if HAVE_STAT_INODE +#if HAVE_STAT_INODE /* get inode info about the file, Windows needs an additional step */ if (stat_inode(path_next, &st) != 0) { fprintf(stderr, "Error in stat_inode file '%s'. %s.\n", path_next, strerror(errno)); @@ -285,8 +283,12 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s } } } else { - if (state->verbose) { - printf("warning: Ignored special file '/%s'\n", sub_next); + if (filter_path(&state->filterlist, sub_next, 0) == 0) { + fprintf(stderr, "warning: Ignoring special file '%s'\n", path_next); + } else { + if (state->verbose) { + printf("Excluding special file '/%s'\n", sub_next); + } } } }