mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-26 07:45:33 -04:00
Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e10163a9d | ||
|
|
5fcf20ee9d | ||
|
|
fc72d2b771 | ||
|
|
b7ea3fcd19 | ||
|
|
9cb7529ba6 | ||
|
|
55ad8757ec | ||
|
|
3e4b01173a | ||
|
|
2f1d1d5cac | ||
|
|
4c0a4067df | ||
|
|
8550142804 | ||
|
|
97f40754ba | ||
|
|
cff8f04477 | ||
|
|
db8034f12e | ||
|
|
c86763dc38 | ||
|
|
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.
|
||||
|
||||
60
NEWS.md
60
NEWS.md
@@ -1,3 +1,62 @@
|
||||
# NEWS for rsync 3.2.5 (14 Aug 2022)
|
||||
|
||||
## 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 handling of filenames specified with backslash-quoted wildcards
|
||||
when the default remote-arg-escaping is enabled.
|
||||
|
||||
- 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.
|
||||
|
||||
- If rsync is compiled with an xxhash 0.8 library and then moved to a system
|
||||
with a dynamically linked xxhash 0.7 library, we now detect this and disable
|
||||
the XX3 hashes (since these routines didn't stabilize until 0.8).
|
||||
|
||||
### ENHANCEMENTS:
|
||||
|
||||
- The [`--trust-sender`](rsync.1#opt) option was added as a way to bypass the
|
||||
extra file-list safety checking (should that be required).
|
||||
|
||||
### PACKAGING RELATED:
|
||||
|
||||
- A note to those wanting to patch older rsync versions: the changes in this
|
||||
release requires the quoted argument change from 3.2.4. Then, you'll want
|
||||
every single code change from 3.2.5 since there is no fluff in this release.
|
||||
|
||||
- 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 +4541,7 @@
|
||||
|
||||
| RELEASE DATE | VER. | DATE OF COMMIT\* | PROTOCOL |
|
||||
|--------------|--------|------------------|-------------|
|
||||
| 14 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 |
|
||||
|
||||
4
batch.c
4
batch.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1999 Weiss
|
||||
* Copyright (C) 2004 Chris Shoemaker
|
||||
* 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
|
||||
@@ -194,7 +194,7 @@ static int write_opt(const char *opt, const char *arg)
|
||||
{
|
||||
int len = strlen(opt);
|
||||
int err = write(batch_sh_fd, " ", 1) != 1;
|
||||
err = write(batch_sh_fd, opt, len) != len ? 1 : 0;
|
||||
err = write(batch_sh_fd, opt, len) != len ? 1 : 0;
|
||||
if (arg) {
|
||||
err |= write(batch_sh_fd, "=", 1) != 1;
|
||||
err |= write_arg(arg);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Simple byteorder handling.
|
||||
*
|
||||
* Copyright (C) 1992-1995 Andrew Tridgell
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-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
|
||||
@@ -129,4 +129,3 @@ SIVAL(char *buf, int pos, uint32 val)
|
||||
{
|
||||
SIVALu((uchar*)buf, pos, val);
|
||||
}
|
||||
|
||||
|
||||
35
checksum.c
35
checksum.c
@@ -62,6 +62,8 @@ struct name_num_obj valid_checksums = {
|
||||
int xfersum_type = 0; /* used for the file transfer checksums */
|
||||
int checksum_type = 0; /* used for the pre-transfer (--checksum) checksums */
|
||||
|
||||
static int initialized_choices = 0;
|
||||
|
||||
int parse_csum_name(const char *name, int len)
|
||||
{
|
||||
struct name_num_item *nni;
|
||||
@@ -79,6 +81,9 @@ int parse_csum_name(const char *name, int len)
|
||||
return CSUM_MD4_ARCHAIC;
|
||||
}
|
||||
|
||||
if (!initialized_choices)
|
||||
init_checksum_choices();
|
||||
|
||||
nni = get_nni_by_name(&valid_checksums, name, len);
|
||||
|
||||
if (!nni) {
|
||||
@@ -574,7 +579,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)
|
||||
@@ -623,3 +628,31 @@ int sum_end(char *sum)
|
||||
|
||||
return csum_len_for_type(cursum_type, 0);
|
||||
}
|
||||
|
||||
void init_checksum_choices()
|
||||
{
|
||||
#ifdef SUPPORT_XXH3
|
||||
char buf[32816];
|
||||
int j;
|
||||
for (j = 0; j < (int)sizeof buf; j++) {
|
||||
buf[j] = ' ' + (j % 96);
|
||||
}
|
||||
sum_init(CSUM_XXH3_64, 0);
|
||||
sum_update(buf, 32816);
|
||||
sum_update(buf, 31152);
|
||||
sum_update(buf, 32474);
|
||||
sum_update(buf, 9322);
|
||||
if (XXH3_64bits_digest(xxh3_state) != 0xadbcf16d4678d1de) {
|
||||
int t, f;
|
||||
struct name_num_item *nni = valid_checksums.list;
|
||||
for (t = f = 0; nni[f].name; f++) {
|
||||
if (nni[f].num == CSUM_XXH3_64 || nni[f].num == CSUM_XXH3_128)
|
||||
continue;
|
||||
if (t != f)
|
||||
nni[t++] = nni[f];
|
||||
}
|
||||
nni[t].name = NULL;
|
||||
}
|
||||
#endif
|
||||
initialized_choices = 1;
|
||||
}
|
||||
|
||||
6
compat.c
6
compat.c
@@ -400,7 +400,7 @@ static const char *getenv_nstr(int ntype)
|
||||
const char *env_str = getenv(ntype == NSTR_COMPRESS ? "RSYNC_COMPRESS_LIST" : "RSYNC_CHECKSUM_LIST");
|
||||
|
||||
/* When writing a batch file, we always negotiate an old-style choice. */
|
||||
if (write_batch)
|
||||
if (write_batch)
|
||||
env_str = ntype == NSTR_COMPRESS ? "zlib" : protocol_version >= 30 ? "md5" : "md4";
|
||||
|
||||
if (am_server && env_str) {
|
||||
@@ -433,7 +433,7 @@ void validate_choice_vs_env(int ntype, int num1, int num2)
|
||||
nno->saw[CSUM_MD4_ARCHAIC] = nno->saw[CSUM_MD4_BUSTED] = nno->saw[CSUM_MD4_OLD] = nno->saw[CSUM_MD4];
|
||||
|
||||
if (!nno->saw[num1] || (num2 >= 0 && !nno->saw[num2])) {
|
||||
rprintf(FERROR, "Your --%s-choice value (%s) was refused by the server.\n",
|
||||
rprintf(FERROR, "Your --%s-choice value (%s) was refused by the server.\n",
|
||||
ntype == NSTR_COMPRESS ? "compress" : "checksum",
|
||||
ntype == NSTR_COMPRESS ? compress_choice : checksum_choice);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
@@ -523,6 +523,8 @@ static void negotiate_the_strings(int f_in, int f_out)
|
||||
{
|
||||
/* We send all the negotiation strings before we start to read them to help avoid a slow startup. */
|
||||
|
||||
init_checksum_choices();
|
||||
|
||||
if (!checksum_choice)
|
||||
send_negotiate_str(f_out, &valid_checksums, NSTR_CHECKSUM);
|
||||
|
||||
|
||||
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,16 +25,21 @@
|
||||
|
||||
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 relative_paths;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int cvs_exclude;
|
||||
extern int sanitize_paths;
|
||||
extern int protocol_version;
|
||||
extern int trust_sender_args;
|
||||
extern int module_id;
|
||||
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
@@ -44,8 +49,11 @@ 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_args = 0;
|
||||
int trust_sender_filter = 0;
|
||||
|
||||
/* Need room enough for ":MODS " prefix plus some room to grow. */
|
||||
#define MAX_RULE_PREFIX (16)
|
||||
@@ -292,6 +300,233 @@ 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);
|
||||
|
||||
for (cp = arg; *cp; cp++) {
|
||||
if (*cp == '\\' && cp[1]) {
|
||||
cp++;
|
||||
} else if (*cp == '[')
|
||||
cnt++;
|
||||
}
|
||||
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);
|
||||
for (cp = arg; *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;
|
||||
}
|
||||
partial_string_len = 0; /* paranoia */
|
||||
}
|
||||
|
||||
/* 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, int skip_daemon_module)
|
||||
{
|
||||
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 (trust_sender_args)
|
||||
return;
|
||||
if (partial_string_len) {
|
||||
arg_len = strlen(arg);
|
||||
if (partial_string_len + arg_len >= MAXPATHLEN) {
|
||||
partial_string_len = 0;
|
||||
return; /* Should be impossible... */
|
||||
}
|
||||
memcpy(partial_string_buf + partial_string_len, arg, arg_len + 1);
|
||||
partial_string_len = 0;
|
||||
arg = partial_string_buf;
|
||||
}
|
||||
if (skip_daemon_module) {
|
||||
if ((cp = strchr(arg, '/')) != NULL)
|
||||
arg = cp + 1;
|
||||
else
|
||||
arg = "";
|
||||
}
|
||||
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. */
|
||||
for (cp = arg; (cp = strchr(cp, '\\')) != NULL; cp++)
|
||||
arg_len++;
|
||||
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++ = '/';
|
||||
for (cp = arg; *cp; ) {
|
||||
switch (*cp) {
|
||||
case '\\':
|
||||
if (cp[1] == ']') {
|
||||
if (!saw_wild)
|
||||
cp++; /* A \] in a non-wild filter causes a problem, so drop the \ . */
|
||||
} 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);
|
||||
for (cp = arg; *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, 0);
|
||||
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, 0);
|
||||
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
|
||||
|
||||
178
lib/sysacls.c
178
lib/sysacls.c
@@ -2,7 +2,7 @@
|
||||
* Unix SMB/CIFS implementation.
|
||||
* Based on the Samba ACL support code.
|
||||
* Copyright (C) Jeremy Allison 2000.
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-2022 Wayne Davison
|
||||
*
|
||||
* The permission functions have been changed to get/set all bits via
|
||||
* one call. Some functions that rsync doesn't need were also removed.
|
||||
@@ -175,7 +175,7 @@ int sys_acl_delete_def_file(const char *name)
|
||||
return acl_delete_def_file(name);
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
{
|
||||
return acl_free(the_acl);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
* The interface to DEC/Compaq Tru64 UNIX ACLs
|
||||
* is based on Draft 13 of the POSIX spec which is
|
||||
* slightly different from the Draft 16 interface.
|
||||
*
|
||||
*
|
||||
* Also, some of the permset manipulation functions
|
||||
* such as acl_clear_perm() and acl_add_perm() appear
|
||||
* to be broken on Tru64 so we have to manipulate
|
||||
@@ -310,7 +310,7 @@ int sys_acl_delete_def_file(const char *name)
|
||||
return acl_delete_def_file((char *)name);
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
int sys_acl_free_acl(SMB_ACL_T the_acl)
|
||||
{
|
||||
return acl_free(the_acl);
|
||||
}
|
||||
@@ -457,7 +457,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
break;
|
||||
}
|
||||
ndefault = count - naccess;
|
||||
|
||||
|
||||
/*
|
||||
* if the caller wants the default ACL we have to copy
|
||||
* the entries down to the start of the acl[] buffer
|
||||
@@ -517,7 +517,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
acl_d->count = naccess;
|
||||
|
||||
return acl_d;
|
||||
@@ -532,7 +532,7 @@ int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *b
|
||||
|
||||
if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
|
||||
*u_g_id_p = entry->a_id;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -633,7 +633,7 @@ static int acl_sort(SMB_ACL_T acl_d)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sys_acl_valid(SMB_ACL_T acl_d)
|
||||
{
|
||||
return acl_sort(acl_d);
|
||||
@@ -755,11 +755,11 @@ int sys_acl_delete_def_file(const char *path)
|
||||
ret = acl(path, SETACL, acl_d->count, acl_d->acl);
|
||||
|
||||
sys_acl_free_acl(acl_d);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
{
|
||||
SAFE_FREE(acl_d);
|
||||
return 0;
|
||||
@@ -895,10 +895,10 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
int ndefault; /* # of default ACL entries */
|
||||
|
||||
if (hpux_acl_call_presence() == False) {
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
* May be the system doesn't have the latest version of JFS.
|
||||
*/
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
|
||||
@@ -949,7 +949,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
break;
|
||||
}
|
||||
ndefault = count - naccess;
|
||||
|
||||
|
||||
/*
|
||||
* if the caller wants the default ACL we have to copy
|
||||
* the entries down to the start of the acl[] buffer
|
||||
@@ -1109,9 +1109,9 @@ struct hpux_acl_types {
|
||||
* aclp - Array of ACL structures.
|
||||
* acl_type_count - Pointer to acl_types structure. Should already be
|
||||
* allocated.
|
||||
* Output:
|
||||
* Output:
|
||||
*
|
||||
* acl_type_count - This structure is filled up with counts of various
|
||||
* acl_type_count - This structure is filled up with counts of various
|
||||
* acl types.
|
||||
*/
|
||||
|
||||
@@ -1123,28 +1123,28 @@ static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_type
|
||||
|
||||
for (i = 0; i < acl_count; i++) {
|
||||
switch (aclp[i].a_type) {
|
||||
case USER:
|
||||
case USER:
|
||||
acl_type_count->n_user++;
|
||||
break;
|
||||
case USER_OBJ:
|
||||
case USER_OBJ:
|
||||
acl_type_count->n_user_obj++;
|
||||
break;
|
||||
case DEF_USER_OBJ:
|
||||
case DEF_USER_OBJ:
|
||||
acl_type_count->n_def_user_obj++;
|
||||
break;
|
||||
case GROUP:
|
||||
case GROUP:
|
||||
acl_type_count->n_group++;
|
||||
break;
|
||||
case GROUP_OBJ:
|
||||
case GROUP_OBJ:
|
||||
acl_type_count->n_group_obj++;
|
||||
break;
|
||||
case DEF_GROUP_OBJ:
|
||||
case DEF_GROUP_OBJ:
|
||||
acl_type_count->n_def_group_obj++;
|
||||
break;
|
||||
case OTHER_OBJ:
|
||||
case OTHER_OBJ:
|
||||
acl_type_count->n_other_obj++;
|
||||
break;
|
||||
case DEF_OTHER_OBJ:
|
||||
case DEF_OTHER_OBJ:
|
||||
acl_type_count->n_def_other_obj++;
|
||||
break;
|
||||
case CLASS_OBJ:
|
||||
@@ -1159,14 +1159,14 @@ static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_type
|
||||
case DEF_GROUP:
|
||||
acl_type_count->n_def_group++;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
acl_type_count->n_illegal_obj++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* swap_acl_entries: Swaps two ACL entries.
|
||||
/* swap_acl_entries: Swaps two ACL entries.
|
||||
*
|
||||
* Inputs: aclp0, aclp1 - ACL entries to be swapped.
|
||||
*/
|
||||
@@ -1189,25 +1189,25 @@ static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
|
||||
}
|
||||
|
||||
/* prohibited_duplicate_type
|
||||
* Identifies if given ACL type can have duplicate entries or
|
||||
* Identifies if given ACL type can have duplicate entries or
|
||||
* not.
|
||||
*
|
||||
* Inputs: acl_type - ACL Type.
|
||||
*
|
||||
* Outputs:
|
||||
* Outputs:
|
||||
*
|
||||
* Return..
|
||||
* Return..
|
||||
*
|
||||
* True - If the ACL type matches any of the prohibited types.
|
||||
* False - If the ACL type doesn't match any of the prohibited types.
|
||||
*/
|
||||
*/
|
||||
|
||||
static BOOL hpux_prohibited_duplicate_type(int acl_type)
|
||||
{
|
||||
switch (acl_type) {
|
||||
case USER:
|
||||
case GROUP:
|
||||
case DEF_USER:
|
||||
case DEF_USER:
|
||||
case DEF_GROUP:
|
||||
return True;
|
||||
default:
|
||||
@@ -1217,7 +1217,7 @@ static BOOL hpux_prohibited_duplicate_type(int acl_type)
|
||||
|
||||
/* get_needed_class_perm
|
||||
* Returns the permissions of a ACL structure only if the ACL
|
||||
* type matches one of the pre-determined types for computing
|
||||
* type matches one of the pre-determined types for computing
|
||||
* CLASS_OBJ permissions.
|
||||
*
|
||||
* Inputs: aclp - Pointer to ACL structure.
|
||||
@@ -1226,17 +1226,17 @@ static BOOL hpux_prohibited_duplicate_type(int acl_type)
|
||||
static int hpux_get_needed_class_perm(struct acl *aclp)
|
||||
{
|
||||
switch (aclp->a_type) {
|
||||
case USER:
|
||||
case GROUP_OBJ:
|
||||
case GROUP:
|
||||
case DEF_USER_OBJ:
|
||||
case USER:
|
||||
case GROUP_OBJ:
|
||||
case GROUP:
|
||||
case DEF_USER_OBJ:
|
||||
case DEF_USER:
|
||||
case DEF_GROUP_OBJ:
|
||||
case DEF_GROUP_OBJ:
|
||||
case DEF_GROUP:
|
||||
case DEF_CLASS_OBJ:
|
||||
case DEF_OTHER_OBJ:
|
||||
case DEF_OTHER_OBJ:
|
||||
return aclp->a_perm;
|
||||
default:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1267,15 +1267,15 @@ static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
|
||||
#if !defined(HAVE_HPUX_ACLSORT)
|
||||
/*
|
||||
* The aclsort() system call is available on the latest HPUX General
|
||||
* Patch Bundles. So for HPUX, we developed our version of acl_sort
|
||||
* function. Because, we don't want to update to a new
|
||||
* Patch Bundles. So for HPUX, we developed our version of acl_sort
|
||||
* function. Because, we don't want to update to a new
|
||||
* HPUX GR bundle just for aclsort() call.
|
||||
*/
|
||||
|
||||
struct hpux_acl_types acl_obj_count;
|
||||
int n_class_obj_perm = 0;
|
||||
int i, j;
|
||||
|
||||
|
||||
if (!acl_count) {
|
||||
DEBUG(10, ("Zero acl count passed. Returning Success\n"));
|
||||
return 0;
|
||||
@@ -1290,8 +1290,8 @@ static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
|
||||
|
||||
hpux_count_obj(acl_count, aclp, &acl_obj_count);
|
||||
|
||||
/* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
|
||||
* CLASS_OBJ and OTHER_OBJ
|
||||
/* There should be only one entry each of type USER_OBJ, GROUP_OBJ,
|
||||
* CLASS_OBJ and OTHER_OBJ
|
||||
*/
|
||||
|
||||
if (acl_obj_count.n_user_obj != 1
|
||||
@@ -1313,15 +1313,15 @@ or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
|
||||
* structures.
|
||||
/* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl
|
||||
* structures.
|
||||
*
|
||||
* Sorting crieteria - First sort by ACL type. If there are multiple entries of
|
||||
* same ACL type, sort by ACL id.
|
||||
*
|
||||
* I am using the trivial kind of sorting method here because, performance isn't
|
||||
* I am using the trivial kind of sorting method here because, performance isn't
|
||||
* really effected by the ACLs feature. More over there aren't going to be more
|
||||
* than 17 entries on HPUX.
|
||||
* than 17 entries on HPUX.
|
||||
*/
|
||||
|
||||
for (i = 0; i < acl_count; i++) {
|
||||
@@ -1390,7 +1390,7 @@ static int acl_sort(SMB_ACL_T acl_d)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sys_acl_valid(SMB_ACL_T acl_d)
|
||||
{
|
||||
return acl_sort(acl_d);
|
||||
@@ -1405,11 +1405,11 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
|
||||
int ret;
|
||||
|
||||
if (hpux_acl_call_presence() == False) {
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
/* Looks like we don't have the acl() system call on HPUX.
|
||||
* May be the system doesn't have the latest version of JFS.
|
||||
*/
|
||||
errno=ENOSYS;
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
|
||||
@@ -1538,11 +1538,11 @@ int sys_acl_delete_def_file(const char *path)
|
||||
ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
|
||||
|
||||
sys_acl_free_acl(acl_d);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
{
|
||||
free(acl_d);
|
||||
return 0;
|
||||
@@ -1723,7 +1723,7 @@ int sys_acl_delete_def_file(const char *name)
|
||||
return acl_delete_def_file(name);
|
||||
}
|
||||
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
int sys_acl_free_acl(SMB_ACL_T acl_d)
|
||||
{
|
||||
if (acl_d->freeaclp) {
|
||||
acl_free(acl_d->aclp);
|
||||
@@ -1834,12 +1834,12 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
}
|
||||
|
||||
/* Get the acl using statacl */
|
||||
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_get_file\n"));
|
||||
DEBUG(10, ("path_p is %s\n", path_p));
|
||||
|
||||
file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
|
||||
|
||||
|
||||
if (file_acl == NULL) {
|
||||
errno=ENOMEM;
|
||||
DEBUG(0, ("Error in AIX sys_acl_get_file: %d\n", errno));
|
||||
@@ -1931,9 +1931,9 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
* to be specified but, it's better than leaving it 0 */
|
||||
|
||||
acl_entry_link->entryp->ace_type = acl_entry->ace_type;
|
||||
|
||||
|
||||
acl_entry_link->entryp->ace_access = acl_entry->ace_access;
|
||||
|
||||
|
||||
memcpy(acl_entry_link->entryp->ace_id, idp, sizeof (struct ace_id));
|
||||
|
||||
/* The access in the acl entries must be left shifted by *
|
||||
@@ -1962,7 +1962,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
|
||||
DEBUG(10, ("acl_entry = %d\n", acl_entry));
|
||||
DEBUG(10, ("The ace_type is %d\n", acl_entry->ace_type));
|
||||
|
||||
|
||||
acl_entry = acl_nxt(acl_entry);
|
||||
}
|
||||
} /* end of if enabled */
|
||||
@@ -2014,12 +2014,12 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
|
||||
new_acl_entry->ace_access = file_acl->o_access << 6;
|
||||
idp->id_type = SMB_ACL_OTHER;
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
new_acl_entry->ace_access = file_acl->u_access << 6;
|
||||
idp->id_type = SMB_ACL_USER_OBJ;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
@@ -2048,7 +2048,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
int rc = 0;
|
||||
|
||||
/* Get the acl using fstatacl */
|
||||
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_get_fd\n"));
|
||||
DEBUG(10, ("fd is %d\n", fd));
|
||||
file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
|
||||
@@ -2095,12 +2095,12 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
|
||||
DEBUG(10, ("acl_entry is %d\n", acl_entry));
|
||||
DEBUG(10, ("acl_last(file_acl) id %d\n", acl_last(file_acl)));
|
||||
|
||||
|
||||
/* Check if the extended acl bit is on. *
|
||||
* If it isn't, do not show the *
|
||||
* contents of the acl since AIX intends *
|
||||
* the extended info to remain unused */
|
||||
|
||||
|
||||
if (file_acl->acl_mode & S_IXACL){
|
||||
/* while we are not pointing to the very end */
|
||||
while (acl_entry < acl_last(file_acl)) {
|
||||
@@ -2115,7 +2115,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
}
|
||||
|
||||
idp = acl_entry->ace_id;
|
||||
|
||||
|
||||
/* Check if this is the first entry in the linked list. *
|
||||
* The first entry needs to keep prevp pointing to NULL *
|
||||
* and already has entryp allocated. */
|
||||
@@ -2177,7 +2177,7 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
|
||||
DEBUG(10, ("acl_entry = %d\n", acl_entry));
|
||||
DEBUG(10, ("The ace_type is %d\n", acl_entry->ace_type));
|
||||
|
||||
|
||||
acl_entry = acl_nxt(acl_entry);
|
||||
}
|
||||
} /* end of if enabled */
|
||||
@@ -2210,43 +2210,43 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
}
|
||||
|
||||
acl_entry_link->nextp = NULL;
|
||||
|
||||
|
||||
new_acl_entry = acl_entry_link->entryp;
|
||||
idp = new_acl_entry->ace_id;
|
||||
|
||||
|
||||
new_acl_entry->ace_len = sizeof (struct acl_entry);
|
||||
new_acl_entry->ace_type = ACC_PERMIT;
|
||||
idp->id_len = sizeof (struct ace_id);
|
||||
DEBUG(10, ("idp->id_len = %d\n", idp->id_len));
|
||||
memset(idp->id_data, 0, sizeof (uid_t));
|
||||
|
||||
|
||||
switch (i) {
|
||||
case 2:
|
||||
new_acl_entry->ace_access = file_acl->g_access << 6;
|
||||
idp->id_type = SMB_ACL_GROUP_OBJ;
|
||||
break;
|
||||
|
||||
|
||||
case 3:
|
||||
new_acl_entry->ace_access = file_acl->o_access << 6;
|
||||
idp->id_type = SMB_ACL_OTHER;
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
new_acl_entry->ace_access = file_acl->u_access << 6;
|
||||
idp->id_type = SMB_ACL_USER_OBJ;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
acl_entry_link_head->count++;
|
||||
DEBUG(10, ("new_acl_entry->ace_access = %d\n", new_acl_entry->ace_access));
|
||||
}
|
||||
|
||||
acl_entry_link_head->count = 0;
|
||||
SAFE_FREE(file_acl);
|
||||
|
||||
|
||||
return acl_entry_link_head;
|
||||
}
|
||||
#endif
|
||||
@@ -2274,7 +2274,7 @@ int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *b
|
||||
SMB_ACL_T sys_acl_init(int count)
|
||||
{
|
||||
struct acl_entry_link *theacl = NULL;
|
||||
|
||||
|
||||
if (count < 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
@@ -2383,9 +2383,9 @@ int sys_acl_valid(SMB_ACL_T theacl)
|
||||
}
|
||||
|
||||
DEBUG(10, ("user_obj=%d, group_obj=%d, other_obj=%d\n", user_obj, group_obj, other_obj));
|
||||
|
||||
|
||||
if (user_obj != 1 || group_obj != 1 || other_obj != 1)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2404,7 +2404,7 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_set_file\n"));
|
||||
DEBUG(10, ("File name is %s\n", name));
|
||||
|
||||
|
||||
/* AIX has no default ACL */
|
||||
if (acltype == SMB_ACL_TYPE_DEFAULT)
|
||||
return 0;
|
||||
@@ -2449,7 +2449,7 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
|
||||
errno = ENOMEM;
|
||||
DEBUG(0, ("Error in sys_acl_set_file is %d\n", errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(file_acl_temp, file_acl, file_acl->acl_len);
|
||||
SAFE_FREE(file_acl);
|
||||
@@ -2460,15 +2460,15 @@ int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
|
||||
file_acl->acl_len += sizeof (struct acl_entry);
|
||||
acl_entry->ace_len = acl_entry_link->entryp->ace_len;
|
||||
acl_entry->ace_access = acl_entry_link->entryp->ace_access;
|
||||
|
||||
|
||||
/* In order to use this, we'll need to wait until we can get denies */
|
||||
/* if (!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
|
||||
acl_entry->ace_type = ACC_SPECIFY; */
|
||||
|
||||
acl_entry->ace_type = ACC_SPECIFY;
|
||||
|
||||
|
||||
ace_id = acl_entry->ace_id;
|
||||
|
||||
|
||||
ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
|
||||
DEBUG(10, ("The id type is %d\n", ace_id->id_type));
|
||||
ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
|
||||
@@ -2496,7 +2496,7 @@ int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
|
||||
uint user_id;
|
||||
uint acl_length;
|
||||
uint rc;
|
||||
|
||||
|
||||
DEBUG(10, ("Entering sys_acl_set_fd\n"));
|
||||
acl_length = BUFSIZ;
|
||||
file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
|
||||
@@ -2508,7 +2508,7 @@ int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
|
||||
}
|
||||
|
||||
memset(file_acl, 0, BUFSIZ);
|
||||
|
||||
|
||||
file_acl->acl_len = ACL_SIZ;
|
||||
file_acl->acl_mode = S_IXACL;
|
||||
|
||||
@@ -2550,22 +2550,22 @@ int sys_acl_set_fd(int fd, SMB_ACL_T theacl)
|
||||
file_acl->acl_len += sizeof (struct acl_entry);
|
||||
acl_entry->ace_len = acl_entry_link->entryp->ace_len;
|
||||
acl_entry->ace_access = acl_entry_link->entryp->ace_access;
|
||||
|
||||
|
||||
/* In order to use this, we'll need to wait until we can get denies */
|
||||
/* if (!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
|
||||
acl_entry->ace_type = ACC_SPECIFY; */
|
||||
|
||||
|
||||
acl_entry->ace_type = ACC_SPECIFY;
|
||||
|
||||
|
||||
ace_id = acl_entry->ace_id;
|
||||
|
||||
|
||||
ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
|
||||
DEBUG(10, ("The id type is %d\n", ace_id->id_type));
|
||||
ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
|
||||
memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof (uid_t));
|
||||
memcpy(ace_id->id_data, &user_id, sizeof (uid_t));
|
||||
}
|
||||
|
||||
|
||||
rc = fchacl(fd, file_acl, file_acl->acl_len);
|
||||
DEBUG(10, ("errno is %d\n", errno));
|
||||
DEBUG(10, ("return code is %d\n", rc));
|
||||
@@ -2594,7 +2594,7 @@ int sys_acl_free_acl(SMB_ACL_T posix_acl)
|
||||
SAFE_FREE(acl_entry_link->prevp);
|
||||
SAFE_FREE(acl_entry_link->entryp);
|
||||
SAFE_FREE(acl_entry_link);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Version 2.2.x
|
||||
* Portable SMB ACL interface
|
||||
* Copyright (C) Jeremy Allison 2000
|
||||
* Copyright (C) 2007-2020 Wayne Davison
|
||||
* Copyright (C) 2007-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
|
||||
@@ -232,7 +232,7 @@ struct new_acl_entry{
|
||||
|
||||
#define SMB_ACL_ENTRY_T struct new_acl_entry*
|
||||
#define SMB_ACL_T struct acl_entry_link*
|
||||
|
||||
|
||||
#define SMB_ACL_TAG_T unsigned short
|
||||
#define SMB_ACL_TYPE_T int
|
||||
|
||||
|
||||
6
main.c
6
main.c
@@ -104,7 +104,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;
|
||||
@@ -1076,6 +1076,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 +1501,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], daemon_connection);
|
||||
/* 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 +1526,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, daemon_connection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
|
||||
23
options.c
23
options.c
@@ -27,6 +27,8 @@
|
||||
extern int module_id;
|
||||
extern int local_server;
|
||||
extern int sanitize_paths;
|
||||
extern int trust_sender_args;
|
||||
extern int trust_sender_filter;
|
||||
extern unsigned int module_dirlen;
|
||||
extern filter_rule_list filter_list;
|
||||
extern filter_rule_list daemon_filter_list;
|
||||
@@ -64,6 +66,7 @@ int preserve_atimes = 0;
|
||||
int preserve_crtimes = 0;
|
||||
int omit_dir_times = 0;
|
||||
int omit_link_times = 0;
|
||||
int trust_sender = 0;
|
||||
int update_only = 0;
|
||||
int open_noatime = 0;
|
||||
int cvs_exclude = 0;
|
||||
@@ -293,7 +296,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"),
|
||||
@@ -788,6 +791,7 @@ static struct poptOption long_options[] = {
|
||||
{"protect-args", 's', POPT_ARG_VAL, &protect_args, 1, 0, 0},
|
||||
{"no-protect-args", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
|
||||
{"no-s", 0, POPT_ARG_VAL, &protect_args, 0, 0, 0},
|
||||
{"trust-sender", 0, POPT_ARG_VAL, &trust_sender, 1, 0, 0},
|
||||
{"numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 1, 0, 0 },
|
||||
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
|
||||
{"usermap", 0, POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 },
|
||||
@@ -2465,6 +2469,11 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
}
|
||||
}
|
||||
|
||||
if (trust_sender || am_server || read_batch)
|
||||
trust_sender_args = trust_sender_filter = 1;
|
||||
else if (old_style_args || filesfrom_host != NULL)
|
||||
trust_sender_args = 1;
|
||||
|
||||
am_starting_up = 0;
|
||||
|
||||
return 1;
|
||||
@@ -2492,12 +2501,17 @@ char *safe_arg(const char *opt, const char *arg)
|
||||
BOOL is_filename_arg = !opt;
|
||||
char *escapes = is_filename_arg ? SHELL_CHARS : WILD_CHARS SHELL_CHARS;
|
||||
BOOL escape_leading_dash = is_filename_arg && *arg == '-';
|
||||
BOOL escape_leading_tilde = 0;
|
||||
int len1 = opt && *opt ? strlen(opt) + 1 : 0;
|
||||
int len2 = strlen(arg);
|
||||
int extras = escape_leading_dash ? 2 : 0;
|
||||
char *ret;
|
||||
if (!protect_args && old_style_args < 2 && (!old_style_args || (!is_filename_arg && opt != SPLIT_ARG_WHEN_OLD))) {
|
||||
const char *f;
|
||||
if (!trust_sender_args && *arg == '~' && (relative_paths || !strchr(arg, '/'))) {
|
||||
extras++;
|
||||
escape_leading_tilde = 1;
|
||||
}
|
||||
for (f = arg; *f; f++) {
|
||||
if (strchr(escapes, *f))
|
||||
extras++;
|
||||
@@ -2520,8 +2534,13 @@ char *safe_arg(const char *opt, const char *arg)
|
||||
else {
|
||||
const char *f = arg;
|
||||
char *t = ret + len1;
|
||||
if (escape_leading_tilde)
|
||||
*t++ = '\\';
|
||||
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,6 +1,6 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.2.4
|
||||
Version: 3.2.5
|
||||
%define fullversion %{version}
|
||||
Release: 1
|
||||
%define srcdir src
|
||||
@@ -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.
|
||||
* Sun Aug 14 2022 Wayne Davison <wayne@opencoder.net>
|
||||
Released 3.2.5.
|
||||
|
||||
* 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)
|
||||
|
||||
683
rsync.1.md
683
rsync.1.md
@@ -154,6 +154,47 @@ 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
|
||||
|
||||
See the [`--trust-sender`](#opt) option for additional details.
|
||||
|
||||
## ADVANCED USAGE
|
||||
|
||||
The syntax for requesting multiple files from a remote host is done by
|
||||
@@ -164,20 +205,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 +315,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 +332,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
|
||||
|
||||
@@ -446,6 +465,7 @@ has its own detailed description later in this manpage.
|
||||
--from0, -0 all *-from/filter files are delimited by 0s
|
||||
--old-args disable the modern arg-protection idiom
|
||||
--protect-args, -s no space-splitting; wildcard chars only
|
||||
--trust-sender trust the remote sender's file list
|
||||
--copy-as=USER[:GROUP] specify user & optional group for the copy
|
||||
--address=ADDRESS bind address for outgoing socket to daemon
|
||||
--port=PORT specify double-colon alternate port number
|
||||
@@ -508,14 +528,22 @@ 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 local 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 +821,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 +976,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 +1196,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 +1505,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 +1760,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 +1769,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 +1899,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 saves you from having to edit a bunch of
|
||||
`-f'- foo'` rules into `-f'-s foo'` (aka `-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 +1978,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 +2236,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 +2248,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 +2272,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 +2373,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`
|
||||
@@ -2356,6 +2412,42 @@ your home directory (remove the '=' for that).
|
||||
Note that this option is incompatible with the use of the restricted rsync
|
||||
script (`rrsync`) since it hides options from the script's inspection.
|
||||
|
||||
0. `--trust-sender`
|
||||
|
||||
This option disables two extra validation checks that a local client
|
||||
performs on the file list generated by a remote sender. This option should
|
||||
only be used if you trust the sender to not put something malicious in the
|
||||
file list (something that could possibly be done via a modified rsync, a
|
||||
modified shell, or some other similar manipulation).
|
||||
|
||||
Normally, the rsync client (as of version 3.2.5) runs two extra validation
|
||||
checks when pulling files from a remote rsync:
|
||||
|
||||
- It verifies that additional arg items didn't get added at the top of the
|
||||
transfer.
|
||||
- It verifies that none of the items in the file list are names that should
|
||||
have been excluded (if filter rules were specified).
|
||||
|
||||
Note that various options can turn off one or both of these checks if the
|
||||
option interferes with the validation. For instance:
|
||||
|
||||
- Using a per-directory filter file reads filter rules that only the server
|
||||
knows about, so the filter checking is disabled.
|
||||
- Using the [`--old-args`](#opt) option allows the sender to manipulate the
|
||||
requested args, so the arg checking is disabled.
|
||||
- Reading the files-from list from the server side means that the client
|
||||
doesn't know the arg list, so the arg checking is disabled.
|
||||
- Using [`--read-batch`](#opt) disables both checks since the batch file's
|
||||
contents will have been verified when it was created.
|
||||
|
||||
This option may help an under-powered client server if the extra pattern
|
||||
matching is slowing things down on a huge transfer. It can also be used to
|
||||
work around a currently-unknown bug in the verification logic for a transfer
|
||||
from a trusted sender.
|
||||
|
||||
When using this option it is a good idea to specify a dedicated destination
|
||||
directory, as discussed in the [MULTI-HOST SECURITY](#) section.
|
||||
|
||||
0. `--copy-as=USER[:GROUP]`
|
||||
|
||||
This option instructs rsync to use the USER and (if specified after a
|
||||
@@ -3017,7 +3109,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 +3347,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
|
||||
@@ -3394,8 +3484,8 @@ your home directory (remove the '=' for that).
|
||||
include the destination.
|
||||
|
||||
CAUTION: keep in mind that a source arg with a wild-card is expanded by the
|
||||
shell into multiple args, so it is never safe to try to list such an arg
|
||||
without using this option. For example:
|
||||
shell into multiple args, so it is never safe to try to specify a single
|
||||
wild-card arg to try to infer this option. A safe example is:
|
||||
|
||||
> rsync -av --list-only foo* dest/
|
||||
|
||||
@@ -3721,27 +3811,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 was 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 +3958,36 @@ 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 underscores 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, so
|
||||
it has the side-effect mentioned under the [`--trust-sender`](#opt) option.
|
||||
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 +3995,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 (non-trailing) `/` 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 (if foo is in the transfer)
|
||||
- Option `-f'- /foo/**/bar'` would exclude any file/dir named bar that was two
|
||||
or more levels below a top-level directory named foo (note that /foo/bar is
|
||||
**not** excluded by this)
|
||||
- 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 +4094,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 +4228,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 +4236,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 +4291,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 +4337,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 +4677,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
|
||||
|
||||
2
rsync.c
2
rsync.c
@@ -642,7 +642,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
#ifdef SUPPORT_ACLS
|
||||
/* It's OK to call set_acl() now, even for a dir, as the generator
|
||||
* will enable owner-writability using chmod, if necessary.
|
||||
*
|
||||
*
|
||||
* If set_acl() changes permission bits in the process of setting
|
||||
* an access ACL, it changes sxp->st.st_mode so we know whether we
|
||||
* need to chmod(). */
|
||||
|
||||
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;
|
||||
|
||||
2
usage.c
2
usage.c
@@ -195,6 +195,8 @@ void print_rsync_version(enum logcode f)
|
||||
|
||||
print_info_flags(f);
|
||||
|
||||
init_checksum_choices();
|
||||
|
||||
rprintf(f, "Checksum list:\n");
|
||||
get_default_nno_list(&valid_checksums, tmpbuf, sizeof tmpbuf, '(');
|
||||
rprintf(f, " %s\n", tmpbuf);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
#define RSYNC_VERSION "3.2.4"
|
||||
#define RSYNC_VERSION "3.2.5"
|
||||
#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