#include "rsync.h"
#include "itypes.h"
#include "ifuncs.h"
-#include "latest-year.h"
-#include "git-version.h"
#include <popt.h>
extern int module_id;
extern int local_server;
extern int sanitize_paths;
extern unsigned int module_dirlen;
-extern struct name_num_obj valid_checksums;
-extern struct name_num_obj valid_compressions;
extern filter_rule_list filter_list;
extern filter_rule_list daemon_filter_list;
int preserve_specials = 0;
int preserve_uid = 0;
int preserve_gid = 0;
-int preserve_times = 0;
+int preserve_mtimes = 0;
int preserve_atimes = 0;
int preserve_crtimes = 0;
+int omit_dir_times = 0;
+int omit_link_times = 0;
int update_only = 0;
int open_noatime = 0;
int cvs_exclude = 0;
int dry_run = 0;
int do_xfers = 1;
+int do_fsync = 0;
int ignore_times = 0;
int delete_mode = 0;
int delete_during = 0;
const char *checksum_choice = NULL;
const char *compress_choice = NULL;
-#ifndef __APPLE__ /* Do we need a configure check for this? */
-#define SUPPORT_ATIMES 1
-#endif
-
int quiet = 0;
int output_motd = 1;
int log_before_transfer = 0;
INFO_WORD(NAME, W_SND|W_REC, "Mention 1) updated file/dir names, 2) unchanged names"),
INFO_WORD(PROGRESS, W_CLI, "Mention 1) per-file progress or 2) total transfer progress"),
INFO_WORD(REMOVE, W_SND, "Mention files removed on the sending side"),
- INFO_WORD(SKIP, W_REC, "Mention files that are skipped due to options used"),
+ INFO_WORD(SKIP, W_REC, "Mention files that are skipped due to options used (levels 1-2)"),
INFO_WORD(STATS, W_CLI|W_SRV, "Mention statistics at end of run (levels 1-3)"),
INFO_WORD(SYMSAFE, W_SND|W_REC, "Mention symlinks that are unsafe"),
{ NULL, "--info", 0, 0, 0, 0 }
static int do_stats = 0;
static int do_progress = 0;
static int daemon_opt; /* sets am_daemon after option error-reporting */
-static int omit_dir_times = 0;
-static int omit_link_times = 0;
static int F_option_cnt = 0;
static int modify_window_set;
static int itemize_changes = 0;
debug_levels[j] *= -1;
}
-static char *istring(const char *fmt, int val)
-{
- char *str;
- if (asprintf(&str, fmt, val) < 0)
- out_of_memory("istring");
- return str;
-}
-
-static void print_info_flags(enum logcode f)
-{
- STRUCT_STAT *dumstat;
- char line_buf[75];
- int line_len, j;
- char *info_flags[] = {
-
- "*Capabilities",
-
- istring("%d-bit files", (int)(sizeof (OFF_T) * 8)),
- istring("%d-bit inums", (int)(sizeof dumstat->st_ino * 8)), /* Don't check ino_t! */
- istring("%d-bit timestamps", (int)(sizeof (time_t) * 8)),
- istring("%d-bit long ints", (int)(sizeof (int64) * 8)),
-
-#ifndef HAVE_SOCKETPAIR
- "no "
-#endif
- "socketpairs",
-
-#ifndef SUPPORT_HARD_LINKS
- "no "
-#endif
- "hardlinks",
-
-#ifndef CAN_HARDLINK_SPECIAL
- "no "
-#endif
- "hardlink-specials",
-
-#ifndef SUPPORT_LINKS
- "no "
-#endif
- "symlinks",
-
-#ifndef INET6
- "no "
-#endif
- "IPv6",
-
-#ifndef SUPPORT_ATIMES
- "no "
-#endif
- "atimes",
-
- "batchfiles",
-
-#ifndef HAVE_FTRUNCATE
- "no "
-#endif
- "inplace",
-
-#ifndef HAVE_FTRUNCATE
- "no "
-#endif
- "append",
-
-#ifndef SUPPORT_ACLS
- "no "
-#endif
- "ACLs",
-
-#ifndef SUPPORT_XATTRS
- "no "
-#endif
- "xattrs",
-
-#ifdef RSYNC_USE_PROTECTED_ARGS
- "default "
-#else
- "optional "
-#endif
- "protect-args",
-
-#ifndef ICONV_OPTION
- "no "
-#endif
- "iconv",
-
-#ifndef CAN_SET_SYMLINK_TIMES
- "no "
-#endif
- "symtimes",
-
-#ifndef SUPPORT_PREALLOCATION
- "no "
-#endif
- "prealloc",
-
-#ifndef HAVE_MKTIME
- "no "
-#endif
- "stop-at",
-
-#ifndef SUPPORT_CRTIMES
- "no "
-#endif
- "crtimes",
-
- "*Optimizations",
-
-#ifndef HAVE_SIMD
- "no "
-#endif
- "SIMD",
-
-#ifndef HAVE_ASM
- "no "
-#endif
- "asm",
-
-#ifndef USE_OPENSSL
- "no "
-#endif
- "openssl-crypto",
-
- NULL
- };
-
- for (line_len = 0, j = 0; ; j++) {
- char *str = info_flags[j], *next_nfo = str ? info_flags[j+1] : NULL;
- int str_len = str && *str != '*' ? strlen(str) : 1000;
- int need_comma = next_nfo && *next_nfo != '*' ? 1 : 0;
- if (line_len && line_len + 1 + str_len + need_comma >= (int)sizeof line_buf) {
- rprintf(f, " %s\n", line_buf);
- line_len = 0;
- }
- if (!str)
- break;
- if (*str == '*') {
- rprintf(f, "%s:\n", str+1);
- continue;
- }
- line_len += snprintf(line_buf+line_len, sizeof line_buf - line_len, " %s%s", str, need_comma ? "," : "");
- }
-}
-
-static void print_rsync_version(enum logcode f)
-{
- char tmpbuf[256], *subprotocol = "";
-
-#if SUBPROTOCOL_VERSION != 0
- subprotocol = istring(".PR%d", SUBPROTOCOL_VERSION);
-#endif
- rprintf(f, "%s version %s protocol version %d%s\n",
- RSYNC_NAME, RSYNC_GITVER, PROTOCOL_VERSION, subprotocol);
-
- rprintf(f, "Copyright (C) 1996-" LATEST_YEAR " by Andrew Tridgell, Wayne Davison, and others.\n");
- rprintf(f, "Web site: https://rsync.samba.org/\n");
-
- print_info_flags(f);
-
- rprintf(f, "Checksum list:\n");
- get_default_nno_list(&valid_checksums, tmpbuf, sizeof tmpbuf, '(');
- rprintf(f, " %s\n", tmpbuf);
-
- rprintf(f, "Compress list:\n");
- get_default_nno_list(&valid_compressions, tmpbuf, sizeof tmpbuf, '(');
- rprintf(f, " %s\n", tmpbuf);
-
-#ifdef MAINTAINER_MODE
- rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-#endif
-
-#if SIZEOF_INT64 < 8
- rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
-#endif
- if (sizeof (int64) != SIZEOF_INT64) {
- rprintf(f,
- "WARNING: size mismatch in SIZEOF_INT64 define (%d != %d)\n",
- (int) SIZEOF_INT64, (int) sizeof (int64));
- }
-
- rprintf(f,"\n");
- rprintf(f,"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n");
- rprintf(f,"are welcome to redistribute it under certain conditions. See the GNU\n");
- rprintf(f,"General Public Licence for details.\n");
-}
-
-
-void usage(enum logcode F)
-{
- print_rsync_version(F);
-
- rprintf(F,"\n");
- rprintf(F,"rsync is a file transfer program capable of efficient remote update\n");
- rprintf(F,"via a fast differencing algorithm.\n");
-
- rprintf(F,"\n");
- rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... DEST\n");
- rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
- rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
- rprintf(F," or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/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]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
- rprintf(F,"The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect\n");
- rprintf(F,"to an rsync daemon, and require SRC or DEST to start with a module name.\n");
- rprintf(F,"\n");
- rprintf(F,"Options\n");
-#include "help-rsync.h"
- rprintf(F,"\n");
- rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
- rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation.\n");
- rprintf(F,"See https://rsync.samba.org/ for updates, bug reports, and answers\n");
-}
-
enum {OPT_SERVER = 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_CHMOD,
{"xattrs", 'X', POPT_ARG_NONE, 0, 'X', 0, 0 },
{"no-xattrs", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
{"no-X", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
- {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
- {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
- {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
+ {"times", 't', POPT_ARG_VAL, &preserve_mtimes, 1, 0, 0 },
+ {"no-times", 0, POPT_ARG_VAL, &preserve_mtimes, 0, 0, 0 },
+ {"no-t", 0, POPT_ARG_VAL, &preserve_mtimes, 0, 0, 0 },
{"atimes", 'U', POPT_ARG_NONE, 0, 'U', 0, 0 },
{"no-atimes", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
{"no-U", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
{"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 },
{"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 },
{"no-contimeout", 0, POPT_ARG_VAL, &connect_timeout, 0, 0, 0 },
+ {"fsync", 0, POPT_ARG_NONE, &do_fsync, 0, 0, 0 },
{"stop-after", 0, POPT_ARG_STRING, 0, OPT_STOP_AFTER, 0, 0 },
{"time-limit", 0, POPT_ARG_STRING, 0, OPT_STOP_AFTER, 0, 0 }, /* earlier stop-after name */
{"stop-at", 0, POPT_ARG_STRING, 0, OPT_STOP_AT, 0, 0 },
{0,0,0,0, 0, 0, 0}
};
-static void daemon_usage(enum logcode F)
-{
- print_rsync_version(F);
-
- rprintf(F,"\n");
- rprintf(F,"Usage: rsync --daemon [OPTION]...\n");
-#include "help-rsyncd.h"
- rprintf(F,"\n");
- rprintf(F,"If you were not trying to invoke rsync as a daemon, avoid using any of the\n");
- rprintf(F,"daemon-specific rsync options. See also the rsyncd.conf(5) man page.\n");
-}
-
static struct poptOption long_daemon_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
preserve_links = 1;
#endif
preserve_perms = 1;
- preserve_times = 1;
+ preserve_mtimes = 1;
preserve_gid = 1;
preserve_uid = 1;
preserve_devices = 1;
parse_filter_str(&filter_list, backup_dir_buf, rule_template(0), 0);
}
- if (preserve_times) {
- preserve_times = PRESERVE_FILE_TIMES;
- if (!omit_dir_times)
- preserve_times |= PRESERVE_DIR_TIMES;
-#ifdef CAN_SET_SYMLINK_TIMES
- if (!omit_link_times)
- preserve_times |= PRESERVE_LINK_TIMES;
-#endif
- }
-
- if (make_backups && !backup_dir) {
- omit_dir_times = 0; /* Implied, so avoid -O to sender. */
- preserve_times &= ~PRESERVE_DIR_TIMES;
- }
+ if (make_backups && !backup_dir)
+ omit_dir_times = -1; /* Implied, so avoid -O to sender. */
if (stdout_format) {
if (am_server && log_format_has(stdout_format, 'I'))
argstr[x++] = 'K';
if (prune_empty_dirs)
argstr[x++] = 'm';
- if (omit_dir_times)
+ if (omit_dir_times > 0)
argstr[x++] = 'O';
if (omit_link_times)
argstr[x++] = 'J';
argstr[x++] = 'g';
if (preserve_devices) /* ignore preserve_specials here */
argstr[x++] = 'D';
- if (preserve_times)
+ if (preserve_mtimes)
argstr[x++] = 't';
if (preserve_atimes) {
argstr[x++] = 'U';
set_allow_inc_recurse();
- /* We don't really know the actual protocol_version at this point,
- * but checking the pre-negotiated value allows the user to use a
- * --protocol=29 override to avoid the use of this -eFLAGS opt. */
- if (protocol_version >= 30) {
- /* Use "eFlags" alias so that cull_options doesn't think that these are no-arg option letters. */
-#define eFlags argstr
- /* We make use of the -e option to let the server know about
- * any pre-release protocol version && some behavior flags. */
- eFlags[x++] = 'e';
-#if SUBPROTOCOL_VERSION != 0
- if (protocol_version == PROTOCOL_VERSION) {
- x += snprintf(argstr+x, sizeof argstr - x,
- "%d.%d",
- PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
- } else
-#endif
- eFlags[x++] = '.';
- if (allow_inc_recurse)
- eFlags[x++] = 'i';
-#ifdef CAN_SET_SYMLINK_TIMES
- eFlags[x++] = 'L'; /* symlink time-setting support */
-#endif
-#ifdef ICONV_OPTION
- eFlags[x++] = 's'; /* symlink iconv translation support */
-#endif
- eFlags[x++] = 'f'; /* flist I/O-error safety support */
- eFlags[x++] = 'x'; /* xattr hardlink optimization not desired */
- eFlags[x++] = 'C'; /* support checksum seed order fix */
- eFlags[x++] = 'I'; /* support inplace_partial behavior */
- eFlags[x++] = 'v'; /* use varint for flist & compat flags; negotiate checksum */
- eFlags[x++] = 'u'; /* include name of uid 0 & gid 0 in the id map */
- /* NOTE: Avoid using 'V' -- it was the high bit of a write_byte() that became write_varint(). */
-#undef eFlags
- }
-
- if (x >= (int)sizeof argstr) { /* Not possible... */
- rprintf(FERROR, "argstr overflow in server_options().\n");
- exit_cleanup(RERR_MALLOC);
- }
-
- argstr[x] = '\0';
+ /* This '\0'-terminates argstr and makes sure it didn't overflow. */
+ x += maybe_add_e_option(argstr + x, (int)sizeof argstr - x);
if (x > 1)
args[ac++] = argstr;
args[ac++] = tmpdir;
}
+ if (do_fsync)
+ args[ac++] = "--fsync";
+
if (basis_dir[0]) {
/* the server only needs this option if it is not the sender,
* and it may be an older version that doesn't know this
if (append_mode > 1)
args[ac++] = "--append";
args[ac++] = "--append";
- } else if (inplace)
+ } else if (inplace) {
args[ac++] = "--inplace";
+ /* Work around a bug in older rsync versions (on the remote side) for --inplace --sparse */
+ if (sparse_files && !whole_file)
+ args[ac++] = "--no-W";
+ }
if (files_from && (!am_sender || filesfrom_host)) {
if (filesfrom_host) {
out_of_memory("server_options");
}
+int maybe_add_e_option(char *buf, int buf_len)
+{
+ int x = 0;
+
+ /* We don't really know the actual protocol_version at this point,
+ * but checking the pre-negotiated value allows the user to use a
+ * --protocol=29 override to avoid the use of this -eFLAGS opt. */
+ if (protocol_version >= 30 && buf_len > 0) {
+ /* We make use of the -e option to let the server know about
+ * any pre-release protocol version && some behavior flags. */
+ buf[x++] = 'e';
+
+#if SUBPROTOCOL_VERSION != 0
+ if (protocol_version == PROTOCOL_VERSION)
+ x += snprintf(buf + x, buf_len - x, "%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
+ else
+#endif
+ buf[x++] = '.';
+ if (allow_inc_recurse)
+ buf[x++] = 'i';
+#ifdef CAN_SET_SYMLINK_TIMES
+ buf[x++] = 'L'; /* symlink time-setting support */
+#endif
+#ifdef ICONV_OPTION
+ buf[x++] = 's'; /* symlink iconv translation support */
+#endif
+ buf[x++] = 'f'; /* flist I/O-error safety support */
+ buf[x++] = 'x'; /* xattr hardlink optimization not desired */
+ buf[x++] = 'C'; /* support checksum seed order fix */
+ buf[x++] = 'I'; /* support inplace_partial behavior */
+ buf[x++] = 'v'; /* use varint for flist & compat flags; negotiate checksum */
+ buf[x++] = 'u'; /* include name of uid 0 & gid 0 in the id map */
+
+ /* NOTE: Avoid using 'V' -- it was represented with the high bit of a write_byte() that became a write_varint(). */
+ }
+
+ if (x >= buf_len) { /* Not possible... */
+ rprintf(FERROR, "overflow in add_e_flags().\n");
+ exit_cleanup(RERR_MALLOC);
+ }
+
+ buf[x] = '\0';
+
+ return x;
+}
+
/* If str points to a valid hostspec, return allocated memory containing the
* [USER@]HOST part of the string, and set the path_start_ptr to the part of
* the string after the host part. Otherwise, return NULL. If port_ptr is