From 42d8ec616d5108d1dc2bc949fe967620da653451 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Fri, 13 Mar 2009 09:33:51 -0700 Subject: [PATCH] My version of Matt's improvements related to missing source args: - Implement --ignore-missing-args. - In the absence of --*-missing-args, a missing source arg is an FERROR_XFER, but doesn't need to be an IOERR_GENERAL. - Revise the man page. --- flist.c | 19 +++++++++++++------ generator.c | 6 +++--- options.c | 18 +++++++++++++----- rsync.yo | 25 ++++++++++++++++++------- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/flist.c b/flist.c index 860bf834..09b4fc5a 100644 --- a/flist.c +++ b/flist.c @@ -51,7 +51,7 @@ extern int preserve_links; extern int preserve_hard_links; extern int preserve_devices; extern int preserve_specials; -extern int delete_missing_args; +extern int missing_args; extern int uid_ndx; extern int gid_ndx; extern int eol_nulls; @@ -2177,14 +2177,21 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode))) || (relative_paths && path_is_daemon_excluded(fbuf, 1))) { - if (errno == ENOENT && delete_missing_args) { - /* Rsync will treat a mode of 0 as deleted. */ - memset(&st, 0, sizeof st); - } else { - io_error |= IOERR_GENERAL; + if (errno != ENOENT || missing_args == 0) { + /* This is a transfer error, but inhibit deletion + * only if we might be omitting an existing file. */ + if (errno != ENOENT) + io_error |= IOERR_GENERAL; rsyserr(FERROR_XFER, errno, "link_stat %s failed", full_fname(fbuf)); continue; + } else if (missing_args == 1) { + /* Just ignore the arg. */ + continue; + } else /* (missing_args == 2) */ { + /* Send the arg as a "missing" entry with + * mode 0, which tells the generator to delete it. */ + memset(&st, 0, sizeof st); } } diff --git a/generator.c b/generator.c index 4fad7f71..12007a18 100644 --- a/generator.c +++ b/generator.c @@ -50,7 +50,7 @@ extern int delete_mode; extern int delete_before; extern int delete_during; extern int delete_after; -extern int delete_missing_args; +extern int missing_args; extern int msgdone_cnt; extern int ignore_errors; extern int remove_source_files; @@ -1031,7 +1031,7 @@ static void list_file_entry(struct file_struct *f) F_SYMLINK(f)); } else #endif - if (delete_missing_args && !f->mode) { + if (missing_args == 2 && f->mode == 0) { rprintf(FINFO, "%-*s %s\n", colwidth + 31, "*missing", f_name(f, NULL)); @@ -1177,7 +1177,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, stat_errno = errno; } - if (delete_missing_args && file->mode == 0) { + if (missing_args == 2 && file->mode == 0) { if (filter_list.head && check_filter(&filter_list, FINFO, fname, is_dir) < 0) return; if (statret == 0) diff --git a/options.c b/options.c index 51697adf..e7c6c612 100644 --- a/options.c +++ b/options.c @@ -69,7 +69,6 @@ int delete_during = 0; int delete_before = 0; int delete_after = 0; int delete_excluded = 0; -int delete_missing_args = 0; int remove_source_files = 0; int one_file_system = 0; int protocol_version = PROTOCOL_VERSION; @@ -82,6 +81,7 @@ int am_sender = 0; int am_starting_up = 1; int relative_paths = -1; int implied_dirs = 1; +int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */ int numeric_ids = 0; int msgs2stderr = 0; int allow_8bit_chars = 0; @@ -719,7 +719,8 @@ void usage(enum logcode F) rprintf(F," --delete-delay find deletions during, delete after\n"); rprintf(F," --delete-after receiver deletes after transfer, not during\n"); rprintf(F," --delete-excluded also delete excluded files from destination dirs\n"); - rprintf(F," --delete-missing-args receiver deletes each missing source arg\n"); + rprintf(F," --ignore-missing-args ignore missing source args without error\n"); + rprintf(F," --delete-missing-args delete missing source args from destination\n"); rprintf(F," --ignore-errors delete even if there are I/O errors\n"); rprintf(F," --force force deletion of directories even if not empty\n"); rprintf(F," --max-delete=NUM don't delete more than NUM files\n"); @@ -910,7 +911,8 @@ static struct poptOption long_options[] = { {"delete-delay", 0, POPT_ARG_VAL, &delete_during, 2, 0, 0 }, {"delete-after", 0, POPT_ARG_NONE, &delete_after, 0, 0, 0 }, {"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 }, - {"delete-missing-args",0,POPT_ARG_NONE, &delete_missing_args, 0, 0, 0 }, + {"delete-missing-args",0,POPT_BIT_SET, &missing_args, 2, 0, 0 }, + {"ignore-missing-args",0,POPT_BIT_SET, &missing_args, 1, 0, 0 }, {"remove-sent-files",0, POPT_ARG_VAL, &remove_source_files, 2, 0, 0 }, /* deprecated */ {"remove-source-files",0,POPT_ARG_VAL, &remove_source_files, 1, 0, 0 }, {"force", 0, POPT_ARG_VAL, &force_delete, 1, 0, 0 }, @@ -1925,7 +1927,9 @@ int parse_arguments(int *argc_p, const char ***argv_p) return 0; } - if (refused_delete && (delete_mode || delete_missing_args)) { + if (missing_args == 3) /* simplify if both options were specified */ + missing_args = 2; + if (refused_delete && (delete_mode || missing_args == 2)) { create_refuse_error(refused_delete); return 0; } @@ -2482,8 +2486,12 @@ void server_options(char **args, int *argc_p) } } - if (delete_missing_args) + /* --delete-missing-args needs the cooperation of both sides, but + * the sender can handle --ignore-missing-args by itself. */ + if (missing_args == 2) args[ac++] = "--delete-missing-args"; + else if (missing_args == 1 && !am_sender) + args[ac++] = "--ignore-missing-args"; if (modify_window_set) { if (asprintf(&arg, "--modify-window=%d", modify_window) < 0) diff --git a/rsync.yo b/rsync.yo index 2ff224f4..941f7a58 100644 --- a/rsync.yo +++ b/rsync.yo @@ -375,7 +375,8 @@ to the detailed description below for a complete description. verb( --delete-delay find deletions during, delete after --delete-after receiver deletes after transfer, not before --delete-excluded also delete excluded files from dest dirs - --delete-missing-args receiver deletes each missing source arg + --ignore-missing-args ignore missing source args without error + --delete-missing-args delete missing source args from destination --ignore-errors delete even if there are I/O errors --force force deletion of dirs even if not empty --max-delete=NUM don't delete more than NUM files @@ -1264,12 +1265,22 @@ this way on the receiver, and for a way to protect files from bf(--delete-excluded). See bf(--delete) (which is implied) for more details on file-deletion. -dit(bf(--delete-missing-args)) Any source arg that is found to me missing is -treated as a request to delete the file by the receiver rather than the sender -generating a missing-file error. Does not affect vanished files discovered -through recursive scanning of directories, just the args mentioned on the -command-line or in the bf(--files-from) list. Can be used with or without any -other type of delete processing. +dit(bf(--ignore-missing-args)) When rsync is first processing the explicitly +requested source files (e.g. command-line arguments or bf(--files-from) +entries), it is normally an error if the file cannot be found. This option +suppresses that error, and does not try to transfer the file. This does not +affect subsequent vanished-file errors if a file was initially found to be +present and later is no longer there. + +dit(bf(--delete-missing-args)) This option takes the behavior of (the implied) +bf(--ignore-missing-args) option a step farther: each missing arg will become +a deletion request of the corresponding destination file on the receiving side +(should it exist). If the destination file is a non-empty directory, it will +only be successfully deleted if --force or --delete are in effect. Other than +that, this option is independent of any other type of delete processing. + +The missing source files are represented by special file-list entries which +display as a "*missing" entry in the bf(--list-only) output. dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files even when there are I/O errors. -- 2.34.1