#include "rsync.h"
#include "popt.h"
+extern struct exclude_struct **exclude_list;
+
int make_backups = 0;
/**
int delete_mode=0;
int delete_excluded=0;
int one_file_system=0;
-int remote_version=0;
+int protocol_version = PROTOCOL_VERSION;
int sparse_files=0;
int do_compression=0;
int am_root=0;
int numeric_ids = 0;
int force_delete = 0;
int io_timeout = 0;
-int io_error = 0;
int read_only = 0;
int module_id = -1;
int am_server = 0;
int keep_partial=0;
int safe_symlinks=0;
int copy_unsafe_links=0;
-int block_size=0;
int size_only=0;
int bwlimit=0;
int delete_after=0;
int ignore_errors=0;
int modify_window=0;
int blocking_io=-1;
+unsigned int block_size = 0;
/** Network address family. **/
int write_batch = 0;
int read_batch = 0;
-int suffix_specified = 0;
+int backup_dir_len = 0;
+int backup_suffix_len;
-char *backup_suffix = BACKUP_SUFFIX;
+char *backup_suffix = NULL;
char *tmpdir = NULL;
char *compare_dest = NULL;
char *config_file = NULL;
int always_checksum = 0;
int list_only = 0;
+#define MAX_BATCH_PREFIX_LEN 256 /* Must be less than MAXPATHLEN-13 */
char *batch_prefix = NULL;
static int modify_window_set;
rprintf(f, "%s version %s protocol version %d\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
rprintf(f,
- "Copyright (C) 1996-2002 by Andrew Tridgell and others\n");
+ "Copyright (C) 1996-2004 by Andrew Tridgell and others\n");
rprintf(f, "<http://rsync.samba.org/>\n");
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
"%shard links, %ssymlinks, batchfiles, \n",
rprintf(F," -R, --relative use relative path names\n");
rprintf(F," --no-relative turn off --relative\n");
rprintf(F," --no-implied-dirs don't send implied dirs with -R\n");
- rprintf(F," -b, --backup make backups (default %s suffix)\n",BACKUP_SUFFIX);
+ rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
rprintf(F," --backup-dir make backups into this directory\n");
- rprintf(F," --suffix=SUFFIX override backup suffix\n");
+ rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
rprintf(F," -l, --links copy symlinks as symlinks\n");
rprintf(F," -L, --copy-links copy the referent of symlinks\n");
rprintf(F," -e, --rsh=COMMAND specify the remote shell\n");
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
rprintf(F," --existing only update files that already exist\n");
- rprintf(F," --ignore-existing ignore files that already exist on the receiving side\n");
+ rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
rprintf(F," --delete delete files that don't exist on the sending side\n");
rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
- rprintf(F," --delete-after delete after transferring, not before\n");
+ rprintf(F," --delete-after receiver deletes after transferring, not before\n");
rprintf(F," --ignore-errors delete even if there are IO errors\n");
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
rprintf(F," --partial keep partially transferred files\n");
rprintf(F," --force force deletion of directories even if not empty\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
- rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
- rprintf(F," --size-only only use file size when determining if a file should be transferred\n");
- rprintf(F," --modify-window=NUM Timestamp window (seconds) for file match (default=%d)\n",modify_window);
+ rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
+ rprintf(F," --size-only ignore mod time for quick check (use size)\n");
+ rprintf(F," --modify-window=NUM compare mod times with reduced accuracy\n");
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
+ rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
rprintf(F," -P equivalent to --partial --progress\n");
rprintf(F," -z, --compress compress file data\n");
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
- rprintf(F," -0 --from0 file names we read are separated by nulls, not newlines\n");
+ rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
rprintf(F," --no-detach do not detach from the parent\n");
rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
}
-enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
- OPT_EXCLUDE_FROM, OPT_DELETE, OPT_DELETE_EXCLUDED, OPT_NUMERIC_IDS,
- OPT_RSYNC_PATH, OPT_FORCE, OPT_TIMEOUT, OPT_DAEMON, OPT_CONFIG, OPT_PORT,
- OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
- OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST, OPT_LINK_DEST,
- OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
- OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
- OPT_IGNORE_ERRORS, OPT_BWLIMIT,
- OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_IGNORE_EXISTING};
+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};
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, OPT_SUFFIX, 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 },
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"files-from", 0, POPT_ARG_STRING, &files_from, 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 },
#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 },
{
if (err_buf[0]) {
rprintf(FLOG, "%s", err_buf);
- rprintf(FERROR, "%s: %s", RSYNC_NAME, 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");
print_rsync_version(FINFO);
exit_cleanup(0);
- case OPT_SUFFIX:
- /* The value has already been set by popt, but
- * we need to remember that a suffix was specified
- * in case a backup-directory is used. */
- suffix_specified = 1;
- break;
-
case OPT_MODIFY_WINDOW:
/* The value has already been set by popt, but
* we need to remember that we're using a
break;
case OPT_EXCLUDE:
- add_exclude(poptGetOptArg(pc), 0);
+ add_exclude(&exclude_list, poptGetOptArg(pc),
+ ADD_EXCLUDE);
break;
case OPT_INCLUDE:
- add_exclude(poptGetOptArg(pc), 1);
+ add_exclude(&exclude_list, poptGetOptArg(pc),
+ ADD_INCLUDE);
break;
case OPT_EXCLUDE_FROM:
- add_exclude_file(poptGetOptArg(pc), 1, 0);
+ add_exclude_file(&exclude_list, poptGetOptArg(pc),
+ MISSING_FATAL, ADD_EXCLUDE);
break;
case OPT_INCLUDE_FROM:
- add_exclude_file(poptGetOptArg(pc), 1, 1);
+ add_exclude_file(&exclude_list, poptGetOptArg(pc),
+ MISSING_FATAL, ADD_INCLUDE);
break;
case 'h':
* rprintf? Everybody who gets this message
* ought to send it to the client and also to
* the logs. */
- snprintf(err_buf,sizeof(err_buf),
+ snprintf(err_buf, sizeof err_buf,
"hard links are not supported on this %s\n",
am_server ? "server" : "client");
- rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
+ rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
#endif /* SUPPORT_HARD_LINKS */
break;
link_dest = 1;
break;
#else
- snprintf(err_buf,sizeof(err_buf),
+ snprintf(err_buf, sizeof err_buf,
"hard links are not supported on this %s\n",
am_server ? "server" : "client");
- rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
+ rprintf(FERROR, "ERROR: %s", err_buf);
return 0;
#endif
}
if (write_batch && read_batch) {
- snprintf(err_buf,sizeof(err_buf),
- "write-batch and read-batch can not be used together\n");
- rprintf(FERROR,"ERROR: write-batch and read-batch"
- " can not be used together\n");
- return 0;
+ rprintf(FERROR,
+ "write-batch and read-batch can not be used together\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (batch_prefix && strlen(batch_prefix) > MAX_BATCH_PREFIX_LEN) {
+ rprintf(FERROR,
+ "the batch-file prefix must be %d characters or less.\n",
+ MAX_BATCH_PREFIX_LEN);
+ exit_cleanup(RERR_SYNTAX);
+ }
+
+ if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
+ rprintf(FERROR, "the --temp-dir path is WAY too long.\n");
+ exit_cleanup(RERR_SYNTAX);
}
if (do_compression && (write_batch || read_batch)) {
- snprintf(err_buf,sizeof(err_buf),
- "compress can not be used with write-batch or read-batch\n");
- rprintf(FERROR,"ERROR: compress can not be used with"
- " write-batch or read-batch\n");
- return 0;
+ rprintf(FERROR,
+ "compress can not be used with write-batch or read-batch\n");
+ exit_cleanup(RERR_SYNTAX);
}
if (archive_mode) {
if (relative_paths < 0)
relative_paths = files_from? 1 : 0;
+ if (!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) {
+ 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);
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
- if (strcmp(files_from, "-") == 0)
+ if (strcmp(files_from, "-") == 0) {
filesfrom_fd = 0;
+ if (am_server)
+ remote_filesfrom_file = "-";
+ }
else if ((colon = find_colon(files_from)) != 0) {
if (am_server) {
usage(FERROR);
static char mwindow[30];
static char bw[50];
/* Leave room for ``--(write|read)-batch='' */
- static char fext[MAXPATHLEN + 15];
+ static char fext[MAX_BATCH_PREFIX_LEN + 15];
int i, x;
if (x != 1) args[ac++] = argstr;
if (block_size) {
- snprintf(bsize,sizeof(bsize),"-B%d",block_size);
+ snprintf(bsize, sizeof bsize, "-B%u", block_size);
args[ac++] = bsize;
}
args[ac++] = bw;
}
- if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
- args[ac++] = "--suffix";
- args[ac++] = backup_suffix;
+ if (backup_dir) {
+ args[ac++] = "--backup-dir";
+ args[ac++] = 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");
+ /* We use the following syntax to avoid weirdness with '~'. */
+ sprintf(s, "--suffix=%s", backup_suffix);
+ args[ac++] = s;
}
if (delete_mode && !delete_excluded)
args[ac++] = tmpdir;
}
- if (backup_dir && am_sender) {
- /* only the receiver needs this option, if we are the sender
- * then we need to send it to the receiver.
- */
- args[ac++] = "--backup-dir";
- args[ac++] = backup_dir;
- }
-
if (compare_dest && am_sender) {
/* the server only needs this option if it is not the sender,
* and it may be an older version that doesn't know this
return p;
}
-
-