extern int module_id;
extern int sanitize_paths;
-extern int select_timeout;
extern struct filter_list_struct filter_list;
extern struct filter_list_struct server_filter_list;
**/
int whole_file = -1;
+int append_mode = 0;
int archive_mode = 0;
int keep_dirlinks = 0;
int copy_links = 0;
int numeric_ids = 0;
int force_delete = 0;
int io_timeout = 0;
+int allowed_lull = 0;
char *files_from = NULL;
int filesfrom_fd = -1;
char *filesfrom_host = NULL;
static int itemize_changes = 0;
static int refused_delete, refused_archive_part;
static int refused_partial, refused_progress, refused_delete_before;
+static int refused_inplace;
static char *max_size_arg;
static char partialdir_for_delayupdate[] = ".~tmp~";
rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
- rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
+ rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");
rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
rprintf(F," -u, --update skip files that are newer on the receiver\n");
rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
+ rprintf(F," --append append data onto shorter files\n");
rprintf(F," -d, --dirs transfer directories without recursing\n");
rprintf(F," -l, --links copy symlinks as symlinks\n");
rprintf(F," -L, --copy-links transform symlink into referent file/dir\n");
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
rprintf(F," --include-from=FILE read include patterns from FILE\n");
rprintf(F," --files-from=FILE read list of source-file names from FILE\n");
- rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n");
- rprintf(F," --version print version number\n");
+ rprintf(F," -0, --from0 all *-from/filter files are delimited by 0s\n");
rprintf(F," --address=ADDRESS bind address for outgoing socket to daemon\n");
rprintf(F," --port=PORT specify double-colon alternate port number\n");
rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
rprintf(F," --progress show progress during transfer\n");
rprintf(F," -P same as --partial --progress\n");
rprintf(F," -i, --itemize-changes output a change-summary for all updates\n");
- rprintf(F," --log-format=FORMAT log file-transfers using specified format\n");
+ rprintf(F," --log-format=FORMAT output filenames using the specified format\n");
rprintf(F," --password-file=FILE read password from FILE\n");
rprintf(F," --list-only list the files instead of copying them\n");
rprintf(F," --bwlimit=KBPS limit I/O bandwidth; KBytes per second\n");
rprintf(F," -4, --ipv4 prefer IPv4\n");
rprintf(F," -6, --ipv6 prefer IPv6\n");
#endif
+ rprintf(F," --version print version number\n");
rprintf(F," -h, --help show this help screen\n");
rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
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_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
- OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH,
- OPT_TIMEOUT, OPT_MAX_SIZE,
+ OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
{"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
{"copy-links", 'L', POPT_ARG_NONE, ©_links, 0, 0, 0 },
{"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
+ {"append", 0, POPT_ARG_VAL, &append_mode, 1, 0, 0 },
{"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },
{"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 },
{"copy-unsafe-links",0, POPT_ARG_NONE, ©_unsafe_links, 0, 0, 0 },
{"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 },
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
- {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 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, 0, OPT_COMPARE_DEST, 0, 0 },
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
refused_partial = op->val;
else if (wildmatch("progress", op->longName))
refused_progress = op->val;
+ else if (wildmatch("inplace", op->longName))
+ refused_inplace = op->val;
break;
}
if (!is_wild)
}
+static OFF_T parse_size_arg(const char *size_arg)
+{
+ const char *arg;
+ OFF_T size;
+
+ for (arg = size_arg; isdigit(*(uchar*)arg); arg++) {}
+ if (*arg == '.')
+ for (arg++; isdigit(*(uchar*)arg); arg++) {}
+ switch (*arg) {
+ case 'k': case 'K':
+ size = atof(size_arg) * 1024;
+ break;
+ case 'm': case 'M':
+ size = atof(size_arg) * 1024*1024;
+ break;
+ case 'g': case 'G':
+ size = atof(size_arg) * 1024*1024*1024;
+ break;
+ case '\0':
+ size = atof(size_arg);
+ break;
+ default:
+ size = 0;
+ break;
+ }
+ return size;
+}
+
+
static void create_refuse_error(int which)
{
/* The "which" value is the index + OPT_REFUSED_BASE. */
break;
case OPT_MAX_SIZE:
- for (arg = max_size_arg; isdigit(*(uchar*)arg); arg++) {}
- if (*arg == '.')
- for (arg++; isdigit(*(uchar*)arg); arg++) {}
- switch (*arg) {
- case 'k': case 'K':
- max_size = atof(max_size_arg) * 1024;
- break;
- case 'm': case 'M':
- max_size = atof(max_size_arg) * 1024*1024;
- break;
- case 'g': case 'G':
- max_size = atof(max_size_arg) * 1024*1024*1024;
- break;
- case '\0':
- max_size = atof(max_size_arg);
- break;
- default:
- max_size = 0;
- break;
- }
- if (max_size <= 0) {
+ if ((max_size = parse_size_arg(max_size_arg)) <= 0) {
snprintf(err_buf, sizeof err_buf,
"--max-size value is invalid: %s\n",
max_size_arg);
}
break;
- case OPT_TIMEOUT:
- if (io_timeout && io_timeout < select_timeout)
- select_timeout = io_timeout;
- break;
-
case OPT_LINK_DEST:
#ifdef HAVE_LINK
link_dest = 1;
if (relative_paths < 0)
relative_paths = files_from? 1 : 0;
+ if (!relative_paths)
+ implied_dirs = 0;
if (!!delete_before + delete_during + delete_after > 1) {
snprintf(err_buf, sizeof err_buf,
if (dry_run)
do_xfers = 0;
+ set_io_timeout(io_timeout);
+
if (verbose && !log_format) {
log_format = "%n%L";
log_before_transfer = !am_server;
bwlimit_writemax = 512;
}
+ if (append_mode) {
+ if (whole_file > 0) {
+ snprintf(err_buf, sizeof err_buf,
+ "--append cannot be used with --whole-file\n");
+ return 0;
+ }
+ if (refused_inplace) {
+ create_refuse_error(refused_inplace);
+ return 0;
+ }
+ inplace = 1;
+ }
+
if (delay_updates && !partial_dir)
partial_dir = partialdir_for_delayupdate;
#ifdef HAVE_FTRUNCATE
if (partial_dir) {
snprintf(err_buf, sizeof err_buf,
- "--inplace cannot be used with --%s\n",
+ "--%s cannot be used with --%s\n",
+ append_mode ? "append" : "inplace",
delay_updates ? "delay-updates" : "partial-dir");
return 0;
}
keep_partial = 0;
#else
snprintf(err_buf, sizeof err_buf,
- "--inplace is not supported on this %s\n",
+ "--%s is not supported on this %s\n",
+ append_mode ? "append" : "inplace",
am_server ? "server" : "client");
return 0;
#endif
**/
void server_options(char **args,int *argc)
{
- static char argstr[50+MAX_BASIS_DIRS*2];
+ static char argstr[64];
int ac = *argc;
char *arg;
argstr[x++] = 'b';
if (update_only)
argstr[x++] = 'u';
- if (!do_xfers)
+ if (!do_xfers) /* NOT "dry_run"! */
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if (opt_ignore_existing && am_sender)
args[ac++] = "--ignore-existing";
- if (inplace)
+ if (append_mode)
+ args[ac++] = "--append";
+ else if (inplace)
args[ac++] = "--inplace";
if (tmpdir) {
if (!relative_paths)
args[ac++] = "--no-relative";
}
- if (!implied_dirs && !am_sender)
+ if (relative_paths && !implied_dirs && !am_sender)
args[ac++] = "--no-implied-dirs";
if (fuzzy_basis && am_sender)