int ignore_errors = 0;
int modify_window = 0;
int blocking_io = -1;
+int checksum_seed = 0;
unsigned int block_size = 0;
int read_batch = 0;
int backup_dir_len = 0;
int backup_suffix_len;
+unsigned int backup_dir_remainder;
char *backup_suffix = NULL;
char *tmpdir = NULL;
char *password_file = NULL;
char *rsync_path = RSYNC_PATH;
char *backup_dir = NULL;
+char backup_dir_buf[MAXPATHLEN];
int rsync_port = RSYNC_PORT;
int link_dest = 0;
int always_checksum = 0;
int list_only = 0;
+#define FIXED_CHECKSUM_SEED 32761
#define MAX_BATCH_PREFIX_LEN 256 /* Must be less than MAXPATHLEN-13 */
char *batch_prefix = NULL;
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 */
/**
- * 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;
}
char *ref = lp_refuse_options(module_id);
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) {
- if (check_refuse_options(ref, opt)) return 0;
- }
-
/* most options are handled automatically by popt;
* only special cases are returned and listed here. */
break;
case 'q':
- if (frommain) quiet++;
+ if (frommain)
+ quiet++;
break;
case OPT_SENDER:
case OPT_WRITE_BATCH:
/* popt stores the filename in batch_prefix for us */
write_batch = 1;
+ checksum_seed = FIXED_CHECKSUM_SEED;
break;
case OPT_READ_BATCH:
/* popt stores the filename in batch_prefix for us */
read_batch = 1;
+ checksum_seed = FIXED_CHECKSUM_SEED;
break;
case OPT_LINK_DEST:
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;
}
}
relative_paths = files_from? 1 : 0;
if (!backup_suffix)
- backup_suffix = backup_dir? "" : BACKUP_SUFFIX;
+ backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
backup_suffix_len = strlen(backup_suffix);
if (strchr(backup_suffix, '/') != NULL) {
rprintf(FERROR, "--suffix cannot contain slashes: %s\n",
backup_suffix);
exit_cleanup(RERR_SYNTAX);
}
- if (backup_dir)
- backup_dir_len = strlen(backup_dir);
- else if (!backup_suffix_len) {
+ if (backup_dir) {
+ backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
+ backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
+ if (backup_dir_remainder < 32) {
+ rprintf(FERROR, "the --backup-dir path is WAY too long.\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (backup_dir_buf[backup_dir_len - 1] != '/') {
+ backup_dir_buf[backup_dir_len++] = '/';
+ backup_dir_buf[backup_dir_len] = '\0';
+ }
+ if (verbose > 1)
+ rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
+ } else if (!backup_suffix_len) {
rprintf(FERROR,
"--suffix cannot be a null string without --backup-dir\n");
exit_cleanup(RERR_SYNTAX);
{
int ac = *argc;
static char argstr[50];
- static char bsize[30];
- static char iotime[30];
- static char mdelete[30];
- static char mwindow[30];
- static char bw[50];
- /* Leave room for ``--(write|read)-batch='' */
- static char fext[MAX_BATCH_PREFIX_LEN + 15];
+ char *arg;
int i, x;
x = 1;
argstr[0] = '-';
- for (i=0;i<verbose;i++)
+ for (i = 0; i < verbose; i++)
argstr[x++] = 'v';
/* the -q option is intentionally left out */
argstr[x] = 0;
- if (x != 1) args[ac++] = argstr;
+ if (x != 1)
+ args[ac++] = argstr;
if (block_size) {
- snprintf(bsize, sizeof bsize, "-B%u", block_size);
- args[ac++] = bsize;
+ if (asprintf(&arg, "-B%u", block_size) < 0)
+ goto oom;
+ args[ac++] = arg;
}
if (max_delete && am_sender) {
- snprintf(mdelete, sizeof mdelete, "--max-delete=%d",
- max_delete);
- args[ac++] = mdelete;
+ if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
+ goto oom;
+ args[ac++] = arg;
}
- if (batch_prefix != NULL) {
- char *fmt = "";
- if (write_batch)
- fmt = "--write-batch=%s";
- else
- if (read_batch)
- fmt = "--read-batch=%s";
- snprintf(fext, sizeof fext, fmt, batch_prefix);
- args[ac++] = fext;
+ if (batch_prefix) {
+ char *r_or_w = write_batch ? "write" : "read";
+ if (asprintf(&arg, "--%s-batch=%s", r_or_w, batch_prefix) < 0)
+ goto oom;
+ args[ac++] = arg;
}
if (io_timeout) {
- snprintf(iotime, sizeof iotime, "--timeout=%d", io_timeout);
- args[ac++] = iotime;
+ if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
+ goto oom;
+ args[ac++] = arg;
}
if (bwlimit) {
- snprintf(bw, sizeof bw, "--bwlimit=%d", bwlimit);
- args[ac++] = bw;
+ if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
+ goto oom;
+ args[ac++] = arg;
}
if (backup_dir) {
}
/* Only send --suffix if it specifies a non-default value. */
- if (strcmp(backup_suffix, backup_dir? "" : BACKUP_SUFFIX) != 0) {
- char *s = new_array(char, 9+backup_suffix_len+1);
- if (!s)
- out_of_memory("server_options");
+ if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
/* We use the following syntax to avoid weirdness with '~'. */
- sprintf(s, "--suffix=%s", backup_suffix);
- args[ac++] = s;
+ if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
+ goto oom;
+ args[ac++] = arg;
}
- if (delete_mode && !delete_excluded)
- args[ac++] = "--delete";
-
if (delete_excluded)
args[ac++] = "--delete-excluded";
+ else if (delete_mode)
+ args[ac++] = "--delete";
if (size_only)
args[ac++] = "--size-only";
if (modify_window_set) {
- snprintf(mwindow, sizeof mwindow, "--modify-window=%d",
- modify_window);
- args[ac++] = mwindow;
+ if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
+ goto oom;
+ args[ac++] = arg;
}
if (keep_partial)
}
*argc = ac;
+ return;
+
+ oom:
+ out_of_memory("server_options");
}
/**
char *p, *p2;
p = strchr(s,':');
- if (!p) return NULL;
+ if (!p)
+ return NULL;
/* now check to see if there is a / in the string before the : - if there is then
discard the colon on the assumption that the : is part of a filename */
p2 = strchr(s,'/');
- if (p2 && p2 < p) return NULL;
+ if (p2 && p2 < p)
+ return NULL;
return p;
}