#include "rsync.h"
#include "popt.h"
-extern struct exclude_struct **exclude_list;
+extern int sanitize_paths;
+extern char curr_dir[MAXPATHLEN];
+extern struct exclude_list_struct exclude_list;
int make_backups = 0;
rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n",
ipv6,
(int) (sizeof dumstat->st_ino * 8),
- (int) (sizeof (INO64_T) * 8));
+ (int) (sizeof (uint64) * 8));
#ifdef MAINTAINER_MODE
rprintf(f, " panic action: \"%s\"\n",
get_panic_action());
rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
rprintf(F," --write-batch=PREFIX write batch fileset starting with PREFIX\n");
rprintf(F," --read-batch=PREFIX read batch fileset starting with PREFIX\n");
- rprintf(F," -h, --help show this help screen\n");
+ rprintf(F," --checksum-seed=NUM set block/file checksum seed\n");
#ifdef INET6
- rprintf(F," -4 prefer IPv4\n");
- rprintf(F," -6 prefer IPv6\n");
+ rprintf(F," -4 --ipv4 prefer IPv4\n");
+ rprintf(F," -6 --ipv6 prefer IPv6\n");
#endif
+ rprintf(F," -h, --help show this help screen\n");
rprintf(F,"\n");
enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
- OPT_READ_BATCH, OPT_WRITE_BATCH};
+ OPT_READ_BATCH, OPT_WRITE_BATCH,
+ OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
{"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
- {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
- {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
+ {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
+ {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
{"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
{"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
- {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
+ {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
/* TODO: Should this take an optional int giving the compression level? */
{"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
{"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
{"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
{"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
{"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
+ {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
#ifdef INET6
- {0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
- {0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
+ {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
+ {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
#endif
{0,0,0,0, 0, 0, 0}
};
-static char err_buf[100];
+static char err_buf[200];
/**
**/
void option_error(void)
{
- if (err_buf[0]) {
- rprintf(FLOG, "%s", err_buf);
- rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
- } else {
- rprintf (FERROR, "Error parsing options: "
- "option may be supported on client but not on server?\n");
- rprintf (FERROR, RSYNC_NAME ": Error parsing options: "
- "option may be supported on client but not on server?\n");
+ int save_daemon = am_daemon;
+
+ if (!err_buf[0]) {
+ strcpy(err_buf, "Error parsing options: "
+ "option may be supported on client but not on server?\n");
}
+
+ rwrite(FLOG, err_buf, strlen(err_buf));
+ am_daemon = 0;
+ rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
+ am_daemon = save_daemon;
}
/**
- * Check to see if we should refuse this option
+ * Tweak the option table to disable all options that the rsyncd.conf
+ * file has told us to refuse.
**/
-static int check_refuse_options(char *ref, int opt)
+static void set_refuse_options(char *bp)
{
- int i, len;
- char *p;
- const char *name;
-
- for (i = 0; long_options[i].longName; i++) {
- if (long_options[i].val == opt)
- break;
- }
-
- if (!long_options[i].longName)
- return 0;
-
- name = long_options[i].longName;
- len = strlen(name);
-
- while ((p = strstr(ref,name))) {
- if ((p==ref || p[-1]==' ') &&
- (p[len] == ' ' || p[len] == 0)) {
- snprintf(err_buf, sizeof err_buf,
- "The '%s' option is not supported by this server\n", name);
- return 1;
+ struct poptOption *op;
+ char *cp;
+
+ while (1) {
+ if ((cp = strchr(bp, ' ')) != NULL)
+ *cp= '\0';
+ for (op = long_options; ; op++) {
+ if (!op->longName) {
+ rprintf(FLOG,
+ "Unknown option %s in \"refuse options\" setting\n",
+ bp);
+ break;
+ }
+ if (strcmp(bp, op->longName) == 0) {
+ op->val = (op - long_options)+OPT_REFUSED_BASE;
+ break;
+ }
}
- ref += len;
+ if (!cp)
+ break;
+ *cp = ' ';
+ bp = cp + 1;
}
- return 0;
}
{
int opt;
char *ref = lp_refuse_options(module_id);
+ const char *arg;
poptContext pc;
+ if (ref && *ref)
+ set_refuse_options(ref);
+
/* TODO: Call poptReadDefaultConfig; handle errors. */
/* The context leaks in case of an error, but if there's a
pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
while ((opt = poptGetNextOpt(pc)) != -1) {
- if (ref && check_refuse_options(ref, opt))
- return 0;
-
/* most options are handled automatically by popt;
* only special cases are returned and listed here. */
break;
case OPT_EXCLUDE:
- add_exclude(&exclude_list, poptGetOptArg(pc),
- ADD_EXCLUDE);
+ add_exclude(&exclude_list, poptGetOptArg(pc), 0);
break;
case OPT_INCLUDE:
add_exclude(&exclude_list, poptGetOptArg(pc),
- ADD_INCLUDE);
+ XFLG_DEF_INCLUDE);
break;
case OPT_EXCLUDE_FROM:
- add_exclude_file(&exclude_list, poptGetOptArg(pc),
- MISSING_FATAL, ADD_EXCLUDE);
+ arg = poptGetOptArg(pc);
+ if (sanitize_paths)
+ arg = alloc_sanitize_path(arg, curr_dir);
+ add_exclude_file(&exclude_list, arg,
+ XFLG_FATAL_ERRORS);
break;
case OPT_INCLUDE_FROM:
- add_exclude_file(&exclude_list, poptGetOptArg(pc),
- MISSING_FATAL, ADD_INCLUDE);
+ arg = poptGetOptArg(pc);
+ if (sanitize_paths)
+ arg = alloc_sanitize_path(arg, curr_dir);
+ add_exclude_file(&exclude_list, arg,
+ XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
break;
case 'h':
case OPT_LINK_DEST:
#if HAVE_LINK
- compare_dest = (char *)poptGetOptArg(pc);
link_dest = 1;
break;
#else
snprintf(err_buf, sizeof err_buf,
"hard links are not supported on this %s\n",
am_server ? "server" : "client");
- rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
#endif
-
default:
- snprintf(err_buf, sizeof err_buf,
- "%s%s: %s\n",
- am_server ? "on remote machine: " : "",
- poptBadOption(pc, POPT_BADOPTION_NOALIAS),
- poptStrerror(opt));
+ /* A large opt value means that set_refuse_options()
+ * turned this option off (opt-BASE is its index). */
+ if (opt >= OPT_REFUSED_BASE) {
+ struct poptOption *op =
+ &long_options[opt-OPT_REFUSED_BASE];
+ int n = snprintf(err_buf, sizeof err_buf,
+ "This server does not support --%s\n",
+ op->longName) - 1;
+ if (op->shortName) {
+ snprintf(err_buf+n, sizeof err_buf-n,
+ " (-%c)\n", op->shortName);
+ }
+ } else {
+ snprintf(err_buf, sizeof err_buf,
+ "%s%s: %s\n",
+ am_server ? "on remote machine: " : "",
+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
+ poptStrerror(opt));
+ }
return 0;
}
}
snprintf(err_buf, sizeof err_buf,
"symlinks are not supported on this %s\n",
am_server ? "server" : "client");
- rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
}
#endif
snprintf(err_buf, sizeof err_buf,
"hard links are not supported on this %s\n",
am_server ? "server" : "client");
- rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
}
#endif
if (relative_paths < 0)
relative_paths = files_from? 1 : 0;
+ *argv = poptGetArgs(pc);
+ if (*argv)
+ *argc = count_args(*argv);
+ else
+ *argc = 0;
+
+ if (sanitize_paths) {
+ int i;
+ for (i = *argc; i-- > 0; )
+ (*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
+ if (tmpdir)
+ tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
+ if (compare_dest)
+ compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
+ if (backup_dir)
+ backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
+ if (files_from)
+ files_from = alloc_sanitize_path(files_from, curr_dir);
+ }
+
+ if (daemon_opt) {
+ daemon_opt = 0;
+ am_daemon = 1;
+ return 1;
+ }
+
if (!backup_suffix)
backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
backup_suffix_len = strlen(backup_suffix);
backup_dir_buf[backup_dir_len++] = '/';
backup_dir_buf[backup_dir_len] = '\0';
}
- if (verbose > 1)
+ if (verbose > 1 && !am_sender)
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
- } else if (!backup_suffix_len) {
+ } else if (!backup_suffix_len && (!am_server || !am_sender)) {
rprintf(FERROR,
"--suffix cannot be a null string without --backup-dir\n");
exit_cleanup(RERR_SYNTAX);
if (do_progress && !verbose)
verbose = 1;
- *argv = poptGetArgs(pc);
- if (*argv)
- *argc = count_args(*argv);
- else
- *argc = 0;
-
if (files_from) {
char *colon;
- if (*argc != 2) {
+ if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
exit_cleanup(RERR_SYNTAX);
}
} else {
- extern int sanitize_paths;
- if (sanitize_paths) {
- files_from = strdup(files_from);
- sanitize_path(files_from, NULL);
- }
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
if (filesfrom_fd < 0) {
rsyserr(FERROR, errno,
}
}
- if (daemon_opt)
- am_daemon = 1;
-
return 1;
}
args[ac++] = arg;
}
+ if (checksum_seed) {
+ if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
+ goto oom;
+ args[ac++] = arg;
+ }
+
if (keep_partial)
args[ac++] = "--partial";