int dry_run = 0;
int do_xfers = 1;
int ignore_times = 0;
+int saw_delete_opt = 0;
+int saw_delete_excluded_opt = 0;
int delete_mode = 0;
int delete_during = 0;
int delete_before = 0;
char *password_file = NULL;
char *rsync_path = RSYNC_PATH;
char *backup_dir = NULL;
-char *chmod_mode = NULL;
char backup_dir_buf[MAXPATHLEN];
int rsync_port = 0;
int compare_dest = 0;
enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
- OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE,
+ OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
- OPT_REFUSED_BASE = 9000};
+ OPT_SERVER, OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 },
{"no-R", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 },
{"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
- {"chmod", 0, POPT_ARG_STRING, &chmod_mode, 0, 0, 0 },
+ {"chmod", 0, POPT_ARG_STRING, 0, OPT_CHMOD, 0, 0 },
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
{"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
{"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
- {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
+ {"server", 0, POPT_ARG_NONE, 0, OPT_SERVER, 0, 0 },
{"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
/* All the following options switch us into daemon-mode option-parsing. */
{"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
print_rsync_version(FINFO);
exit_cleanup(0);
+ case OPT_SERVER:
+ if (!am_server) {
+ /* Disable popt aliases on the server side and
+ * then start parsing the options again. */
+ poptFreeContext(pc);
+ pc = poptGetContext(RSYNC_NAME, *argc, *argv,
+ long_options, 0);
+ am_server = 1;
+ }
+ break;
+
+ case OPT_SENDER:
+ if (!am_server) {
+ usage(FERROR);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ am_sender = 1;
+ break;
+
case OPT_DAEMON:
if (am_daemon) {
strcpy(err_buf, "Attempt to hack rsync thwarted!\n");
preserve_devices = 1;
break;
- case OPT_HELP:
- usage(FINFO);
- exit_cleanup(0);
-
case 'i':
itemize_changes++;
break;
one_file_system++;
break;
- case OPT_SENDER:
- if (!am_server) {
- usage(FERROR);
- exit_cleanup(RERR_SYNTAX);
- }
- am_sender = 1;
- break;
-
case 'F':
switch (++F_option_cnt) {
case 1:
basis_dir[basis_dir_cnt++] = (char *)arg;
break;
+ case OPT_CHMOD:
+ arg = poptGetOptArg(pc);
+ if (!(chmod_modes = parse_chmod(arg, chmod_modes))) {
+ snprintf(err_buf, sizeof err_buf,
+ "Invalid argument passed to --chmod (%s)\n",
+ arg);
+ return 0;
+ }
+ break;
+
+ case OPT_HELP:
+ usage(FINFO);
+ exit_cleanup(0);
+
default:
/* A large opt value means that set_refuse_options()
* turned this option off. */
"You may not combine multiple --delete-WHEN options.\n");
return 0;
}
- if (!xfer_dirs) {
- delete_before = delete_during = delete_after = 0;
- delete_mode = delete_excluded = 0;
- } else if (delete_before || delete_during || delete_after)
+ if (delete_before || delete_during || delete_after)
delete_mode = 1;
else if (delete_mode || delete_excluded) {
if (refused_delete_before) {
}
delete_mode = delete_before = 1;
}
+ saw_delete_opt = delete_mode;
+ saw_delete_excluded_opt = delete_excluded;
+ if (!xfer_dirs) {
+ delete_before = delete_during = delete_after = 0;
+ delete_mode = delete_excluded = 0;
+ }
if (delete_mode && refused_delete) {
create_refuse_error(refused_delete);
if (make_backups && !backup_dir)
omit_dir_times = 1;
- if (chmod_mode && !(chmod_modes = parse_chmod(chmod_mode))) {
- snprintf(err_buf, sizeof err_buf,
- "Invalid argument passed to --chmod\n");
- return 0;
- }
-
if (log_format) {
if (am_server && log_format_has(log_format, 'I'))
log_format_has_i = 2;
argstr[x++] = 'l';
if (copy_links)
argstr[x++] = 'L';
- if (xfer_dirs > 1)
+ if (xfer_dirs > (recurse || !delete_mode || !am_sender))
argstr[x++] = 'd';
if (keep_dirlinks && am_sender)
argstr[x++] = 'K';
if (list_only == 1 && !recurse)
argstr[x++] = 'r';
- argstr[x] = 0;
+ argstr[x] = '\0';
if (x != 1)
args[ac++] = argstr;
if (list_only > 1)
args[ac++] = "--list-only";
+ /* This makes sure that the remote rsync can handle deleting with -d
+ * sans -r because the --no-r option was added at the same time. */
+ if (xfer_dirs && !recurse && delete_mode && am_sender)
+ args[ac++] = "--no-r";
+
if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
goto oom;
}
}
- if (chmod_mode && !am_sender) {
- args[ac++] = "--chmod";
- args[ac++] = chmod_mode;
- }
-
if (files_from && (!am_sender || filesfrom_host)) {
if (filesfrom_host) {
args[ac++] = "--files-from";