mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-26 07:45:33 -04:00
Compare commits
39 Commits
v3.2.4
...
v3.2.5pre2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce575b157 | ||
|
|
fabef23bea | ||
|
|
685bf58046 | ||
|
|
9e2921fce8 | ||
|
|
80d8f7c7cb | ||
|
|
38e1b075b4 | ||
|
|
d659610afc | ||
|
|
6cafc1f8bf | ||
|
|
788f11ea6a | ||
|
|
b7fdc9ef0e | ||
|
|
0d8cc26044 | ||
|
|
2955888468 | ||
|
|
0773cecc1f | ||
|
|
8e33586359 | ||
|
|
da5c72da4b | ||
|
|
2f7c583143 | ||
|
|
51fd4993ba | ||
|
|
e37bfdb445 | ||
|
|
3d7015afa2 | ||
|
|
7e5424b806 | ||
|
|
43f70b961e | ||
|
|
b7231c7d02 | ||
|
|
15c34f0a8c | ||
|
|
d1e42ffa16 | ||
|
|
36f489c211 | ||
|
|
defe2287aa | ||
|
|
112bef11ad | ||
|
|
b38780f3fd | ||
|
|
5f33238f06 | ||
|
|
3592ac3c02 | ||
|
|
c897b16f32 | ||
|
|
4f741addbd | ||
|
|
355b81d8bc | ||
|
|
6f35553372 | ||
|
|
71090b7e2c | ||
|
|
2ab2ee166e | ||
|
|
1e858e39e6 | ||
|
|
664639e349 | ||
|
|
517b9d91fc |
@@ -26,7 +26,7 @@ build user (after installing python3's pip package):
|
||||
|
||||
You can test if you've got it fixed by running (from the rsync checkout):
|
||||
|
||||
> ./md2man --test rsync-ssl.1.md
|
||||
> ./md-convert --test rsync-ssl.1.md
|
||||
|
||||
Alternately, you can avoid generating the manpages by fetching the very latest
|
||||
versions (that match the latest git source) from the [generated-files][6] dir.
|
||||
|
||||
44
NEWS.md
44
NEWS.md
@@ -1,3 +1,46 @@
|
||||
# NEWS for rsync 3.2.5 (UNRELEASED)
|
||||
|
||||
## Changes in this version:
|
||||
|
||||
### SECURITY FIXES:
|
||||
|
||||
- Added some file-list safety checking that helps to ensure that a rogue
|
||||
sending rsync can't add unrequested top-level names and/or include recursive
|
||||
names that should have been excluded by the sender. These extra safety
|
||||
checks only require the receiver rsync to be updated. When dealing with an
|
||||
untrusted sending host, it is safest to copy into a dedicated destination
|
||||
directory for the remote content (i.e. don't copy into a destination
|
||||
directory that contains files that aren't from the remote host unless you
|
||||
trust the remote host). Fixes CVE-2022-29154.
|
||||
|
||||
- A fix for CVE-2022-37434 in the bundled zlib (buffer overflow issue).
|
||||
|
||||
### BUG FIXES:
|
||||
|
||||
- Fixed the configure check for signed char that was causing a host that
|
||||
defaults to unsigned characters to generate bogus rolling checksums. This
|
||||
made rsync send mostly literal data for a copy instead of finding matching
|
||||
data in the receiver's basis file (for a file that contains high-bit
|
||||
characters).
|
||||
|
||||
- Lots of manpage improvements, including an attempt to better describe how
|
||||
include/exclude filters work.
|
||||
|
||||
### PACKAGING RELATED:
|
||||
|
||||
- The build date that goes into the manpages is now based on the developer's
|
||||
release date, not on the build's local-timezone interpretation of the date.
|
||||
|
||||
### DEVELOPER RELATED:
|
||||
|
||||
- Configure now defaults GETGROUPS_T to gid_t when cross compiling.
|
||||
|
||||
- Configure now looks for the bsd/string.h include file in order to fix the
|
||||
build on a host that has strlcpy() in the main libc but not defined in the
|
||||
main string.h file.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
# NEWS for rsync 3.2.4 (15 Apr 2022)
|
||||
|
||||
## Changes in this version:
|
||||
@@ -4482,6 +4525,7 @@
|
||||
|
||||
| RELEASE DATE | VER. | DATE OF COMMIT\* | PROTOCOL |
|
||||
|--------------|--------|------------------|-------------|
|
||||
| ?? Aug 2022 | 3.2.5 | | 31 |
|
||||
| 15 Apr 2022 | 3.2.4 | | 31 |
|
||||
| 06 Aug 2020 | 3.2.3 | | 31 |
|
||||
| 04 Jul 2020 | 3.2.2 | | 31 |
|
||||
|
||||
@@ -574,7 +574,7 @@ void sum_update(const char *p, int32 len)
|
||||
}
|
||||
|
||||
/* NOTE: all the callers of sum_end() pass in a pointer to a buffer that is
|
||||
* MAX_DIGEST_LEN in size, so even if the csum-len is shorter that that (i.e.
|
||||
* MAX_DIGEST_LEN in size, so even if the csum-len is shorter than that (i.e.
|
||||
* CSUM_MD4_ARCHAIC), we don't have to worry about limiting the data we write
|
||||
* into the "sum" buffer. */
|
||||
int sum_end(char *sum)
|
||||
|
||||
13
configure.ac
13
configure.ac
@@ -13,7 +13,8 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h mcheck.h \
|
||||
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h dl.h \
|
||||
popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netgroup.h \
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h)
|
||||
zlib.h xxhash.h openssl/md4.h openssl/md5.h zstd.h lz4.h sys/file.h \
|
||||
bsd/string.h)
|
||||
AC_CHECK_HEADERS([netinet/ip.h], [], [], [[#include <netinet/in.h>]])
|
||||
AC_HEADER_MAJOR_FIXED
|
||||
|
||||
@@ -22,7 +23,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
PACKAGE_VERSION=`sed 's/.*"\(.*\)".*/\1/' <$srcdir/version.h`
|
||||
PACKAGE_VERSION=`sed -n 's/.*RSYNC_VERSION.*"\(.*\)".*/\1/p' <$srcdir/version.h`
|
||||
|
||||
AC_MSG_NOTICE([Configuring rsync $PACKAGE_VERSION])
|
||||
|
||||
@@ -624,7 +625,11 @@ fi
|
||||
|
||||
AC_TYPE_UID_T
|
||||
AC_CHECK_TYPES([mode_t,off_t,size_t,pid_t,id_t])
|
||||
AC_TYPE_GETGROUPS
|
||||
if test "$cross_compiling" = no; then
|
||||
AC_TYPE_GETGROUPS
|
||||
else
|
||||
AC_DEFINE([GETGROUPS_T],[gid_t],[Define to the type of elements in the array set by `getgroups'. Usually this is either `int' or `gid_t'.])
|
||||
fi
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev,
|
||||
struct stat.st_mtimensec,
|
||||
struct stat.st_mtimespec.tv_nsec,
|
||||
@@ -1117,7 +1122,7 @@ else
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for unsigned char],rsync_cv_SIGNED_CHAR_OK,[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char *s = ""]])],[rsync_cv_SIGNED_CHAR_OK=yes],[rsync_cv_SIGNED_CHAR_OK=no])])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char *s = (signed char *)""]])],[rsync_cv_SIGNED_CHAR_OK=yes],[rsync_cv_SIGNED_CHAR_OK=no])])
|
||||
if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
|
||||
AC_DEFINE(SIGNED_CHAR_OK, 1, [Define to 1 if "signed char" is a valid type])
|
||||
fi
|
||||
|
||||
245
exclude.c
245
exclude.c
@@ -25,18 +25,26 @@
|
||||
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int eol_nulls;
|
||||
extern int io_error;
|
||||
extern int xfer_dirs;
|
||||
extern int recurse;
|
||||
extern int local_server;
|
||||
extern int prune_empty_dirs;
|
||||
extern int ignore_perishable;
|
||||
extern int old_style_args;
|
||||
extern int relative_paths;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int cvs_exclude;
|
||||
extern int sanitize_paths;
|
||||
extern int protocol_version;
|
||||
extern int read_batch;
|
||||
extern int list_only;
|
||||
extern int module_id;
|
||||
|
||||
extern char *filesfrom_host;
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern unsigned int curr_dir_len;
|
||||
extern unsigned int module_dirlen;
|
||||
@@ -44,8 +52,10 @@ extern unsigned int module_dirlen;
|
||||
filter_rule_list filter_list = { .debug_type = "" };
|
||||
filter_rule_list cvs_filter_list = { .debug_type = " [global CVS]" };
|
||||
filter_rule_list daemon_filter_list = { .debug_type = " [daemon]" };
|
||||
filter_rule_list implied_filter_list = { .debug_type = " [implied]" };
|
||||
|
||||
int saw_xattr_filter = 0;
|
||||
int trust_sender_filter = 0;
|
||||
|
||||
/* Need room enough for ":MODS " prefix plus some room to grow. */
|
||||
#define MAX_RULE_PREFIX (16)
|
||||
@@ -292,6 +302,231 @@ static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_
|
||||
}
|
||||
}
|
||||
|
||||
/* If the wildcards failed, the remote shell might give us a file matching the literal
|
||||
* wildcards. Since "*" & "?" already match themselves, this just needs to deal with
|
||||
* failed "[foo]" idioms.
|
||||
*/
|
||||
static void maybe_add_literal_brackets_rule(filter_rule const *based_on, int arg_len)
|
||||
{
|
||||
filter_rule *rule;
|
||||
const char *arg = based_on->pattern, *cp;
|
||||
char *p;
|
||||
int cnt = 0;
|
||||
|
||||
if (arg_len < 0)
|
||||
arg_len = strlen(arg);
|
||||
|
||||
cp = arg;
|
||||
while (*cp) {
|
||||
if (*cp == '\\' && cp[1]) {
|
||||
cp++;
|
||||
} else if (*cp == '[')
|
||||
cnt++;
|
||||
cp++;
|
||||
}
|
||||
if (!cnt)
|
||||
return;
|
||||
|
||||
rule = new0(filter_rule);
|
||||
rule->rflags = based_on->rflags;
|
||||
rule->u.slash_cnt = based_on->u.slash_cnt;
|
||||
p = rule->pattern = new_array(char, arg_len + cnt + 1);
|
||||
cp = arg;
|
||||
while (*cp) {
|
||||
if (*cp == '\\' && cp[1]) {
|
||||
*p++ = *cp++;
|
||||
} else if (*cp == '[')
|
||||
*p++ = '\\';
|
||||
*p++ = *cp++;
|
||||
}
|
||||
*p++ = '\0';
|
||||
|
||||
rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = rule;
|
||||
if (DEBUG_GTE(FILTER, 3)) {
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s%s)\n", who_am_i(), rule->pattern,
|
||||
rule->rflags & FILTRULE_DIRECTORY ? "/" : "");
|
||||
}
|
||||
}
|
||||
|
||||
static char *partial_string_buf = NULL;
|
||||
static int partial_string_len = 0;
|
||||
void implied_include_partial_string(const char *s_start, const char *s_end)
|
||||
{
|
||||
partial_string_len = s_end - s_start;
|
||||
if (partial_string_len <= 0 || partial_string_len >= MAXPATHLEN) { /* too-large should be impossible... */
|
||||
partial_string_len = 0;
|
||||
return;
|
||||
}
|
||||
if (!partial_string_buf)
|
||||
partial_string_buf = new_array(char, MAXPATHLEN);
|
||||
memcpy(partial_string_buf, s_start, partial_string_len);
|
||||
}
|
||||
|
||||
void free_implied_include_partial_string()
|
||||
{
|
||||
if (partial_string_buf) {
|
||||
free(partial_string_buf);
|
||||
partial_string_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Each arg the client sends to the remote sender turns into an implied include
|
||||
* that the receiver uses to validate the file list from the sender. */
|
||||
void add_implied_include(const char *arg)
|
||||
{
|
||||
filter_rule *rule;
|
||||
int arg_len, saw_wild = 0, saw_live_open_brkt = 0, backslash_cnt = 0;
|
||||
int slash_cnt = 1; /* We know we're adding a leading slash. */
|
||||
const char *cp;
|
||||
char *p;
|
||||
if (am_server || old_style_args || list_only || read_batch || filesfrom_host != NULL)
|
||||
return;
|
||||
if (partial_string_len) {
|
||||
arg_len = strlen(arg);
|
||||
if (partial_string_len + arg_len >= MAXPATHLEN)
|
||||
return; /* Should be impossible... */
|
||||
memcpy(partial_string_buf + partial_string_len, arg, arg_len + 1);
|
||||
partial_string_len = 0;
|
||||
arg = partial_string_buf;
|
||||
}
|
||||
if (relative_paths) {
|
||||
if ((cp = strstr(arg, "/./")) != NULL)
|
||||
arg = cp + 3;
|
||||
} else if ((cp = strrchr(arg, '/')) != NULL) {
|
||||
arg = cp + 1;
|
||||
if (*arg == '.' && arg[1] == '\0')
|
||||
arg++;
|
||||
}
|
||||
arg_len = strlen(arg);
|
||||
if (arg_len) {
|
||||
if (strpbrk(arg, "*[?")) {
|
||||
/* We need to add room to escape backslashes if wildcard chars are present. */
|
||||
cp = arg;
|
||||
while ((cp = strchr(cp, '\\')) != NULL) {
|
||||
arg_len++;
|
||||
cp++;
|
||||
}
|
||||
saw_wild = 1;
|
||||
}
|
||||
arg_len++; /* Leave room for the prefixed slash */
|
||||
rule = new0(filter_rule);
|
||||
if (!implied_filter_list.head)
|
||||
implied_filter_list.head = implied_filter_list.tail = rule;
|
||||
else {
|
||||
rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = rule;
|
||||
}
|
||||
rule->rflags = FILTRULE_INCLUDE + (saw_wild ? FILTRULE_WILD : 0);
|
||||
p = rule->pattern = new_array(char, arg_len + 1);
|
||||
*p++ = '/';
|
||||
cp = arg;
|
||||
while (*cp) {
|
||||
switch (*cp) {
|
||||
case '\\':
|
||||
if (cp[1] == ']')
|
||||
cp++; /* A \] in a filter might cause a problem w/o wildcards. */
|
||||
else if (!strchr("*[?", cp[1])) {
|
||||
backslash_cnt++;
|
||||
if (saw_wild)
|
||||
*p++ = '\\';
|
||||
}
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
case '/':
|
||||
if (p[-1] == '/') { /* This is safe because of the initial slash. */
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
if (relative_paths) {
|
||||
filter_rule const *ent;
|
||||
int found = 0;
|
||||
*p = '\0';
|
||||
for (ent = implied_filter_list.head; ent; ent = ent->next) {
|
||||
if (ent != rule && strcmp(ent->pattern, rule->pattern) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
filter_rule *R_rule = new0(filter_rule);
|
||||
R_rule->rflags = FILTRULE_INCLUDE | FILTRULE_DIRECTORY;
|
||||
/* Check if our sub-path has wildcards or escaped backslashes */
|
||||
if (saw_wild && strpbrk(rule->pattern, "*[?\\"))
|
||||
R_rule->rflags |= FILTRULE_WILD;
|
||||
R_rule->pattern = strdup(rule->pattern);
|
||||
R_rule->u.slash_cnt = slash_cnt;
|
||||
R_rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = R_rule;
|
||||
if (DEBUG_GTE(FILTER, 3)) {
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s/)\n",
|
||||
who_am_i(), R_rule->pattern);
|
||||
}
|
||||
if (saw_live_open_brkt)
|
||||
maybe_add_literal_brackets_rule(R_rule, -1);
|
||||
}
|
||||
}
|
||||
slash_cnt++;
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
case '[':
|
||||
saw_live_open_brkt = 1;
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
default:
|
||||
*p++ = *cp++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
rule->u.slash_cnt = slash_cnt;
|
||||
arg = rule->pattern;
|
||||
arg_len = p - arg; /* We recompute it due to backslash weirdness. */
|
||||
if (DEBUG_GTE(FILTER, 3))
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s)\n", who_am_i(), rule->pattern);
|
||||
if (saw_live_open_brkt)
|
||||
maybe_add_literal_brackets_rule(rule, arg_len);
|
||||
}
|
||||
|
||||
if (recurse || xfer_dirs) {
|
||||
/* Now create a rule with an added "/" & "**" or "*" at the end */
|
||||
rule = new0(filter_rule);
|
||||
rule->rflags = FILTRULE_INCLUDE | FILTRULE_WILD;
|
||||
if (recurse)
|
||||
rule->rflags |= FILTRULE_WILD2;
|
||||
/* We must leave enough room for / * * \0. */
|
||||
if (!saw_wild && backslash_cnt) {
|
||||
/* We are appending a wildcard, so now the backslashes need to be escaped. */
|
||||
p = rule->pattern = new_array(char, arg_len + backslash_cnt + 3 + 1);
|
||||
cp = arg;
|
||||
while (*cp) {
|
||||
if (*cp == '\\')
|
||||
*p++ = '\\';
|
||||
*p++ = *cp++;
|
||||
}
|
||||
} else {
|
||||
p = rule->pattern = new_array(char, arg_len + 3 + 1);
|
||||
if (arg_len) {
|
||||
memcpy(p, arg, arg_len);
|
||||
p += arg_len;
|
||||
}
|
||||
}
|
||||
if (p[-1] != '/')
|
||||
*p++ = '/';
|
||||
*p++ = '*';
|
||||
if (recurse)
|
||||
*p++ = '*';
|
||||
*p = '\0';
|
||||
rule->u.slash_cnt = slash_cnt + 1;
|
||||
rule->next = implied_filter_list.head;
|
||||
implied_filter_list.head = rule;
|
||||
if (DEBUG_GTE(FILTER, 3))
|
||||
rprintf(FINFO, "[%s] add_implied_include(%s)\n", who_am_i(), rule->pattern);
|
||||
if (saw_live_open_brkt)
|
||||
maybe_add_literal_brackets_rule(rule, p - rule->pattern);
|
||||
}
|
||||
}
|
||||
|
||||
/* This frees any non-inherited items, leaving just inherited items on the list. */
|
||||
static void pop_filter_list(filter_rule_list *listp)
|
||||
{
|
||||
@@ -706,11 +941,12 @@ static void report_filter_result(enum logcode code, char const *name,
|
||||
filter_rule const *ent,
|
||||
int name_flags, const char *type)
|
||||
{
|
||||
int log_level = am_sender || am_generator ? 1 : 3;
|
||||
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by add_rule(). So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (DEBUG_GTE(FILTER, 1)) {
|
||||
* case we add it back in the log output. */
|
||||
if (DEBUG_GTE(FILTER, log_level)) {
|
||||
static char *actions[2][2]
|
||||
= { {"show", "hid"}, {"risk", "protect"} };
|
||||
const char *w = who_am_i();
|
||||
@@ -718,7 +954,7 @@ static void report_filter_result(enum logcode code, char const *name,
|
||||
: name_flags & NAME_IS_DIR ? "directory"
|
||||
: "file";
|
||||
rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
|
||||
w, actions[*w!='s'][!(ent->rflags & FILTRULE_INCLUDE)],
|
||||
w, actions[*w=='g'][!(ent->rflags & FILTRULE_INCLUDE)],
|
||||
t, name, ent->pattern,
|
||||
ent->rflags & FILTRULE_DIRECTORY ? "/" : "", type);
|
||||
}
|
||||
@@ -890,6 +1126,7 @@ static filter_rule *parse_rule_tok(const char **rulestr_ptr,
|
||||
}
|
||||
switch (ch) {
|
||||
case ':':
|
||||
trust_sender_filter = 1;
|
||||
rule->rflags |= FILTRULE_PERDIR_MERGE
|
||||
| FILTRULE_FINISH_SETUP;
|
||||
/* FALL THROUGH */
|
||||
|
||||
17
flist.c
17
flist.c
@@ -73,6 +73,7 @@ extern int need_unsorted_flist;
|
||||
extern int sender_symlink_iconv;
|
||||
extern int output_needs_newline;
|
||||
extern int sender_keeps_checksum;
|
||||
extern int trust_sender_filter;
|
||||
extern int unsort_ndx;
|
||||
extern uid_t our_uid;
|
||||
extern struct stats stats;
|
||||
@@ -83,8 +84,7 @@ extern char curr_dir[MAXPATHLEN];
|
||||
|
||||
extern struct chmod_mode_struct *chmod_modes;
|
||||
|
||||
extern filter_rule_list filter_list;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
extern filter_rule_list filter_list, implied_filter_list, daemon_filter_list;
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
extern int filesfrom_convert;
|
||||
@@ -986,6 +986,19 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (*thisname != '.' || thisname[1] != '\0') {
|
||||
int filt_flags = S_ISDIR(mode) ? NAME_IS_DIR : NAME_IS_FILE;
|
||||
if (!trust_sender_filter /* a per-dir filter rule means we must trust the sender's filtering */
|
||||
&& filter_list.head && check_filter(&filter_list, FINFO, thisname, filt_flags) < 0) {
|
||||
rprintf(FERROR, "ERROR: rejecting excluded file-list name: %s\n", thisname);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (implied_filter_list.head && check_filter(&implied_filter_list, FINFO, thisname, filt_flags) <= 0) {
|
||||
rprintf(FERROR, "ERROR: rejecting unrequested file-list name: %s\n", thisname);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
|
||||
if (inc_recurse && S_ISDIR(mode)) {
|
||||
if (one_file_system) {
|
||||
/* Room to save the dir's device for -x */
|
||||
|
||||
7
io.c
7
io.c
@@ -376,6 +376,7 @@ static void forward_filesfrom_data(void)
|
||||
free_xbuf(&ff_xb);
|
||||
if (ff_reenable_multiplex >= 0)
|
||||
io_start_multiplex_out(ff_reenable_multiplex);
|
||||
free_implied_include_partial_string();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -419,6 +420,7 @@ static void forward_filesfrom_data(void)
|
||||
while (s != eob) {
|
||||
if (*s++ == '\0') {
|
||||
ff_xb.len = s - sob - 1;
|
||||
add_implied_include(sob);
|
||||
if (iconvbufs(ic_send, &ff_xb, &iobuf.out, flags) < 0)
|
||||
exit_cleanup(RERR_PROTOCOL); /* impossible? */
|
||||
write_buf(iobuf.out_fd, s-1, 1); /* Send the '\0'. */
|
||||
@@ -434,6 +436,7 @@ static void forward_filesfrom_data(void)
|
||||
ff_lastchar = '\0';
|
||||
else {
|
||||
/* Handle a partial string specially, saving any incomplete chars. */
|
||||
implied_include_partial_string(sob, s);
|
||||
flags &= ~ICB_INCLUDE_INCOMPLETE;
|
||||
if (iconvbufs(ic_send, &ff_xb, &iobuf.out, flags) < 0) {
|
||||
if (errno == E2BIG)
|
||||
@@ -450,13 +453,17 @@ static void forward_filesfrom_data(void)
|
||||
char *f = ff_xb.buf + ff_xb.pos;
|
||||
char *t = ff_xb.buf;
|
||||
char *eob = f + len;
|
||||
char *cur = t;
|
||||
/* Eliminate any multi-'\0' runs. */
|
||||
while (f != eob) {
|
||||
if (!(*t++ = *f++)) {
|
||||
add_implied_include(cur);
|
||||
cur = t;
|
||||
while (f != eob && *f == '\0')
|
||||
f++;
|
||||
}
|
||||
}
|
||||
implied_include_partial_string(cur, t);
|
||||
ff_lastchar = f[-1];
|
||||
if ((len = t - ff_xb.buf) != 0) {
|
||||
/* This will not circle back to perform_io() because we only get
|
||||
|
||||
8
main.c
8
main.c
@@ -89,6 +89,7 @@ extern int backup_dir_len;
|
||||
extern int basis_dir_cnt;
|
||||
extern int default_af_hint;
|
||||
extern int stdout_format_has_i;
|
||||
extern int trust_sender_filter;
|
||||
extern struct stats stats;
|
||||
extern char *stdout_format;
|
||||
extern char *logfile_format;
|
||||
@@ -104,7 +105,7 @@ extern char curr_dir[MAXPATHLEN];
|
||||
extern char backup_dir_buf[MAXPATHLEN];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
extern struct file_list *first_flist;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
extern filter_rule_list daemon_filter_list, implied_filter_list;
|
||||
|
||||
uid_t our_uid;
|
||||
gid_t our_gid;
|
||||
@@ -635,6 +636,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
trust_sender_filter = 1;
|
||||
} else if (local_server) {
|
||||
/* If the user didn't request --[no-]whole-file, force
|
||||
* it on, but only if we're not batch processing. */
|
||||
@@ -1076,6 +1078,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
|
||||
}
|
||||
|
||||
am_generator = 1;
|
||||
implied_filter_list.head = implied_filter_list.tail = NULL;
|
||||
flist_receiving_enabled = True;
|
||||
|
||||
io_end_multiplex_in(MPLX_SWITCHING);
|
||||
@@ -1500,6 +1503,8 @@ static int start_client(int argc, char *argv[])
|
||||
char *dummy_host;
|
||||
int dummy_port = rsync_port;
|
||||
int i;
|
||||
if (filesfrom_fd < 0)
|
||||
add_implied_include(remote_argv[0]);
|
||||
/* For remote source, any extra source args must have either
|
||||
* the same hostname or an empty hostname. */
|
||||
for (i = 1; i < remote_argc; i++) {
|
||||
@@ -1523,6 +1528,7 @@ static int start_client(int argc, char *argv[])
|
||||
if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
|
||||
arg = ".";
|
||||
remote_argv[i] = arg;
|
||||
add_implied_include(arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
md-convert
16
md-convert
@@ -115,7 +115,8 @@ NBR_SPACE = ('\xa0', r"\ ")
|
||||
|
||||
FILENAME_RE = re.compile(r'^(?P<fn>(?P<srcdir>.+/)?(?P<name>(?P<prog>[^/]+?)(\.(?P<sect>\d+))?)\.md)$')
|
||||
ASSIGNMENT_RE = re.compile(r'^(\w+)=(.+)')
|
||||
QUOTED_RE = re.compile(r'"(.+?)"')
|
||||
VER_RE = re.compile(r'^#define\s+RSYNC_VERSION\s+"(\d.+?)"', re.M)
|
||||
TZ_RE = re.compile(r'^#define\s+MAINTAINER_TZ_OFFSET\s+(-?\d+(\.\d+)?)', re.M)
|
||||
VAR_REF_RE = re.compile(r'\$\{(\w+)\}')
|
||||
VERSION_RE = re.compile(r' (\d[.\d]+)[, ]')
|
||||
BIN_CHARS_RE = re.compile(r'[\1-\7]+')
|
||||
@@ -213,6 +214,7 @@ def find_man_substitutions():
|
||||
env_subs['VERSION'] = '1.0.0'
|
||||
env_subs['bindir'] = '/usr/bin'
|
||||
env_subs['libdir'] = '/usr/lib/rsync'
|
||||
tz_offset = 0
|
||||
else:
|
||||
for fn in (srcdir + 'version.h', 'Makefile'):
|
||||
try:
|
||||
@@ -224,8 +226,10 @@ def find_man_substitutions():
|
||||
|
||||
with open(srcdir + 'version.h', 'r', encoding='utf-8') as fh:
|
||||
txt = fh.read()
|
||||
m = QUOTED_RE.search(txt)
|
||||
m = VER_RE.search(txt)
|
||||
env_subs['VERSION'] = m.group(1)
|
||||
m = TZ_RE.search(txt) # the tzdata lib may not be installed, so we use a simple hour offset
|
||||
tz_offset = float(m.group(1)) * 60 * 60
|
||||
|
||||
with open('Makefile', 'r', encoding='utf-8') as fh:
|
||||
for line in fh:
|
||||
@@ -241,7 +245,7 @@ def find_man_substitutions():
|
||||
if var == 'srcdir':
|
||||
break
|
||||
|
||||
env_subs['date'] = time.strftime('%d %b %Y', time.localtime(mtime))
|
||||
env_subs['date'] = time.strftime('%d %b %Y', time.gmtime(mtime + tz_offset)).lstrip('0')
|
||||
|
||||
|
||||
def html_via_commonmark(txt):
|
||||
@@ -605,12 +609,12 @@ def die(*msg):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Output html and (optionally) nroff for markdown pages.", add_help=False)
|
||||
parser = argparse.ArgumentParser(description="Convert markdown into html and (optionally) nroff. Each input filename must have a .md suffix, which is changed to .html for the output filename. If the input filename ends with .num.md (e.g. foo.1.md) then a nroff file is also output with the input filename's .md suffix removed (e.g. foo.1).", add_help=False)
|
||||
parser.add_argument('--test', action='store_true', help="Just test the parsing without outputting any files.")
|
||||
parser.add_argument('--dest', metavar='DIR', help="Put files into DIR instead of the current directory.")
|
||||
parser.add_argument('--dest', metavar='DIR', help="Create files in DIR instead of the current directory.")
|
||||
parser.add_argument('--debug', '-D', action='count', default=0, help='Output copious info on the html parsing. Repeat for even more.')
|
||||
parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
|
||||
parser.add_argument("mdfiles", nargs='+', help="The source .md files to convert.")
|
||||
parser.add_argument("mdfiles", metavar='FILE.md', nargs='+', help="One or more .md files to convert.")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
|
||||
@@ -293,7 +293,7 @@ static struct output_struct debug_words[COUNT_DEBUG+1] = {
|
||||
DEBUG_WORD(DELTASUM, W_SND|W_REC, "Debug delta-transfer checksumming (levels 1-4)"),
|
||||
DEBUG_WORD(DUP, W_REC, "Debug weeding of duplicate names"),
|
||||
DEBUG_WORD(EXIT, W_CLI|W_SRV, "Debug exit events (levels 1-3)"),
|
||||
DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-2)"),
|
||||
DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-3)"),
|
||||
DEBUG_WORD(FLIST, W_SND|W_REC, "Debug file-list operations (levels 1-4)"),
|
||||
DEBUG_WORD(FUZZY, W_REC, "Debug fuzzy scoring (levels 1-2)"),
|
||||
DEBUG_WORD(GENR, W_REC, "Debug generator functions"),
|
||||
@@ -2521,7 +2521,10 @@ char *safe_arg(const char *opt, const char *arg)
|
||||
const char *f = arg;
|
||||
char *t = ret + len1;
|
||||
while (*f) {
|
||||
if (strchr(escapes, *f))
|
||||
if (*f == '\\') {
|
||||
if (!is_filename_arg || !strchr(WILD_CHARS, f[1]))
|
||||
*t++ = '\\';
|
||||
} else if (strchr(escapes, *f))
|
||||
*t++ = '\\';
|
||||
*t++ = *f++;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.2.4
|
||||
%define fullversion %{version}
|
||||
Release: 1
|
||||
%define srcdir src
|
||||
Version: 3.2.5
|
||||
%define fullversion %{version}pre2
|
||||
Release: 0.1.pre2
|
||||
%define srcdir src-previews
|
||||
Group: Applications/Internet
|
||||
License: GPL
|
||||
Source0: https://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
|
||||
@@ -79,8 +79,8 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%dir /etc/rsync-ssl/certs
|
||||
|
||||
%changelog
|
||||
* Fri Apr 15 2022 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.4.
|
||||
* Mon Aug 08 2022 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.5pre2.
|
||||
|
||||
* Fri Mar 21 2008 Wayne Davison <wayne@opencoder.net>
|
||||
Added installation of /etc/xinetd.d/rsync file and some commented-out
|
||||
|
||||
@@ -193,7 +193,9 @@ About to:
|
||||
with open(fn, 'r', encoding='utf-8') as fh:
|
||||
old_txt = txt = fh.read()
|
||||
if fn == 'version.h':
|
||||
txt = f'#define RSYNC_VERSION "{version}"\n'
|
||||
x_re = re.compile(r'^(#define RSYNC_VERSION).*', re.M)
|
||||
msg = f"Unable to update RSYNC_VERSION in {fn}"
|
||||
txt = replace_or_die(x_re, r'\1 "%s"' % version, txt, msg)
|
||||
elif '.spec' in fn:
|
||||
for var, val in specvars.items():
|
||||
x_re = re.compile(r'^%s .*' % re.escape(var), re.M)
|
||||
|
||||
11
receiver.c
11
receiver.c
@@ -593,10 +593,13 @@ int recv_files(int f_in, int f_out, char *local_name)
|
||||
if (DEBUG_GTE(RECV, 1))
|
||||
rprintf(FINFO, "recv_files(%s)\n", fname);
|
||||
|
||||
if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0')
|
||||
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) {
|
||||
rprintf(FERROR, "attempt to hack rsync failed.\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
if (daemon_filter_list.head && (*fname != '.' || fname[1] != '\0')) {
|
||||
int filt_flags = S_ISDIR(file->mode) ? NAME_IS_DIR : NAME_IS_FILE;
|
||||
if (check_filter(&daemon_filter_list, FLOG, fname, filt_flags) < 0) {
|
||||
rprintf(FERROR, "ERROR: rejecting file transfer request for daemon excluded file: %s\n",
|
||||
fname);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
|
||||
@@ -94,6 +94,11 @@ The ssl helper scripts are affected by the following environment variables:
|
||||
|
||||
> rsync-ssl -aiv rsync://example.com:9874/mod/ dest
|
||||
|
||||
## THE SERVER SIDE
|
||||
|
||||
For help setting up an SSL/TLS supporting rsync, see the [instructions in
|
||||
rsyncd.conf](rsyncd.conf.5#SSL_TLS_Daemon_Setup).
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
[**rsync**(1)](rsync.1), [**rsyncd.conf**(5)](rsyncd.conf.5)
|
||||
|
||||
641
rsync.1.md
641
rsync.1.md
@@ -154,6 +154,45 @@ rsync daemon by leaving off the module name:
|
||||
|
||||
See the following section for more details.
|
||||
|
||||
## SORTED TRANSFER ORDER
|
||||
|
||||
Rsync always sorts the specified filenames into its internal transfer list.
|
||||
This handles the merging together of the contents of identically named
|
||||
directories, makes it easy to remove duplicate filenames. It can, however,
|
||||
confuse someone when the files are transferred in a different order than what
|
||||
was given on the command-line.
|
||||
|
||||
If you need a particular file to be transferred prior to another, either
|
||||
separate the files into different rsync calls, or consider using
|
||||
[`--delay-updates`](#opt) (which doesn't affect the sorted transfer order, but
|
||||
does make the final file-updating phase happen much more rapidly).
|
||||
|
||||
## MULTI-HOST SECURITY
|
||||
|
||||
Rsync takes steps to ensure that the file requests that are shared in a
|
||||
transfer are protected against various security issues. Most of the potential
|
||||
problems arise on the receiving side where rsync takes steps to ensure that the
|
||||
list of files being transferred remains within the bounds of what was
|
||||
requested.
|
||||
|
||||
Toward this end, rsync 3.1.2 and later have aborted when a file list contains
|
||||
an absolute or relative path that tries to escape out of the top of the
|
||||
transfer. Also, beginning with version 3.2.5, rsync does two more safety
|
||||
checks of the file list to (1) ensure that no extra source arguments were added
|
||||
into the transfer other than those that the client requested and (2) ensure
|
||||
that the file list obeys the exclude rules that were sent to the sender.
|
||||
|
||||
For those that don't yet have a 3.2.5 client rsync (or those that want to be
|
||||
extra careful), it is safest to do a copy into a dedicated destination
|
||||
directory for the remote files when you don't trust the remote host. For
|
||||
example, instead of doing an rsync copy into your home directory:
|
||||
|
||||
> rsync -aiv host1:dir1 ~
|
||||
|
||||
Dedicate a "host1-files" dir to the remote content:
|
||||
|
||||
> rsync -aiv host1:dir1 ~/host1-files
|
||||
|
||||
## ADVANCED USAGE
|
||||
|
||||
The syntax for requesting multiple files from a remote host is done by
|
||||
@@ -164,20 +203,24 @@ the hostname omitted. For instance, all these work:
|
||||
> rsync -aiv host::modname/file{1,2} host::modname/extra /dest/
|
||||
> rsync -aiv host::modname/first ::modname/extra{1,2} /dest/
|
||||
|
||||
In a modern rsync, you only need to quote or backslash-escape things like
|
||||
spaces from the local shell but not also from the remote shell:
|
||||
Really old versions of rsync (2.6.9 and before) only allowed specifying one
|
||||
remote-source arg, so some people have instead relied on the remote-shell
|
||||
performing space splitting to break up an arg into multiple paths. Such
|
||||
unintuitive behavior is no longer supported by default (though you can request
|
||||
it, as described below).
|
||||
|
||||
Starting in 3.2.4, filenames are passed to a remote shell in such a way as to
|
||||
preserve the characters you give it. Thus, if you ask for a file with spaces
|
||||
in the name, that's what the remote rsync looks for:
|
||||
|
||||
> rsync -aiv host:'a simple file.pdf' /dest/
|
||||
|
||||
Really old versions of rsync only allowed specifying one remote-source arg, so
|
||||
it required the remote side to split the args at a space. You can still get
|
||||
this old-style arg splitting by using the [`--old-args`](#opt) option:
|
||||
|
||||
> rsync -ai --old-args host:'dir1/file1 dir2/file2' /dest
|
||||
> rsync -ai --old-args host::'modname/dir1/file1 modname/dir2/file2' /dest
|
||||
|
||||
See that option's section for an [environment variable](#RSYNC_OLD_ARGS) that
|
||||
can be exported to help old scripts.
|
||||
If you use scripts that have been written to manually apply extra quoting to
|
||||
the remote rsync args (or to require remote arg splitting), you can ask rsync
|
||||
to let your script handle the extra escaping. This is done by either adding
|
||||
the [`--old-args`](#opt) option to the rsync runs in the script (which requires
|
||||
a new rsync) or exporting [RSYNC_OLD_ARGS](#)=1 and [RSYNC_PROTECT_ARGS](#)=0
|
||||
(which works with old or new rsync versions).
|
||||
|
||||
## CONNECTING TO AN RSYNC DAEMON
|
||||
|
||||
@@ -270,6 +313,10 @@ example that uses the short version of the [`--rsh`](#opt) option:
|
||||
The "ssh-user" will be used at the ssh level; the "rsync-user" will be used to
|
||||
log-in to the "module".
|
||||
|
||||
In this setup, the daemon is started by the ssh command that is accessing the
|
||||
system (which can be forced via the `~/.ssh/authorized_keys` file, if desired).
|
||||
However, when accessing a daemon directly, it needs to be started beforehand.
|
||||
|
||||
## STARTING AN RSYNC DAEMON TO ACCEPT CONNECTIONS
|
||||
|
||||
In order to connect to an rsync daemon, the remote system needs to have a
|
||||
@@ -283,48 +330,18 @@ the daemon (including stand-alone and inetd configurations).
|
||||
If you're using one of the remote-shell transports for the transfer, there is
|
||||
no need to manually start an rsync daemon.
|
||||
|
||||
## SORTED TRANSFER ORDER
|
||||
|
||||
Rsync always sorts the specified filenames into its internal transfer list.
|
||||
This handles the merging together of the contents of identically named
|
||||
directories, makes it easy to remove duplicate filenames, and may confuse
|
||||
someone when the files are transferred in a different order than what was given
|
||||
on the command-line.
|
||||
|
||||
If you need a particular file to be transferred prior to another, either
|
||||
separate the files into different rsync calls, or consider using
|
||||
[`--delay-updates`](#opt) (which doesn't affect the sorted transfer order, but
|
||||
does make the final file-updating phase happen much more rapidly).
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
Here are some examples of how I use rsync.
|
||||
Here are some examples of how rsync can be used.
|
||||
|
||||
To backup my wife's home directory, which consists of large MS Word files and
|
||||
mail folders, I use a cron job that runs
|
||||
To backup a home directory, which consists of large MS Word files and mail
|
||||
folders, a per-user cron job can be used that runs this each day:
|
||||
|
||||
> rsync -Cavz . arvidsjaur:backup
|
||||
> rsync -aiz . bkhost:backup/joe/
|
||||
|
||||
each night over a PPP connection to a duplicate directory on my machine
|
||||
"arvidsjaur".
|
||||
To move some files from a remote host to the local host, you could run:
|
||||
|
||||
To synchronize my samba source trees I use the following Makefile targets:
|
||||
|
||||
> get:
|
||||
> rsync -avuzb --exclude '*~' samba:samba/ .
|
||||
> put:
|
||||
> rsync -Cavuzb . samba:samba/
|
||||
> sync: get put
|
||||
|
||||
This allows me to sync with a CVS directory at the other end of the connection.
|
||||
I then do CVS operations on the remote machine, which saves a lot of time as
|
||||
the remote CVS protocol isn't very efficient.
|
||||
|
||||
I mirror a directory between my "old" and "new" ftp sites with the command:
|
||||
|
||||
> rsync -az -e ssh --delete ~ftp/pub/samba nimbus:"~ftp/pub/tridge"
|
||||
|
||||
This is launched from cron every few hours.
|
||||
> rsync -aiv --remove-source-files rhost:/tmp/{file1,file2}.c ~/src/
|
||||
|
||||
## OPTION SUMMARY
|
||||
|
||||
@@ -508,14 +525,21 @@ accepted:
|
||||
Rsync accepts both long (double-dash + word) and short (single-dash + letter)
|
||||
options. The full list of the available options are described below. If an
|
||||
option can be specified in more than one way, the choices are comma-separated.
|
||||
Some options only have a long variant, not a short. If the option takes a
|
||||
parameter, the parameter is only listed after the long variant, even though it
|
||||
must also be specified for the short. When specifying a parameter, you can
|
||||
either use the form `--option=param` or replace the '=' with whitespace. The
|
||||
parameter may need to be quoted in some manner for it to survive the shell's
|
||||
command-line parsing. Keep in mind that a leading tilde (`~`) in a filename is
|
||||
substituted by your shell, so `--option=~/foo` will not change the tilde into
|
||||
your home directory (remove the '=' for that).
|
||||
Some options only have a long variant, not a short.
|
||||
|
||||
If the option takes a parameter, the parameter is only listed after the long
|
||||
variant, even though it must also be specified for the short. When specifying
|
||||
a parameter, you can either use the form `--option=param`, `--option param`,
|
||||
`-o=param`, `-o param`, or `-oparam` (the latter choices assume that your
|
||||
option has a short variant).
|
||||
|
||||
The parameter may need to be quoted in some manner for it to survive the
|
||||
shell's command-line parsing. Also keep in mind that a leading tilde (`~`) in
|
||||
a pathname is substituted by your shell, so make sure that you separate the
|
||||
option name from the pathname using a space if you want the shell to expand it.
|
||||
|
||||
[comment]: # (Some markup below uses a literal non-breakable space when a backtick string)
|
||||
[comment]: # (needs to contain a space since markdown strips spaces from the start/end)
|
||||
|
||||
[comment]: # (An OL starting at 0 is converted into a DL by the parser.)
|
||||
|
||||
@@ -793,7 +817,7 @@ your home directory (remove the '=' for that).
|
||||
|
||||
In order to make [`--delete`](#opt) compatible with incremental recursion,
|
||||
rsync 3.0.0 made [`--delete-during`](#opt) the default delete mode (which
|
||||
was first first added in 2.6.4).
|
||||
was first added in 2.6.4).
|
||||
|
||||
One side-effect of incremental recursion is that any missing
|
||||
sub-directories inside a recursively-scanned directory are (by default)
|
||||
@@ -948,9 +972,8 @@ your home directory (remove the '=' for that).
|
||||
directory where the destination has a file, the transfer would occur
|
||||
regardless of the timestamps.
|
||||
|
||||
This option is a transfer rule, not an exclude, so it doesn't affect the
|
||||
data that goes into the file-lists, and thus it doesn't affect deletions.
|
||||
It just limits the files that the receiver requests to be transferred.
|
||||
This option is a [TRANSFER RULE](#TRANSFER_RULES), so don't expect any
|
||||
exclude side effects.
|
||||
|
||||
A caution for those that choose to combine [`--inplace`](#opt) with
|
||||
`--update`: an interrupted transfer will leave behind a partial file on the
|
||||
@@ -1169,7 +1192,7 @@ your home directory (remove the '=' for that).
|
||||
transfer, the client is the sender, so specifying the option directly
|
||||
unmunges symlinks while specifying it as a remote option munges symlinks.
|
||||
|
||||
This option has no affect when sent to a daemon via [`--remote-option`](#opt)
|
||||
This option has no effect when sent to a daemon via [`--remote-option`](#opt)
|
||||
because the daemon configures whether it wants munged symlinks via its
|
||||
"`munge symlinks`" parameter.
|
||||
|
||||
@@ -1478,7 +1501,7 @@ your home directory (remove the '=' for that).
|
||||
|
||||
This tells rsync to treat a device on the sending side as a regular file,
|
||||
allowing it to be copied to a normal destination file (or another device
|
||||
if `--write-devices` was also specifed).
|
||||
if `--write-devices` was also specified).
|
||||
|
||||
This option is refused by default by an rsync daemon.
|
||||
|
||||
@@ -1733,9 +1756,8 @@ your home directory (remove the '=' for that).
|
||||
[`--ignore-existing`](#opt) option, no files will be updated (which can be
|
||||
useful if all you want to do is delete extraneous files).
|
||||
|
||||
This option is a transfer rule, not an exclude, so it doesn't affect the
|
||||
data that goes into the file-lists, and thus it doesn't affect deletions.
|
||||
It just limits the files that the receiver requests to be transferred.
|
||||
This option is a [TRANSFER RULE](#TRANSFER_RULES), so don't expect any
|
||||
exclude side effects.
|
||||
|
||||
0. `--ignore-existing`
|
||||
|
||||
@@ -1743,9 +1765,8 @@ your home directory (remove the '=' for that).
|
||||
destination (this does _not_ ignore existing directories, or nothing would
|
||||
get done). See also [`--ignore-non-existing`](#opt).
|
||||
|
||||
This option is a transfer rule, not an exclude, so it doesn't affect the
|
||||
data that goes into the file-lists, and thus it doesn't affect deletions.
|
||||
It just limits the files that the receiver requests to be transferred.
|
||||
This option is a [TRANSFER RULE](#TRANSFER_RULES), so don't expect any
|
||||
exclude side effects.
|
||||
|
||||
This option can be useful for those doing backups using the
|
||||
[`--link-dest`](#opt) option when they need to continue a backup run that
|
||||
@@ -1874,13 +1895,25 @@ your home directory (remove the '=' for that).
|
||||
|
||||
0. `--delete-excluded`
|
||||
|
||||
In addition to deleting the files on the receiving side that are not on the
|
||||
sending side, this tells rsync to also delete any files on the receiving
|
||||
side that are excluded (see [`--exclude`](#opt)). See the [FILTER
|
||||
RULES](#) section for a way to make individual exclusions behave this way
|
||||
on the receiver, and for a way to protect files from `--delete-excluded`.
|
||||
See [`--delete`](#opt) (which is implied) for more details on
|
||||
file-deletion.
|
||||
This option turns any unqualified exclude/include rules into server-side
|
||||
rules that do not affect the receiver's deletions.
|
||||
|
||||
By default, an exclude or include has both a server-side effect (to "hide"
|
||||
and "show" files when building the server's file list) and a receiver-side
|
||||
effect (to "protect" and "risk" files when deletions are occuring). Any
|
||||
rule that has no modifier to specify what sides it is executed on will be
|
||||
instead treated as if it were a server-side rule only, avoiding any
|
||||
"protect" effects of the rules.
|
||||
|
||||
A rule can still apply to both sides even with this option specified if the
|
||||
rule is given both the sender & receiver modifer letters (e.g., `-f'-sr
|
||||
foo'`). Receiver-side protect/risk rules can also be explicitly specified
|
||||
to limit the deletions. This is saves you from having to edit a bunch of
|
||||
`-f'- foo'` rules into `-f'-s foo'` or `-f'H foo'` rules (not to mention
|
||||
the corresponding includes).
|
||||
|
||||
See the [FILTER RULES](#) section for more information. See
|
||||
[`--delete`](#opt) (which is implied) for more details on deletion.
|
||||
|
||||
0. `--ignore-missing-args`
|
||||
|
||||
@@ -1941,9 +1974,8 @@ your home directory (remove the '=' for that).
|
||||
the numeric units or left unqualified to specify bytes. Feel free to use a
|
||||
fractional value along with the units, such as `--max-size=1.5m`.
|
||||
|
||||
This option is a transfer rule, not an exclude, so it doesn't affect the
|
||||
data that goes into the file-lists, and thus it doesn't affect deletions.
|
||||
It just limits the files that the receiver requests to be transferred.
|
||||
This option is a [TRANSFER RULE](#TRANSFER_RULES), so don't expect any
|
||||
exclude side effects.
|
||||
|
||||
The first letter of a units string can be `B` (bytes), `K` (kilo), `M`
|
||||
(mega), `G` (giga), `T` (tera), or `P` (peta). If the string is a single
|
||||
@@ -2200,8 +2232,8 @@ your home directory (remove the '=' for that).
|
||||
0. `--exclude=PATTERN`
|
||||
|
||||
This option is a simplified form of the [`--filter`](#opt) option that
|
||||
defaults to an exclude rule and does not allow the full rule-parsing syntax
|
||||
of normal filter rules.
|
||||
specifies an exclude rule and does not allow the full rule-parsing syntax
|
||||
of normal filter rules. This is equivalent to specifying `-f'- PATTERN'`.
|
||||
|
||||
See the [FILTER RULES](#) section for detailed information on this option.
|
||||
|
||||
@@ -2212,13 +2244,20 @@ your home directory (remove the '=' for that).
|
||||
file are ignored, as are whole-line comments that start with '`;`' or '`#`'
|
||||
(filename rules that contain those characters are unaffected).
|
||||
|
||||
If a line begins with "`- `" (dash, space) or "`+ `" (plus, space), then
|
||||
the type of rule is being explicitly specified as an exclude or an include
|
||||
(respectively). Any rules without such a prefix are taken to be an exclude.
|
||||
|
||||
If a line consists of just "`!`", then the current filter rules are cleared
|
||||
before adding any further rules.
|
||||
|
||||
If _FILE_ is '`-`', the list will be read from standard input.
|
||||
|
||||
0. `--include=PATTERN`
|
||||
|
||||
This option is a simplified form of the [`--filter`](#opt) option that
|
||||
defaults to an include rule and does not allow the full rule-parsing syntax
|
||||
of normal filter rules.
|
||||
specifies an include rule and does not allow the full rule-parsing syntax
|
||||
of normal filter rules. This is equivalent to specifying `-f'+ PATTERN'`.
|
||||
|
||||
See the [FILTER RULES](#) section for detailed information on this option.
|
||||
|
||||
@@ -2229,6 +2268,13 @@ your home directory (remove the '=' for that).
|
||||
file are ignored, as are whole-line comments that start with '`;`' or '`#`'
|
||||
(filename rules that contain those characters are unaffected).
|
||||
|
||||
If a line begins with "`- `" (dash, space) or "`+ `" (plus, space), then
|
||||
the type of rule is being explicitly specified as an exclude or an include
|
||||
(respectively). Any rules without such a prefix are taken to be an include.
|
||||
|
||||
If a line consists of just "`!`", then the current filter rules are cleared
|
||||
before adding any further rules.
|
||||
|
||||
If _FILE_ is '`-`', the list will be read from standard input.
|
||||
|
||||
0. `--files-from=FILE`
|
||||
@@ -2323,6 +2369,12 @@ your home directory (remove the '=' for that).
|
||||
behavior. The environment is always overridden by manually specified
|
||||
positive or negative options (the negative is `--no-old-args`).
|
||||
|
||||
Note that this option also disables the extra safety check added in 3.2.5
|
||||
that ensures that a remote sender isn't including extra top-level items in
|
||||
the file-list that you didn't request. This side-effect is necessary
|
||||
because we can't know for sure what names to expect when the remote shell
|
||||
is interpreting the args.
|
||||
|
||||
This option conflicts with the [`--protect-args`](#opt) option.
|
||||
|
||||
0. `--protect-args`, `-s`
|
||||
@@ -3017,7 +3069,7 @@ your home directory (remove the '=' for that).
|
||||
of "%i %n%L". See the [`--log-file-format`](#opt) option if you wish to
|
||||
override this.
|
||||
|
||||
Here's a example command that requests the remote side to log what is
|
||||
Here's an example command that requests the remote side to log what is
|
||||
happening:
|
||||
|
||||
> rsync -av --remote-option=--log-file=/tmp/rlog src/ dest/
|
||||
@@ -3255,10 +3307,8 @@ your home directory (remove the '=' for that).
|
||||
directories when the sending rsync is recursively scanning a hierarchy of
|
||||
files using include/exclude/filter rules.
|
||||
|
||||
Note that the use of transfer rules, such as the [`--min-size`](#opt)
|
||||
option, does not affect what goes into the file list, and thus does not
|
||||
leave directories empty, even if none of the files in a directory match the
|
||||
transfer rule.
|
||||
This option can still leave empty directories on the receiving side if you
|
||||
make use of [TRANSFER_RULES](#).
|
||||
|
||||
Because the file-list is actually being pruned, this option also affects
|
||||
what directories get deleted when a delete is active. However, keep in
|
||||
@@ -3721,27 +3771,146 @@ The options allowed when starting an rsync daemon are as follows:
|
||||
|
||||
## FILTER RULES
|
||||
|
||||
The filter rules allow for flexible selection of which files to transfer
|
||||
(include) and which files to skip (exclude). The rules either directly specify
|
||||
include/exclude patterns or they specify a way to acquire more include/exclude
|
||||
patterns (e.g. to read them from a file).
|
||||
The filter rules allow for custom control of several aspects of how files are
|
||||
handled:
|
||||
|
||||
As the list of files/directories to transfer is built, rsync checks each name
|
||||
to be transferred against the list of include/exclude patterns in turn, and the
|
||||
first matching pattern is acted on: if it is an exclude pattern, then that file
|
||||
is skipped; if it is an include pattern then that filename is not skipped; if
|
||||
no matching pattern is found, then the filename is not skipped.
|
||||
- Control which files the sending side puts into the file list that describes
|
||||
the transfer hierarchy
|
||||
- Control which files the receiving side protects from deletion when the file
|
||||
is not in the sender's file list
|
||||
- Control which extended attribute names are skipped when copying xattrs
|
||||
|
||||
Aside: because the interactions of filter rules can be complex, it is useful to
|
||||
use the `--debug=FILTER` option if things aren't working the way you expect.
|
||||
The level-1 output (the default if no level number is specified) mentions the
|
||||
filter rule that is first matched by each file in the transfer. It also warns
|
||||
if a filter rule has trailing whitespace. The level-2 output mentions a lot
|
||||
more filter events, including the definition of each rule and the handling of
|
||||
per-directory filter files.
|
||||
The rules are either directly specified via option arguments or they can be
|
||||
read in from one or more files. The filter-rule files can even be a part of
|
||||
the hierarchy of files being copied, affecting different parts of the tree in
|
||||
different ways.
|
||||
|
||||
Rsync builds an ordered list of filter rules as specified on the command-line.
|
||||
Filter rules have the following syntax:
|
||||
### SIMPLE INCLUDE/EXCLUDE RULES
|
||||
|
||||
We will first cover the basics of how include & exclude rules affect what files
|
||||
are transferred, ignoring any deletion side-effects. Filter rules mainly
|
||||
affect the contents of directories that rsync is "recursing" into, but they can
|
||||
also affect a top-level item in the transfer that were specified as a argument.
|
||||
|
||||
The default for any unmatched file/dir is for it to be included in the
|
||||
transfer, which puts the file/dir into the sender's file list. The use of an
|
||||
exclude rule causes one or more matching files/dirs to be left out of the
|
||||
sender's file list. An include rule can be used to limit the effect of an
|
||||
exclude rule that is matching too many files.
|
||||
|
||||
The order of the rules is important because the first rule that matches is the
|
||||
one that takes effect. Thus, if an early rule excludes a file, no include rule
|
||||
that comes after it can have any effect. This means that you must place any
|
||||
include overrides somewhere prior to the exclude that it is intended to limit.
|
||||
|
||||
When a directory is excluded, all its contents and sub-contents are also
|
||||
excluded. The sender doesn't scan through any of it at all, which can save a
|
||||
lot of time when skipping large unneeded sub-trees.
|
||||
|
||||
It is also important to understand that the include/exclude rules are applied
|
||||
to every file and directory that the sender is recursing into. Thus, if you
|
||||
want a particular deep file to be included, you have to make sure that none of
|
||||
the directories that must be traversed on the way down to that file are
|
||||
excluded or else the file will never be discovered to be included. As an
|
||||
example, if the directory "`a/path`" was given as a transfer argument and you
|
||||
want to ensure that the file "`a/path/down/deep/wanted.txt`" is a part of the
|
||||
transfer, then the sender must not exclude the directories "`a/path`",
|
||||
"`a/path/down`", or "`a/path/down/deep`" as it makes it way scanning through
|
||||
the file tree.
|
||||
|
||||
When you are working on the rules, it can be helpful to ask rsync to tell you
|
||||
what is being excluded/included and why. Specifying `--debug=FILTER` or (when
|
||||
pulling files) `-M--debug=FILTER` turns on level 1 of the FILTER debug
|
||||
information that will output a message any time that a file or directory is
|
||||
included or excluded and which rule it matched. Beginning in 3.2.4 it will
|
||||
also warn if a filter rule has trailing whitespace, since an exclude of "foo "
|
||||
(with a trailing space) will not exclude a file named "foo".
|
||||
|
||||
Exclude and include rules can specify wildcard [PATTERN MATCHING RULES](#)
|
||||
(similar to shell wildcards) that allow you to match things like a file suffix
|
||||
or a portion of a filename.
|
||||
|
||||
A rule can be limited to only affecting a directory by putting a trailing slash
|
||||
onto the filename.
|
||||
|
||||
### SIMPLE INCLUDE/EXCLUDE EXAMPLE
|
||||
|
||||
With the following file tree created on the sending side:
|
||||
|
||||
> mkdir x/
|
||||
> touch x/file.txt
|
||||
> mkdir x/y/
|
||||
> touch x/y/file.txt
|
||||
> touch x/y/zzz.txt
|
||||
> mkdir x/z/
|
||||
> touch x/z/file.txt
|
||||
|
||||
Then the following rsync command will transfer the file "`x/y/file.txt`" and
|
||||
the directories needed to hold it, resulting in the path "`/tmp/x/y/file.txt`"
|
||||
existing on the remote host:
|
||||
|
||||
> rsync -ai -f'+ x/' -f'+ x/y/' -f'+ x/y/file.txt' -f'- *' x host:/tmp/
|
||||
|
||||
Aside: this copy could also have been accomplished using the [`-R`](#opt)
|
||||
option (though the 2 commands behave differently if deletions are enabled):
|
||||
|
||||
> rsync -aiR x/y/file.txt host:/tmp/
|
||||
|
||||
The following command does not need an include of the "x" directory because it
|
||||
is not a part of the transfer (note the traililng slash). Running this command
|
||||
would copy just "`/tmp/x/file.txt`" because the "y" and "z" dirs get excluded:
|
||||
|
||||
> rsync -ai -f'+ file.txt' -f'- *' x/ host:/tmp/x/
|
||||
|
||||
This command would omit the zzz.txt file while copying "x" and everything else
|
||||
it contains:
|
||||
|
||||
> rsync -ai -f'- zzz.txt' x host:/tmp/
|
||||
|
||||
### FILTER RULES WHEN DELETING
|
||||
|
||||
By default the include & exclude filter rules affect both the sender
|
||||
(as it creates its file list)
|
||||
and the receiver (as it creates its file lists for calculating deletions). If
|
||||
no delete option is in effect, the receiver skips creating the delete-related
|
||||
file lists. This two-sided default can be manually overridden so that you are
|
||||
only specifying sender rules or receiver rules, as described in the [FILTER
|
||||
RULES IN DEPTH](#) section.
|
||||
|
||||
When deleting, an exclude protects a file from being removed on the receiving
|
||||
side while an include overrides that protection (putting the file at risk of
|
||||
deletion). The default is for a file to be at risk -- its safety depends on it
|
||||
matching a corresponding file from the sender.
|
||||
|
||||
An example of the two-sided exclude effect can be illustrated by the copying of
|
||||
a C development directory between 2 systems. When doing a touch-up copy, you
|
||||
might want to skip copying the built executable and the `.o` files (sender
|
||||
hide) so that the receiving side can build their own and not lose any object
|
||||
files that are already correct (receiver protect). For instance:
|
||||
|
||||
> rsync -ai --del -f'- *.o' -f'- cmd' src host:/dest/
|
||||
|
||||
Note that using `-f'-p *.o'` is even better than `-f'- *.o'` if there is a
|
||||
chance that the directory structure may have changed. The "p" modifier is
|
||||
discussed in [FILTER RULE MODIFIERS](#).
|
||||
|
||||
One final note, if your shell doesn't mind unexpanded wildcards, you could
|
||||
simplify the typing of the filter options by using an underscore in place of
|
||||
the space and leaving off the quotes. For instance, `-f -_*.o -f -_cmd` (and
|
||||
similar) could be used instead of the filter options above.
|
||||
|
||||
### FILTER RULES IN DEPTH
|
||||
|
||||
Rsync supports old-style include/exclude rules and new-style filter rules. The
|
||||
older rules are specified using [`--include`](#opt) and [`--exclude`](#opt) as
|
||||
well as the [`--include-from`](#opt) and [`--exclude-from`](#opt). These are
|
||||
limited in behavior but they don't require a "-" or "+" prefix. An old-style
|
||||
exclude rule is turned into a "`- name`" filter rule (with no modifiers) and an
|
||||
old-style include rule is turned into a "`+ name`" filter rule (with no
|
||||
modifiers).
|
||||
|
||||
Rsync builds an ordered list of filter rules as specified on the command-line
|
||||
and/or read-in from files. New style filter rules have the following syntax:
|
||||
|
||||
> RULE [PATTERN_OR_FILENAME]
|
||||
> RULE,MODIFIERS [PATTERN_OR_FILENAME]
|
||||
@@ -3749,35 +3918,38 @@ Filter rules have the following syntax:
|
||||
You have your choice of using either short or long RULE names, as described
|
||||
below. If you use a short-named rule, the ',' separating the RULE from the
|
||||
MODIFIERS is optional. The PATTERN or FILENAME that follows (when present)
|
||||
must come after either a single space or an underscore (\_). Here are the
|
||||
available rule prefixes:
|
||||
must come after either a single space or an underscore (\_). Any additional
|
||||
spaces and/or undeerscore are considered to be a part of the pattern name.
|
||||
Here are the available rule prefixes:
|
||||
|
||||
0. `exclude, '-'` specifies an exclude pattern.
|
||||
0. `include, '+'` specifies an include pattern.
|
||||
0. `merge, '.'` specifies a merge-file to read for more rules.
|
||||
0. `dir-merge, ':'` specifies a per-directory merge-file.
|
||||
0. `exclude, '-'` specifies an exclude pattern that (by default) is both a
|
||||
`hide` and a `protect`.
|
||||
0. `include, '+'` specifies an include pattern that (by default) is both a
|
||||
`show` and a `risk`.
|
||||
0. `merge, '.'` specifies a merge-file on the client side to read for more
|
||||
rules.
|
||||
0. `dir-merge, ':'` specifies a per-directory merge-file. Using this kind of
|
||||
filter rule requires that you trust the sending side's filter checking, and
|
||||
thus it disables the receiver's verification of the file-list names against
|
||||
the filter rules (since only the sender can know for sure if it obeyed all
|
||||
the filter rules when some are per-dir merged from the sender's files).
|
||||
0. `hide, 'H'` specifies a pattern for hiding files from the transfer.
|
||||
0. `show, 'S'` files that match the pattern are not hidden.
|
||||
Equivalent to a sender-only exclude, so `-f'H foo'` could also be specified
|
||||
as `-f'-s foo'`.
|
||||
0. `show, 'S'` files that match the pattern are not hidden. Equivalent to a
|
||||
sender-only include, so `-f'S foo'` could also be specified as `-f'+s
|
||||
foo'`.
|
||||
0. `protect, 'P'` specifies a pattern for protecting files from deletion.
|
||||
0. `risk, 'R'` files that match the pattern are not protected.
|
||||
Equivalent to a receiver-only exclude, so `-f'P foo'` could also be
|
||||
specified as `-f'-r foo'`.
|
||||
0. `risk, 'R'` files that match the pattern are not protected. Equivalent to a
|
||||
receiver-only include, so `-f'R foo'` could also be specified as `-f'+r
|
||||
foo'`.
|
||||
0. `clear, '!'` clears the current include/exclude list (takes no arg)
|
||||
|
||||
When rules are being read from a file, empty lines are ignored, as are
|
||||
whole-line comments that start with a '`#`' (filename rules that contain a hash
|
||||
are unaffected).
|
||||
|
||||
[comment]: # (Remember that markdown strips spaces from start/end of ` ... ` sequences!)
|
||||
[comment]: # (Thus, the `x ` sequences below use a literal non-breakable space!)
|
||||
|
||||
Note that the [`--include`](#opt) & [`--exclude`](#opt) command-line options do
|
||||
not allow the full range of rule parsing as described above -- they only allow
|
||||
the specification of include / exclude patterns plus a "`!`" token to clear the
|
||||
list (and the normal comment parsing when rules are read from a file). If a
|
||||
pattern does not begin with "`- `" (dash, space) or "`+ `" (plus, space), then
|
||||
the rule will be interpreted as if "`+ `" (for an include option) or "`- `"
|
||||
(for an exclude option) were prefixed to the string. A [`--filter`](#opt)
|
||||
option, on the other hand, must always contain either a short or long rule name
|
||||
at the start of the rule.
|
||||
When rules are being read from a file (using merge or dir-merge), empty lines
|
||||
are ignored, as are whole-line comments that start with a '`#`' (filename rules
|
||||
that contain a hash character are unaffected).
|
||||
|
||||
Note also that the [`--filter`](#opt), [`--include`](#opt), and
|
||||
[`--exclude`](#opt) options take one rule/pattern each. To add multiple ones,
|
||||
@@ -3785,121 +3957,90 @@ you can repeat the options on the command-line, use the merge-file syntax of
|
||||
the [`--filter`](#opt) option, or the [`--include-from`](#opt) /
|
||||
[`--exclude-from`](#opt) options.
|
||||
|
||||
## INCLUDE/EXCLUDE PATTERN RULES
|
||||
### PATTERN MATCHING RULES
|
||||
|
||||
You can include and exclude files by specifying patterns using the "+", "-",
|
||||
etc. filter rules (as introduced in the [FILTER RULES](#) section above). The
|
||||
include/exclude rules each specify a pattern that is matched against the names
|
||||
of the files that are going to be transferred. These patterns can take several
|
||||
forms:
|
||||
Most of the rules mentioned above take an argument that specifies what the rule
|
||||
should match. If rsync is recursing through a directory hierarchy, keep in
|
||||
mind that each pattern is matched against the name of every directory in the
|
||||
descent path as rsync finds the filenames to send.
|
||||
|
||||
- if the pattern starts with a `/` then it is anchored to a particular spot in
|
||||
the hierarchy of files, otherwise it is matched against the end of the
|
||||
pathname. This is similar to a leading `^` in regular expressions. Thus
|
||||
`/foo` would match a name of "foo" at either the "root of the transfer" (for
|
||||
a global rule) or in the merge-file's directory (for a per-directory rule).
|
||||
An unqualified `foo` would match a name of "foo" anywhere in the tree because
|
||||
the algorithm is applied recursively from the top down; it behaves as if each
|
||||
path component gets a turn at being the end of the filename. Even the
|
||||
unanchored "sub/foo" would match at any point in the hierarchy where a "foo"
|
||||
was found within a directory named "sub". See the section on ANCHORING
|
||||
INCLUDE/EXCLUDE PATTERNS for a full discussion of how to specify a pattern
|
||||
that matches at the root of the transfer.
|
||||
- if the pattern ends with a `/` then it will only match a directory, not a
|
||||
regular file, symlink, or device.
|
||||
- rsync chooses between doing a simple string match and wildcard matching by
|
||||
checking if the pattern contains one of these three wildcard characters:
|
||||
'`*`', '`?`', and '`[`' .
|
||||
- a '`*`' matches any path component, but it stops at slashes.
|
||||
- use '`**`' to match anything, including slashes.
|
||||
- a '`?`' matches any character except a slash (`/`).
|
||||
- a '`[`' introduces a character class, such as `[a-z]` or `[[:alpha:]]`.
|
||||
- in a wildcard pattern, a backslash can be used to escape a wildcard
|
||||
character, but it is matched literally when no wildcards are present. This
|
||||
means that there is an extra level of backslash removal when a pattern
|
||||
contains wildcard characters compared to a pattern that has none. e.g. if
|
||||
you add a wildcard to "`foo\bar`" (which matches the backslash) you would
|
||||
need to use "`foo\\bar*`" to avoid the "`\b`" becoming just "b".
|
||||
- if the pattern contains a `/` (not counting a trailing /) or a "`**`", then it
|
||||
is matched against the full pathname, including any leading directories. If
|
||||
the pattern doesn't contain a `/` or a "`**`", then it is matched only against
|
||||
the final component of the filename. (Remember that the algorithm is applied
|
||||
recursively so "full filename" can actually be any portion of a path from the
|
||||
starting directory on down.)
|
||||
- a trailing "`dir_name/***`" will match both the directory (as if "dir_name/"
|
||||
The matching rules for the pattern argument take several forms:
|
||||
|
||||
- If a pattern contains a `/` (not counting a trailing slash) or a "`**`"
|
||||
(which can match a slash), then the pattern is matched against the full
|
||||
pathname, including any leading directories within the transfer. If the
|
||||
pattern doesn't contain a `/` or a "`**`", then it is matched only against
|
||||
the final component of the filename or pathname. For example, `foo` means
|
||||
that the final path component must be "foo" while `foo/bar` would match the
|
||||
last 2 elements of the path (as long as both elements are within the
|
||||
transfer).
|
||||
- A pattern that ends with a `/` only matches a directory, not a regular file,
|
||||
symlink, or device.
|
||||
- A pattern that starts with a `/` is anchored to the start of the transfer
|
||||
path instead of the end. For example, `/foo` or `/foo/bar` match only
|
||||
leading elements in the path. If the rule is read from a per-directory
|
||||
filter file, the transfer path being matched will begin at the level of the
|
||||
filter file instead of the top of the transfer. See the section on
|
||||
[ANCHORING INCLUDE/EXCLUDE PATTERNS](#) for a full discussion of how to
|
||||
specify a pattern that matches at the root of the transfer.
|
||||
|
||||
Rsync chooses between doing a simple string match and wildcard matching by
|
||||
checking if the pattern contains one of these three wildcard characters: '`*`',
|
||||
'`?`', and '`[`' :
|
||||
|
||||
- a '`?`' matches any single character except a slash (`/`).
|
||||
- a '`*`' matches zero or more non-slash characters.
|
||||
- a '`**`' matches zero or more characters, including slashes.
|
||||
- a '`[`' introduces a character class, such as `[a-z]` or `[[:alpha:]]`, that
|
||||
must match one character.
|
||||
- a trailing `***` in the pattern is a shorthand that allows you to match a
|
||||
directory and all its contents using a single rule. For example, specifying
|
||||
"`dir_name/***`" will match both the "dir_name" directory (as if "`dir_name/`"
|
||||
had been specified) and everything in the directory (as if "`dir_name/**`"
|
||||
had been specified). This behavior was added in version 2.6.7.
|
||||
|
||||
Note that, when using the [`--recursive`](#opt) (`-r`) option (which is implied
|
||||
by [`-a`](#opt)), every subdir component of every path is visited left to
|
||||
right, with each directory having a chance for exclusion before its content.
|
||||
In this way include/exclude patterns are applied recursively to the pathname of
|
||||
each node in the filesystem's tree (those inside the transfer). The exclude
|
||||
patterns short-circuit the directory traversal stage as rsync finds the files
|
||||
to send.
|
||||
|
||||
For instance, to include "`/foo/bar/baz`", the directories "`/foo`" and "`/foo/bar`"
|
||||
must not be excluded. Excluding one of those parent directories prevents the
|
||||
examination of its content, cutting off rsync's recursion into those paths and
|
||||
rendering the include for "`/foo/bar/baz`" ineffectual (since rsync can't match
|
||||
something it never sees in the cut-off section of the directory hierarchy).
|
||||
|
||||
The concept path exclusion is particularly important when using a trailing '`*`'
|
||||
rule. For instance, this won't work:
|
||||
|
||||
> + /some/path/this-file-will-not-be-found
|
||||
> + /file-is-included
|
||||
> - *
|
||||
|
||||
This fails because the parent directory "some" is excluded by the '`*`' rule, so
|
||||
rsync never visits any of the files in the "some" or "some/path" directories.
|
||||
One solution is to ask for all directories in the hierarchy to be included by
|
||||
using a single rule: "`+ */`" (put it somewhere before the "`- *`" rule), and
|
||||
perhaps use the [`--prune-empty-dirs`](#opt) option. Another solution is to add
|
||||
specific include rules for all the parent dirs that need to be visited. For
|
||||
instance, this set of rules works fine:
|
||||
|
||||
> + /some/
|
||||
> + /some/path/
|
||||
> + /some/path/this-file-is-found
|
||||
> + /file-also-included
|
||||
> - *
|
||||
had been specified).
|
||||
- a backslash can be used to escape a wildcard character, but it is only
|
||||
interpreted as an escape character if at least one wildcard character is
|
||||
present in the match pattern. For instance, the pattern "`foo\bar`" matches
|
||||
that single backslash literally, while the pattern "`foo\bar*`" would need to
|
||||
be changed to "`foo\\bar*`" to avoid the "`\b`" becoming just "b".
|
||||
|
||||
Here are some examples of exclude/include matching:
|
||||
|
||||
- "`- *.o`" would exclude all names matching `*.o`
|
||||
- "`- /foo`" would exclude a file (or directory) named foo in the transfer-root
|
||||
directory
|
||||
- "`- foo/`" would exclude any directory named foo
|
||||
- "`- /foo/*/bar`" would exclude any file named bar which is at two levels
|
||||
below a directory named foo in the transfer-root directory
|
||||
- "`- /foo/**/bar`" would exclude any file named bar two or more levels below a
|
||||
directory named foo in the transfer-root directory
|
||||
- The combination of "`+ */`", "`+ *.c`", and "`- *`" would include all
|
||||
directories and C source files but nothing else (see also the
|
||||
[`--prune-empty-dirs`](#opt) option)
|
||||
- The combination of "`+ foo/`", "`+ foo/bar.c`", and "`- *`" would include
|
||||
only the foo directory and foo/bar.c (the foo directory must be explicitly
|
||||
included or it would be excluded by the "`*`")
|
||||
- Option `-f'- *.o'` would exclude all filenames ending with `.o`
|
||||
- Option `-f'- /foo'` would exclude a file (or directory) named foo in the
|
||||
transfer-root directory
|
||||
- Option `-f'- foo/'` would exclude any directory named foo
|
||||
- Option `-f'- /foo/*/bar'` would exclude any file/dir named bar which is at
|
||||
two levels below a directory named foo, which must be at the root of the
|
||||
transfer
|
||||
- Option `-f'- /foo/**/bar'` would exclude any file/dir named bar two or more
|
||||
levels below a directory named foo, which must be at the root of the transfer
|
||||
- Options `-f'+ */' -f'+ *.c' -f'- *'` would include all directories and .c
|
||||
source files but nothing else
|
||||
- Options `-f'+ foo/' -f'+ foo/bar.c' -f'- *'` would include only the foo
|
||||
directory and foo/bar.c (the foo directory must be explicitly included or it
|
||||
would be excluded by the "`- *`")
|
||||
|
||||
The following modifiers are accepted after a "`+`" or "`-`":
|
||||
### FILTER RULE MODIFIERS
|
||||
|
||||
The following modifiers are accepted after an include (+) or exclude (-) rule:
|
||||
|
||||
- A `/` specifies that the include/exclude rule should be matched against the
|
||||
absolute pathname of the current item. For example, "`-/ /etc/passwd`" would
|
||||
exclude the passwd file any time the transfer was sending files from the
|
||||
"/etc" directory, and "-/ subdir/foo" would always exclude "foo" when it is
|
||||
in a dir named "subdir", even if "foo" is at the root of the current
|
||||
absolute pathname of the current item. For example, `-f'-/ /etc/passwd'`
|
||||
would exclude the passwd file any time the transfer was sending files from
|
||||
the "/etc" directory, and "-/ subdir/foo" would always exclude "foo" when it
|
||||
is in a dir named "subdir", even if "foo" is at the root of the current
|
||||
transfer.
|
||||
- A `!` specifies that the include/exclude should take effect if the pattern
|
||||
fails to match. For instance, "`-! */`" would exclude all non-directories.
|
||||
fails to match. For instance, `-f'-! */'` would exclude all non-directories.
|
||||
- A `C` is used to indicate that all the global CVS-exclude rules should be
|
||||
inserted as excludes in place of the "-C". No arg should follow.
|
||||
- An `s` is used to indicate that the rule applies to the sending side. When a
|
||||
rule affects the sending side, it prevents files from being transferred. The
|
||||
default is for a rule to affect both sides unless [`--delete-excluded`](#opt)
|
||||
was specified, in which case default rules become sender-side only. See also
|
||||
the hide (H) and show (S) rules, which are an alternate way to specify
|
||||
sending-side includes/excludes.
|
||||
rule affects the sending side, it affects what files are put into the
|
||||
sender's file list. The default is for a rule to affect both sides unless
|
||||
[`--delete-excluded`](#opt) was specified, in which case default rules become
|
||||
sender-side only. See also the hide (H) and show (S) rules, which are an
|
||||
alternate way to specify sending-side includes/excludes.
|
||||
- An `r` is used to indicate that the rule applies to the receiving side. When
|
||||
a rule affects the receiving side, it prevents files from being deleted. See
|
||||
the `s` modifier for more info. See also the protect (P) and risk (R) rules,
|
||||
@@ -3915,7 +4056,7 @@ The following modifiers are accepted after a "`+`" or "`-`":
|
||||
xattr-matching rules are specified, a default xattr filtering rule is used
|
||||
(see the [`--xattrs`](#opt) option).
|
||||
|
||||
## MERGE-FILE FILTER RULES
|
||||
### MERGE-FILE FILTER RULES
|
||||
|
||||
You can merge whole files into your filter rules by specifying either a merge
|
||||
(.) or a dir-merge (:) filter rule (as introduced in the [FILTER RULES](#)
|
||||
@@ -4049,7 +4190,7 @@ $HOME/.cvsignore, and the value of $CVSIGNORE) you should omit the `-C`
|
||||
command-line option and instead insert a "-C" rule into your filter rules; e.g.
|
||||
"`--filter=-C`".
|
||||
|
||||
## LIST-CLEARING FILTER RULE
|
||||
### LIST-CLEARING FILTER RULE
|
||||
|
||||
You can clear the current include/exclude list by using the "!" filter rule (as
|
||||
introduced in the [FILTER RULES](#) section above). The "current" list is either
|
||||
@@ -4057,7 +4198,7 @@ the global list of rules (if the rule is encountered while parsing the filter
|
||||
options) or a set of per-directory rules (which are inherited in their own
|
||||
sub-list, so a subdirectory can use this to clear out the parent's rules).
|
||||
|
||||
## ANCHORING INCLUDE/EXCLUDE PATTERNS
|
||||
### ANCHORING INCLUDE/EXCLUDE PATTERNS
|
||||
|
||||
As mentioned earlier, global include/exclude patterns are anchored at the "root
|
||||
of the transfer" (as opposed to per-directory patterns, which are anchored at
|
||||
@@ -4112,7 +4253,7 @@ The easiest way to see what name you should filter is to just look at the
|
||||
output when using [`--verbose`](#opt) and put a / in front of the name (use the
|
||||
`--dry-run` option if you're not yet ready to copy any files).
|
||||
|
||||
## PER-DIRECTORY RULES AND DELETE
|
||||
### PER-DIRECTORY RULES AND DELETE
|
||||
|
||||
Without a delete option, per-directory rules are only relevant on the sending
|
||||
side, so you can feel free to exclude the merge files themselves without
|
||||
@@ -4158,6 +4299,38 @@ one of these commands:
|
||||
> rsync -avFF --delete host:src/dir /dest
|
||||
> ```
|
||||
|
||||
## TRANSFER RULES
|
||||
|
||||
In addition to the [FILTER RULES](#) that affect the recursive file scans that
|
||||
generate the file list on the sending and (when deleting) receiving sides,
|
||||
there are transfer rules. These rules affect which files the generator decides
|
||||
need to be transferred without the side effects of an exclude filter rule.
|
||||
Transfer rules affect only files and never directories.
|
||||
|
||||
Because a transfer rule does not affect what goes into the sender's (and
|
||||
receiver's) file list, it cannot have any effect on which files get deleted on
|
||||
the receiving side. For example, if the file "foo" is present in the sender's
|
||||
list but its size is such that it is omitted due to a transfer rule, the
|
||||
receiving side does not request the file. However, its presence in the file
|
||||
list means that a delete pass will not remove a matching file named "foo" on
|
||||
the receiving side. On the other hand, a server-side exclude (hide) of the
|
||||
file "foo" leaves the file out of the server's file list, and absent a
|
||||
receiver-side exclude (protect) the receiver will remove a matching file named
|
||||
"foo" if deletions are requested.
|
||||
|
||||
Given that the files are still in the sender's file list, the
|
||||
[`--prune-empty-dirs`](#opt) option will not judge a directory as being empty
|
||||
even if it contains only files that the transfer rules omitted.
|
||||
|
||||
Similarly, a transfer rule does not have any extra effect on which files are
|
||||
deleted on the receiving side, so setting a maximum file size for the transfer
|
||||
does not prevent big files from being deleted.
|
||||
|
||||
Examples of transfer rules include the default "quick check" algorithm (which
|
||||
compares size & modify time), the [`--update`](#opt) option, the
|
||||
[`--max-size`](#opt) option, the [`--ignore-non-existing`](#opt) option, and a
|
||||
few others.
|
||||
|
||||
## BATCH MODE
|
||||
|
||||
Batch mode can be used to apply the same set of updates to many identical
|
||||
@@ -4466,7 +4639,7 @@ file is included or excluded.
|
||||
0. `RSYNC_SHELL`
|
||||
|
||||
This environment variable is mainly used in debug setups to set the program
|
||||
to use to run the program specified by [`RSYNC_CONNECT_PROG`]. See
|
||||
to use to run the program specified by [`RSYNC_CONNECT_PROG`](#). See
|
||||
[CONNECTING TO AN RSYNC DAEMON](#) for full details.
|
||||
|
||||
## FILES
|
||||
|
||||
3
rsync.h
3
rsync.h
@@ -338,6 +338,9 @@ enum delret {
|
||||
# endif
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_BSD_STRING_H
|
||||
# include <bsd/string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
@@ -1114,15 +1114,15 @@ SSL proxy.
|
||||
## SSL/TLS Daemon Setup
|
||||
|
||||
When setting up an rsync daemon for access via SSL/TLS, you will need to
|
||||
configure a proxy (such as haproxy or nginx) as the front-end that handles the
|
||||
encryption.
|
||||
configure a TCP proxy (such as haproxy or nginx) as the front-end that handles
|
||||
the encryption.
|
||||
|
||||
- You should limit the access to the backend-rsyncd port to only allow the
|
||||
proxy to connect. If it is on the same host as the proxy, then configuring
|
||||
it to only listen on localhost is a good idea.
|
||||
- You should consider turning on the `proxy protocol` parameter if your proxy
|
||||
supports sending that information. The examples below assume that this is
|
||||
enabled.
|
||||
- You should consider turning on the `proxy protocol` rsync-daemon parameter if
|
||||
your proxy supports sending that information. The examples below assume that
|
||||
this is enabled.
|
||||
|
||||
An example haproxy setup is as follows:
|
||||
|
||||
@@ -1149,14 +1149,14 @@ An example nginx proxy setup is as follows:
|
||||
> ssl_certificate_key /etc/letsencrypt/example.com/privkey.pem;
|
||||
>
|
||||
> proxy_pass localhost:873;
|
||||
> proxy_protocol on; # Requires "proxy protocol = true"
|
||||
> proxy_protocol on; # Requires rsyncd.conf "proxy protocol = true"
|
||||
> proxy_timeout 1m;
|
||||
> proxy_connect_timeout 5s;
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
|
||||
## EXAMPLES
|
||||
## DAEMON CONFIG EXAMPLES
|
||||
|
||||
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
|
||||
`/home/ftp` would be:
|
||||
@@ -1237,8 +1237,9 @@ Thanks to Karsten Thygesen for his many suggestions and documentation!
|
||||
|
||||
## AUTHOR
|
||||
|
||||
Rsync was written by Andrew Tridgell and Paul Mackerras. Many people have
|
||||
later contributed to it.
|
||||
Rsync was originally written by Andrew Tridgell and Paul Mackerras. Many
|
||||
people have later contributed to it. It is currently maintained by Wayne
|
||||
Davison.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
<https://lists.samba.org/>.
|
||||
|
||||
@@ -11,14 +11,16 @@ rrsync [-ro|-rw] [-munge] [-no-del] [-no-lock] DIR
|
||||
The single non-option argument specifies the restricted _DIR_ to use. It can be
|
||||
relative to the user's home directory or an absolute path.
|
||||
|
||||
The online version of this man page (that includes cross-linking of topics)
|
||||
The online version of this manpage (that includes cross-linking of topics)
|
||||
is available at <https://download.samba.org/pub/rsync/rrsync.1>.
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
A user's ssh login can be restricted to only allow the running of an rsync
|
||||
transfer in one of two easy ways: forcing the running of the rrsync script
|
||||
or forcing the running of an rsync daemon-over-ssh command.
|
||||
transfer in one of two easy ways:
|
||||
|
||||
* forcing the running of the rrsync script
|
||||
* forcing the running of an rsync daemon-over-ssh command.
|
||||
|
||||
To use the rrsync script, edit the user's `~/.ssh/authorized_keys` file and add
|
||||
a prefix like one of the following (followed by a space) in front of each
|
||||
@@ -47,13 +49,14 @@ ssh-key line that should be restricted:
|
||||
Then, ensure that the rsyncd.conf file is created with one or more module names
|
||||
with the appropriate path and option restrictions. If rsync's
|
||||
[`--config`](rsync.1#dopt) option is omitted, it defaults to `~/rsyncd.conf`.
|
||||
See the `rsyncd.conf` man page for details of how to configure an rsync daemon.
|
||||
See the [**rsyncd.conf**(5)](rsyncd.conf.5) manpage for details of how to
|
||||
configure an rsync daemon.
|
||||
|
||||
When using rrsync, there can be just one restricted dir per authorized key. A
|
||||
daemon setup, on the other hand, allows multiple module names inside the config
|
||||
file, each one with its own path setting.
|
||||
|
||||
The remainder of this man page is dedicated to using the rrsync script.
|
||||
The remainder of this manpage is dedicated to using the rrsync script.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
@@ -119,11 +122,11 @@ The `~/.ssh/authorized_keys` file might have lines in it like this:
|
||||
|
||||
## SEE ALSO
|
||||
|
||||
[**rsync**(1)](rsync.1)
|
||||
[**rsync**(1)](rsync.1), [**rsyncd.conf**(5)](rsyncd.conf.5)
|
||||
|
||||
## VERSION
|
||||
|
||||
This man page is current for version @VERSION@ of rsync.
|
||||
This manpage is current for version @VERSION@ of rsync.
|
||||
|
||||
## CREDITS
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2004-2020 Wayne Davison
|
||||
* Copyright (C) 2004-2022 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -210,7 +210,7 @@ static int is_in_group(gid_t gid)
|
||||
ngroups = getgroups(ngroups, gidset);
|
||||
/* The default gid might not be in the list on some systems. */
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
if (gidset[n] == our_gid)
|
||||
if ((gid_t)gidset[n] == our_gid)
|
||||
break;
|
||||
}
|
||||
if (n == ngroups)
|
||||
@@ -229,7 +229,7 @@ static int is_in_group(gid_t gid)
|
||||
|
||||
last_in = gid;
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
if (gidset[n] == gid)
|
||||
if ((gid_t)gidset[n] == gid)
|
||||
return last_out = 1;
|
||||
}
|
||||
return last_out = 0;
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
#define RSYNC_VERSION "3.2.4"
|
||||
#define RSYNC_VERSION "3.2.5pre2"
|
||||
#define MAINTAINER_TZ_OFFSET -7.0
|
||||
|
||||
@@ -740,8 +740,9 @@ int flush;
|
||||
if (copy > have) copy = have;
|
||||
if (copy) {
|
||||
if (state->head != Z_NULL &&
|
||||
state->head->extra != Z_NULL) {
|
||||
len = state->head->extra_len - state->length;
|
||||
state->head->extra != Z_NULL &&
|
||||
(len = state->head->extra_len - state->length) <
|
||||
state->head->extra_max) {
|
||||
zmemcpy(state->head->extra + len, next,
|
||||
len + copy > state->head->extra_max ?
|
||||
state->head->extra_max - len : copy);
|
||||
|
||||
Reference in New Issue
Block a user