mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40afd365cc | ||
|
|
d702b97838 | ||
|
|
53a46d9e09 | ||
|
|
510c5ab7ff | ||
|
|
033697d96d | ||
|
|
abc796661d | ||
|
|
998df4b0c0 | ||
|
|
675f864c6d | ||
|
|
dbd58bb2d0 | ||
|
|
a5ef696953 | ||
|
|
ae6dea711d | ||
|
|
5a9933c85c | ||
|
|
b91ab5f9c8 | ||
|
|
5340571ab6 | ||
|
|
e7dd0e5004 | ||
|
|
5822f988f5 | ||
|
|
881455f7b2 | ||
|
|
fe2c165fca | ||
|
|
4c0055ecbb | ||
|
|
d706e888fc | ||
|
|
c0d07c0987 | ||
|
|
606c603943 | ||
|
|
5fed6c076a | ||
|
|
30fb28cc97 | ||
|
|
3a2495cb22 | ||
|
|
1916a7a2a6 | ||
|
|
121082fa9b | ||
|
|
c6bed2d9ee | ||
|
|
ecae885a51 | ||
|
|
f350413814 | ||
|
|
93bdc6478e | ||
|
|
2d07fa6350 | ||
|
|
33e37a49ba | ||
|
|
5782ac04d7 | ||
|
|
fc41c32159 | ||
|
|
365124a214 | ||
|
|
dbf68ca4c1 | ||
|
|
ba35ba06c9 | ||
|
|
0b519262c6 | ||
|
|
3ef38b0d1b | ||
|
|
5a1d092ae1 | ||
|
|
1ddcdaf3f6 | ||
|
|
93562b1941 | ||
|
|
959bd70820 | ||
|
|
a7271fb30f | ||
|
|
277036153a | ||
|
|
bc6363f9ab | ||
|
|
e71130fd77 | ||
|
|
38c9f1becf | ||
|
|
779663fc6c | ||
|
|
9562cc8925 | ||
|
|
a945aa19d9 | ||
|
|
2a1d251750 | ||
|
|
8750f64ec7 | ||
|
|
922895d9a3 | ||
|
|
72193c82a6 | ||
|
|
b178eb04d3 | ||
|
|
3158b8df6c | ||
|
|
aa3640c09b | ||
|
|
07b5c770db | ||
|
|
8b7f20b6d3 | ||
|
|
1dabd5dc9a | ||
|
|
58d657c98f | ||
|
|
e46262f36d | ||
|
|
4d92246a54 | ||
|
|
8f48ba03b5 | ||
|
|
eb8058577d | ||
|
|
3c624bba85 | ||
|
|
24e76f840e | ||
|
|
b62ea517f6 | ||
|
|
a6b3c2b512 | ||
|
|
4e95f91f27 | ||
|
|
fad4ab9d0b | ||
|
|
f91b15fbd6 | ||
|
|
83b94efa6b | ||
|
|
2064c28d6d | ||
|
|
c499002e51 | ||
|
|
c8255147b0 | ||
|
|
eee85e3c36 | ||
|
|
0c0219fe84 | ||
|
|
a92edcbf5c | ||
|
|
17549c95de | ||
|
|
9d6fe1a6f0 | ||
|
|
c43624c575 | ||
|
|
4baef8d663 | ||
|
|
c3ee6ac369 | ||
|
|
63c5ac38a2 | ||
|
|
ce41e68995 | ||
|
|
8538db7829 | ||
|
|
559bd2ff31 | ||
|
|
485a40318c | ||
|
|
ede8cae34b | ||
|
|
58ab32037d | ||
|
|
00cde6582c | ||
|
|
e6ba6e1107 | ||
|
|
efad2e85ea | ||
|
|
c463617443 | ||
|
|
6abb59adf6 | ||
|
|
d79bc5c791 | ||
|
|
10cd07c225 | ||
|
|
62e9eb7bc2 | ||
|
|
de20d72541 | ||
|
|
f8cd1c4730 | ||
|
|
5de3fe19b6 | ||
|
|
0ac2d243bf | ||
|
|
14556a30b3 | ||
|
|
8c1f2d53ec | ||
|
|
f532cede11 | ||
|
|
05022e00a2 | ||
|
|
24a743b565 | ||
|
|
e36f5c9f6c | ||
|
|
c9c3215698 | ||
|
|
dbfde9e50a | ||
|
|
1cdb5e1c86 | ||
|
|
24afdc500a | ||
|
|
303759b803 | ||
|
|
a699f7c6af | ||
|
|
a250fa251b | ||
|
|
e44aa644c2 | ||
|
|
ef67c238b5 | ||
|
|
111599be2b | ||
|
|
8e918e1861 | ||
|
|
0874fc4872 | ||
|
|
55dbbdeafe | ||
|
|
cbd27d5e18 | ||
|
|
178ccdde7d | ||
|
|
e51bb8f330 | ||
|
|
6d9207bd38 | ||
|
|
6b87566744 | ||
|
|
b384d71e53 | ||
|
|
11f4f34ed9 | ||
|
|
fe2c582af8 | ||
|
|
2ecd8b7cd2 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,4 +38,5 @@ config.status
|
||||
/support/savetransfer
|
||||
/testsuite/chown-fake.test
|
||||
/testsuite/devices-fake.test
|
||||
/testsuite/xattrs-hlink.test
|
||||
/patches
|
||||
|
||||
13
INSTALL
13
INSTALL
@@ -17,7 +17,7 @@ for the daemon by editing the NOBODY_USER and NOBODY_GROUP defines in
|
||||
config.h, or just override them in your /etc/rsyncd.conf file.
|
||||
|
||||
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
|
||||
cut-down copy of release 1.6.4 is included in the rsync distribution,
|
||||
cut-down copy of a recent release is included in the rsync distribution,
|
||||
and will be used if there is no popt library on your build host, or if
|
||||
the --with-included-popt option is passed to ./configure.
|
||||
|
||||
@@ -25,6 +25,17 @@ If you configure using --enable-maintainer-mode, then rsync will try
|
||||
to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
|
||||
useful, but it should be turned off for production builds.
|
||||
|
||||
MAKE COMPATIBILITY
|
||||
------------------
|
||||
|
||||
Note that Makefile.in has a rule that uses a wildcard in a prerequisite. If
|
||||
your make has a problem with this rule, you will see an error like this:
|
||||
|
||||
Don't know how to make ./*.c
|
||||
|
||||
You can change the "proto.h-tstamp" target in Makefile.in to list all the *.c
|
||||
filenames explicitly in order to avoid this issue.
|
||||
|
||||
RPM NOTES
|
||||
---------
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxa
|
||||
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
|
||||
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
|
||||
|
||||
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
|
||||
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test testsuite/xattrs-hlink.test
|
||||
|
||||
# Objects for CHECK_PROGS to clean
|
||||
CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
@@ -123,7 +123,7 @@ gensend: gen
|
||||
conf:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
|
||||
|
||||
configure.sh config.h.in: configure.in aclocal.m4
|
||||
configure.sh config.h.in: configure.ac aclocal.m4
|
||||
@if test -f configure.sh; then cp -p configure.sh configure.sh.old; else touch configure.sh.old; fi
|
||||
@if test -f config.h.in; then cp -p config.h.in config.h.in.old; else touch config.h.in.old; fi
|
||||
autoconf -o configure.sh
|
||||
@@ -249,6 +249,9 @@ testsuite/chown-fake.test:
|
||||
testsuite/devices-fake.test:
|
||||
ln -s devices.test $(srcdir)/testsuite/devices-fake.test
|
||||
|
||||
testsuite/xattrs-hlink.test:
|
||||
ln -s xattrs.test $(srcdir)/testsuite/xattrs-hlink.test
|
||||
|
||||
# This does *not* depend on building or installing: you can use it to
|
||||
# check a version installed from a binary or some other source tree,
|
||||
# if you want.
|
||||
|
||||
70
NEWS
70
NEWS
@@ -1,64 +1,56 @@
|
||||
NEWS for rsync 3.0.7 (31 Dec 2009)
|
||||
NEWS for rsync 3.0.9 (23 Sep 2011)
|
||||
Protocol: 30 (unchanged)
|
||||
Changes since 3.0.6:
|
||||
Changes since 3.0.8:
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fixed a bogus free when using --xattrs with --backup.
|
||||
- Fix a crash bug in checksum scanning when --inplace is used.
|
||||
|
||||
- Avoid an error when --dry-run was trying to stat a prior hard-link file
|
||||
that hasn't really been created.
|
||||
- Fix a hang if a hard-linked file cannot be opened by the sender (e.g.
|
||||
if it has no read permission).
|
||||
|
||||
- Fixed a problem with --compress (-z) where the receiving side could
|
||||
return the error "inflate (token) returned -5".
|
||||
- Fix preservation of a symlink's system xattrs (e.g. selinux) on Linux.
|
||||
|
||||
- Fixed a bug where --delete-during could delete in a directory before it
|
||||
noticed that the sending side sent an I/O error for that directory (both
|
||||
sides of the transfer must be at least 3.0.7).
|
||||
- Fix a memory leak in the xattr code.
|
||||
|
||||
- Improved --skip-compress's error handling of bad character-sets and got
|
||||
rid of a lingering debug fprintf().
|
||||
- Fixed a bug with --delete-excluded when a filter merge file has a rule
|
||||
that specifies a receiver-only side restriction.
|
||||
|
||||
- Fixed the daemon's conveyance of io_error value from the sender.
|
||||
- Fix a bug with the modifying of unwritable directories.
|
||||
|
||||
- An rsync daemon use seteuid() (when available) if it used setuid().
|
||||
- Fix --fake-super's interaction with --link-dest same-file comparisons.
|
||||
|
||||
- Get the permissions right on a --fake-super transferred directory that
|
||||
needs more owner permissions to emulate root behavior.
|
||||
- Fix the updating of the curr_dir buffer to avoid a duplicate slash.
|
||||
|
||||
- An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
|
||||
its modifier when sending the filter rules to the remote rsync.
|
||||
- Fix the directory permissions on an implied dot-dir when using --relative
|
||||
(e.g. /outside/path/././send/path).
|
||||
|
||||
- Improved the "--delete does not work without -r or -d" message.
|
||||
- Fixed some too-long sleeping instances when using --bwlimit.
|
||||
|
||||
- Improved rsync's handling of --timeout to avoid a weird timeout case
|
||||
where the sender could timeout even though it has recently written data
|
||||
to the socket (but hasn't read data recently, due to the writing).
|
||||
- Fixed when symlink ownership difference-checking gets compiled into
|
||||
unchanged_attrs().
|
||||
|
||||
- Some misc manpage improvements.
|
||||
- Improved the socket-error reporting when multiple protocols fail.
|
||||
|
||||
- Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
|
||||
- Fixed a case where a socket error could reference just-freed memory.
|
||||
|
||||
- Make sure that a timeout specified in the daemon's config is used as a
|
||||
maximum timeout value when the user also specifies a timeout.
|
||||
- Failing to use a password file that was specified on the command-line is
|
||||
now a fatal error.
|
||||
|
||||
- Improved the error-exit reporting when rsync gets an error trying to
|
||||
cleanup after an error: the initial error is reported.
|
||||
- Fix the non-root updating of directories that don't have the read and/or
|
||||
execute permission.
|
||||
|
||||
- Improved configure's detection of IPv6 for solaris and cygwin.
|
||||
- Make daemon-excluded file errors more error-like.
|
||||
|
||||
- The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
|
||||
- Fix a compilation issue on older C compilers (due to a misplaced var
|
||||
declaration).
|
||||
|
||||
- Made our (only used if missing) getaddrinfo() routine use inet_pton()
|
||||
(which we also provide) instead of inet_aton().
|
||||
- Make configure avoid finding socketpair on cygwin.
|
||||
|
||||
- The exit-related debug messages now mention the program's role so it is
|
||||
clear who output what message.
|
||||
- Avoid trying to reference SO_BROADCAST if the OS doesn't support it.
|
||||
|
||||
DEVELOPER RELATED:
|
||||
- Fix some issues with the post-processing of the man pages.
|
||||
|
||||
- Got rid of type-punned compiler warnings output by newer gcc versions.
|
||||
- Fixed the user home-dir handling in the support/lsh script.
|
||||
|
||||
- The Makefile now ensures that proto.h will be rebuilt if config.h changes.
|
||||
|
||||
- The testsuite no longer uses "id -u", so it works better on solaris.
|
||||
- Some minor manpage improvements.
|
||||
|
||||
209
OLDNEWS
209
OLDNEWS
@@ -1,3 +1,209 @@
|
||||
NEWS for rsync 3.0.8 (26 Mar 2011)
|
||||
Protocol: 30 (unchanged)
|
||||
Changes since 3.0.7:
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fixed two buffer-overflow issues: one where a directory path that is
|
||||
exactly MAXPATHLEN was not handled correctly, and one handling a
|
||||
--backup-dir that is extra extra large.
|
||||
|
||||
- Fixed a data-corruption issue when preserving hard-links without
|
||||
preserving file ownership, and doing deletions either before or during
|
||||
the transfer (CVE-2011-1097). This fixes some assert errors in the
|
||||
hard-linking code, and some potential failed checksums (via -c) that
|
||||
should have matched.
|
||||
|
||||
- Fixed a potential crash when an rsync daemon has a filter/exclude list
|
||||
and the transfer is using ACLs or xattrs.
|
||||
|
||||
- Fixed a hang if a really large file is being processed by an rsync that
|
||||
can't handle 64-bit numbers. Rsync will now complain about the file
|
||||
being too big and skip it.
|
||||
|
||||
- For devices and special files, we now avoid gathering useless ACL and/or
|
||||
xattr information for files that aren't being copied. (The un-copied
|
||||
files are still put into the file list, but there's no need to gather
|
||||
data that is not going to be used.) This ensures that if the user uses
|
||||
--no-D, that rsync can't possibly complain about being unable to gather
|
||||
extended information from special files that are in the file list (but
|
||||
not in the transfer).
|
||||
|
||||
- Properly handle requesting remote filenames that start with a dash. This
|
||||
avoids a potential error where a filename could be interpreted as a
|
||||
(usually invalid) option.
|
||||
|
||||
- Fixed a bug in the comparing of upper-case letters in file suffixes for
|
||||
--skip-compress.
|
||||
|
||||
- If an rsync daemon has a module configured without a path setting, rsync
|
||||
will now disallow access to that module.
|
||||
|
||||
- If the destination arg is an empty string, it will be treated as a
|
||||
reference to the current directory (as 2.x used to do).
|
||||
|
||||
- If rsync was compiled with a newer time-setting function (such as
|
||||
lutimes), rsync will fall-back to an older function (such as utimes) on a
|
||||
system where the newer function is not around. This helps to make the
|
||||
rsync binary more portable in mixed-OS-release situations.
|
||||
|
||||
- Fixed a batch-file writing bug that would not write out the full set of
|
||||
compatibility flags that the transfer was using. This fixes a potential
|
||||
protocol problem for a batch file that contains a sender-side I/O error:
|
||||
it would have been sent in a way that the batch-reader wasn't expecting.
|
||||
|
||||
- Some improvements to the hard-linking code to ensure that device-number
|
||||
hashing is working right, and to supply more information if the hard-link
|
||||
code fails.
|
||||
|
||||
- The --inplace code was improved to not search for an impossible checksum
|
||||
position. The quadruple-verbose chunk[N] message will now mention when
|
||||
an inplace chunk was handled by a seek rather than a read+write.
|
||||
|
||||
- Improved ACL mask handling, e.g. for Solaris.
|
||||
|
||||
- Fixed a bug that prevented --numeric-ids from disabling the translation
|
||||
of user/group IDs for ACLs.
|
||||
|
||||
- Fixed an issue where an xattr and/or ACL transfer that used an alt-dest
|
||||
option (e.g. --link-dest) could output an error trying to itemize the
|
||||
changes against the alt-dest directory's xattr/ACL info but was instead
|
||||
trying to access the not-yet-existing new destination directory.
|
||||
|
||||
- Improved xattr system-error messages to mention the full path to the
|
||||
file.
|
||||
|
||||
- The --link-dest checking for identical symlinks now avoids considering
|
||||
attribute differences that cannot be changed on the receiver.
|
||||
|
||||
- Avoid trying to read/write xattrs on certain file types for certain OSes.
|
||||
Improved configure to set NO_SYMLINK_XATTRS, NO_DEVICE_XATTRS, and/or
|
||||
NO_SPECIAL_XATTRS defines in config.h.
|
||||
|
||||
- Improved the unsafe-symlink errors messages.
|
||||
|
||||
- Fixed a bug setting xattrs on new files that aren't user writable.
|
||||
|
||||
- Avoid re-setting xattrs on a hard-linked file w/the same xattrs.
|
||||
|
||||
- Fixed a bug with --fake-super when copying files and dirs that aren't
|
||||
user writable.
|
||||
|
||||
- Fixed a bug where a sparse file could have its last sparse block turned
|
||||
into a real block when rsync sets the file size (requires ftruncate).
|
||||
|
||||
- If a temp-file name is too long, rsync now avoids truncating the name in
|
||||
the middle of adjacent high-bit characters. This prevents a potential
|
||||
filename error if the filesystem doesn't allow a name to contain an
|
||||
invalid multi-byte sequence.
|
||||
|
||||
- If a muli-protocol socket connection fails (i.e., when contacting a
|
||||
daemon), we now report all the failures, not just the last one. This
|
||||
avoids losing a relevant error (e.g. an IPv4 connection-refused error)
|
||||
that happened before the final error (e.g. an IPv6 protocol-not-supported
|
||||
error).
|
||||
|
||||
- Generate a transfer error if we try to call chown with a -1 for a uid or
|
||||
a gid (which is not settable).
|
||||
|
||||
- Fixed the working of --force when used with --one-file-system.
|
||||
|
||||
- Fix the popt arg parsing so that an option that doesn't take an arg will
|
||||
reject an attempt to supply one (can configure --with-included-popt if
|
||||
your system's popt library doesn't yet have this fix).
|
||||
|
||||
- A couple minor option tweaks to the support/rrsync script, and also some
|
||||
regex changes that make vim highlighting happier.
|
||||
|
||||
- Fixed some issues in the support/mnt-excl script.
|
||||
|
||||
- Various manpage improvements.
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Added ".hg/" to the default cvs excludes (see -C & --cvs-exclude).
|
||||
|
||||
DEVELOPER RELATED:
|
||||
|
||||
- Use lchmod() whenever it is available (not just on symlinks).
|
||||
|
||||
- A couple fixes to the socketpair_tcp() routine.
|
||||
|
||||
- Updated the helper scripts in the packaging subdirectory.
|
||||
|
||||
- Renamed configure.in to configure.ac.
|
||||
|
||||
- Fixed configure's checking for iconv routines for newer OS X versions.
|
||||
|
||||
- Fixed the testsuite/xattrs.test script on OS X.
|
||||
|
||||
|
||||
NEWS for rsync 3.0.7 (31 Dec 2009)
|
||||
Protocol: 30 (unchanged)
|
||||
Changes since 3.0.6:
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fixed a bogus free when using --xattrs with --backup.
|
||||
|
||||
- Avoid an error when --dry-run was trying to stat a prior hard-link file
|
||||
that hasn't really been created.
|
||||
|
||||
- Fixed a problem with --compress (-z) where the receiving side could
|
||||
return the error "inflate (token) returned -5".
|
||||
|
||||
- Fixed a bug where --delete-during could delete in a directory before it
|
||||
noticed that the sending side sent an I/O error for that directory (both
|
||||
sides of the transfer must be at least 3.0.7).
|
||||
|
||||
- Improved --skip-compress's error handling of bad character-sets and got
|
||||
rid of a lingering debug fprintf().
|
||||
|
||||
- Fixed the daemon's conveyance of io_error value from the sender.
|
||||
|
||||
- An rsync daemon use seteuid() (when available) if it used setuid().
|
||||
|
||||
- Get the permissions right on a --fake-super transferred directory that
|
||||
needs more owner permissions to emulate root behavior.
|
||||
|
||||
- An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
|
||||
its modifier when sending the filter rules to the remote rsync.
|
||||
|
||||
- Improved the "--delete does not work without -r or -d" message.
|
||||
|
||||
- Improved rsync's handling of --timeout to avoid a weird timeout case
|
||||
where the sender could timeout even though it has recently written data
|
||||
to the socket (but hasn't read data recently, due to the writing).
|
||||
|
||||
- Some misc manpage improvements.
|
||||
|
||||
- Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
|
||||
|
||||
- Make sure that a timeout specified in the daemon's config is used as a
|
||||
maximum timeout value when the user also specifies a timeout.
|
||||
|
||||
- Improved the error-exit reporting when rsync gets an error trying to
|
||||
cleanup after an error: the initial error is reported.
|
||||
|
||||
- Improved configure's detection of IPv6 for solaris and cygwin.
|
||||
|
||||
- The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
|
||||
|
||||
- Made our (only used if missing) getaddrinfo() routine use inet_pton()
|
||||
(which we also provide) instead of inet_aton().
|
||||
|
||||
- The exit-related debug messages now mention the program's role so it is
|
||||
clear who output what message.
|
||||
|
||||
DEVELOPER RELATED:
|
||||
|
||||
- Got rid of type-punned compiler warnings output by newer gcc versions.
|
||||
|
||||
- The Makefile now ensures that proto.h will be rebuilt if config.h changes.
|
||||
|
||||
- The testsuite no longer uses "id -u", so it works better on solaris.
|
||||
|
||||
|
||||
NEWS for rsync 3.0.6 (8 May 2009)
|
||||
Protocol: 30 (unchanged)
|
||||
Changes since 3.0.5:
|
||||
@@ -3025,9 +3231,12 @@ Changes since 2.4.6:
|
||||
* The existing test.sh script by Phil Hands has been merged into a
|
||||
test framework that works from both "make check" and the Samba
|
||||
build farm.
|
||||
|
||||
|
||||
Partial Protocol History
|
||||
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
|
||||
23 Sep 2011 3.0.9 30
|
||||
26 Mar 2011 3.0.8 30
|
||||
31 Dec 2009 3.0.7 30
|
||||
08 May 2009 3.0.6 30
|
||||
28 Dec 2008 3.0.5 30
|
||||
|
||||
152
acls.c
152
acls.c
@@ -31,6 +31,8 @@ extern int list_only;
|
||||
extern int orig_umask;
|
||||
extern int numeric_ids;
|
||||
extern int inc_recurse;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_specials;
|
||||
|
||||
/* Flags used to indicate what items are being transmitted for an entry. */
|
||||
#define XMIT_USER_OBJ (1<<0)
|
||||
@@ -115,10 +117,11 @@ static int calc_sacl_entries(const rsync_acl *racl)
|
||||
/* A System ACL always gets user/group/other permission entries. */
|
||||
return racl->names.count
|
||||
#ifdef ACLS_NEED_MASK
|
||||
+ 4;
|
||||
+ 1
|
||||
#else
|
||||
+ (racl->mask_obj != NO_ENTRY) + 3;
|
||||
+ (racl->mask_obj != NO_ENTRY)
|
||||
#endif
|
||||
+ 3;
|
||||
}
|
||||
|
||||
/* Extracts and returns the permission bits from the ACL. This cannot be
|
||||
@@ -132,16 +135,21 @@ static int rsync_acl_get_perms(const rsync_acl *racl)
|
||||
|
||||
/* Removes the permission-bit entries from the ACL because these
|
||||
* can be reconstructed from the file's mode. */
|
||||
static void rsync_acl_strip_perms(rsync_acl *racl)
|
||||
static void rsync_acl_strip_perms(stat_x *sxp)
|
||||
{
|
||||
rsync_acl *racl = sxp->acc_acl;
|
||||
|
||||
racl->user_obj = NO_ENTRY;
|
||||
if (racl->mask_obj == NO_ENTRY)
|
||||
racl->group_obj = NO_ENTRY;
|
||||
else {
|
||||
if (racl->group_obj == racl->mask_obj)
|
||||
int group_perms = (sxp->st.st_mode >> 3) & 7;
|
||||
if (racl->group_obj == group_perms)
|
||||
racl->group_obj = NO_ENTRY;
|
||||
if (racl->names.count != 0)
|
||||
#ifndef HAVE_SOLARIS_ACLS
|
||||
if (racl->names.count != 0 && racl->mask_obj == group_perms)
|
||||
racl->mask_obj = NO_ENTRY;
|
||||
#endif
|
||||
}
|
||||
racl->other_obj = NO_ENTRY;
|
||||
}
|
||||
@@ -340,15 +348,6 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
|
||||
/* Truncate the temporary list now that its idas have been saved. */
|
||||
temp_ida_list.count = 0;
|
||||
|
||||
#ifdef ACLS_NEED_MASK
|
||||
if (!racl->names.count && racl->mask_obj != NO_ENTRY) {
|
||||
/* Throw away a superfluous mask, but mask off the
|
||||
* group perms with it first. */
|
||||
racl->group_obj &= racl->mask_obj;
|
||||
racl->mask_obj = NO_ENTRY;
|
||||
}
|
||||
#endif
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
@@ -496,9 +495,15 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
}
|
||||
|
||||
racl->user_obj = IVAL(buf, 0);
|
||||
if (racl->user_obj == NO_ENTRY)
|
||||
racl->user_obj = (mode >> 6) & 7;
|
||||
racl->group_obj = IVAL(buf, 4);
|
||||
if (racl->group_obj == NO_ENTRY)
|
||||
racl->group_obj = (mode >> 3) & 7;
|
||||
racl->mask_obj = IVAL(buf, 8);
|
||||
racl->other_obj = IVAL(buf, 12);
|
||||
if (racl->other_obj == NO_ENTRY)
|
||||
racl->other_obj = mode & 7;
|
||||
|
||||
if (cnt) {
|
||||
char *bp = buf + 4*4;
|
||||
@@ -540,6 +545,23 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
int get_acl(const char *fname, stat_x *sxp)
|
||||
{
|
||||
sxp->acc_acl = create_racl();
|
||||
|
||||
if (S_ISREG(sxp->st.st_mode) || S_ISDIR(sxp->st.st_mode)) {
|
||||
/* Everyone supports this. */
|
||||
} else if (S_ISLNK(sxp->st.st_mode)) {
|
||||
return 0;
|
||||
} else if (IS_SPECIAL(sxp->st.st_mode)) {
|
||||
#ifndef NO_SPECIAL_ACLS
|
||||
if (!preserve_specials)
|
||||
#endif
|
||||
return 0;
|
||||
} else if (IS_DEVICE(sxp->st.st_mode)) {
|
||||
#ifndef NO_DEVICE_ACLS
|
||||
if (!preserve_devices)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (get_rsync_acl(fname, sxp->acc_acl, SMB_ACL_TYPE_ACCESS,
|
||||
sxp->st.st_mode) < 0) {
|
||||
free_acl(sxp);
|
||||
@@ -561,7 +583,7 @@ int get_acl(const char *fname, stat_x *sxp)
|
||||
/* === Send functions === */
|
||||
|
||||
/* Send the ida list over the file descriptor. */
|
||||
static void send_ida_entries(const ida_entries *idal, int f)
|
||||
static void send_ida_entries(int f, const ida_entries *idal)
|
||||
{
|
||||
id_access *ida;
|
||||
size_t count = idal->count;
|
||||
@@ -573,9 +595,9 @@ static void send_ida_entries(const ida_entries *idal, int f)
|
||||
const char *name;
|
||||
if (ida->access & NAME_IS_USER) {
|
||||
xbits |= XFLAG_NAME_IS_USER;
|
||||
name = add_uid(ida->id);
|
||||
name = numeric_ids ? NULL : add_uid(ida->id);
|
||||
} else
|
||||
name = add_gid(ida->id);
|
||||
name = numeric_ids ? NULL : add_gid(ida->id);
|
||||
write_varint(f, ida->id);
|
||||
if (inc_recurse && name) {
|
||||
int len = strlen(name);
|
||||
@@ -587,8 +609,8 @@ static void send_ida_entries(const ida_entries *idal, int f)
|
||||
}
|
||||
}
|
||||
|
||||
static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
|
||||
item_list *racl_list, int f)
|
||||
static void send_rsync_acl(int f, rsync_acl *racl, SMB_ACL_TYPE_T type,
|
||||
item_list *racl_list)
|
||||
{
|
||||
int ndx = find_matching_rsync_acl(racl, type, racl_list);
|
||||
|
||||
@@ -621,7 +643,7 @@ static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
|
||||
if (flags & XMIT_OTHER_OBJ)
|
||||
write_varint(f, racl->other_obj);
|
||||
if (flags & XMIT_NAME_LIST)
|
||||
send_ida_entries(&racl->names, f);
|
||||
send_ida_entries(f, &racl->names);
|
||||
|
||||
/* Give the allocated data to the new list object. */
|
||||
*new_racl = *racl;
|
||||
@@ -631,28 +653,28 @@ static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
|
||||
|
||||
/* Send the ACL from the stat_x structure down the indicated file descriptor.
|
||||
* This also frees the ACL data. */
|
||||
void send_acl(stat_x *sxp, int f)
|
||||
void send_acl(int f, stat_x *sxp)
|
||||
{
|
||||
if (!sxp->acc_acl) {
|
||||
sxp->acc_acl = create_racl();
|
||||
rsync_acl_fake_perms(sxp->acc_acl, sxp->st.st_mode);
|
||||
}
|
||||
/* Avoid sending values that can be inferred from other data. */
|
||||
rsync_acl_strip_perms(sxp->acc_acl);
|
||||
rsync_acl_strip_perms(sxp);
|
||||
|
||||
send_rsync_acl(sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list, f);
|
||||
send_rsync_acl(f, sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list);
|
||||
|
||||
if (S_ISDIR(sxp->st.st_mode)) {
|
||||
if (!sxp->def_acl)
|
||||
sxp->def_acl = create_racl();
|
||||
|
||||
send_rsync_acl(sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list, f);
|
||||
send_rsync_acl(f, sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list);
|
||||
}
|
||||
}
|
||||
|
||||
/* === Receive functions === */
|
||||
|
||||
static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
|
||||
static uint32 recv_acl_access(int f, uchar *name_follows_ptr)
|
||||
{
|
||||
uint32 access = read_varint(f);
|
||||
|
||||
@@ -677,7 +699,7 @@ static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
|
||||
return access;
|
||||
}
|
||||
|
||||
static uchar recv_ida_entries(ida_entries *ent, int f)
|
||||
static uchar recv_ida_entries(int f, ida_entries *ent)
|
||||
{
|
||||
uchar computed_mask_bits = 0;
|
||||
int i, count = read_varint(f);
|
||||
@@ -693,7 +715,7 @@ static uchar recv_ida_entries(ida_entries *ent, int f)
|
||||
for (i = 0; i < count; i++) {
|
||||
uchar has_name;
|
||||
id_t id = read_varint(f);
|
||||
uint32 access = recv_acl_access(&has_name, f);
|
||||
uint32 access = recv_acl_access(f, &has_name);
|
||||
|
||||
if (has_name) {
|
||||
if (access & NAME_IS_USER)
|
||||
@@ -716,7 +738,7 @@ static uchar recv_ida_entries(ida_entries *ent, int f)
|
||||
return computed_mask_bits & ~NO_ENTRY;
|
||||
}
|
||||
|
||||
static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
|
||||
static int recv_rsync_acl(int f, item_list *racl_list, SMB_ACL_TYPE_T type, mode_t mode)
|
||||
{
|
||||
uchar computed_mask_bits = 0;
|
||||
acl_duo *duo_item;
|
||||
@@ -731,7 +753,7 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
|
||||
|
||||
if (ndx != 0)
|
||||
return ndx - 1;
|
||||
|
||||
|
||||
ndx = racl_list->count;
|
||||
duo_item = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
|
||||
duo_item->racl = empty_rsync_acl;
|
||||
@@ -739,22 +761,28 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
|
||||
flags = read_byte(f);
|
||||
|
||||
if (flags & XMIT_USER_OBJ)
|
||||
duo_item->racl.user_obj = recv_acl_access(NULL, f);
|
||||
duo_item->racl.user_obj = recv_acl_access(f, NULL);
|
||||
if (flags & XMIT_GROUP_OBJ)
|
||||
duo_item->racl.group_obj = recv_acl_access(NULL, f);
|
||||
duo_item->racl.group_obj = recv_acl_access(f, NULL);
|
||||
if (flags & XMIT_MASK_OBJ)
|
||||
duo_item->racl.mask_obj = recv_acl_access(NULL, f);
|
||||
duo_item->racl.mask_obj = recv_acl_access(f, NULL);
|
||||
if (flags & XMIT_OTHER_OBJ)
|
||||
duo_item->racl.other_obj = recv_acl_access(NULL, f);
|
||||
duo_item->racl.other_obj = recv_acl_access(f, NULL);
|
||||
if (flags & XMIT_NAME_LIST)
|
||||
computed_mask_bits |= recv_ida_entries(&duo_item->racl.names, f);
|
||||
computed_mask_bits |= recv_ida_entries(f, &duo_item->racl.names);
|
||||
|
||||
#ifdef HAVE_OSX_ACLS
|
||||
/* If we received a superfluous mask, throw it away. */
|
||||
duo_item->racl.mask_obj = NO_ENTRY;
|
||||
#else
|
||||
if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) /* Must be non-empty with lists. */
|
||||
duo_item->racl.mask_obj = (computed_mask_bits | duo_item->racl.group_obj) & ~NO_ENTRY;
|
||||
if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) {
|
||||
/* Mask must be non-empty with lists. */
|
||||
if (type == SMB_ACL_TYPE_ACCESS)
|
||||
computed_mask_bits = (mode >> 3) & 7;
|
||||
else
|
||||
computed_mask_bits |= duo_item->racl.group_obj & ~NO_ENTRY;
|
||||
duo_item->racl.mask_obj = computed_mask_bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
duo_item->sacl = NULL;
|
||||
@@ -763,12 +791,12 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
|
||||
}
|
||||
|
||||
/* Receive the ACL info the sender has included for this file-list entry. */
|
||||
void receive_acl(struct file_struct *file, int f)
|
||||
void receive_acl(int f, struct file_struct *file)
|
||||
{
|
||||
F_ACL(file) = recv_rsync_acl(&access_acl_list, SMB_ACL_TYPE_ACCESS, f);
|
||||
F_ACL(file) = recv_rsync_acl(f, &access_acl_list, SMB_ACL_TYPE_ACCESS, file->mode);
|
||||
|
||||
if (S_ISDIR(file->mode))
|
||||
F_DIR_DEFACL(file) = recv_rsync_acl(&default_acl_list, SMB_ACL_TYPE_DEFAULT, f);
|
||||
F_DIR_DEFACL(file) = recv_rsync_acl(f, &default_acl_list, SMB_ACL_TYPE_DEFAULT, 0);
|
||||
}
|
||||
|
||||
static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl_list)
|
||||
@@ -880,12 +908,14 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
|
||||
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
|
||||
break;
|
||||
case SMB_ACL_MASK:
|
||||
#ifndef HAVE_SOLARIS_ACLS
|
||||
#ifndef ACLS_NEED_MASK
|
||||
/* mask is only empty when we don't need it. */
|
||||
if (racl->mask_obj == NO_ENTRY)
|
||||
break;
|
||||
#endif
|
||||
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
|
||||
#endif
|
||||
break;
|
||||
case SMB_ACL_OTHER:
|
||||
COE2( store_access_in_entry,(mode & 7, entry) );
|
||||
@@ -898,7 +928,7 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
|
||||
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
|
||||
errfun);
|
||||
}
|
||||
return (mode_t)~0;
|
||||
return (mode_t)-1;
|
||||
}
|
||||
|
||||
#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
|
||||
@@ -967,7 +997,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
|
||||
if (type == SMB_ACL_TYPE_ACCESS) {
|
||||
cur_mode = change_sacl_perms(duo_item->sacl, &duo_item->racl,
|
||||
cur_mode, mode);
|
||||
if (cur_mode == (mode_t)~0)
|
||||
if (cur_mode == (mode_t)-1)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -983,17 +1013,17 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set ACL on indicated filename.
|
||||
/* Given a fname, this sets extended access ACL entries, the default ACL (for a
|
||||
* dir), and the regular mode bits on the file. Call this with fname set to
|
||||
* NULL to just check if the ACL is different.
|
||||
*
|
||||
* This sets extended access ACL entries and default ACL. If convenient,
|
||||
* it sets permission bits along with the access ACL and signals having
|
||||
* done so by modifying sxp->st.st_mode.
|
||||
* If the ACL operation has a side-effect of changing the file's mode, the
|
||||
* sxp->st.st_mode value will be changed to match.
|
||||
*
|
||||
* Returns 1 for unchanged, 0 for changed, -1 for failed. Call this
|
||||
* with fname set to NULL to just check if the ACL is unchanged. */
|
||||
int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp)
|
||||
* Returns 0 for an unchanged ACL, 1 for changed, -1 for failed. */
|
||||
int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp, mode_t new_mode)
|
||||
{
|
||||
int unchanged = 1;
|
||||
int changed = 0;
|
||||
int32 ndx;
|
||||
BOOL eq;
|
||||
|
||||
@@ -1007,18 +1037,18 @@ int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp)
|
||||
acl_duo *duo_item = access_acl_list.items;
|
||||
duo_item += ndx;
|
||||
eq = sxp->acc_acl
|
||||
&& rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, file->mode);
|
||||
&& rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, new_mode);
|
||||
if (!eq) {
|
||||
unchanged = 0;
|
||||
changed = 1;
|
||||
if (!dry_run && fname
|
||||
&& set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_ACCESS,
|
||||
sxp, file->mode) < 0)
|
||||
unchanged = -1;
|
||||
sxp, new_mode) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!S_ISDIR(sxp->st.st_mode))
|
||||
return unchanged;
|
||||
if (!S_ISDIR(new_mode))
|
||||
return changed;
|
||||
|
||||
ndx = F_DIR_DEFACL(file);
|
||||
if (ndx >= 0 && (size_t)ndx < default_acl_list.count) {
|
||||
@@ -1026,16 +1056,15 @@ int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp)
|
||||
duo_item += ndx;
|
||||
eq = sxp->def_acl && rsync_acl_equal(sxp->def_acl, &duo_item->racl);
|
||||
if (!eq) {
|
||||
if (unchanged > 0)
|
||||
unchanged = 0;
|
||||
changed = 1;
|
||||
if (!dry_run && fname
|
||||
&& set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_DEFAULT,
|
||||
sxp, file->mode) < 0)
|
||||
unchanged = -1;
|
||||
sxp, new_mode) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return unchanged;
|
||||
return changed;
|
||||
}
|
||||
|
||||
/* Non-incremental recursion needs to convert all the received IDs.
|
||||
@@ -1078,6 +1107,9 @@ int default_perms_for_dir(const char *dir)
|
||||
if (sacl == NULL) {
|
||||
/* Couldn't get an ACL. Darn. */
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
/* If SMB_ACL_TYPE_DEFAULT isn't valid, then the ACLs must be non-POSIX. */
|
||||
break;
|
||||
#ifdef ENOTSUP
|
||||
case ENOTSUP:
|
||||
#endif
|
||||
|
||||
@@ -156,36 +156,27 @@ static const char *getpassf(const char *filename)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
char buffer[512], *p;
|
||||
int fd, n, ok = 1;
|
||||
const char *envpw = getenv("RSYNC_PASSWORD");
|
||||
int fd, n;
|
||||
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
if ((fd = open(filename,O_RDONLY)) < 0) {
|
||||
rsyserr(FWARNING, errno, "could not open password file \"%s\"",
|
||||
filename);
|
||||
if (envpw)
|
||||
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
return NULL;
|
||||
rsyserr(FERROR, errno, "could not open password file %s", filename);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (do_stat(filename, &st) == -1) {
|
||||
rsyserr(FWARNING, errno, "stat(%s)", filename);
|
||||
ok = 0;
|
||||
} else if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FWARNING, "password file must not be other-accessible\n");
|
||||
ok = 0;
|
||||
} else if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
rprintf(FWARNING, "password file must be owned by root when running as root\n");
|
||||
ok = 0;
|
||||
rsyserr(FERROR, errno, "stat(%s)", filename);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (!ok) {
|
||||
close(fd);
|
||||
rprintf(FWARNING, "continuing without password file\n");
|
||||
if (envpw)
|
||||
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
return NULL;
|
||||
if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FERROR, "ERROR: password file must not be other-accessible\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
n = read(fd, buffer, sizeof buffer - 1);
|
||||
@@ -196,7 +187,8 @@ static const char *getpassf(const char *filename)
|
||||
return strdup(p);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
rprintf(FERROR, "ERROR: failed to read a password from %s\n", filename);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
/* Generate an MD4 hash created from the combination of the password
|
||||
|
||||
4
backup.c
4
backup.c
@@ -309,8 +309,8 @@ static int keep_backup(const char *fname)
|
||||
const char *sl = F_SYMLINK(file);
|
||||
if (safe_symlinks && unsafe_symlink(sl, fname)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
|
||||
full_fname(buf), sl);
|
||||
rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
|
||||
fname, sl);
|
||||
}
|
||||
kept = 1;
|
||||
} else {
|
||||
|
||||
79
case_N.h
79
case_N.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* End-of-run cleanup helper code used by cleanup.c.
|
||||
* Allow an arbitrary sequence of case labels.
|
||||
*
|
||||
* Copyright (C) 2006-2008 Wayne Davison
|
||||
* Copyright (C) 2006-2010 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
|
||||
@@ -17,63 +17,60 @@
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
/* This is included by cleanup.c multiple times, once for every segement in
|
||||
* the _exit_cleanup() code. This produces the next "case N:" statement in
|
||||
* sequence and increments the cleanup_step variable by 1. This ensures that
|
||||
* our case statements never get out of whack due to added/removed steps. */
|
||||
/* This is included multiple times, once for every segement in a switch statement.
|
||||
* This produces the next "case N:" statement in sequence. */
|
||||
|
||||
#if !defined EXIT_CLEANUP_CASE_0
|
||||
#define EXIT_CLEANUP_CASE_0
|
||||
#if !defined CASE_N_STATE_0
|
||||
#define CASE_N_STATE_0
|
||||
case 0:
|
||||
#elif !defined EXIT_CLEANUP_CASE_1
|
||||
#define EXIT_CLEANUP_CASE_1
|
||||
#elif !defined CASE_N_STATE_1
|
||||
#define CASE_N_STATE_1
|
||||
case 1:
|
||||
#elif !defined EXIT_CLEANUP_CASE_2
|
||||
#define EXIT_CLEANUP_CASE_2
|
||||
#elif !defined CASE_N_STATE_2
|
||||
#define CASE_N_STATE_2
|
||||
case 2:
|
||||
#elif !defined EXIT_CLEANUP_CASE_3
|
||||
#define EXIT_CLEANUP_CASE_3
|
||||
#elif !defined CASE_N_STATE_3
|
||||
#define CASE_N_STATE_3
|
||||
case 3:
|
||||
#elif !defined EXIT_CLEANUP_CASE_4
|
||||
#define EXIT_CLEANUP_CASE_4
|
||||
#elif !defined CASE_N_STATE_4
|
||||
#define CASE_N_STATE_4
|
||||
case 4:
|
||||
#elif !defined EXIT_CLEANUP_CASE_5
|
||||
#define EXIT_CLEANUP_CASE_5
|
||||
#elif !defined CASE_N_STATE_5
|
||||
#define CASE_N_STATE_5
|
||||
case 5:
|
||||
#elif !defined EXIT_CLEANUP_CASE_6
|
||||
#define EXIT_CLEANUP_CASE_6
|
||||
#elif !defined CASE_N_STATE_6
|
||||
#define CASE_N_STATE_6
|
||||
case 6:
|
||||
#elif !defined EXIT_CLEANUP_CASE_7
|
||||
#define EXIT_CLEANUP_CASE_7
|
||||
#elif !defined CASE_N_STATE_7
|
||||
#define CASE_N_STATE_7
|
||||
case 7:
|
||||
#elif !defined EXIT_CLEANUP_CASE_8
|
||||
#define EXIT_CLEANUP_CASE_8
|
||||
#elif !defined CASE_N_STATE_8
|
||||
#define CASE_N_STATE_8
|
||||
case 8:
|
||||
#elif !defined EXIT_CLEANUP_CASE_9
|
||||
#define EXIT_CLEANUP_CASE_9
|
||||
#elif !defined CASE_N_STATE_9
|
||||
#define CASE_N_STATE_9
|
||||
case 9:
|
||||
#elif !defined EXIT_CLEANUP_CASE_10
|
||||
#define EXIT_CLEANUP_CASE_10
|
||||
#elif !defined CASE_N_STATE_10
|
||||
#define CASE_N_STATE_10
|
||||
case 10:
|
||||
#elif !defined EXIT_CLEANUP_CASE_11
|
||||
#define EXIT_CLEANUP_CASE_11
|
||||
#elif !defined CASE_N_STATE_11
|
||||
#define CASE_N_STATE_11
|
||||
case 11:
|
||||
#elif !defined EXIT_CLEANUP_CASE_12
|
||||
#define EXIT_CLEANUP_CASE_12
|
||||
#elif !defined CASE_N_STATE_12
|
||||
#define CASE_N_STATE_12
|
||||
case 12:
|
||||
#elif !defined EXIT_CLEANUP_CASE_13
|
||||
#define EXIT_CLEANUP_CASE_13
|
||||
#elif !defined CASE_N_STATE_13
|
||||
#define CASE_N_STATE_13
|
||||
case 13:
|
||||
#elif !defined EXIT_CLEANUP_CASE_14
|
||||
#define EXIT_CLEANUP_CASE_14
|
||||
#elif !defined CASE_N_STATE_14
|
||||
#define CASE_N_STATE_14
|
||||
case 14:
|
||||
#elif !defined EXIT_CLEANUP_CASE_15
|
||||
#define EXIT_CLEANUP_CASE_15
|
||||
#elif !defined CASE_N_STATE_15
|
||||
#define CASE_N_STATE_15
|
||||
case 15:
|
||||
#elif !defined EXIT_CLEANUP_CASE_16
|
||||
#define EXIT_CLEANUP_CASE_16
|
||||
#elif !defined CASE_N_STATE_16
|
||||
#define CASE_N_STATE_16
|
||||
case 16:
|
||||
#else
|
||||
#error Need to add more case statements!
|
||||
#endif
|
||||
cleanup_step++;
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
extern int checksum_seed;
|
||||
extern int protocol_version;
|
||||
|
||||
int csum_length = SHORT_SUM_LENGTH; /* initial value */
|
||||
|
||||
/*
|
||||
a simple 32 bit checksum that can be upadted from either end
|
||||
(inspired by Mark Adler's Adler-32 checksum)
|
||||
|
||||
13
cleanup.c
13
cleanup.c
@@ -94,7 +94,7 @@ pid_t cleanup_child_pid = -1;
|
||||
**/
|
||||
NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
{
|
||||
static int cleanup_step = 0;
|
||||
static int switch_step = 0;
|
||||
static int exit_code = 0, exit_line = 0;
|
||||
static const char *exit_file = NULL;
|
||||
static int unmodified_code = 0;
|
||||
@@ -115,8 +115,9 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
/* Some of our actions might cause a recursive call back here, so we
|
||||
* keep track of where we are in the cleanup and never repeat a step. */
|
||||
switch (cleanup_step) {
|
||||
#include "case_N.h" /* case 0: cleanup_step++; */
|
||||
switch (switch_step) {
|
||||
#include "case_N.h" /* case 0: */
|
||||
switch_step++;
|
||||
|
||||
exit_code = unmodified_code = code;
|
||||
exit_file = file;
|
||||
@@ -130,6 +131,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
if (cleanup_child_pid != -1) {
|
||||
int status;
|
||||
@@ -143,6 +145,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
|
||||
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
|
||||
@@ -160,12 +163,14 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
if (!code || am_server || am_receiver)
|
||||
io_flush(FULL_FLUSH);
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
if (cleanup_fname)
|
||||
do_unlink(cleanup_fname);
|
||||
@@ -191,6 +196,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,
|
||||
@@ -201,6 +207,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
/* FALLTHROUGH */
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
|
||||
if (am_server && code)
|
||||
msleep(100);
|
||||
|
||||
@@ -259,7 +259,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
if (strncmp(*argv, modname, modlen) == 0
|
||||
&& argv[0][modlen] == '\0')
|
||||
sargs[sargc++] = modname; /* we send "modname/" */
|
||||
else
|
||||
else if (**argv == '-') {
|
||||
if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
|
||||
out_of_memory("start_inband_exchange");
|
||||
} else
|
||||
sargs[sargc++] = *argv;
|
||||
argv++;
|
||||
argc--;
|
||||
@@ -509,6 +512,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
* supplementary groups. */
|
||||
|
||||
module_dir = lp_path(i);
|
||||
if (*module_dir == '\0') {
|
||||
rprintf(FLOG, "No path specified for module %s\n", name);
|
||||
io_printf(f_out, "@ERROR: no path setting.\n");
|
||||
return -1;
|
||||
}
|
||||
if (use_chroot) {
|
||||
if ((p = strstr(module_dir, "/./")) != NULL) {
|
||||
*p = '\0'; /* Temporary... */
|
||||
@@ -1063,7 +1071,7 @@ int daemon_main(void)
|
||||
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
|
||||
RSYNC_VERSION, rsync_port);
|
||||
/* TODO: If listening on a particular address, then show that
|
||||
* address too. In fact, why not just do inet_ntop on the
|
||||
* address too. In fact, why not just do getnameinfo on the
|
||||
* local address??? */
|
||||
|
||||
start_accept_loop(rsync_port, start_daemon);
|
||||
|
||||
8
compat.c
8
compat.c
@@ -24,6 +24,7 @@
|
||||
int remote_protocol = 0;
|
||||
int file_extra_cnt = 0; /* count of file-list extras that everyone gets */
|
||||
int inc_recurse = 0;
|
||||
int compat_flags = 0;
|
||||
int use_safe_inc_flist = 0;
|
||||
|
||||
extern int verbose;
|
||||
@@ -248,10 +249,9 @@ void setup_protocol(int f_out,int f_in)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
} else if (protocol_version >= 30) {
|
||||
int compat_flags;
|
||||
if (am_server) {
|
||||
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
compat_flags |= CF_SYMLINK_TIMES;
|
||||
#endif
|
||||
#ifdef ICONV_OPTION
|
||||
@@ -269,7 +269,7 @@ void setup_protocol(int f_out,int f_in)
|
||||
? strchr(client_info, 'L') != NULL
|
||||
: !!(compat_flags & CF_SYMLINK_TIMES);
|
||||
}
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
else
|
||||
receiver_symlink_times = 1;
|
||||
#endif
|
||||
@@ -287,7 +287,7 @@ void setup_protocol(int f_out,int f_in)
|
||||
}
|
||||
use_safe_inc_flist = !!(compat_flags & CF_SAFE_FLIST);
|
||||
need_messages_from_generator = 1;
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
} else if (!am_sender) {
|
||||
receiver_symlink_times = 1;
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
RSYNC_VERSION=3.0.7
|
||||
RSYNC_VERSION=3.0.9
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -46,7 +46,7 @@ AC_DEFINE([_GNU_SOURCE], 1,
|
||||
[Define _GNU_SOURCE so that we get all necessary prototypes])
|
||||
|
||||
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you do not seem to have one])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(profile,
|
||||
@@ -193,7 +193,7 @@ ipv6trylibc=yes
|
||||
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AC_HELP_STRING([--disable-ipv6],
|
||||
[don't even try to use IPv6]))
|
||||
[do not even try to use IPv6]))
|
||||
if test x"$enable_ipv6" != x"no"; then
|
||||
AC_MSG_CHECKING([ipv6 stack type])
|
||||
for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta cygwin; do
|
||||
@@ -307,7 +307,7 @@ AC_ARG_ENABLE([locale],
|
||||
AC_HELP_STRING([--disable-locale],
|
||||
[disable locale features]))
|
||||
AH_TEMPLATE([CONFIG_LOCALE],
|
||||
[Undefine if you don't want locale features. By default this is defined.])
|
||||
[Undefine if you do not want locale features. By default this is defined.])
|
||||
if test x"$enable_locale" != x"no"; then
|
||||
AC_DEFINE(CONFIG_LOCALE)
|
||||
fi
|
||||
@@ -331,7 +331,7 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
sys/un.h sys/attr.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h \
|
||||
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
|
||||
popt.h popt/popt.h)
|
||||
popt.h popt/popt.h netinet/in_systm.h netinet/ip.h)
|
||||
AC_HEADER_MAJOR
|
||||
|
||||
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
|
||||
@@ -428,8 +428,10 @@ fi
|
||||
|
||||
AC_SEARCH_LIBS(inet_ntop, resolv)
|
||||
|
||||
# Solaris and HP-UX weirdness:
|
||||
# Search for libiconv_open (not iconv_open) to discover if -liconv is needed!
|
||||
# For OS X, Solaris, HP-UX, etc.: figure out if -liconv is needed. We'll
|
||||
# accept either iconv_open or libiconv_open, since some include files map
|
||||
# the former to the latter.
|
||||
AC_SEARCH_LIBS(iconv_open, iconv)
|
||||
AC_SEARCH_LIBS(libiconv_open, iconv)
|
||||
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
@@ -571,7 +573,8 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
|
||||
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
|
||||
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
|
||||
seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
|
||||
extattr_get_link sigaction sigprocmask setattrlist)
|
||||
extattr_get_link sigaction sigprocmask setattrlist \
|
||||
utimensat)
|
||||
|
||||
dnl cygwin iconv.h defines iconv_open as libiconv_open
|
||||
if test x"$ac_cv_func_iconv_open" != x"yes"; then
|
||||
@@ -672,7 +675,11 @@ AC_TRY_RUN([
|
||||
|
||||
main() {
|
||||
int fd[2];
|
||||
#ifdef __CYGWIN__
|
||||
exit(1);
|
||||
#else
|
||||
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
|
||||
#endif
|
||||
}],
|
||||
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
|
||||
if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
|
||||
@@ -968,12 +975,18 @@ else
|
||||
AC_MSG_RESULT(Using OS X xattrs)
|
||||
AC_DEFINE(HAVE_OSX_XATTRS, 1, [True if you have Mac OS X xattrs])
|
||||
AC_DEFINE(SUPPORT_XATTRS, 1)
|
||||
AC_DEFINE(NO_DEVICE_XATTRS, 1, [True if device files do not support xattrs])
|
||||
AC_DEFINE(NO_SPECIAL_XATTRS, 1, [True if special files do not support xattrs])
|
||||
;;
|
||||
freebsd*)
|
||||
AC_MSG_RESULT(Using FreeBSD extattrs)
|
||||
AC_DEFINE(HAVE_FREEBSD_XATTRS, 1, [True if you have FreeBSD xattrs])
|
||||
AC_DEFINE(SUPPORT_XATTRS, 1)
|
||||
;;
|
||||
solaris*)
|
||||
# Better Solaris support coming in 3.1.0...
|
||||
AC_DEFINE(NO_SYMLINK_XATTRS, 1, [True if symlinks do not support xattrs])
|
||||
;;
|
||||
*)
|
||||
if test x"$enable_xattr_support" = x"yes"; then
|
||||
AC_MSG_ERROR(Failed to find extended attribute support)
|
||||
12
exclude.c
12
exclude.c
@@ -37,7 +37,7 @@ extern int sanitize_paths;
|
||||
extern int protocol_version;
|
||||
extern int module_id;
|
||||
|
||||
extern char curr_dir[];
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern unsigned int curr_dir_len;
|
||||
extern unsigned int module_dirlen;
|
||||
|
||||
@@ -901,13 +901,9 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
/* --delete-excluded turns an un-modified include/exclude into a
|
||||
* sender-side rule. We also affect per-dir merge files that take
|
||||
* no prefixes as a simple optimization. */
|
||||
/* --delete-excluded turns an un-modified include/exclude into a sender-side rule. */
|
||||
if (delete_excluded
|
||||
&& !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE))
|
||||
&& (!(new_mflags & MATCHFLG_PERDIR_MERGE)
|
||||
|| new_mflags & MATCHFLG_NO_PREFIXES))
|
||||
&& !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE|MATCHFLG_MERGE_FILE|MATCHFLG_PERDIR_MERGE)))
|
||||
new_mflags |= MATCHFLG_SENDER_SIDE;
|
||||
|
||||
*len_ptr = len;
|
||||
@@ -924,7 +920,7 @@ static char default_cvsignore[] =
|
||||
" *.a *.olb *.o *.obj *.so *.exe"
|
||||
" *.Z *.elc *.ln core"
|
||||
/* The rest we added to suit ourself. */
|
||||
" .svn/ .git/ .bzr/";
|
||||
" .svn/ .git/ .hg/ .bzr/";
|
||||
|
||||
static void get_cvs_excludes(uint32 mflags)
|
||||
{
|
||||
|
||||
28
fileio.c
28
fileio.c
@@ -27,24 +27,32 @@
|
||||
|
||||
extern int sparse_files;
|
||||
|
||||
static char last_byte;
|
||||
static OFF_T sparse_seek = 0;
|
||||
|
||||
int sparse_end(int f)
|
||||
int sparse_end(int f, OFF_T size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!sparse_seek)
|
||||
return 0;
|
||||
|
||||
do_lseek(f, sparse_seek-1, SEEK_CUR);
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
ret = do_ftruncate(f, size);
|
||||
#else
|
||||
if (do_lseek(f, sparse_seek-1, SEEK_CUR) != size-1)
|
||||
ret = -1;
|
||||
else {
|
||||
do {
|
||||
ret = write(f, "", 1);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
ret = ret <= 0 ? -1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
sparse_seek = 0;
|
||||
|
||||
do {
|
||||
ret = write(f, "", 1);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
return ret <= 0 ? -1 : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,10 +64,6 @@ static int write_sparse(int f, char *buf, int len)
|
||||
for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
|
||||
for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}
|
||||
|
||||
/* XXX Riddle me this: why does this function SLOW DOWN when I
|
||||
* remove the following (unneeded) line?? Core Duo weirdness? */
|
||||
last_byte = buf[len-1];
|
||||
|
||||
sparse_seek += l1;
|
||||
|
||||
if (l1 == len)
|
||||
|
||||
93
flist.c
93
flist.c
@@ -52,12 +52,9 @@ extern int preserve_hard_links;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_specials;
|
||||
extern int delete_during;
|
||||
extern int uid_ndx;
|
||||
extern int gid_ndx;
|
||||
extern int eol_nulls;
|
||||
extern int relative_paths;
|
||||
extern int implied_dirs;
|
||||
extern int file_extra_cnt;
|
||||
extern int ignore_perishable;
|
||||
extern int non_perishable_cnt;
|
||||
extern int prune_empty_dirs;
|
||||
@@ -70,6 +67,7 @@ extern int use_safe_inc_flist;
|
||||
extern int need_unsorted_flist;
|
||||
extern int sender_symlink_iconv;
|
||||
extern int unsort_ndx;
|
||||
extern uid_t our_uid;
|
||||
extern struct stats stats;
|
||||
extern char *filesfrom_host;
|
||||
|
||||
@@ -118,7 +116,7 @@ int flist_eof = 0; /* all the file-lists are now known */
|
||||
* will survive just long enough to be used by send_file_entry(). */
|
||||
static dev_t tmp_rdev;
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
static int64 tmp_dev, tmp_ino;
|
||||
static int64 tmp_dev = -1, tmp_ino;
|
||||
#endif
|
||||
static char tmp_sum[MAX_DIGEST_LEN];
|
||||
|
||||
@@ -480,7 +478,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
modtime = file->modtime;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (tmp_dev != 0) {
|
||||
if (tmp_dev != -1) {
|
||||
if (protocol_version >= 30) {
|
||||
struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino);
|
||||
first_hlink_ndx = (int32)(long)np->data - 1;
|
||||
@@ -598,15 +596,17 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (tmp_dev != 0 && protocol_version < 30) {
|
||||
if (tmp_dev != -1 && protocol_version < 30) {
|
||||
/* Older protocols expect the dev number to be transmitted
|
||||
* 1-incremented so that it is never zero. */
|
||||
if (protocol_version < 26) {
|
||||
/* 32-bit dev_t and ino_t */
|
||||
write_int(f, (int32)dev);
|
||||
write_int(f, (int32)(dev+1));
|
||||
write_int(f, (int32)tmp_ino);
|
||||
} else {
|
||||
/* 64-bit dev_t and ino_t */
|
||||
if (!(xflags & XMIT_SAME_DEV_pre30))
|
||||
write_longint(f, dev);
|
||||
write_longint(f, dev+1);
|
||||
write_longint(f, tmp_ino);
|
||||
}
|
||||
}
|
||||
@@ -630,8 +630,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
|
||||
stats.total_size += F_LENGTH(file);
|
||||
}
|
||||
|
||||
static struct file_struct *recv_file_entry(struct file_list *flist,
|
||||
int xflags, int f)
|
||||
static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
|
||||
{
|
||||
static int64 modtime;
|
||||
static mode_t mode;
|
||||
@@ -1051,11 +1050,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(mode))
|
||||
receive_acl(file, f);
|
||||
receive_acl(f, file);
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs)
|
||||
receive_xattr(file, f );
|
||||
receive_xattr(f, file);
|
||||
#endif
|
||||
|
||||
if (S_ISREG(mode) || S_ISLNK(mode))
|
||||
@@ -1259,10 +1258,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
if (protocol_version >= 28
|
||||
? (!S_ISDIR(st.st_mode) && st.st_nlink > 1)
|
||||
: S_ISREG(st.st_mode)) {
|
||||
tmp_dev = (int64)st.st_dev + 1;
|
||||
tmp_dev = (int64)st.st_dev;
|
||||
tmp_ino = (int64)st.st_ino;
|
||||
} else
|
||||
tmp_dev = 0;
|
||||
tmp_dev = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1284,10 +1283,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
}
|
||||
#endif
|
||||
file->mode = st.st_mode;
|
||||
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
|
||||
if (preserve_uid)
|
||||
F_OWNER(file) = st.st_uid;
|
||||
if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
|
||||
if (preserve_gid)
|
||||
F_GROUP(file) = st.st_gid;
|
||||
if (am_generator && st.st_uid == our_uid)
|
||||
file->flags |= FLAG_OWNED_BY_US;
|
||||
|
||||
if (basename != thisname)
|
||||
file->dirname = lastdir;
|
||||
@@ -1427,6 +1428,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs) {
|
||||
sx.st.st_mode = file->mode;
|
||||
sx.xattr = NULL;
|
||||
if (get_xattr(fname, &sx) < 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
@@ -1443,13 +1445,13 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode)) {
|
||||
send_acl(&sx, f);
|
||||
send_acl(f, &sx);
|
||||
free_acl(&sx);
|
||||
}
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs) {
|
||||
F_XATTR(file) = send_xattr(&sx, f);
|
||||
F_XATTR(file) = send_xattr(f, &sx);
|
||||
free_xattr(&sx);
|
||||
}
|
||||
#endif
|
||||
@@ -1476,12 +1478,6 @@ static void send_if_directory(int f, struct file_list *flist,
|
||||
unsigned int len = strlen(fbuf);
|
||||
if (len > 1 && fbuf[len-1] == '/')
|
||||
fbuf[--len] = '\0';
|
||||
if (len >= MAXPATHLEN - 1) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR_XFER, "skipping long-named directory: %s\n",
|
||||
full_fname(fbuf));
|
||||
return;
|
||||
}
|
||||
save_filters = push_local_filters(fbuf, len);
|
||||
send_directory(f, flist, fbuf, len, flags);
|
||||
pop_local_filters(save_filters);
|
||||
@@ -1640,21 +1636,30 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
|
||||
}
|
||||
|
||||
p = fbuf + len;
|
||||
if (len != 1 || *fbuf != '/')
|
||||
if (len == 1 && *fbuf == '/')
|
||||
remainder = MAXPATHLEN - 1;
|
||||
else if (len < MAXPATHLEN-1) {
|
||||
*p++ = '/';
|
||||
*p = '\0';
|
||||
remainder = MAXPATHLEN - (p - fbuf);
|
||||
*p = '\0';
|
||||
remainder = MAXPATHLEN - (len + 1);
|
||||
} else
|
||||
remainder = 0;
|
||||
|
||||
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
|
||||
unsigned name_len;
|
||||
char *dname = d_name(di);
|
||||
if (dname[0] == '.' && (dname[1] == '\0'
|
||||
|| (dname[1] == '.' && dname[2] == '\0')))
|
||||
continue;
|
||||
if (strlcpy(p, dname, remainder) >= remainder) {
|
||||
name_len = strlcpy(p, dname, remainder);
|
||||
if (name_len >= remainder) {
|
||||
char save = fbuf[len];
|
||||
fbuf[len] = '\0';
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR_XFER,
|
||||
"cannot send long-named file %s\n",
|
||||
full_fname(fbuf));
|
||||
"filename overflows max-path len by %u: %s/%s\n",
|
||||
name_len - remainder + 1, fbuf, dname);
|
||||
fbuf[len] = save;
|
||||
continue;
|
||||
}
|
||||
if (dname[0] == '\0') {
|
||||
@@ -2097,12 +2102,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
fn = fbuf;
|
||||
/* A leading ./ can be used in relative mode to affect
|
||||
* the dest dir without its name being in the path. */
|
||||
if (*fn == '.' && fn[1] == '/' && !implied_dot_dir) {
|
||||
send_file_name(f, flist, ".", NULL,
|
||||
(flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR,
|
||||
ALL_FILTERS);
|
||||
implied_dot_dir = 1;
|
||||
}
|
||||
if (*fn == '.' && fn[1] == '/' && fn[2] && !implied_dot_dir)
|
||||
implied_dot_dir = -1;
|
||||
len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
|
||||
| CFN_DROP_TRAILING_DOT_DIR);
|
||||
if (len == 1) {
|
||||
@@ -2140,11 +2141,20 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
dirlen = dir ? strlen(dir) : 0;
|
||||
if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
|
||||
if (!change_pathname(NULL, dir, -dirlen))
|
||||
continue;
|
||||
goto bad_path;
|
||||
lastdir = pathname;
|
||||
lastdir_len = pathname_len;
|
||||
} else if (!change_pathname(NULL, lastdir, lastdir_len))
|
||||
} else if (!change_pathname(NULL, lastdir, lastdir_len)) {
|
||||
bad_path:
|
||||
if (implied_dot_dir < 0)
|
||||
implied_dot_dir = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (implied_dot_dir < 0) {
|
||||
implied_dot_dir = 1;
|
||||
send_file_name(f, flist, ".", NULL, (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR, ALL_FILTERS);
|
||||
}
|
||||
|
||||
if (fn != fbuf)
|
||||
memmove(fbuf, fn, len + 1);
|
||||
@@ -2355,7 +2365,7 @@ struct file_list *recv_file_list(int f)
|
||||
}
|
||||
|
||||
flist_expand(flist, 1);
|
||||
file = recv_file_entry(flist, flags, f);
|
||||
file = recv_file_entry(f, flist, flags);
|
||||
|
||||
if (inc_recurse && S_ISDIR(file->mode)) {
|
||||
flist_expand(dir_flist, 1);
|
||||
@@ -3039,13 +3049,14 @@ char *f_name(const struct file_struct *f, char *fbuf)
|
||||
* of the dirname string, and also indicates that "dirname" is a MAXPATHLEN
|
||||
* buffer (the functions we call will append names onto the end, but the old
|
||||
* dir value will be restored on exit). */
|
||||
struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
|
||||
struct file_list *get_dirlist(char *dirname, int dlen, int flags)
|
||||
{
|
||||
struct file_list *dirlist;
|
||||
char dirbuf[MAXPATHLEN];
|
||||
int save_recurse = recurse;
|
||||
int save_xfer_dirs = xfer_dirs;
|
||||
int save_prune_empty_dirs = prune_empty_dirs;
|
||||
int senddir_fd = flags & GDL_IGNORE_FILTER_RULES ? -2 : -1;
|
||||
|
||||
if (dlen < 0) {
|
||||
dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
|
||||
@@ -3058,7 +3069,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
|
||||
|
||||
recurse = 0;
|
||||
xfer_dirs = 1;
|
||||
send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, FLAG_CONTENT_DIR);
|
||||
send_directory(senddir_fd, dirlist, dirname, dlen, FLAG_CONTENT_DIR);
|
||||
xfer_dirs = save_xfer_dirs;
|
||||
recurse = save_recurse;
|
||||
if (do_progress)
|
||||
|
||||
207
generator.c
207
generator.c
@@ -44,8 +44,6 @@ extern int preserve_hard_links;
|
||||
extern int preserve_executability;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_times;
|
||||
extern int uid_ndx;
|
||||
extern int gid_ndx;
|
||||
extern int delete_mode;
|
||||
extern int delete_before;
|
||||
extern int delete_during;
|
||||
@@ -76,7 +74,7 @@ extern int fuzzy_basis;
|
||||
extern int always_checksum;
|
||||
extern int checksum_len;
|
||||
extern char *partial_dir;
|
||||
extern char *basis_dir[];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
extern int compare_dest;
|
||||
extern int copy_dest;
|
||||
extern int link_dest;
|
||||
@@ -169,19 +167,12 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
|
||||
do_chmod(fbuf, mode | S_IWUSR);
|
||||
|
||||
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
|
||||
int save_uid_ndx = uid_ndx;
|
||||
/* This only happens on the first call to delete_item() since
|
||||
* delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
|
||||
if (!uid_ndx)
|
||||
uid_ndx = ++file_extra_cnt;
|
||||
ignore_perishable = 1;
|
||||
/* If DEL_RECURSE is not set, this just reports emptiness. */
|
||||
ret = delete_dir_contents(fbuf, flags);
|
||||
ignore_perishable = 0;
|
||||
if (!save_uid_ndx) {
|
||||
--file_extra_cnt;
|
||||
uid_ndx = 0;
|
||||
}
|
||||
if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
|
||||
goto check_ret;
|
||||
/* OK: try to delete the directory. */
|
||||
@@ -294,7 +285,7 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
|
||||
}
|
||||
|
||||
strlcpy(p, fp->basename, remainder);
|
||||
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
|
||||
if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
|
||||
do_chmod(fname, fp->mode | S_IWUSR);
|
||||
/* Save stack by recursing to ourself directly. */
|
||||
if (S_ISDIR(fp->mode)) {
|
||||
@@ -472,7 +463,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
struct file_list *dirlist;
|
||||
char delbuf[MAXPATHLEN];
|
||||
int dlen, i;
|
||||
int save_uid_ndx = uid_ndx;
|
||||
|
||||
if (!fbuf) {
|
||||
change_local_filter_dir(NULL, 0, 0);
|
||||
@@ -504,9 +494,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uid_ndx)
|
||||
uid_ndx = ++file_extra_cnt;
|
||||
|
||||
dirlist = get_dirlist(fbuf, dlen, 0);
|
||||
|
||||
/* If an item in dirlist is not found in flist, delete it
|
||||
@@ -526,7 +513,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
* a delete_item call with a DEL_MAKE_ROOM flag. */
|
||||
if (flist_find_ignore_dirness(cur_flist, fp) < 0) {
|
||||
int flags = DEL_RECURSE;
|
||||
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
|
||||
if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
|
||||
flags |= DEL_NO_UID_WRITE;
|
||||
f_name(fp, delbuf);
|
||||
if (delete_during == 2) {
|
||||
@@ -538,11 +525,6 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
}
|
||||
|
||||
flist_free(dirlist);
|
||||
|
||||
if (!save_uid_ndx) {
|
||||
--file_extra_cnt;
|
||||
uid_ndx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* This deletes any files on the receiving side that are not present on the
|
||||
@@ -582,46 +564,101 @@ static void do_delete_pass(void)
|
||||
rprintf(FINFO, " \r");
|
||||
}
|
||||
|
||||
int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
|
||||
static inline int time_differs(struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
|
||||
if (S_ISLNK(file->mode)) {
|
||||
;
|
||||
} else
|
||||
#endif
|
||||
if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
|
||||
return 0;
|
||||
return cmp_time(sxp->st.st_mtime, file->modtime);
|
||||
}
|
||||
|
||||
if (preserve_perms) {
|
||||
if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
|
||||
return 0;
|
||||
} else if (preserve_executability
|
||||
&& ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
|
||||
return 0;
|
||||
static inline int perms_differ(struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (preserve_perms)
|
||||
return !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS);
|
||||
|
||||
if (preserve_executability)
|
||||
return (sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ownership_differs(struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file))
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode)) {
|
||||
static inline int acls_differ(const char *fname, struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (preserve_acls) {
|
||||
if (!ACL_READY(*sxp))
|
||||
get_acl(fname, sxp);
|
||||
if (set_acl(NULL, file, sxp) == 0)
|
||||
return 0;
|
||||
if (set_acl(NULL, file, sxp, file->mode))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
static inline int xattrs_differ(const char *fname, struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (preserve_xattrs) {
|
||||
if (!XATTR_READY(*sxp))
|
||||
get_xattr(fname, sxp);
|
||||
if (xattr_diff(file, sxp, 0))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
|
||||
{
|
||||
if (S_ISLNK(file->mode)) {
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
if (preserve_times & PRESERVE_LINK_TIMES && time_differs(file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef CAN_CHMOD_SYMLINK
|
||||
if (perms_differ(file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef CAN_CHOWN_SYMLINK
|
||||
if (ownership_differs(file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
#if defined SUPPORT_ACLS && 0 /* no current symlink-ACL support */
|
||||
if (acls_differ(fname, file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
#if defined SUPPORT_XATTRS && !defined NO_SYMLINK_XATTRS
|
||||
if (xattrs_differ(fname, file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
} else {
|
||||
if (preserve_times && time_differs(file, sxp))
|
||||
return 0;
|
||||
if (perms_differ(file, sxp))
|
||||
return 0;
|
||||
if (ownership_differs(file, sxp))
|
||||
return 0;
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (acls_differ(fname, file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (xattrs_differ(fname, file, sxp))
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -631,12 +668,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
|
||||
{
|
||||
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
|
||||
int keep_time = !preserve_times ? 0
|
||||
: S_ISDIR(file->mode) ? preserve_times > 1 :
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
1;
|
||||
#else
|
||||
!S_ISLNK(file->mode);
|
||||
#endif
|
||||
: S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
|
||||
: S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
|
||||
: 1;
|
||||
|
||||
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
|
||||
iflags |= ITEM_REPORT_SIZE;
|
||||
@@ -668,7 +702,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
|
||||
if (preserve_acls && !S_ISLNK(file->mode)) {
|
||||
if (!ACL_READY(*sxp))
|
||||
get_acl(fnamecmp, sxp);
|
||||
if (set_acl(NULL, file, sxp) == 0)
|
||||
if (set_acl(NULL, file, sxp, file->mode))
|
||||
iflags |= ITEM_REPORT_ACL;
|
||||
}
|
||||
#endif
|
||||
@@ -761,6 +795,12 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
|
||||
int s2length;
|
||||
int64 l;
|
||||
|
||||
if (len < 0) {
|
||||
/* The file length overflowed our int64 var, so we can't process this file. */
|
||||
sum->count = -1; /* indicate overflow error */
|
||||
return;
|
||||
}
|
||||
|
||||
if (block_size)
|
||||
blength = block_size;
|
||||
else if (len <= BLOCK_SIZE * BLOCK_SIZE)
|
||||
@@ -1300,6 +1340,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
skip_dir = NULL;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
sx.acc_acl = sx.def_acl = NULL;
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
sx.xattr = NULL;
|
||||
#endif
|
||||
if (daemon_filter_list.head && (*fname != '.' || fname[1])) {
|
||||
if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {
|
||||
if (is_dir < 0)
|
||||
@@ -1309,7 +1355,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
handle_skipped_hlink(file, itemizing, code, f_out);
|
||||
#endif
|
||||
rprintf(FERROR_XFER,
|
||||
"skipping daemon-excluded %s \"%s\"\n",
|
||||
"ERROR: daemon refused to receive %s \"%s\"\n",
|
||||
is_dir ? "directory" : "file", fname);
|
||||
if (is_dir)
|
||||
goto skipping_dir_contents;
|
||||
@@ -1317,12 +1363,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
sx.acc_acl = sx.def_acl = NULL;
|
||||
#endif
|
||||
#ifdef SUPPORT_XATTRS
|
||||
sx.xattr = NULL;
|
||||
#endif
|
||||
if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
|
||||
parent_is_dry_missing:
|
||||
if (fuzzy_dirlist) {
|
||||
@@ -1361,7 +1401,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
|
||||
if (need_fuzzy_dirlist && S_ISREG(file->mode)) {
|
||||
strlcpy(fnamecmpbuf, dn, sizeof fnamecmpbuf);
|
||||
fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1);
|
||||
fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, GDL_IGNORE_FILTER_RULES);
|
||||
need_fuzzy_dirlist = 0;
|
||||
}
|
||||
|
||||
@@ -1402,9 +1442,18 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fnamecmp = fname;
|
||||
|
||||
if (is_dir) {
|
||||
mode_t added_perms;
|
||||
if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
|
||||
goto cleanup;
|
||||
if (am_root < 0) {
|
||||
/* For --fake-super, the dir must be useable by the copying
|
||||
* user, just like it would be for root. */
|
||||
added_perms = S_IRUSR|S_IWUSR|S_IXUSR;
|
||||
} else
|
||||
added_perms = 0;
|
||||
if (is_dir < 0) {
|
||||
/* In inc_recurse mode we want to make sure any missing
|
||||
* directories get created while we're still processing
|
||||
@@ -1415,7 +1464,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
&& (S_ISDIR(sx.st.st_mode)
|
||||
|| delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
|
||||
goto cleanup; /* Any errors get reported later. */
|
||||
if (do_mkdir(fname, file->mode & 0700) == 0)
|
||||
if (do_mkdir(fname, (file->mode|added_perms) & 0700) == 0)
|
||||
file->flags |= FLAG_DIR_CREATED;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1449,17 +1498,19 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
itemizing = 0;
|
||||
code = FNONE;
|
||||
statret = 1;
|
||||
} else if (j >= 0)
|
||||
} else if (j >= 0) {
|
||||
statret = 1;
|
||||
fnamecmp = fnamecmpbuf;
|
||||
}
|
||||
}
|
||||
if (itemizing && f_out != -1) {
|
||||
itemize(fname, file, ndx, statret, &sx,
|
||||
itemize(fnamecmp, file, ndx, statret, &sx,
|
||||
statret ? ITEM_LOCAL_CHANGE : 0, 0, NULL);
|
||||
}
|
||||
if (real_ret != 0 && do_mkdir(fname,file->mode) < 0 && errno != EEXIST) {
|
||||
if (real_ret != 0 && do_mkdir(fname,file->mode|added_perms) < 0 && errno != EEXIST) {
|
||||
if (!relative_paths || errno != ENOENT
|
||||
|| create_directory_path(fname) < 0
|
||||
|| (do_mkdir(fname, file->mode) < 0 && errno != EEXIST)) {
|
||||
|| create_directory_path(fname) < 0
|
||||
|| (do_mkdir(fname, file->mode|added_perms) < 0 && errno != EEXIST)) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"recv_generator: mkdir %s failed",
|
||||
full_fname(fname));
|
||||
@@ -1471,6 +1522,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && statret == 1)
|
||||
copy_xattrs(fnamecmpbuf, fname);
|
||||
@@ -1479,12 +1531,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
&& verbose && code != FNONE && f_out != -1)
|
||||
rprintf(code, "%s/\n", fname);
|
||||
|
||||
/* We need to ensure that the dirs in the transfer have writable
|
||||
* permissions during the time we are putting files within them.
|
||||
* This is then fixed after the transfer is done. */
|
||||
/* We need to ensure that the dirs in the transfer have both
|
||||
* readable and writable permissions during the time we are
|
||||
* putting files within them. This is then restored to the
|
||||
* former permissions after the transfer is done. */
|
||||
#ifdef HAVE_CHMOD
|
||||
if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) {
|
||||
mode_t mode = file->mode | S_IWUSR;
|
||||
if (!am_root && (file->mode & S_IRWXU) != S_IRWXU && dir_tweaking) {
|
||||
mode_t mode = file->mode | S_IRWXU;
|
||||
if (do_chmod(fname, mode) < 0) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to modify permissions on %s",
|
||||
@@ -1532,11 +1585,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
const char *sl = F_SYMLINK(file);
|
||||
if (safe_symlinks && unsafe_symlink(sl, fname)) {
|
||||
if (verbose) {
|
||||
if (solo_file)
|
||||
if (solo_file) {
|
||||
/* fname contains the destination path, but we
|
||||
* want to report the source path. */
|
||||
fname = f_name(file, NULL);
|
||||
}
|
||||
rprintf(FINFO,
|
||||
"ignoring unsafe symlink %s -> \"%s\"\n",
|
||||
full_fname(fname), sl);
|
||||
"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
|
||||
fname, sl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1730,7 +1786,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fnamecmp = fname;
|
||||
fnamecmp_type = FNAMECMP_FNAME;
|
||||
|
||||
if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
|
||||
@@ -2088,10 +2143,16 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
|
||||
while (1) {
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
|
||||
int send_failed = (ndx == -2);
|
||||
if (send_failed)
|
||||
ndx = get_hlink_num();
|
||||
flist = flist_for_ndx(ndx, "check_for_finished_files.1");
|
||||
file = flist->files[ndx - flist->ndx_start];
|
||||
assert(file->flags & FLAG_HLINKED);
|
||||
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
|
||||
if (send_failed)
|
||||
handle_skipped_hlink(file, itemizing, code, sock_f_out);
|
||||
else
|
||||
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
|
||||
flist->in_progress--;
|
||||
continue;
|
||||
}
|
||||
@@ -2184,7 +2245,7 @@ void generate_files(int f_out, const char *local_name)
|
||||
}
|
||||
solo_file = local_name;
|
||||
dir_tweaking = !(list_only || solo_file || dry_run);
|
||||
need_retouch_dir_times = preserve_times > 1;
|
||||
need_retouch_dir_times = preserve_times & PRESERVE_DIR_TIMES;
|
||||
loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
|
||||
symlink_timeset_failed_flags = ITEM_REPORT_TIME
|
||||
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
|
||||
|
||||
@@ -41,7 +41,7 @@ struct hashtable *hashtable_create(int size, int key64)
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
tbl->node_size = node_size;
|
||||
tbl->key64 = key64;
|
||||
tbl->key64 = key64 ? 1 : 0;
|
||||
|
||||
return tbl;
|
||||
}
|
||||
@@ -60,6 +60,11 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
|
||||
struct ht_int32_node *node;
|
||||
uint32 ndx;
|
||||
|
||||
if (key64 ? key == 0 : (int32)key == 0) {
|
||||
rprintf(FERROR, "Internal hashtable error: illegal key supplied!\n");
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
|
||||
if (allocate_if_missing && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
|
||||
void *old_nodes = tbl->nodes;
|
||||
int size = tbl->size * 2;
|
||||
@@ -142,7 +147,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
|
||||
if (key64)
|
||||
((struct ht_int64_node*)node)->key = key;
|
||||
else
|
||||
node->key = key;
|
||||
node->key = (int32)key;
|
||||
tbl->entries++;
|
||||
return node;
|
||||
}
|
||||
|
||||
26
hlink.c
26
hlink.c
@@ -37,7 +37,7 @@ extern int remove_source_files;
|
||||
extern int stdout_format_has_i;
|
||||
extern int maybe_ATTRS_REPORT;
|
||||
extern int unsort_ndx;
|
||||
extern char *basis_dir[];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
extern struct file_list *cur_flist;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
@@ -57,7 +57,7 @@ static struct file_list *hlink_flist;
|
||||
void init_hard_links(void)
|
||||
{
|
||||
if (am_sender || protocol_version < 30)
|
||||
dev_tbl = hashtable_create(16, SIZEOF_INT64 == 8);
|
||||
dev_tbl = hashtable_create(16, 1);
|
||||
else if (inc_recurse)
|
||||
prior_hlinks = hashtable_create(1024, 0);
|
||||
}
|
||||
@@ -67,11 +67,12 @@ struct ht_int64_node *idev_find(int64 dev, int64 ino)
|
||||
static struct ht_int64_node *dev_node = NULL;
|
||||
struct hashtable *tbl;
|
||||
|
||||
if (!dev_node || dev_node->key != dev) {
|
||||
/* Note that some OSes have a dev == 0, so increment to avoid storing a 0. */
|
||||
if (!dev_node || dev_node->key != dev+1) {
|
||||
/* We keep a separate hash table of inodes for every device. */
|
||||
dev_node = hashtable_find(dev_tbl, dev, 1);
|
||||
dev_node = hashtable_find(dev_tbl, dev+1, 1);
|
||||
if (!(tbl = dev_node->data))
|
||||
tbl = dev_node->data = hashtable_create(512, SIZEOF_INT64 == 8);
|
||||
tbl = dev_node->data = hashtable_create(512, 1);
|
||||
} else
|
||||
tbl = dev_node->data;
|
||||
|
||||
@@ -533,8 +534,19 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
if (inc_recurse) {
|
||||
int gnum = F_HL_GNUM(file);
|
||||
struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
|
||||
assert(node != NULL && node->data != NULL);
|
||||
assert(CVAL(node->data, 0) == 0);
|
||||
if (node == NULL) {
|
||||
rprintf(FERROR, "Unable to find a hlink node for %d (%s)\n", gnum, f_name(file, prev_name));
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
if (node->data == NULL) {
|
||||
rprintf(FERROR, "Hlink node data for %d is NULL (%s)\n", gnum, f_name(file, prev_name));
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
if (CVAL(node->data, 0) != 0) {
|
||||
rprintf(FERROR, "Hlink node data for %d already has path=%s (%s)\n",
|
||||
gnum, (char*)node->data, f_name(file, prev_name));
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
free(node->data);
|
||||
if (!(node->data = strdup(our_name)))
|
||||
out_of_memory("finish_hard_link");
|
||||
|
||||
20
io.c
20
io.c
@@ -36,7 +36,6 @@
|
||||
extern int bwlimit;
|
||||
extern size_t bwlimit_writemax;
|
||||
extern int io_timeout;
|
||||
extern int allowed_lull;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int am_sender;
|
||||
@@ -47,7 +46,7 @@ extern int eol_nulls;
|
||||
extern int flist_eof;
|
||||
extern int list_only;
|
||||
extern int read_batch;
|
||||
extern int csum_length;
|
||||
extern int compat_flags;
|
||||
extern int protect_args;
|
||||
extern int checksum_seed;
|
||||
extern int protocol_version;
|
||||
@@ -60,7 +59,8 @@ extern int filesfrom_convert;
|
||||
extern iconv_t ic_send, ic_recv;
|
||||
#endif
|
||||
|
||||
const char phase_unknown[] = "unknown";
|
||||
int csum_length = SHORT_SUM_LENGTH; /* initial value */
|
||||
int allowed_lull = 0;
|
||||
int ignore_timeout = 0;
|
||||
int batch_fd = -1;
|
||||
int msgdone_cnt = 0;
|
||||
@@ -177,13 +177,19 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
|
||||
case FES_SUCCESS:
|
||||
if (remove_source_files)
|
||||
send_msg(MSG_SUCCESS, buf, 4, 0);
|
||||
/* FALL THROUGH */
|
||||
case FES_NO_SEND:
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links) {
|
||||
struct file_struct *file = flist->files[ndx - flist->ndx_start];
|
||||
if (F_IS_HLINKED(file)) {
|
||||
if (status == FES_NO_SEND)
|
||||
flist_ndx_push(&hlink_list, -2); /* indicates a failure follows */
|
||||
flist_ndx_push(&hlink_list, ndx);
|
||||
flist->in_progress++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case FES_REDO:
|
||||
if (read_batch) {
|
||||
@@ -195,8 +201,6 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
|
||||
flist->to_redo++;
|
||||
flist_ndx_push(&redo_list, ndx);
|
||||
break;
|
||||
case FES_NO_SEND:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,7 +1066,6 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
xbuf outbuf, inbuf;
|
||||
char ibuf[512];
|
||||
int add_null = 0;
|
||||
int pos = 0;
|
||||
|
||||
INIT_CONST_XBUF(outbuf, line);
|
||||
INIT_XBUF(inbuf, ibuf, 0, -1);
|
||||
@@ -1077,7 +1080,6 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
if (iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE) < 0)
|
||||
goto overflow;
|
||||
pos = -1;
|
||||
}
|
||||
if (add_null) {
|
||||
if (outbuf.len == outbuf.size)
|
||||
@@ -1402,7 +1404,7 @@ static void sleep_for_bwlimit(int bytes_written)
|
||||
if (prior_tv.tv_sec) {
|
||||
elapsed_usec = (start_tv.tv_sec - prior_tv.tv_sec) * ONE_SEC
|
||||
+ (start_tv.tv_usec - prior_tv.tv_usec);
|
||||
total_written -= elapsed_usec * bwlimit / (ONE_SEC/1024);
|
||||
total_written -= (int64)elapsed_usec * bwlimit / (ONE_SEC/1024);
|
||||
if (total_written < 0)
|
||||
total_written = 0;
|
||||
}
|
||||
@@ -1901,7 +1903,7 @@ void start_write_batch(int fd)
|
||||
* is involved. */
|
||||
write_int(batch_fd, protocol_version);
|
||||
if (protocol_version >= 30)
|
||||
write_byte(batch_fd, inc_recurse);
|
||||
write_byte(batch_fd, compat_flags);
|
||||
write_int(batch_fd, checksum_seed);
|
||||
|
||||
if (am_sender)
|
||||
|
||||
@@ -2781,6 +2781,11 @@ int no_acl_syscall_error(int err)
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if (err == EINVAL) {
|
||||
/* If the type of SMB_ACL_TYPE_ACCESS or SMB_ACL_TYPE_DEFAULT
|
||||
* isn't valid, then the ACLs must be non-POSIX. */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
6
log.c
6
log.c
@@ -35,8 +35,6 @@ extern int msg_fd_out;
|
||||
extern int allow_8bit_chars;
|
||||
extern int protocol_version;
|
||||
extern int preserve_times;
|
||||
extern int uid_ndx;
|
||||
extern int gid_ndx;
|
||||
extern int progress_is_active;
|
||||
extern int stdout_format_has_i;
|
||||
extern int stdout_format_has_o_or_i;
|
||||
@@ -52,9 +50,9 @@ extern char *logfile_name;
|
||||
extern iconv_t ic_chck;
|
||||
#endif
|
||||
#ifdef ICONV_OPTION
|
||||
extern iconv_t ic_send, ic_recv;
|
||||
extern iconv_t ic_recv;
|
||||
#endif
|
||||
extern char curr_dir[];
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern char *full_module_path;
|
||||
extern unsigned int module_dirlen;
|
||||
|
||||
|
||||
16
main.c
16
main.c
@@ -64,13 +64,14 @@ extern int write_batch;
|
||||
extern int batch_fd;
|
||||
extern int filesfrom_fd;
|
||||
extern int connect_timeout;
|
||||
extern dev_t filesystem_dev;
|
||||
extern pid_t cleanup_child_pid;
|
||||
extern unsigned int module_dirlen;
|
||||
extern struct stats stats;
|
||||
extern char *filesfrom_host;
|
||||
extern char *partial_dir;
|
||||
extern char *dest_option;
|
||||
extern char *basis_dir[];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
extern char *rsync_path;
|
||||
extern char *shell_cmd;
|
||||
extern char *batch_name;
|
||||
@@ -428,7 +429,11 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
args[argc++] = *remote_argv++;
|
||||
if (**remote_argv == '-') {
|
||||
if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
|
||||
out_of_memory("do_cmd");
|
||||
} else
|
||||
args[argc++] = *remote_argv++;
|
||||
remote_argc--;
|
||||
}
|
||||
}
|
||||
@@ -508,6 +513,10 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
if (!dest_path || list_only)
|
||||
return NULL;
|
||||
|
||||
/* Treat an empty string as a copy into the current directory. */
|
||||
if (!*dest_path)
|
||||
dest_path = ".";
|
||||
|
||||
if (daemon_filter_list.head) {
|
||||
char *slash = strrchr(dest_path, '/');
|
||||
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
|
||||
@@ -517,7 +526,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
if ((*dest_path != '.' || dest_path[1] != '\0')
|
||||
&& (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
|
||||
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
|
||||
rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
|
||||
rprintf(FERROR, "ERROR: daemon has excluded destination \"%s\"\n",
|
||||
dest_path);
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -534,6 +543,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
full_fname(dest_path));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
|
||||
return NULL;
|
||||
}
|
||||
if (file_total > 1) {
|
||||
|
||||
47
match.c
47
match.c
@@ -90,8 +90,7 @@ static void build_hash_table(struct sum_struct *s)
|
||||
static OFF_T last_match;
|
||||
|
||||
|
||||
/**
|
||||
* Transmit a literal and/or match token.
|
||||
/* Transmit a literal and/or match token.
|
||||
*
|
||||
* This delightfully-named function is called either when we find a
|
||||
* match and need to transmit all the unmatched data leading up to it,
|
||||
@@ -99,9 +98,9 @@ static OFF_T last_match;
|
||||
* transmit it. As a result of this second case, it is called even if
|
||||
* we have not matched at all!
|
||||
*
|
||||
* @param i If >0, the number of a matched token. If 0, indicates we
|
||||
* have only literal data.
|
||||
**/
|
||||
* If i >= 0, the number of a matched token. If < 0, indicates we have
|
||||
* only literal data. A -1 will send a 0-token-int too, and a -2 sends
|
||||
* only literal data, w/o any token-int. */
|
||||
static void matched(int f, struct sum_struct *s, struct map_struct *buf,
|
||||
OFF_T offset, int32 i)
|
||||
{
|
||||
@@ -141,8 +140,8 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
|
||||
static void hash_search(int f,struct sum_struct *s,
|
||||
struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
OFF_T offset, end;
|
||||
int32 k, want_i, backup;
|
||||
OFF_T offset, aligned_offset, end;
|
||||
int32 k, want_i, aligned_i, backup;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
int more;
|
||||
@@ -167,7 +166,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "sum=%.8x k=%ld\n", sum, (long)k);
|
||||
|
||||
offset = 0;
|
||||
offset = aligned_offset = aligned_i = 0;
|
||||
|
||||
end = len + 1 - s->sums[s->count-1].len;
|
||||
|
||||
@@ -232,27 +231,28 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
|
||||
/* When updating in-place, the best possible match is
|
||||
* one with an identical offset, so we prefer that over
|
||||
* the following want_i optimization. */
|
||||
* the adjacent want_i optimization. */
|
||||
if (updating_basis_file) {
|
||||
int32 i2;
|
||||
for (i2 = i; i2 >= 0; i2 = s->sums[i2].chain) {
|
||||
if (s->sums[i2].offset != offset)
|
||||
continue;
|
||||
if (i2 != i) {
|
||||
if (sum != s->sums[i2].sum1)
|
||||
break;
|
||||
if (memcmp(sum2, s->sums[i2].sum2,
|
||||
s->s2length) != 0)
|
||||
break;
|
||||
i = i2;
|
||||
/* All the generator's chunks start at blength boundaries. */
|
||||
while (aligned_offset < offset) {
|
||||
aligned_offset += s->blength;
|
||||
aligned_i++;
|
||||
}
|
||||
if (offset == aligned_offset && aligned_i < s->count) {
|
||||
if (i != aligned_i) {
|
||||
if (sum != s->sums[aligned_i].sum1
|
||||
|| l != s->sums[aligned_i].len
|
||||
|| memcmp(sum2, s->sums[aligned_i].sum2, s->s2length) != 0)
|
||||
goto check_want_i;
|
||||
i = aligned_i;
|
||||
}
|
||||
/* This chunk was at the same offset on
|
||||
* both the sender and the receiver. */
|
||||
/* This identical chunk is in the same spot in the old and new file. */
|
||||
s->sums[i].flags |= SUMFLG_SAME_OFFSET;
|
||||
goto set_want_i;
|
||||
want_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
check_want_i:
|
||||
/* we've found a match, but now check to see
|
||||
* if want_i can hint at a better match. */
|
||||
if (i != want_i && want_i < s->count
|
||||
@@ -264,7 +264,6 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
* will be happy */
|
||||
i = want_i;
|
||||
}
|
||||
set_want_i:
|
||||
want_i = i + 1;
|
||||
|
||||
matched(f,s,buf,offset,i);
|
||||
|
||||
43
options.c
43
options.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2009 Wayne Davison
|
||||
* Copyright (C) 2002-2011 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
|
||||
@@ -85,7 +85,6 @@ int numeric_ids = 0;
|
||||
int allow_8bit_chars = 0;
|
||||
int force_delete = 0;
|
||||
int io_timeout = 0;
|
||||
int allowed_lull = 0;
|
||||
int prune_empty_dirs = 0;
|
||||
int use_qsort = 0;
|
||||
char *files_from = NULL;
|
||||
@@ -254,13 +253,13 @@ static void print_rsync_version(enum logcode f)
|
||||
#ifdef ICONV_OPTION
|
||||
iconv = "";
|
||||
#endif
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
symtimes = "";
|
||||
#endif
|
||||
|
||||
rprintf(f, "%s version %s protocol version %d%s\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
|
||||
rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n");
|
||||
rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n");
|
||||
rprintf(f, "Web site: http://rsync.samba.org/\n");
|
||||
rprintf(f, "Capabilities:\n");
|
||||
rprintf(f, " %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
|
||||
@@ -370,7 +369,7 @@ void usage(enum logcode F)
|
||||
rprintf(F," --del an alias for --delete-during\n");
|
||||
rprintf(F," --delete delete extraneous files from destination dirs\n");
|
||||
rprintf(F," --delete-before receiver deletes before transfer, not during\n");
|
||||
rprintf(F," --delete-during receiver deletes during transfer (default)\n");
|
||||
rprintf(F," --delete-during receiver deletes during the transfer\n");
|
||||
rprintf(F," --delete-delay find deletions during, delete after\n");
|
||||
rprintf(F," --delete-after receiver deletes after transfer, not during\n");
|
||||
rprintf(F," --delete-excluded also delete excluded files from destination dirs\n");
|
||||
@@ -434,7 +433,7 @@ void usage(enum logcode F)
|
||||
rprintf(F," -4, --ipv4 prefer IPv4\n");
|
||||
rprintf(F," -6, --ipv6 prefer IPv6\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F,"(-h) --help show this help (-h works with no other options)\n");
|
||||
rprintf(F,"(-h) --help show this help (-h is --help only if used alone)\n");
|
||||
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
|
||||
@@ -487,7 +486,7 @@ static struct poptOption long_options[] = {
|
||||
{"xattrs", 'X', POPT_ARG_NONE, 0, 'X', 0, 0 },
|
||||
{"no-xattrs", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
|
||||
{"no-X", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
|
||||
{"times", 't', POPT_ARG_VAL, &preserve_times, 2, 0, 0 },
|
||||
{"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
|
||||
{"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
|
||||
{"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
|
||||
{"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 1, 0, 0 },
|
||||
@@ -531,8 +530,8 @@ static struct poptOption long_options[] = {
|
||||
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
|
||||
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
|
||||
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
|
||||
{"no-one-file-system",'x',POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
|
||||
{"no-x", 'x', POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
|
||||
{"no-one-file-system",0, POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
|
||||
{"no-x", 0, POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
|
||||
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
|
||||
{"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
|
||||
{"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
|
||||
@@ -1065,7 +1064,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
preserve_links = 1;
|
||||
#endif
|
||||
preserve_perms = 1;
|
||||
preserve_times = 2;
|
||||
preserve_times = 1;
|
||||
preserve_gid = 1;
|
||||
preserve_uid = 1;
|
||||
preserve_devices = 1;
|
||||
@@ -1492,17 +1491,18 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
return 0;
|
||||
}
|
||||
if (backup_dir) {
|
||||
backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
|
||||
backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
|
||||
if (backup_dir_remainder < 32) {
|
||||
size_t len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
|
||||
if (len > sizeof backup_dir_buf - 128) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"the --backup-dir path is WAY too long.\n");
|
||||
return 0;
|
||||
}
|
||||
backup_dir_len = (int)len;
|
||||
if (backup_dir_buf[backup_dir_len - 1] != '/') {
|
||||
backup_dir_buf[backup_dir_len++] = '/';
|
||||
backup_dir_buf[backup_dir_len] = '\0';
|
||||
}
|
||||
backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
|
||||
if (verbose > 1 && !am_sender)
|
||||
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
|
||||
} else if (!backup_suffix_len && (!am_server || !am_sender)) {
|
||||
@@ -1515,13 +1515,18 @@ int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
parse_rule(&filter_list, backup_dir_buf, 0, 0);
|
||||
}
|
||||
|
||||
if (preserve_times) {
|
||||
preserve_times = PRESERVE_FILE_TIMES;
|
||||
if (!omit_dir_times)
|
||||
preserve_times |= PRESERVE_DIR_TIMES;
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
preserve_times |= PRESERVE_LINK_TIMES;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (make_backups && !backup_dir) {
|
||||
omit_dir_times = 0; /* Implied, so avoid -O to sender. */
|
||||
if (preserve_times > 1)
|
||||
preserve_times = 1;
|
||||
} else if (omit_dir_times) {
|
||||
if (preserve_times > 1)
|
||||
preserve_times = 1;
|
||||
preserve_times &= ~PRESERVE_DIR_TIMES;
|
||||
}
|
||||
|
||||
if (stdout_format) {
|
||||
@@ -1831,7 +1836,7 @@ void server_options(char **args, int *argc_p)
|
||||
argstr[x++] = '.';
|
||||
if (allow_inc_recurse)
|
||||
argstr[x++] = 'i';
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
#ifdef CAN_SET_SYMLINK_TIMES
|
||||
argstr[x++] = 'L';
|
||||
#endif
|
||||
#ifdef ICONV_OPTION
|
||||
|
||||
@@ -7,7 +7,7 @@ use strict;
|
||||
our %short_no_arg;
|
||||
our %short_with_num;
|
||||
our %long_opt = (
|
||||
'no-i-r' => 0,
|
||||
'daemon' => -1,
|
||||
'fake-super' => 0,
|
||||
'log-file' => 3,
|
||||
);
|
||||
@@ -24,7 +24,7 @@ while (<IN>) {
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
|
||||
$last_long_opt = $1;
|
||||
$long_opt{$1} = 0;
|
||||
$long_opt{$1} = 0 unless exists $long_opt{$1};
|
||||
} elsif (defined($last_long_opt)
|
||||
&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
|
||||
$long_opt{$last_long_opt} = 2;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
# This script finds extraneous "extern" variables in the *.c files.
|
||||
# Run it from inside the main rsync directory.
|
||||
|
||||
use strict;
|
||||
|
||||
my @files = glob('*.c');
|
||||
|
||||
foreach my $fn (@files) {
|
||||
open(IN, '<', $fn) or die;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
my @externs = /^extern .*?([^[\s(*;&.]+)(?:\[.*?\])?;/mg;
|
||||
foreach my $find (@externs) {
|
||||
my @matches = /(?<!\sstruct )\b(\Q$find\E)\b/g;
|
||||
print $fn, ': ', $find, "\n" if @matches == 1;
|
||||
}
|
||||
}
|
||||
48
packaging/git-status.pl
Normal file
48
packaging/git-status.pl
Normal file
@@ -0,0 +1,48 @@
|
||||
# Do some git-status checking for the current dir and (optionally)
|
||||
# the patches dir.
|
||||
|
||||
sub check_git_state
|
||||
{
|
||||
my($master_branch, $fatal_unless_clean, $check_patches_dir) = @_;
|
||||
|
||||
my($cur_branch) = check_git_status($fatal_unless_clean);
|
||||
if ($cur_branch ne $master_branch) {
|
||||
print "The checkout is not on the $master_branch branch.\n";
|
||||
exit 1 if $master_branch ne 'master';
|
||||
print "Do you want me to continue with --branch=$cur_branch? [n] ";
|
||||
$_ = <STDIN>;
|
||||
exit 1 unless /^y/i;
|
||||
$_[0] = $master_branch = $cur_branch; # Updates caller's $master_branch too.
|
||||
}
|
||||
|
||||
if ($check_patches_dir && -d 'patches/.git') {
|
||||
($cur_branch) = check_git_status($fatal_unless_clean, 'patches');
|
||||
if ($cur_branch ne $master_branch) {
|
||||
print "The *patches* checkout is on branch $cur_branch, not branch $master_branch.\n";
|
||||
print "Do you want to change it to branch $master_branch? [n] ";
|
||||
$_ = <STDIN>;
|
||||
exit 1 unless /^y/i;
|
||||
system "cd patches && git checkout '$master_branch'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_git_status
|
||||
{
|
||||
my($fatal_unless_clean, $subdir) = @_;
|
||||
$subdir = '.' unless defined $subdir;
|
||||
my $status = `cd '$subdir' && git status`;
|
||||
my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
my($cur_branch) = $status =~ /^# On branch (.+)\n/;
|
||||
if ($fatal_unless_clean && !$is_clean) {
|
||||
if ($subdir eq '.') {
|
||||
$subdir = '';
|
||||
} else {
|
||||
$subdir = " *$subdir*";
|
||||
}
|
||||
die "The$subdir checkout is not clean:\n", $status;
|
||||
}
|
||||
($cur_branch, $is_clean, $status);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,6 +1,6 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.0.7
|
||||
Version: 3.0.9
|
||||
%define fullversion %{version}
|
||||
Release: 1
|
||||
%define srcdir src
|
||||
@@ -66,8 +66,8 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_mandir}/man5/rsyncd.conf.5*
|
||||
|
||||
%changelog
|
||||
* Thu Dec 31 2009 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.7.
|
||||
* Fri Sep 23 2011 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.9.
|
||||
|
||||
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
|
||||
Added installation of /etc/xinetd.d/rsync file and some commented-out
|
||||
|
||||
@@ -3,8 +3,8 @@ use strict;
|
||||
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
|
||||
# copy of the /home/ftp/pub/rsync dir on samba.org. It also requires a
|
||||
# pristine CVS checkout of rsync (don't use your normal rsync build dir
|
||||
# unless you're 100% sure that there are not unchecked-in changes).
|
||||
# git checkout of rsync (feel free to use your normal rsync build dir as
|
||||
# long as it doesn't have any uncommitted changes).
|
||||
#
|
||||
# If this is run with -ctu, it will make an updated "nightly" tar file in
|
||||
# the nightly dir. It will also remove any old tar files, regenerate the
|
||||
@@ -56,6 +56,58 @@ if ($make_tar) {
|
||||
}
|
||||
close IN;
|
||||
|
||||
my $confversion;
|
||||
open(IN, '<', 'configure.ac') or die "Unable to open configure.ac: $!\n";
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$confversion = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to find RSYNC_VERSION in configure.ac\n" unless defined $confversion;
|
||||
|
||||
open(IN, '<', 'OLDNEWS') or die "Unable to open OLDNEWS: $!\n";
|
||||
$_ = <IN>;
|
||||
my($lastversion) = /(\d+\.\d+\.\d+)/;
|
||||
my $last_protocol_version;
|
||||
while (<IN>) {
|
||||
if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
|
||||
$last_protocol_version = $pver if $ver eq $lastversion;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
|
||||
|
||||
my($protocol_version,$subprotocol_version);
|
||||
open(IN, '<', 'rsync.h') or die "Unable to open rsync.h: $!\n";
|
||||
while (<IN>) {
|
||||
if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
|
||||
$protocol_version = $1;
|
||||
} elsif (/^#define\s+SUBPROTOCOL_VERSION\s+(\d+)/) {
|
||||
$subprotocol_version = $1;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
|
||||
die "Unable to determine the current SUBPROTOCOL_VERSION.\n" unless defined $subprotocol_version;
|
||||
|
||||
if ($confversion =~ /dev|pre/) {
|
||||
if ($last_protocol_version ne $protocol_version) {
|
||||
if ($subprotocol_version == 0) {
|
||||
die "SUBPROTOCOL_VERSION must not be 0 for a non-final release with a changed PROTOCOL_VERSION.\n";
|
||||
}
|
||||
} else {
|
||||
if ($subprotocol_version != 0) {
|
||||
die "SUBPROTOCOL_VERSION must be 0 when the PROTOCOL_VERSION hasn't changed from the last release.\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($subprotocol_version != 0) {
|
||||
die "SUBPROTOCOL_VERSION must be 0 for a final release.\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "Creating $name.tar.gz\n";
|
||||
system "rsync -a @extra_files $name/";
|
||||
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#!/usr/bin/perl -w
|
||||
# This script is used to turn one or more of the "patch/*" branches
|
||||
#!/usr/bin/perl
|
||||
# This script is used to turn one or more of the "patch/BASE/*" branches
|
||||
# into one or more diffs in the "patches" directory. Pass the option
|
||||
# --gen if you want generated files in the diffs. Pass the name of
|
||||
# one or more diffs if you want to just update a subset of all the
|
||||
# diffs.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
|
||||
my $patches_dir = 'patches';
|
||||
@@ -30,10 +31,19 @@ if (defined $incl_generated_files) {
|
||||
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
|
||||
die "No '.git' directory present in the current dir.\n" unless -d '.git';
|
||||
|
||||
my($status, $is_clean, $starting_branch) = &check_git_status;
|
||||
if (!$skip_branch_check && !$is_clean) {
|
||||
die "The checkout is not clean:\n", $status;
|
||||
require 'packaging/git-status.pl';
|
||||
check_git_state($master_branch, !$skip_branch_check, 1);
|
||||
|
||||
my $master_commit;
|
||||
open PIPE, '-|', "git log -1 --no-color $master_branch" or die $!;
|
||||
while (<PIPE>) {
|
||||
if (/^commit (\S+)/) {
|
||||
$master_commit = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close PIPE;
|
||||
die "Unable to determine commit hash for master branch: $master_branch\n" unless defined $master_commit;
|
||||
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
@@ -60,7 +70,7 @@ my %patches;
|
||||
# Start by finding all patches so that we can load all possible parents.
|
||||
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
|
||||
while (<PIPE>) {
|
||||
if (m# patch/(.*)#) {
|
||||
if (m# patch/\Q$master_branch\E/(.*)#o) {
|
||||
$patches{$1} = 1;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +80,7 @@ my @patches = sort keys %patches;
|
||||
|
||||
my(%parent, %description);
|
||||
foreach my $patch (@patches) {
|
||||
my $branch = "patch/$patch";
|
||||
my $branch = "patch/$master_branch/$patch";
|
||||
my $desc = '';
|
||||
open(PIPE, '-|', 'git', 'diff', '-U1000', "$master_branch...$branch", '--', "PATCH.$patch") or die $!;
|
||||
while (<PIPE>) {
|
||||
@@ -114,7 +124,7 @@ if ($incl_generated_files) {
|
||||
}
|
||||
|
||||
sleep 1 while $last_touch >= time;
|
||||
system "git checkout $starting_branch" and exit 1;
|
||||
system "git checkout $master_branch" and exit 1;
|
||||
|
||||
exit;
|
||||
|
||||
@@ -124,24 +134,27 @@ sub update_patch
|
||||
my($patch) = @_;
|
||||
|
||||
my $parent = $parent{$patch};
|
||||
my $based_on;
|
||||
if (defined $parent) {
|
||||
unless ($completed{$parent}++) {
|
||||
update_patch($parent);
|
||||
}
|
||||
$parent = "patch/$parent";
|
||||
$based_on = $parent = "patch/$master_branch/$parent";
|
||||
} else {
|
||||
$parent = $master_branch;
|
||||
$based_on = $master_commit;
|
||||
}
|
||||
|
||||
print "======== $patch ========\n";
|
||||
|
||||
sleep 1 while $incl_generated_files && $last_touch >= time;
|
||||
system "git checkout patch/$patch" and return 0;
|
||||
system "git checkout patch/$master_branch/$patch" and return 0;
|
||||
|
||||
my $ok = system("git merge $parent") == 0;
|
||||
my $ok = system("git merge $based_on") == 0;
|
||||
if (!$ok || $launch_shell) {
|
||||
print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
|
||||
$ENV{PS1} = "[$parent] patch/$patch: ";
|
||||
my($parent_dir) = $parent =~ m{([^/]+)$};
|
||||
print qq|"git merge $based_on" incomplete -- please fix.\n| if !$ok;
|
||||
$ENV{PS1} = "[$parent_dir] $patch: ";
|
||||
while (1) {
|
||||
if (system($ENV{SHELL}) != 0) {
|
||||
print "Abort? [n/y] ";
|
||||
@@ -149,21 +162,21 @@ sub update_patch
|
||||
next unless /^y/i;
|
||||
return 0;
|
||||
}
|
||||
($status, $is_clean) = &check_git_status;
|
||||
my($cur_branch, $is_clean, $status) = check_git_status(0);
|
||||
last if $is_clean;
|
||||
print $status;
|
||||
}
|
||||
}
|
||||
|
||||
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
|
||||
print OUT $description{$patch}, "\n";
|
||||
print OUT $description{$patch}, "\nbased-on: $based_on\n";
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
|
||||
}
|
||||
$last_touch = time;
|
||||
|
||||
open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
|
||||
open(PIPE, '-|', 'git', 'diff', $based_on) or die $!;
|
||||
DIFF: while (<PIPE>) {
|
||||
while (m{^diff --git a/PATCH}) {
|
||||
while (<PIPE>) {
|
||||
@@ -200,22 +213,18 @@ sub update_patch
|
||||
|
||||
exit;
|
||||
|
||||
sub check_git_status
|
||||
{
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
my($starting_branch) = $status =~ /^# On branch (.+)\n/;
|
||||
($status, $is_clean, $starting_branch);
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: patch-update [OPTIONS]
|
||||
Usage: patch-update [OPTIONS] [patches/DIFF...]
|
||||
|
||||
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
|
||||
--skip-check Skip the check that ensures starting with a clean branch.
|
||||
Options:
|
||||
-b, --branch=BRANCH The master branch to merge into the patch/BASE/* branches.
|
||||
--gen[=DIR] Include generated files. Optional destination DIR
|
||||
arg overrides the default of using the "patches" dir.
|
||||
--skip-check Skip the check that ensures starting with a clean branch.
|
||||
-s, --shell Launch a shell for every patch/BASE/* branch updated, not
|
||||
just when a conflict occurs.
|
||||
-h, --help Output this help message.
|
||||
EOT
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
|
||||
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
|
||||
# the git repository in the current directory will be updated, and the local
|
||||
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd;
|
||||
use Getopt::Long;
|
||||
use Term::ReadKey;
|
||||
@@ -14,6 +14,7 @@ use Date::Format;
|
||||
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
|
||||
my $passfile = $ENV{HOME} . '/.rsyncpass';
|
||||
my $path = $ENV{PATH};
|
||||
my $make_gen_cmd = 'make -f prepare-source.mak conf && ./config.status && make gen';
|
||||
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
@@ -60,14 +61,11 @@ die "There is no .git dir in the current directory.\n" unless -d '.git';
|
||||
die "'a' must not exist in the current directory.\n" if -e 'a';
|
||||
die "'b' must not exist in the current directory.\n" if -e 'b';
|
||||
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
die "The checkout is not on the $master_branch branch.\n" unless $status =~ /^# On branch $master_branch\n/;
|
||||
require 'packaging/git-status.pl';
|
||||
check_git_state($master_branch, 1, 1);
|
||||
|
||||
my $confversion;
|
||||
open(IN, '<', 'configure.in') or die $!;
|
||||
open(IN, '<', 'configure.ac') or die $!;
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$confversion = $1;
|
||||
@@ -75,12 +73,31 @@ while (<IN>) {
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to find RSYNC_VERSION in configure.in\n" unless defined $confversion;
|
||||
die "Unable to find RSYNC_VERSION in configure.ac\n" unless defined $confversion;
|
||||
|
||||
open(IN, '<', 'OLDNEWS') or die $!;
|
||||
$_ = <IN>;
|
||||
close IN;
|
||||
my($lastversion) = /(\d+\.\d+\.\d+)/;
|
||||
my($last_protocol_version, %pdate);
|
||||
while (<IN>) {
|
||||
if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
|
||||
$pdate{$ver} = $pdate if defined $pdate;
|
||||
$last_protocol_version = $pver if $ver eq $lastversion;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
|
||||
|
||||
my $protocol_version;
|
||||
open(IN, '<', 'rsync.h') or die $!;
|
||||
while (<IN>) {
|
||||
if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
|
||||
$protocol_version = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
|
||||
|
||||
my $version = $confversion;
|
||||
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
|
||||
@@ -118,6 +135,23 @@ chomp($_ = <STDIN>);
|
||||
$release = $_ if $_ ne '';
|
||||
$release .= ".$pre" if $pre;
|
||||
|
||||
(my $finalversion = $version) =~ s/pre\d+//;
|
||||
my($proto_changed,$proto_change_date);
|
||||
if ($protocol_version eq $last_protocol_version) {
|
||||
$proto_changed = 'unchanged';
|
||||
$proto_change_date = "\t\t";
|
||||
} else {
|
||||
$proto_changed = 'changed';
|
||||
if (!defined($proto_change_date = $pdate{$finalversion})) {
|
||||
while (1) {
|
||||
print "On what date did the protocol change to $protocol_version get checked in? (dd Mmm yyyy) ";
|
||||
chomp($_ = <STDIN>);
|
||||
last if /^\d\d \w\w\w \d\d\d\d$/;
|
||||
}
|
||||
$proto_change_date = "$_\t";
|
||||
}
|
||||
}
|
||||
|
||||
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
|
||||
if ($lastversion =~ /pre/) {
|
||||
if (!$pre) {
|
||||
@@ -146,9 +180,9 @@ print "\n", $break, <<EOT;
|
||||
\$release is "$release"
|
||||
|
||||
About to:
|
||||
- make sure that SUBPROTOCOL_VERSION is 0$skipping
|
||||
- tweak the version in configure.in and the spec files
|
||||
- tweak NEWS and OLDNEWS to update the release date$skipping
|
||||
- tweak SUBPROTOCOL_VERSION in rsync.h, if needed
|
||||
- tweak the version in configure.ac and the spec files
|
||||
- tweak NEWS and OLDNEWS to ensure header values are correct
|
||||
- tweak the date in the *.yo files and generate the manpages
|
||||
- generate configure.sh, config.h.in, and proto.h
|
||||
- page through the differences
|
||||
@@ -157,12 +191,11 @@ EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
(my $finalversion = $version) =~ s/pre\d+//;
|
||||
my %specvars = ( 'Version:' => $finalversion, 'Release:' => $release,
|
||||
'%define fullversion' => "\%{version}$pre", 'Released' => "$version.",
|
||||
'%define srcdir' => $srcdir );
|
||||
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'), glob('*.yo'),
|
||||
qw( configure.in rsync.h NEWS OLDNEWS options.c ) );
|
||||
qw( configure.ac rsync.h NEWS OLDNEWS options.c ) );
|
||||
|
||||
foreach my $fn (@tweak_files) {
|
||||
open(IN, '<', $fn) or die $!;
|
||||
@@ -184,18 +217,19 @@ foreach my $fn (@tweak_files) {
|
||||
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m
|
||||
or die "Unable to update current version info in $fn\n";
|
||||
} elsif ($fn eq 'rsync.h') {
|
||||
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/
|
||||
s{(#define\s+SUBPROTOCOL_VERSION)\s+(\d+)}
|
||||
{ $1 . ' ' . get_subprotocol_version($2) }e
|
||||
or die "Unable to find SUBPROTOCOL_VERSION define in $fn\n";
|
||||
next if $pre;
|
||||
} elsif ($fn eq 'NEWS') {
|
||||
s/^(NEWS for rsync \Q$finalversion\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
|
||||
or die "The first line of $fn is not in the right format. It must be:\n"
|
||||
. "NEWS for rsync $finalversion (UNRELEASED)\n";
|
||||
next if $pre;
|
||||
s{^(NEWS for rsync \Q$finalversion\E )(\(UNRELEASED\))\s*(\nProtocol: )(\d+) (\([^)]+\))\n}
|
||||
{ $1 . ($pre ? $2 : "($today)") . "$3$protocol_version ($proto_changed)\n" }ei
|
||||
or die "The first 2 lines of $fn are not in the right format. They must be:\n"
|
||||
. "NEWS for rsync $finalversion (UNRELEASED)\n"
|
||||
. "Protocol: $protocol_version ($proto_changed)\n";
|
||||
} elsif ($fn eq 'OLDNEWS') {
|
||||
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$finalversion\E)/\t$ztoday$1/m
|
||||
s{^(\t\S\S\s\S\S\S\s\d\d\d\d)(\t\Q$finalversion\E\t).*}
|
||||
{ ($pre ? $1 : "\t$ztoday") . $2 . $proto_change_date . $protocol_version }em
|
||||
or die "Unable to find \"?? ??? $year\t$finalversion\" line in $fn\n";
|
||||
next if $pre;
|
||||
} elsif ($fn eq 'options.c') {
|
||||
if (s/(Copyright \(C\) 2002-)(\d+)( Wayne Davison)/$1$year$3/
|
||||
&& $2 ne $year) {
|
||||
@@ -229,7 +263,7 @@ print $break, <<EOT;
|
||||
|
||||
About to:
|
||||
- commit all version changes
|
||||
- merge the $master_branch branch into the patch/* branches
|
||||
- merge the $master_branch branch into the patch/$master_branch/* branches
|
||||
- update the files in the "patches" dir and OPTIONALLY
|
||||
(if you type 'y') to launch a shell for each patch
|
||||
|
||||
@@ -243,10 +277,14 @@ print "Updating files in \"patches\" dir ...\n";
|
||||
system "packaging/patch-update --branch=$master_branch";
|
||||
|
||||
if ($ans =~ /^y/i) {
|
||||
print "\nVisiting all \"patch/*\" branches ...\n";
|
||||
print "\nVisiting all \"patch/$master_branch/*\" branches ...\n";
|
||||
system "packaging/patch-update --branch=$master_branch --shell";
|
||||
}
|
||||
|
||||
if (-d 'patches/.git') {
|
||||
system "cd patches && git commit -a -m 'The patches for $version.'" and exit 1;
|
||||
}
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to:
|
||||
@@ -264,6 +302,9 @@ EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
|
||||
$ENV{PATH} = "$curdir/packaging/bin:$path";
|
||||
|
||||
my $passphrase;
|
||||
while (1) {
|
||||
ReadMode('noecho');
|
||||
@@ -281,17 +322,23 @@ while (1) {
|
||||
umask $oldmask;
|
||||
$ENV{'GPG_PASSFILE'} = $passfile;
|
||||
|
||||
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
|
||||
$ENV{PATH} = "packaging/bin:$path";
|
||||
$_ = `git tag -s -m 'Version $version.' v$version 2>&1`;
|
||||
$ENV{PATH} = $path;
|
||||
unlink($passfile);
|
||||
print $_;
|
||||
next if /bad passphrase/;
|
||||
last unless /failed/;
|
||||
exit 1;
|
||||
exit 1 if /failed/;
|
||||
|
||||
if (-d 'patches/.git') {
|
||||
$_ = `cd patches && git tag -s -m 'Version $version.' v$version 2>&1`;
|
||||
print $_;
|
||||
exit 1 if /bad passphrase|failed/;
|
||||
}
|
||||
|
||||
unlink($passfile);
|
||||
last;
|
||||
}
|
||||
|
||||
$ENV{PATH} = $path;
|
||||
|
||||
# Extract the generated files from the old tar.
|
||||
@_ = @extra_files;
|
||||
map { s#^#rsync-$lastversion/# } @_;
|
||||
@@ -299,7 +346,7 @@ system "tar xzf $lasttar_file @_";
|
||||
rename("rsync-$lastversion", 'a');
|
||||
|
||||
print "Creating $diff_file ...\n";
|
||||
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
|
||||
system "$make_gen_cmd && rsync -a @extra_files b/" and exit 1;
|
||||
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
|
||||
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
|
||||
system "rm -rf a";
|
||||
@@ -354,6 +401,15 @@ EOT
|
||||
|
||||
exit;
|
||||
|
||||
sub get_subprotocol_version
|
||||
{
|
||||
my($subver) = @_;
|
||||
if ($pre && $proto_changed eq 'changed') {
|
||||
return $subver == 0 ? 1 : $subver;
|
||||
}
|
||||
0;
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
|
||||
83
packaging/var-checker
Executable file
83
packaging/var-checker
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/perl
|
||||
# This script checks the *.c files for extraneous "extern" variables,
|
||||
# for vars that are defined but not used, and for inconsistent array
|
||||
# sizes. Run it from inside the main rsync directory.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %add_syscall_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c tls.c trimslash.c );
|
||||
my %add_compat_c = map { $_ => 1 } qw( t_stub.c tls.c trimslash.c wildtest.c );
|
||||
my %add_util_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c );
|
||||
my %sizes;
|
||||
|
||||
open(IN, '<', 'syscall.c') or die $!;
|
||||
undef $/; my $syscall_c = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
$syscall_c =~ s/^extern\s.*//mg;
|
||||
|
||||
open(IN, '<', 'lib/compat.c') or die $!;
|
||||
undef $/; my $compat_c = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
$compat_c =~ s/^extern\s.*//mg;
|
||||
|
||||
open(IN, '<', 'util.c') or die $!;
|
||||
undef $/; my $util_c = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
$util_c =~ s/^extern\s.*//mg;
|
||||
|
||||
my @files = glob('*.c');
|
||||
|
||||
foreach my $fn (@files) {
|
||||
open(IN, '<', $fn) or die $!;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
|
||||
my @vars = /^(?!(?:extern|enum)\s)([a-zA-Z]\S*\s+.*);/mg;
|
||||
my @externs = /^extern\s+(.*);/mg;
|
||||
|
||||
$_ .= $syscall_c if $add_syscall_c{$fn};
|
||||
$_ .= $compat_c if $add_compat_c{$fn};
|
||||
$_ .= $util_c if $add_util_c{$fn};
|
||||
s/INFO_GTE/info_levels/g;
|
||||
s/DEBUG_GTE/debug_levels/g;
|
||||
|
||||
check_vars($fn, 'var', @vars);
|
||||
check_vars($fn, 'extern', @externs);
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
# The file's contents are in $_.
|
||||
sub check_vars
|
||||
{
|
||||
my $fn = shift;
|
||||
my $type = shift;
|
||||
|
||||
foreach my $line (@_) {
|
||||
$line =~ s/\s*\{.*\}//;
|
||||
$line =~ s/\s*\(.*\)//;
|
||||
foreach my $item (split(/\s*,\s*/, $line)) {
|
||||
$item =~ s/\s*=.*//;
|
||||
my $sz = $item =~ s/(\[.*?\])// ? $1 : '';
|
||||
my($var) = $item =~ /([^*\s]+)$/;
|
||||
if (!defined $var) {
|
||||
print "Bogus match? ($item)\n";
|
||||
next;
|
||||
}
|
||||
if ($sz) {
|
||||
if (defined $sizes{$var}) {
|
||||
if ($sizes{$var} ne $sz) {
|
||||
print $fn, ' has inconsistent size for "', $var,
|
||||
"\": $sizes{$var} vs $sz\n";
|
||||
}
|
||||
} else {
|
||||
$sizes{$var} = $sz;
|
||||
}
|
||||
}
|
||||
my @matches = /(?<!\sstruct )\b(\Q$var\E)(?!\w)/g;
|
||||
push(@matches, /(\QSIGACTION(\E)/g) if $var eq 'sigact';
|
||||
print $fn, " has extraneous $type: \"", $var, "\"\n" if @matches == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
popt/popt.c
19
popt/popt.c
@@ -860,20 +860,21 @@ int poptGetNextOpt(poptContext con)
|
||||
|
||||
origOptString++;
|
||||
if (*origOptString != '\0')
|
||||
con->os->nextCharArg = origOptString + (*origOptString == '=');
|
||||
con->os->nextCharArg = origOptString;
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
|
||||
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
|
||||
if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
|
||||
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE
|
||||
|| (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
|
||||
if (longArg || (con->os->nextCharArg && con->os->nextCharArg[0] == '='))
|
||||
return POPT_ERROR_UNWANTEDARG;
|
||||
if (opt->arg) {
|
||||
if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
|
||||
long val = (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL ? opt->val : 1;
|
||||
if (poptSaveInt((int *)opt->arg, opt->argInfo, val))
|
||||
return POPT_ERROR_BADOPERATION;
|
||||
}
|
||||
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
|
||||
} else {
|
||||
con->os->nextArg = _free(con->os->nextArg);
|
||||
/*@-usedef@*/ /* FIX: W2DO? */
|
||||
if (longArg) {
|
||||
@@ -881,7 +882,7 @@ int poptGetNextOpt(poptContext con)
|
||||
longArg = expandNextArg(con, longArg);
|
||||
con->os->nextArg = longArg;
|
||||
} else if (con->os->nextCharArg) {
|
||||
longArg = expandNextArg(con, con->os->nextCharArg);
|
||||
longArg = expandNextArg(con, con->os->nextCharArg + (con->os->nextCharArg[0] == '='));
|
||||
con->os->nextArg = longArg;
|
||||
con->os->nextCharArg = NULL;
|
||||
} else {
|
||||
@@ -1202,6 +1203,8 @@ const char * poptStrerror(const int error)
|
||||
switch (error) {
|
||||
case POPT_ERROR_NOARG:
|
||||
return POPT_("missing argument");
|
||||
case POPT_ERROR_UNWANTEDARG:
|
||||
return POPT_("option does not take an argument");
|
||||
case POPT_ERROR_BADOPT:
|
||||
return POPT_("unknown option");
|
||||
case POPT_ERROR_BADOPERATION:
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
/*@{*/
|
||||
#define POPT_ERROR_NOARG -10 /*!< missing argument */
|
||||
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
|
||||
#define POPT_ERROR_UNWANTEDARG -12 /*!< option does not take an argument */
|
||||
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
|
||||
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
|
||||
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
conf: configure.sh config.h.in
|
||||
|
||||
configure.sh: configure.in aclocal.m4
|
||||
configure.sh: configure.ac aclocal.m4
|
||||
autoconf -o configure.sh
|
||||
|
||||
config.h.in: configure.in aclocal.m4
|
||||
config.h.in: configure.ac aclocal.m4
|
||||
autoheader && touch config.h.in
|
||||
|
||||
87
receiver.c
87
receiver.c
@@ -24,6 +24,7 @@
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int do_xfers;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int do_progress;
|
||||
extern int inc_recurse;
|
||||
@@ -53,7 +54,7 @@ extern mode_t orig_umask;
|
||||
extern struct stats stats;
|
||||
extern char *tmpdir;
|
||||
extern char *partial_dir;
|
||||
extern char *basis_dir[];
|
||||
extern char *basis_dir[MAX_BASIS_DIRS+1];
|
||||
extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
extern struct filter_list_struct daemon_filter_list;
|
||||
|
||||
@@ -63,31 +64,29 @@ static flist_ndx_list batch_redo_list;
|
||||
/* We're either updating the basis file or an identical copy: */
|
||||
static int updating_basis_or_equiv;
|
||||
|
||||
/*
|
||||
* get_tmpname() - create a tmp filename for a given filename
|
||||
*
|
||||
* If a tmpdir is defined, use that as the directory to
|
||||
* put it in. Otherwise, the tmp filename is in the same
|
||||
* directory as the given name. Note that there may be no
|
||||
* directory at all in the given name!
|
||||
*
|
||||
* The tmp filename is basically the given filename with a
|
||||
* dot prepended, and .XXXXXX appended (for mkstemp() to
|
||||
* put its unique gunk in). Take care to not exceed
|
||||
* either the MAXPATHLEN or NAME_MAX, esp. the last, as
|
||||
* the basename basically becomes 8 chars longer. In that
|
||||
* case, the original name is shortened sufficiently to
|
||||
* make it all fit.
|
||||
*
|
||||
* Of course, there's no real reason for the tmp name to
|
||||
* look like the original, except to satisfy us humans.
|
||||
* As long as it's unique, rsync will work.
|
||||
*/
|
||||
#define TMPNAME_SUFFIX ".XXXXXX"
|
||||
#define TMPNAME_SUFFIX_LEN ((int)sizeof TMPNAME_SUFFIX - 1)
|
||||
|
||||
/* get_tmpname() - create a tmp filename for a given filename
|
||||
*
|
||||
* If a tmpdir is defined, use that as the directory to put it in. Otherwise,
|
||||
* the tmp filename is in the same directory as the given name. Note that
|
||||
* there may be no directory at all in the given name!
|
||||
*
|
||||
* The tmp filename is basically the given filename with a dot prepended, and
|
||||
* .XXXXXX appended (for mkstemp() to put its unique gunk in). We take care
|
||||
* to not exceed either the MAXPATHLEN or NAME_MAX, especially the last, as
|
||||
* the basename basically becomes 8 characters longer. In such a case, the
|
||||
* original name is shortened sufficiently to make it all fit.
|
||||
*
|
||||
* Of course, the only reason the file is based on the original name is to
|
||||
* make it easier to figure out what purpose a temp file is serving when a
|
||||
* transfer is in progress. */
|
||||
int get_tmpname(char *fnametmp, const char *fname)
|
||||
{
|
||||
int maxname, added, length = 0;
|
||||
const char *f;
|
||||
char *suf;
|
||||
|
||||
if (tmpdir) {
|
||||
/* Note: this can't overflow, so the return value is safe */
|
||||
@@ -107,8 +106,9 @@ int get_tmpname(char *fnametmp, const char *fname)
|
||||
fnametmp[length++] = '.';
|
||||
|
||||
/* The maxname value is bufsize, and includes space for the '\0'.
|
||||
* (Note that NAME_MAX get -8 for the leading '.' above.) */
|
||||
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
|
||||
* NAME_MAX needs an extra -1 for the name's leading dot. */
|
||||
maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,
|
||||
NAME_MAX - 1 - TMPNAME_SUFFIX_LEN);
|
||||
|
||||
if (maxname < 1) {
|
||||
rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
|
||||
@@ -119,7 +119,17 @@ int get_tmpname(char *fnametmp, const char *fname)
|
||||
added = strlcpy(fnametmp + length, f, maxname);
|
||||
if (added >= maxname)
|
||||
added = maxname - 1;
|
||||
memcpy(fnametmp + length + added, ".XXXXXX", 8);
|
||||
suf = fnametmp + length + added;
|
||||
|
||||
/* Trim any dangling high-bit chars if the first-trimmed char (if any) is
|
||||
* also a high-bit char, just in case we cut into a multi-byte sequence.
|
||||
* We are guaranteed to stop because of the leading '.' we added. */
|
||||
if ((int)f[added] & 0x80) {
|
||||
while ((int)suf[-1] & 0x80)
|
||||
suf--;
|
||||
}
|
||||
|
||||
memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -131,15 +141,25 @@ int get_tmpname(char *fnametmp, const char *fname)
|
||||
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
|
||||
{
|
||||
int fd;
|
||||
mode_t added_perms;
|
||||
|
||||
if (!get_tmpname(fnametmp, fname))
|
||||
return -1;
|
||||
|
||||
if (am_root < 0) {
|
||||
/* For --fake-super, the file must be useable by the copying
|
||||
* user, just like it would be for root. */
|
||||
added_perms = S_IRUSR|S_IWUSR;
|
||||
} else {
|
||||
/* For a normal copy, we need to be able to tweak things like xattrs. */
|
||||
added_perms = S_IWUSR;
|
||||
}
|
||||
|
||||
/* We initially set the perms without the setuid/setgid bits or group
|
||||
* access to ensure that there is no race condition. They will be
|
||||
* correctly updated after the right owner and group info is set.
|
||||
* (Thanks to snabb@epipe.fi for pointing this out.) */
|
||||
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
|
||||
|
||||
#if 0
|
||||
/* In most cases parent directories will already exist because their
|
||||
@@ -149,7 +169,7 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
|
||||
&& create_directory_path(fnametmp) == 0) {
|
||||
/* Get back to name with XXXXXX in it. */
|
||||
get_tmpname(fnametmp, fname);
|
||||
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -249,8 +269,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"chunk[%d] of size %ld at %.0f offset=%.0f\n",
|
||||
i, (long)len, (double)offset2, (double)offset);
|
||||
"chunk[%d] of size %ld at %.0f offset=%.0f%s\n",
|
||||
i, (long)len, (double)offset2, (double)offset,
|
||||
updating_basis_or_equiv && offset == offset2 ? " (seek)" : "");
|
||||
}
|
||||
|
||||
if (mapbuf) {
|
||||
@@ -285,8 +306,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
goto report_write_error;
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
if (inplace && fd != -1
|
||||
&& ftruncate(fd, offset) < 0) {
|
||||
if (inplace && fd != -1 && do_ftruncate(fd, offset) < 0) {
|
||||
rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
@@ -295,7 +315,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
if (do_progress)
|
||||
end_progress(total_size);
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {
|
||||
report_write_error:
|
||||
rsyserr(FERROR_XFER, errno, "write failed on %s",
|
||||
full_fname(fname));
|
||||
@@ -483,14 +503,15 @@ int recv_files(int f_in, char *local_name)
|
||||
rprintf(FINFO, "recv_files(%s)\n", fname);
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (iflags & ITEM_REPORT_XATTR && do_xfers)
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
|
||||
recv_xattr_request(file, f_in);
|
||||
#endif
|
||||
|
||||
if (!(iflags & ITEM_TRANSFER)) {
|
||||
maybe_log_item(file, iflags, itemizing, xname);
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
|
||||
&& !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))
|
||||
set_file_attrs(fname, file, NULL, fname, 0);
|
||||
#endif
|
||||
continue;
|
||||
|
||||
24
rsync.c
24
rsync.c
@@ -42,8 +42,6 @@ extern int am_generator;
|
||||
extern int am_starting_up;
|
||||
extern int allow_8bit_chars;
|
||||
extern int protocol_version;
|
||||
extern int uid_ndx;
|
||||
extern int gid_ndx;
|
||||
extern int inc_recurse;
|
||||
extern int inplace;
|
||||
extern int flist_eof;
|
||||
@@ -425,7 +423,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
set_xattr(fname, file, fnamecmp, sxp);
|
||||
#endif
|
||||
|
||||
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
|
||||
if (!preserve_times
|
||||
|| (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
|
||||
|| (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
|
||||
flags |= ATTRS_SKIP_MTIME;
|
||||
if (!(flags & ATTRS_SKIP_MTIME)
|
||||
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
|
||||
@@ -444,7 +444,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
|
||||
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
|
||||
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
|
||||
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
|
||||
#ifndef CAN_CHOWN_SYMLINK
|
||||
if (S_ISLNK(sxp->st.st_mode)) {
|
||||
;
|
||||
} else
|
||||
@@ -463,9 +463,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
}
|
||||
}
|
||||
if (am_root >= 0) {
|
||||
if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
|
||||
gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
|
||||
if (do_lchown(fname, uid, gid) != 0) {
|
||||
/* We shouldn't have attempted to change uid
|
||||
* or gid unless have the privilege. */
|
||||
rsyserr(FERROR_XFER, errno, "%s %s failed",
|
||||
@@ -473,6 +473,10 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
|
||||
rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
|
||||
if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
|
||||
rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
|
||||
/* A lchown had been done, so we need to re-stat if
|
||||
* the destination had the setuid or setgid bits set
|
||||
* (due to the side effect of the chown call). */
|
||||
@@ -491,8 +495,10 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
* 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(). */
|
||||
if (preserve_acls && !S_ISLNK(new_mode) && set_acl(fname, file, sxp) == 0)
|
||||
updated = 1;
|
||||
if (preserve_acls && !S_ISLNK(new_mode)) {
|
||||
if (set_acl(fname, file, sxp, new_mode) > 0)
|
||||
updated = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
|
||||
27
rsync.h
27
rsync.h
@@ -65,6 +65,7 @@
|
||||
/* These flags are used in the live flist data. */
|
||||
|
||||
#define FLAG_TOP_DIR (1<<0) /* sender/receiver/generator */
|
||||
#define FLAG_OWNED_BY_US (1<<0) /* generator: set by make_file() for aux flists only */
|
||||
#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
|
||||
#define FLAG_DIR_CREATED (1<<1) /* generator */
|
||||
#define FLAG_CONTENT_DIR (1<<2) /* sender/receiver/generator */
|
||||
@@ -83,8 +84,12 @@
|
||||
|
||||
/* These flags are passed to functions but not stored. */
|
||||
|
||||
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
|
||||
#define FLAG_DIVERT_DIRS (1<<16) /* sender, but must be unique */
|
||||
|
||||
/* These flags are for get_dirlist(). */
|
||||
#define GDL_IGNORE_FILTER_RULES (1<<0)
|
||||
|
||||
/* Some helper macros for matching bits. */
|
||||
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
|
||||
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
|
||||
#define BITS_EQUAL(b1,b2,mask) (((unsigned)(b1) & (unsigned)(mask)) \
|
||||
@@ -95,7 +100,7 @@
|
||||
|
||||
/* This is used when working on a new protocol version in CVS, and should
|
||||
* be a new non-zero value for each CVS change that affects the protocol.
|
||||
* It must ALWAYS be 0 when the protocol goes final! */
|
||||
* It must ALWAYS be 0 when the protocol goes final (and NEVER before)! */
|
||||
#define SUBPROTOCOL_VERSION 0
|
||||
|
||||
/* We refuse to interoperate with versions that are not in this range.
|
||||
@@ -335,6 +340,18 @@ enum msgcode {
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_LUTIMES || defined HAVE_UTIMENSAT
|
||||
#define CAN_SET_SYMLINK_TIMES 1
|
||||
#endif
|
||||
|
||||
#if defined HAVE_LCHOWN || defined CHOWN_MODIFIES_SYMLINK
|
||||
#define CAN_CHOWN_SYMLINK 1
|
||||
#endif
|
||||
|
||||
#if defined HAVE_LCHMOD || defined HAVE_SETATTRLIST
|
||||
#define CAN_CHMOD_SYMLINK 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
@@ -430,6 +447,8 @@ typedef unsigned int mode_t;
|
||||
#endif
|
||||
#ifndef HAVE_OFF_T
|
||||
typedef long off_t;
|
||||
#undef SIZEOF_OFF_T
|
||||
#define SIZEOF_OFF_T SIZEOF_LONG
|
||||
#endif
|
||||
#ifndef HAVE_SIZE_T
|
||||
typedef unsigned int size_t;
|
||||
@@ -1067,6 +1086,10 @@ extern int errno;
|
||||
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
|
||||
|
||||
#define PRESERVE_FILE_TIMES (1<<0)
|
||||
#define PRESERVE_DIR_TIMES (1<<1)
|
||||
#define PRESERVE_LINK_TIMES (1<<2)
|
||||
|
||||
/* Initial mask on permissions given to temporary files. Mask off setuid
|
||||
bits and group access because of potential race-condition security
|
||||
holes, and mask other access because mode 707 is bizarre */
|
||||
|
||||
197
rsync.yo
197
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(31 Dec 2009)()()
|
||||
manpage(rsync)(1)(23 Sep 2011)()()
|
||||
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -281,6 +281,19 @@ 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.
|
||||
|
||||
manpagesection(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
|
||||
bf(--delay-updates) (which doesn't affect the sorted transfer order, but
|
||||
does make the final file-updating phase happen much more rapidly).
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
|
||||
Here are some examples of how I use rsync.
|
||||
@@ -367,10 +380,10 @@ to the detailed description below for a complete description. verb(
|
||||
--remove-source-files sender removes synchronized files (non-dir)
|
||||
--del an alias for --delete-during
|
||||
--delete delete extraneous files from dest dirs
|
||||
--delete-before receiver deletes before transfer (default)
|
||||
--delete-during receiver deletes during xfer, not before
|
||||
--delete-before receiver deletes before xfer, not during
|
||||
--delete-during receiver deletes during the transfer
|
||||
--delete-delay find deletions during, delete after
|
||||
--delete-after receiver deletes after transfer, not before
|
||||
--delete-after receiver deletes after transfer, not during
|
||||
--delete-excluded also delete excluded files from dest dirs
|
||||
--ignore-errors delete even if there are I/O errors
|
||||
--force force deletion of dirs even if not empty
|
||||
@@ -451,11 +464,17 @@ accepted: verb(
|
||||
|
||||
manpageoptions()
|
||||
|
||||
rsync uses the GNU long options package. Many of the command line
|
||||
options have two variants, one short and one long. These are shown
|
||||
below, separated by commas. Some options only have a long variant.
|
||||
The '=' for options that take a parameter is optional; whitespace
|
||||
can be used instead.
|
||||
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).
|
||||
|
||||
startdit()
|
||||
dit(bf(--help)) Print a short help page describing the options
|
||||
@@ -688,6 +707,12 @@ specify a backup suffix using the bf(--suffix) option
|
||||
(otherwise the files backed up in the specified directory
|
||||
will keep their original filenames).
|
||||
|
||||
Note that if you specify a relative path, the backup directory will be
|
||||
relative to the destination directory, so you probably want to specify
|
||||
either an absolute path or a path that starts with "../". If an rsync
|
||||
daemon is the receiver, the backup dir cannot go outside the module's path
|
||||
hierarchy, so take extra care not to delete it or copy into it.
|
||||
|
||||
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
|
||||
backup suffix used with the bf(--backup) (bf(-b)) option. The default suffix is a ~
|
||||
if no -bf(-backup-dir) was specified, otherwise it is an empty string.
|
||||
@@ -713,24 +738,36 @@ its data needs to be updated: instead of the default method of creating
|
||||
a new copy of the file and moving it into place when it is complete, rsync
|
||||
instead writes the updated data directly to the destination file.
|
||||
|
||||
This has several effects: (1) in-use binaries cannot be updated (either the
|
||||
OS will prevent this from happening, or binaries that attempt to swap-in
|
||||
their data will misbehave or crash), (2) the file's data will be in an
|
||||
inconsistent state during the transfer, (3) a file's data may be left in an
|
||||
inconsistent state after the transfer if the transfer is interrupted or if
|
||||
an update fails, (4) a file that does not have write permissions can not be
|
||||
updated, and (5) the efficiency of rsync's delta-transfer algorithm may be
|
||||
reduced if some data in the destination file is overwritten before it can
|
||||
be copied to a position later in the file (one exception to this is if you
|
||||
combine this option with bf(--backup), since rsync is smart enough to use
|
||||
the backup file as the basis file for the transfer).
|
||||
This has several effects:
|
||||
|
||||
quote(itemization(
|
||||
it() Hard links are not broken. This means the new data will be visible
|
||||
through other hard links to the destination file. Moreover, attempts to
|
||||
copy differing source files onto a multiply-linked destination file will
|
||||
result in a "tug of war" with the destination data changing back and forth.
|
||||
it() In-use binaries cannot be updated (either the OS will prevent this from
|
||||
happening, or binaries that attempt to swap-in their data will misbehave or
|
||||
crash).
|
||||
it() The file's data will be in an inconsistent state during the transfer
|
||||
and will be left that way if the transfer is interrupted or if an update
|
||||
fails.
|
||||
it() A file that rsync cannot write to cannot be updated. While a super user
|
||||
can update any file, a normal user needs to be granted write permission for
|
||||
the open of the file for writing to be successful.
|
||||
it() The efficiency of rsync's delta-transfer algorithm may be reduced if
|
||||
some data in the destination file is overwritten before it can be copied to
|
||||
a position later in the file. This does not apply if you use bf(--backup),
|
||||
since rsync is smart enough to use the backup file as the basis file for the
|
||||
transfer.
|
||||
))
|
||||
|
||||
WARNING: you should not use this option to update files that are being
|
||||
accessed by others, so be careful when choosing to use this for a copy.
|
||||
|
||||
This option is useful for transferring large files with block-based changes
|
||||
or appended data, and also on systems that are disk bound, not network
|
||||
bound.
|
||||
bound. It can also help keep a copy-on-write filesystem snapshot from
|
||||
diverging the entire contents of a file that only has minor changes.
|
||||
|
||||
The option implies bf(--partial) (since an interrupted transfer does not delete
|
||||
the file), but conflicts with bf(--partial-dir) and bf(--delay-updates).
|
||||
@@ -814,6 +851,17 @@ bf(--force) or bf(--delete) is in effect).
|
||||
See also bf(--keep-dirlinks) for an analogous option for the receiving
|
||||
side.
|
||||
|
||||
bf(--copy-dirlinks) applies to all symlinks to directories in the source. If
|
||||
you want to follow only a few specified symlinks, a trick you can use is to
|
||||
pass them as additional source args with a trailing slash, using bf(--relative)
|
||||
to make the paths match up right. For example:
|
||||
|
||||
quote(tt(rsync -r --relative src/./ src/./follow-me/ dest/))
|
||||
|
||||
This works because rsync calls bf(lstat)(2) on the source arg as given, and the
|
||||
trailing slash makes bf(lstat)(2) follow the symlink, giving rise to a directory
|
||||
in the file-list which overrides the symlink found during the scan of "src/./".
|
||||
|
||||
dit(bf(-K, --keep-dirlinks)) This option causes the receiving side to treat
|
||||
a symlink to a directory as though it were a real directory, but only if it
|
||||
matches a real directory from the sender. Without this option, the
|
||||
@@ -837,17 +885,25 @@ to modify your receiving hierarchy.
|
||||
See also bf(--copy-dirlinks) for an analogous option for the sending side.
|
||||
|
||||
dit(bf(-H, --hard-links)) This tells rsync to look for hard-linked files in
|
||||
the transfer and link together the corresponding files on the receiving
|
||||
side. Without this option, hard-linked files in the transfer are treated
|
||||
the source and link together the corresponding files on the destination.
|
||||
Without this option, hard-linked files in the source are treated
|
||||
as though they were separate files.
|
||||
|
||||
When you are updating a non-empty destination, this option only ensures
|
||||
that files that are hard-linked together on the source are hard-linked
|
||||
together on the destination. It does NOT currently endeavor to break
|
||||
already existing hard links on the destination that do not exist between
|
||||
the source files. Note, however, that if one or more extra-linked files
|
||||
have content changes, they will become unlinked when updated (assuming you
|
||||
are not using the bf(--inplace) option).
|
||||
This option does NOT necessarily ensure that the pattern of hard links on the
|
||||
destination exactly matches that on the source. Cases in which the
|
||||
destination may end up with extra hard links include the following:
|
||||
|
||||
quote(itemization(
|
||||
it() If the destination contains extraneous hard-links (more linking than
|
||||
what is present in the source file list), the copying algorithm will not
|
||||
break them explicitly. However, if one or more of the paths have content
|
||||
differences, the normal file-update process will break those extra links
|
||||
(unless you are using the bf(--inplace) option).
|
||||
it() If you specify a bf(--link-dest) directory that contains hard links,
|
||||
the linking of the destination files against the bf(--link-dest) files can
|
||||
cause some paths in the destination to become linked together due to the
|
||||
bf(--link-dest) associations.
|
||||
))
|
||||
|
||||
Note that rsync can only detect hard links between files that are inside
|
||||
the transfer set. If rsync updates a file that has extra hard-link
|
||||
@@ -860,7 +916,10 @@ see the bf(--inplace) option for more caveats).
|
||||
If incremental recursion is active (see bf(--recursive)), rsync may transfer
|
||||
a missing hard-linked file before it finds that another link for that contents
|
||||
exists elsewhere in the hierarchy. This does not affect the accuracy of
|
||||
the transfer, just its efficiency. One way to avoid this is to disable
|
||||
the transfer (i.e. which files are hard-linked together), just its efficiency
|
||||
(i.e. copying the data for a new, early copy of a hard-linked file that could
|
||||
have been found later in the transfer in another member of the hard-linked
|
||||
set of files). One way to avoid this inefficiency is to disable
|
||||
incremental recursion using the bf(--no-inc-recursive) option.
|
||||
|
||||
dit(bf(-p, --perms)) This option causes the receiving rsync to set the
|
||||
@@ -938,16 +997,20 @@ The source and destination systems must have compatible ACL entries for this
|
||||
option to work properly. See the bf(--fake-super) option for a way to backup
|
||||
and restore ACLs that are not compatible.
|
||||
|
||||
dit(bf(-X, --xattrs)) This option causes rsync to update the remote
|
||||
extended attributes to be the same as the local ones.
|
||||
dit(bf(-X, --xattrs)) This option causes rsync to update the destination
|
||||
extended attributes to be the same as the source ones.
|
||||
|
||||
For systems that support extended-attribute namespaces, a copy being done by a
|
||||
super-user copies all namespaces except system.*. A normal user only copies
|
||||
the user.* namespace. To be able to backup and restore non-user namespaces as
|
||||
a normal user, see the bf(--fake-super) option.
|
||||
|
||||
Note that this option does not copy rsyncs special xattr values (e.g. those
|
||||
used by bf(--fake-super)) unless you repeat the option (e.g. -XX). This
|
||||
"copy all xattrs" mode cannot be used with bf(--fake-super).
|
||||
|
||||
dit(bf(--chmod)) This option tells rsync to apply one or more
|
||||
comma-separated "chmod" strings to the permission of the files in the
|
||||
comma-separated "chmod" modes to the permission of the files in the
|
||||
transfer. The resulting value is treated as though it were the permissions
|
||||
that the sending side supplied for the file, which means that this option
|
||||
can seem to have no effect on existing files if bf(--perms) is not enabled.
|
||||
@@ -955,7 +1018,10 @@ can seem to have no effect on existing files if bf(--perms) is not enabled.
|
||||
In addition to the normal parsing rules specified in the bf(chmod)(1)
|
||||
manpage, you can specify an item that should only apply to a directory by
|
||||
prefixing it with a 'D', or specify an item that should only apply to a
|
||||
file by prefixing it with a 'F'. For example:
|
||||
file by prefixing it with a 'F'. For example, the following will ensure
|
||||
that all directories get marked set-gid, that no files are other-writable,
|
||||
that both are user-writable and group-writable, and that both have
|
||||
consistent executability across all bits:
|
||||
|
||||
quote(--chmod=Dg+s,ug+w,Fo-w,+X)
|
||||
|
||||
@@ -1056,10 +1122,6 @@ dit(bf(-S, --sparse)) Try to handle sparse files efficiently so they take
|
||||
up less space on the destination. Conflicts with bf(--inplace) because it's
|
||||
not possible to overwrite data in a sparse fashion.
|
||||
|
||||
NOTE: Don't use this option when the destination is a Solaris "tmpfs"
|
||||
filesystem. It seems to have problems seeking over null regions,
|
||||
and ends up corrupting the files.
|
||||
|
||||
dit(bf(-n, --dry-run)) This makes rsync perform a trial run that doesn't
|
||||
make any changes (and produces mostly the same output as a real run). It
|
||||
is most commonly used in combination with the bf(-v, --verbose) and/or
|
||||
@@ -1131,6 +1193,16 @@ dit(bf(--remove-source-files)) This tells rsync to remove from the sending
|
||||
side the files (meaning non-directories) that are a part of the transfer
|
||||
and have been successfully duplicated on the receiving side.
|
||||
|
||||
Note that you should only use this option on source files that are quiescent.
|
||||
If you are using this to move files that show up in a particular directory over
|
||||
to another host, make sure that the finished files get renamed into the source
|
||||
directory, not directly written into it, so that rsync can't possibly transfer
|
||||
a file that is not yet fully written. If you can't first write the files into
|
||||
a different directory, you should use a naming idiom that lets rsync avoid
|
||||
transferring files that are not yet finished (e.g. name the file "foo.new" when
|
||||
it is written, rename it to "foo" when it is done, and then use the option
|
||||
bf(--exclude='*.new') for the rsync transfer).
|
||||
|
||||
dit(bf(--delete)) This tells rsync to delete extraneous files from the
|
||||
receiving side (ones that aren't on the sending side), but only for the
|
||||
directories that are being synchronized. You must have asked rsync to
|
||||
@@ -1322,7 +1394,7 @@ initial items are marked as perishable -- see the FILTER RULES section):
|
||||
|
||||
quote(quote(tt(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
|
||||
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej .del-*
|
||||
*.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .git/ .bzr/)))
|
||||
*.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .git/ .hg/ .bzr/)))
|
||||
|
||||
then, files listed in a $HOME/.cvsignore are added to the list and any
|
||||
files listed in the CVSIGNORE environment variable (all cvsignore names
|
||||
@@ -1452,6 +1524,12 @@ bf(--files-from) filenames are being sent from one host to another, the
|
||||
filenames will be translated from the sending host's charset to the
|
||||
receiving host's charset.
|
||||
|
||||
NOTE: sorting the list of files in the --files-from input helps rsync to be
|
||||
more efficient, as it will avoid re-visiting the path elements that are shared
|
||||
between adjacent entries. If the input is not sorted, some path elements
|
||||
(implied directories) may end up being scanned multiple times, and rsync will
|
||||
eventually unduplicate them after they get turned into file-list elements.
|
||||
|
||||
dit(bf(-0, --from0)) This tells rsync that the rules/filenames it reads from a
|
||||
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
|
||||
This affects bf(--exclude-from), bf(--include-from), bf(--files-from), and any
|
||||
@@ -1610,7 +1688,7 @@ You may specify an empty string to indicate that no file should be skipped.
|
||||
|
||||
Simple character-class matching is supported: each must consist of a list
|
||||
of letters inside the square brackets (e.g. no special classes, such as
|
||||
"[:alpha:]", are supported).
|
||||
"[:alpha:]", are supported, and '-' has no special meaning).
|
||||
|
||||
The characters asterisk (*) and question-mark (?) have no special meaning.
|
||||
|
||||
@@ -1619,10 +1697,26 @@ matches 2 suffixes):
|
||||
|
||||
verb( --skip-compress=gz/jpg/mp[34]/7z/bz2)
|
||||
|
||||
The default list of suffixes that will not be compressed is this (several
|
||||
of these are newly added for 3.0.0):
|
||||
The default list of suffixes that will not be compressed is this (in this
|
||||
version of rsync):
|
||||
|
||||
verb( gz/zip/z/rpm/deb/iso/bz2/t[gb]z/7z/mp[34]/mov/avi/ogg/jpg/jpeg)
|
||||
bf(7z)
|
||||
bf(avi)
|
||||
bf(bz2)
|
||||
bf(deb)
|
||||
bf(gz)
|
||||
bf(iso)
|
||||
bf(jpeg)
|
||||
bf(jpg)
|
||||
bf(mov)
|
||||
bf(mp3)
|
||||
bf(mp4)
|
||||
bf(ogg)
|
||||
bf(rpm)
|
||||
bf(tbz)
|
||||
bf(tgz)
|
||||
bf(z)
|
||||
bf(zip)
|
||||
|
||||
This list will be replaced by your bf(--skip-compress) list in all but one
|
||||
situation: a copy from a daemon rsync will add your skipped suffixes to
|
||||
@@ -2021,7 +2115,8 @@ transfer that may be interrupted.
|
||||
|
||||
dit(bf(--password-file)) This option allows you to provide a password in a
|
||||
file for accessing an rsync daemon. The file must not be world readable.
|
||||
It should contain just the password as a single line.
|
||||
It should contain just the password as the first line of the file (all
|
||||
other lines are ignored).
|
||||
|
||||
This option does not supply a password to a remote shell transport such as
|
||||
ssh; to learn how to do that, consult the remote shell's documentation.
|
||||
@@ -2464,10 +2559,14 @@ itemization(
|
||||
also disabled).
|
||||
it() You may also specify any of the modifiers for the "+" or "-" rules
|
||||
(above) in order to have the rules that are read in from the file
|
||||
default to having that modifier set. For instance, "merge,-/ .excl" would
|
||||
default to having that modifier set (except for the bf(!) modifier, which
|
||||
would not be useful). For instance, "merge,-/ .excl" would
|
||||
treat the contents of .excl as absolute-path excludes,
|
||||
while "dir-merge,s .filt" and ":sC" would each make all their
|
||||
per-directory rules apply only on the sending side.
|
||||
per-directory rules apply only on the sending side. If the merge rule
|
||||
specifies sides to affect (via the bf(s) or bf(r) modifier or both),
|
||||
then the rules in the file must not specify sides (via a modifier or
|
||||
a rule prefix such as bf(hide)).
|
||||
)
|
||||
|
||||
Per-directory rules are inherited in all subdirectories of the directory
|
||||
@@ -2881,7 +2980,7 @@ dit(bf(CVSIGNORE)) The CVSIGNORE environment variable supplements any
|
||||
ignore patterns in .cvsignore files. See the bf(--cvs-exclude) option for
|
||||
more details.
|
||||
dit(bf(RSYNC_ICONV)) Specify a default bf(--iconv) setting using this
|
||||
environment variable.
|
||||
environment variable. (First supported in 3.0.0.)
|
||||
dit(bf(RSYNC_RSH)) The RSYNC_RSH environment variable allows you to
|
||||
override the default shell used as the transport for rsync. Command line
|
||||
options are permitted after the command name, just as in the bf(-e) option.
|
||||
@@ -2926,7 +3025,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.7 of rsync.
|
||||
This man page is current for version 3.0.9 of rsync.
|
||||
|
||||
manpagesection(INTERNAL OPTIONS)
|
||||
|
||||
|
||||
30
rsync3.txt
30
rsync3.txt
@@ -1,6 +1,6 @@
|
||||
-*- indented-text -*-
|
||||
|
||||
Notes towards a new version of rsync
|
||||
Notes towards a new version of rsync
|
||||
Martin Pool <mbp@samba.org>, September 2001.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ Good things about the current implementation:
|
||||
|
||||
- Fairly reliable.
|
||||
|
||||
- The choice of runnning over a plain TCP socket or tunneling over
|
||||
- The choice of running over a plain TCP socket or tunneling over
|
||||
ssh.
|
||||
|
||||
- rsync operations are idempotent: you can always run the same
|
||||
@@ -51,7 +51,7 @@ Bad things about the current implementation:
|
||||
hard to modify/extend
|
||||
|
||||
- Both the program and the protocol assume a single non-interactive
|
||||
one-way transfer
|
||||
one-way transfer
|
||||
|
||||
- A list of all files are held in memory for the entire transfer,
|
||||
which cripples scalability to large file trees
|
||||
@@ -88,7 +88,7 @@ Protocol philosophy:
|
||||
|
||||
Questionable features:
|
||||
|
||||
These are neat, but not necessarily clean or worth preserving.
|
||||
These are neat, but not necessarily clean or worth preserving.
|
||||
|
||||
- The remote rsync can be wrapped by some other program, such as in
|
||||
tridge's rsync-mail scripts. The general feature of sending and
|
||||
@@ -100,7 +100,7 @@ Desirable features:
|
||||
|
||||
These don't really require architectural changes; they're just
|
||||
something to keep in mind.
|
||||
|
||||
|
||||
- Synchronize ACLs and extended attributes
|
||||
|
||||
- Anonymous servers should be efficient
|
||||
@@ -122,7 +122,7 @@ Desirable features:
|
||||
Alternatively, as long as transfers are idempotent, we can just
|
||||
restart the whole thing. [NFSv4]
|
||||
|
||||
- Scripting support.
|
||||
- Scripting support.
|
||||
|
||||
- Propagate atimes and do not modify them. This is very ugly on
|
||||
Unix. It might be better to try to add O_NOATIME to kernels, and
|
||||
@@ -224,7 +224,7 @@ Scripting hooks:
|
||||
- What basis file to use
|
||||
|
||||
- Logging
|
||||
|
||||
|
||||
- Whether to allow transfers (for public servers)
|
||||
|
||||
- Authentication
|
||||
@@ -275,7 +275,7 @@ Pie-in-the-sky features:
|
||||
|
||||
These might have a severe impact on the protocol, and are not
|
||||
clearly in our core requirements. It looks like in many of them
|
||||
having scripting hooks will allow us
|
||||
having scripting hooks will allow us
|
||||
|
||||
- Transport over UDP multicast. The hard part is handling multiple
|
||||
destinations which have different basis files. We can look at
|
||||
@@ -344,7 +344,7 @@ In favour of using a new protocol:
|
||||
|
||||
- If we start from scratch, it can be documented as we go, and we
|
||||
can avoid design decisions that make the protocol complex or
|
||||
implementation-bound.
|
||||
implementation-bound.
|
||||
|
||||
|
||||
Error handling:
|
||||
@@ -365,7 +365,7 @@ Concurrency:
|
||||
- We can do nonblocking network IO, but not so for disk.
|
||||
|
||||
- It makes sense to on the destination be generating signatures and
|
||||
applying patches at the same time.
|
||||
applying patches at the same time.
|
||||
|
||||
- Can structure this with nonblocking, threads, separate processes,
|
||||
etc.
|
||||
@@ -381,7 +381,7 @@ Uses:
|
||||
http://www.ietf.org/proceedings/00jul/00july-133.htm#P24510_1276764
|
||||
|
||||
- Sync with PDA
|
||||
|
||||
|
||||
- Network backup systems
|
||||
|
||||
- CVS filemover
|
||||
@@ -419,7 +419,7 @@ Filesystem migration:
|
||||
Atomic updates:
|
||||
|
||||
The NFSv4 working group wants atomic migration. Most of the
|
||||
responsibility for this lies on the NFS server or OS.
|
||||
responsibility for this lies on the NFS server or OS.
|
||||
|
||||
If migrating a whole tree, then we could do a nearly-atomic rename
|
||||
at the end. This ties in to having separate basis and destination
|
||||
@@ -427,11 +427,11 @@ Atomic updates:
|
||||
|
||||
There's no way in Unix to replace a whole set of files atomically.
|
||||
However, if we get them all onto the destination machine and then do
|
||||
the updates quickly it would greatly reduce the window.
|
||||
the updates quickly it would greatly reduce the window.
|
||||
|
||||
|
||||
Scalability:
|
||||
|
||||
|
||||
We should aim to work well on machines in use in a year or two.
|
||||
That probably means transfers of many millions of files in one
|
||||
batch, and gigabytes or terabytes of data.
|
||||
@@ -466,4 +466,4 @@ Related work:
|
||||
- http://freshmeat.net/search/?site=Freshmeat&q=mirror§ion=projects
|
||||
|
||||
- BitTorrent -- p2p mirroring
|
||||
http://bitconjurer.org/BitTorrent/
|
||||
http://bitconjurer.org/BitTorrent/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(31 Dec 2009)()()
|
||||
manpage(rsyncd.conf)(5)(23 Sep 2011)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -127,6 +127,12 @@ dit(bf(path)) This parameter specifies the directory in the daemon's
|
||||
filesystem to make available in this module. You must specify this parameter
|
||||
for each module in tt(rsyncd.conf).
|
||||
|
||||
It is fine if the path includes internal spaces -- they will be retained
|
||||
verbatim (which means that you shouldn't try to escape them). If your final
|
||||
directory has a trailing space (and this is somehow not something you wish to
|
||||
fix), append a trailing slash to the path to avoid losing the trailing
|
||||
whitespace.
|
||||
|
||||
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
|
||||
to the "path" before starting the file transfer with the client. This has
|
||||
the advantage of extra protection against possible implementation security
|
||||
@@ -310,7 +316,7 @@ was run as root. This complements the "uid" parameter. The default is gid -2,
|
||||
which is normally the group "nobody".
|
||||
|
||||
dit(bf(fake super)) Setting "fake super = yes" for a module causes the
|
||||
daemon side to behave as if the bf(--fake-user) command-line option had
|
||||
daemon side to behave as if the bf(--fake-super) command-line option had
|
||||
been specified. This allows the full attributes of a file to be stored
|
||||
without having to have the daemon actually running as root.
|
||||
|
||||
@@ -700,7 +706,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.7 of rsync.
|
||||
This man page is current for version 3.0.9 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
|
||||
@@ -129,7 +129,10 @@ RUNSHFLAGS='-e'
|
||||
export RUNSHFLAGS
|
||||
|
||||
# for Solaris
|
||||
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
|
||||
if [ -d /usr/xpg4/bin ]; then
|
||||
PATH="/usr/xpg4/bin/:$PATH"
|
||||
export PATH
|
||||
fi
|
||||
|
||||
if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
|
||||
if set -x; then
|
||||
|
||||
155
socket.c
155
socket.c
@@ -26,8 +26,12 @@
|
||||
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
#ifdef HAVE_NETINET_IN_SYSTM_H
|
||||
#include <netinet/in_systm.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IP_H
|
||||
#include <netinet/ip.h>
|
||||
#endif
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
extern char *bind_address;
|
||||
@@ -39,12 +43,11 @@ extern int connect_timeout;
|
||||
static struct sigaction sigact;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Establish a proxy connection on an open socket to a web proxy by
|
||||
* using the CONNECT method. If proxy_user and proxy_pass are not NULL,
|
||||
* they are used to authenticate to the proxy using the "Basic"
|
||||
* proxy-authorization protocol
|
||||
**/
|
||||
static int sock_exec(const char *prog);
|
||||
|
||||
/* Establish a proxy connection on an open socket to a web proxy by using the
|
||||
* CONNECT method. If proxy_user and proxy_pass are not NULL, they are used to
|
||||
* authenticate to the proxy using the "Basic" proxy-authorization protocol. */
|
||||
static int establish_proxy_connection(int fd, char *host, int port,
|
||||
char *proxy_user, char *proxy_pass)
|
||||
{
|
||||
@@ -125,10 +128,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to set the local address for a newly-created socket. Return -1
|
||||
* if this fails.
|
||||
**/
|
||||
/* Try to set the local address for a newly-created socket.
|
||||
* Return -1 if this fails. */
|
||||
int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
const char *bind_addr)
|
||||
{
|
||||
@@ -165,31 +166,27 @@ static RETSIGTYPE contimeout_handler(UNUSED(int val))
|
||||
connect_timeout = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a socket to a tcp remote host with the specified port .
|
||||
/* Open a socket to a tcp remote host with the specified port.
|
||||
*
|
||||
* Based on code from Warren. Proxy support by Stephen Rothwell.
|
||||
* getaddrinfo() rewrite contributed by KAME.net.
|
||||
*
|
||||
* Now that we support IPv6 we need to look up the remote machine's
|
||||
* address first, using @p af_hint to set a preference for the type
|
||||
* of address. Then depending on whether it has v4 or v6 addresses we
|
||||
* try to open a connection.
|
||||
* Now that we support IPv6 we need to look up the remote machine's address
|
||||
* first, using af_hint to set a preference for the type of address. Then
|
||||
* depending on whether it has v4 or v6 addresses we try to open a connection.
|
||||
*
|
||||
* The loop allows for machines with some addresses which may not be
|
||||
* reachable, perhaps because we can't e.g. route ipv6 to that network
|
||||
* but we can get ip4 packets through.
|
||||
* The loop allows for machines with some addresses which may not be reachable,
|
||||
* perhaps because we can't e.g. route ipv6 to that network but we can get ip4
|
||||
* packets through.
|
||||
*
|
||||
* @param bind_addr Local address to use. Normally NULL to bind
|
||||
* the wildcard address.
|
||||
* bind_addr: local address to use. Normally NULL to bind the wildcard address.
|
||||
*
|
||||
* @param af_hint Address family, e.g. AF_INET or AF_INET6.
|
||||
**/
|
||||
* af_hint: address family, e.g. AF_INET or AF_INET6. */
|
||||
int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
int type = SOCK_STREAM;
|
||||
int error, s;
|
||||
int error, s, j, addr_cnt, *errnos;
|
||||
struct addrinfo hints, *res0, *res;
|
||||
char portbuf[10];
|
||||
char *h, *cp;
|
||||
@@ -251,12 +248,17 @@ int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}
|
||||
errnos = new_array0(int, addr_cnt);
|
||||
if (!errnos)
|
||||
out_of_memory("open_socket_out");
|
||||
|
||||
s = -1;
|
||||
/* Try to connect to all addresses for this machine until we get
|
||||
* through. It might e.g. be multi-homed, or have both IPv4 and IPv6
|
||||
* addresses. We need to create a socket for each record, since the
|
||||
* address record tells us what protocol to use to try to connect. */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
for (res = res0, j = 0; res; res = res->ai_next, j++) {
|
||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (s < 0)
|
||||
continue;
|
||||
@@ -287,8 +289,10 @@ int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
if (connect_timeout > 0)
|
||||
alarm(0);
|
||||
|
||||
if (s < 0)
|
||||
if (s < 0) {
|
||||
errnos[j] = errno;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (proxied
|
||||
&& establish_proxy_connection(s, host, port,
|
||||
@@ -297,19 +301,36 @@ int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
char buf[2048];
|
||||
if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0)
|
||||
snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error));
|
||||
rprintf(FINFO, "Connected to %s (%s)\n", h, buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
if (s < 0) {
|
||||
rsyserr(FERROR, errno, "failed to connect to %s", h);
|
||||
return -1;
|
||||
|
||||
if (s < 0 || verbose >= 3) {
|
||||
char buf[2048];
|
||||
for (res = res0, j = 0; res; res = res->ai_next, j++) {
|
||||
if (errnos[j] == 0)
|
||||
continue;
|
||||
if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0)
|
||||
snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error));
|
||||
rsyserr(FERROR, errnos[j], "failed to connect to %s (%s)", h, buf);
|
||||
}
|
||||
if (s < 0)
|
||||
s = -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
free(errnos);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open an outgoing socket, but allow for it to be intercepted by
|
||||
/* Open an outgoing socket, but allow for it to be intercepted by
|
||||
* $RSYNC_CONNECT_PROG, which will execute a program across a TCP
|
||||
* socketpair rather than really opening a socket.
|
||||
*
|
||||
@@ -318,8 +339,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
*
|
||||
* This is based on the Samba LIBSMB_PROG feature.
|
||||
*
|
||||
* @param bind_addr Local address to use. Normally NULL to get the stack default.
|
||||
**/
|
||||
* bind_addr: local address to use. Normally NULL to get the stack default. */
|
||||
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
@@ -372,9 +392,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Open one or more sockets for incoming data using the specified type,
|
||||
/* Open one or more sockets for incoming data using the specified type,
|
||||
* port, and address.
|
||||
*
|
||||
* The getaddrinfo() call may return several address results, e.g. for
|
||||
@@ -383,9 +401,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
|
||||
* We return an array of file-descriptors to the sockets, with a trailing
|
||||
* -1 value to indicate the end of the list.
|
||||
*
|
||||
* @param bind_addr Local address to bind, or NULL to allow it to
|
||||
* default.
|
||||
**/
|
||||
* bind_addr: local address to bind, or NULL to allow it to default. */
|
||||
static int *open_socket_in(int type, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
@@ -490,9 +506,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine if a file descriptor is in fact a socket
|
||||
*/
|
||||
/* Determine if a file descriptor is in fact a socket. */
|
||||
int is_a_socket(int fd)
|
||||
{
|
||||
int v;
|
||||
@@ -632,7 +646,9 @@ struct
|
||||
} socket_options[] = {
|
||||
{"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
|
||||
{"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
|
||||
#ifdef SO_BROADCAST
|
||||
{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
|
||||
#endif
|
||||
#ifdef TCP_NODELAY
|
||||
{"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
|
||||
#endif
|
||||
@@ -660,13 +676,11 @@ struct
|
||||
#ifdef SO_RCVTIMEO
|
||||
{"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
|
||||
#endif
|
||||
{NULL,0,0,0,0}};
|
||||
{NULL,0,0,0,0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set user socket options
|
||||
**/
|
||||
/* Set user socket options. */
|
||||
void set_socket_options(int fd, char *options)
|
||||
{
|
||||
char *tok;
|
||||
@@ -732,15 +746,10 @@ void set_socket_options(int fd, char *options)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is like socketpair but uses tcp. It is used by the Samba
|
||||
* regression test code.
|
||||
*
|
||||
* The function guarantees that nobody else can attach to the socket,
|
||||
* or if they do that this function fails and the socket gets closed
|
||||
* returns 0 on success, -1 on failure the resulting file descriptors
|
||||
* are symmetrical.
|
||||
**/
|
||||
/* This is like socketpair but uses tcp. The function guarantees that nobody
|
||||
* else can attach to the socket, or if they do that this function fails and
|
||||
* the socket gets closed. Returns 0 on success, -1 on failure. The resulting
|
||||
* file descriptors are symmetrical. Currently only for RSYNC_CONNECT_PROG. */
|
||||
static int socketpair_tcp(int fd[2])
|
||||
{
|
||||
int listener;
|
||||
@@ -761,16 +770,12 @@ static int socketpair_tcp(int fd[2])
|
||||
sock2.sin_len = sizeof sock2;
|
||||
#endif
|
||||
sock2.sin_family = PF_INET;
|
||||
sock2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
|
||||
|
||||
if (listen(listener, 1) != 0)
|
||||
goto failed;
|
||||
|
||||
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
|
||||
goto failed;
|
||||
|
||||
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
if (bind(listener, (struct sockaddr *)&sock2, sizeof sock2) != 0
|
||||
|| listen(listener, 1) != 0
|
||||
|| getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0
|
||||
|| (fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
goto failed;
|
||||
|
||||
set_nonblocking(fd[1]);
|
||||
@@ -783,7 +788,7 @@ static int socketpair_tcp(int fd[2])
|
||||
} else
|
||||
connect_done = 1;
|
||||
|
||||
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
|
||||
if ((fd[0] = accept(listener, (struct sockaddr *)&sock2, &socklen)) == -1)
|
||||
goto failed;
|
||||
|
||||
close(listener);
|
||||
@@ -811,17 +816,13 @@ static int socketpair_tcp(int fd[2])
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run a program on a local tcp socket, so that we can talk to it's
|
||||
* stdin and stdout. This is used to fake a connection to a daemon
|
||||
* for testing -- not for the normal case of running SSH.
|
||||
/* Run a program on a local tcp socket, so that we can talk to it's stdin and
|
||||
* stdout. This is used to fake a connection to a daemon for testing -- not
|
||||
* for the normal case of running SSH.
|
||||
*
|
||||
* @return a socket which is attached to a subprocess running
|
||||
* "prog". stdin and stdout are attached. stderr is left attached to
|
||||
* the original stderr
|
||||
**/
|
||||
int sock_exec(const char *prog)
|
||||
* Retruns a socket which is attached to a subprocess running "prog". stdin and
|
||||
* stdout are attached. stderr is left attached to the original stderr. */
|
||||
static int sock_exec(const char *prog)
|
||||
{
|
||||
pid_t pid;
|
||||
int fd[2];
|
||||
|
||||
18
support/lsh
18
support/lsh
@@ -7,13 +7,12 @@
|
||||
# command.
|
||||
|
||||
user=''
|
||||
prefix=''
|
||||
do_cd=y # Default path is user's home dir, just like ssh.
|
||||
|
||||
while : ; do
|
||||
case "$1" in
|
||||
-l) user="$2"; shift; shift ;;
|
||||
-l*) user=`echo $1 | sed 's/^-l//'`; shift ;;
|
||||
-l*) user=`echo "$1" | sed 's/^-l//'`; shift ;;
|
||||
--no-cd) do_cd=n; shift ;;
|
||||
-*) shift ;;
|
||||
localhost) shift; break ;;
|
||||
@@ -22,14 +21,13 @@ while : ; do
|
||||
done
|
||||
|
||||
if [ "$user" ]; then
|
||||
prefix="sudo -H -u $user"
|
||||
prefix=''
|
||||
if [ $do_cd = y ]; then
|
||||
home=`perl -e "print((getpwnam("$user"))[7])"`
|
||||
# Yeah, this may fail, but attempts to get sudo to cd are harder.
|
||||
cd $home
|
||||
home=`perl -e "print((getpwnam('$user'))[7])"`
|
||||
prefix="cd '$home' ;"
|
||||
fi
|
||||
elif [ $do_cd = y ]; then
|
||||
cd
|
||||
sudo -H -u "$user" sh -c "$prefix $*"
|
||||
else
|
||||
[ $do_cd = y ] && cd
|
||||
eval "${@}"
|
||||
fi
|
||||
|
||||
eval $prefix "${@}"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/perl -w
|
||||
#!/usr/bin/perl
|
||||
# This script takes a command-line arg of a source directory
|
||||
# that will be passed to rsync, and generates a set of excludes
|
||||
# that will exclude all mount points from the list. This is
|
||||
@@ -18,19 +18,24 @@
|
||||
# easily adapted to read /etc/mtab or similar.
|
||||
#
|
||||
# ADDENDUM: The addition of the --filter option (which has support for
|
||||
# absolute-anchored excludes) has made this script less useful than it
|
||||
# was. Beginning with 2.6.4, you can achieve the effect of this script
|
||||
# through this command:
|
||||
# absolute-anchored excludes) can make this script unneeded in some
|
||||
# scenarios. If you don't need delete protection on the receiving side
|
||||
# (or if the destination path is identical to the source path), then you
|
||||
# can exclude some absolute paths from the transfer based on the mount
|
||||
# dirs. For instance:
|
||||
#
|
||||
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/
|
||||
# awk '{print $2}' /proc/mounts | grep -v '^/$' | \
|
||||
# rsync -avf 'merge,/- -' /dir host:/dest/
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Cwd 'abs_path';
|
||||
|
||||
my $file = '/proc/mounts';
|
||||
my $dir = shift || '/';
|
||||
$dir = abs_path($dir);
|
||||
$dir =~ s#([^/]*)$##;
|
||||
my $trailing_slash = $dir =~ m{./$} ? '/' : '';
|
||||
$dir = abs_path($dir) . $trailing_slash;
|
||||
$dir =~ s{([^/]*)$}{};
|
||||
my $trailing = $1;
|
||||
$trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
|
||||
$trailing .= '/' if $trailing ne '';
|
||||
@@ -38,7 +43,7 @@ $trailing .= '/' if $trailing ne '';
|
||||
open(IN, $file) or die "Unable to open $file: $!\n";
|
||||
while (<IN>) {
|
||||
$_ = (split)[1];
|
||||
next unless s#^\Q$dir$trailing\E##o && $_ ne '';
|
||||
next unless s{^\Q$dir$trailing\E}{}o && $_ ne '';
|
||||
print "- /$trailing$_\n";
|
||||
}
|
||||
close IN;
|
||||
|
||||
@@ -92,7 +92,6 @@ our %long_opt = (
|
||||
'max-size' => 1,
|
||||
'min-size' => 1,
|
||||
'modify-window' => 1,
|
||||
'no-i-r' => 0,
|
||||
'no-implied-dirs' => 0,
|
||||
'no-r' => 0,
|
||||
'no-relative' => 0,
|
||||
@@ -109,6 +108,7 @@ our %long_opt = (
|
||||
'size-only' => 0,
|
||||
'skip-compress' => 1,
|
||||
'specials' => 0,
|
||||
'stats' => 0,
|
||||
'suffix' => 1,
|
||||
'super' => 0,
|
||||
'temp-dir' => 2,
|
||||
@@ -175,10 +175,10 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
|
||||
} else {
|
||||
if ($subdir ne '/') {
|
||||
# Validate args to ensure they don't try to leave our restricted dir.
|
||||
s#//+#/#g;
|
||||
s#^/##;
|
||||
s#^$#.#;
|
||||
die "Do not use .. in any path!\n" if m#(^|/)\\?\.\\?\.(\\?/|$)#;
|
||||
s{//+}{/}g;
|
||||
s{^/}{};
|
||||
s{^$}{.};
|
||||
die "$0: do not use .. in any path!\n" if m{(^|/)\\?\.\\?\.(\\?/|$)};
|
||||
}
|
||||
push(@args, bsd_glob($_, GLOB_LIMIT|GLOB_NOCHECK|GLOB_BRACE|GLOB_QUOTE));
|
||||
}
|
||||
@@ -205,10 +205,10 @@ sub check_arg
|
||||
my($opt, $arg, $type) = @_;
|
||||
$arg =~ s/\\(.)/$1/g;
|
||||
if ($subdir ne '/' && ($type == 3 || ($type == 2 && !$am_sender))) {
|
||||
$arg =~ s#//#/#g;
|
||||
$arg =~ s{//}{/}g;
|
||||
die "Do not use .. in --$opt; anchor the path at the root of your restricted dir.\n"
|
||||
if $arg =~ m#(^|/)\.\.(/|$)#;
|
||||
$arg =~ s#^/#$subdir/#;
|
||||
if $arg =~ m{(^|/)\.\.(/|$)};
|
||||
$arg =~ s{^/}{$subdir/};
|
||||
}
|
||||
$arg;
|
||||
}
|
||||
|
||||
102
syscall.c
102
syscall.c
@@ -152,10 +152,11 @@ int do_chmod(const char *path, mode_t mode)
|
||||
int code;
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
if (S_ISLNK(mode)) {
|
||||
#ifdef HAVE_LCHMOD
|
||||
code = lchmod(path, mode & CHMOD_BITS);
|
||||
#elif defined HAVE_SETATTRLIST
|
||||
code = lchmod(path, mode & CHMOD_BITS);
|
||||
#else
|
||||
if (S_ISLNK(mode)) {
|
||||
# if defined HAVE_SETATTRLIST
|
||||
struct attrlist attrList;
|
||||
uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
|
||||
|
||||
@@ -163,11 +164,12 @@ int do_chmod(const char *path, mode_t mode)
|
||||
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList.commonattr = ATTR_CMN_ACCESSMASK;
|
||||
code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
|
||||
#else
|
||||
# else
|
||||
code = 1;
|
||||
#endif
|
||||
# endif
|
||||
} else
|
||||
code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
|
||||
#endif /* !HAVE_LCHMOD */
|
||||
if (code != 0 && (preserve_perms || preserve_executability))
|
||||
return code;
|
||||
return 0;
|
||||
@@ -181,6 +183,22 @@ int do_rename(const char *fname1, const char *fname2)
|
||||
return rename(fname1, fname2);
|
||||
}
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
int do_ftruncate(int fd, OFF_T size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void trim_trailing_slashes(char *name)
|
||||
{
|
||||
int l;
|
||||
@@ -282,3 +300,77 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
|
||||
return lseek(fd, offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_UTIMENSAT
|
||||
int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
|
||||
{
|
||||
struct timespec t[2];
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
t[0].tv_sec = 0;
|
||||
t[0].tv_nsec = UTIME_NOW;
|
||||
t[1].tv_sec = modtime;
|
||||
t[1].tv_nsec = mod_nsec;
|
||||
return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LUTIMES
|
||||
int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
|
||||
{
|
||||
struct timeval t[2];
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
t[0].tv_sec = time(NULL);
|
||||
t[0].tv_usec = 0;
|
||||
t[1].tv_sec = modtime;
|
||||
t[1].tv_usec = mod_nsec / 1000;
|
||||
return lutimes(fname, t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIMES
|
||||
int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
|
||||
{
|
||||
struct timeval t[2];
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
t[0].tv_sec = time(NULL);
|
||||
t[0].tv_usec = 0;
|
||||
t[1].tv_sec = modtime;
|
||||
t[1].tv_usec = mod_nsec / 1000;
|
||||
return utimes(fname, t);
|
||||
}
|
||||
|
||||
#elif defined HAVE_UTIME
|
||||
int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
|
||||
{
|
||||
#ifdef HAVE_STRUCT_UTIMBUF
|
||||
struct utimbuf tbuf;
|
||||
#else
|
||||
time_t t[2];
|
||||
#endif
|
||||
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
|
||||
# ifdef HAVE_STRUCT_UTIMBUF
|
||||
tbuf.actime = time(NULL);
|
||||
tbuf.modtime = modtime;
|
||||
return utime(fname, &tbuf);
|
||||
# else
|
||||
t[0] = time(NULL);
|
||||
t[1] = modtime;
|
||||
return utime(fname, t);
|
||||
# endif
|
||||
}
|
||||
|
||||
#else
|
||||
#error Need utimes or utime function.
|
||||
#endif
|
||||
|
||||
1
t_stub.c
1
t_stub.c
@@ -26,6 +26,7 @@ int module_id = -1;
|
||||
int relative_paths = 0;
|
||||
int human_readable = 0;
|
||||
int module_dirlen = 0;
|
||||
int preserve_times = 0;
|
||||
int preserve_xattrs = 0;
|
||||
mode_t orig_umask = 002;
|
||||
char *partial_dir;
|
||||
|
||||
@@ -117,7 +117,7 @@ cD$all_plus char3
|
||||
cS$all_plus fifo
|
||||
EOT
|
||||
if test ! -r "$fromdir/block2.5"; then
|
||||
sed -e '/block2\.5/d' <"$chkfile" >"$chkfile.new"
|
||||
grep -v block2.5 <"$chkfile" >"$chkfile.new"
|
||||
mv "$chkfile.new" "$chkfile"
|
||||
fi
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
|
||||
@@ -128,7 +128,7 @@ echo ""
|
||||
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
|
||||
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
|
||||
|
||||
if test -b "$fromdir/block2.5"; then
|
||||
if test -r "$fromdir/block2.5"; then
|
||||
set -x
|
||||
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
|
||||
| tee "$outfile"
|
||||
@@ -143,7 +143,7 @@ hD$allspace char2
|
||||
hD$allspace char3
|
||||
hS$allspace fifo
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
|
||||
fi
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
|
||||
@@ -28,7 +28,7 @@ name2="$fromdir/name2"
|
||||
name3="$fromdir/name3"
|
||||
name4="$fromdir/name4"
|
||||
echo "This is the file" > "$name1"
|
||||
ln "$name1" "$name2" || fail "Can't create hardlink"
|
||||
ln "$name1" "$name2" || test_skipped "Can't create hardlink"
|
||||
ln "$name2" "$name3" || fail "Can't create hardlink"
|
||||
cp "$name2" "$name4" || fail "Can't copy file"
|
||||
cat $srcdir/*.c >"$fromdir/text"
|
||||
|
||||
@@ -17,7 +17,7 @@ outfile="$scratchdir/rsync.out"
|
||||
|
||||
makepath "$fromdir/foo"
|
||||
makepath "$fromdir/bar/baz"
|
||||
cp -p "$srcdir/configure.in" "$fromdir/foo/config1"
|
||||
cp -p "$srcdir/configure.ac" "$fromdir/foo/config1"
|
||||
cp -p "$srcdir/config.h.in" "$fromdir/foo/config2"
|
||||
cp -p "$srcdir/rsync.h" "$fromdir/bar/baz/rsync"
|
||||
chmod 600 "$fromdir"/foo/config? "$fromdir/bar/baz/rsync"
|
||||
@@ -66,7 +66,7 @@ diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
|
||||
# Ensure there are no accidental directory-time problems.
|
||||
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
|
||||
|
||||
cp -p "$srcdir/configure.in" "$fromdir/foo/config2"
|
||||
cp -p "$srcdir/configure.ac" "$fromdir/foo/config2"
|
||||
chmod 601 "$fromdir/foo/config2"
|
||||
$RSYNC -iplrH "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
@@ -99,7 +99,7 @@ cLc$T.$dots foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
cp -p "$srcdir/configure.in" "$fromdir/foo/config2"
|
||||
cp -p "$srcdir/configure.ac" "$fromdir/foo/config2"
|
||||
chmod 600 "$fromdir/foo/config2"
|
||||
# Lack of -t is for unchanged hard-link stress-test!
|
||||
$RSYNC -vvplrH "$fromdir/" "$todir/" \
|
||||
|
||||
@@ -27,6 +27,7 @@ chkdir="$tmpdir/chk"
|
||||
all_plus='+++++++++'
|
||||
allspace=' '
|
||||
dots='.....' # trailing dots after changes
|
||||
tab_ch=' ' # a single tab character
|
||||
|
||||
# Berkley's nice.
|
||||
PATH="$PATH:/usr/ucb"
|
||||
@@ -223,7 +224,7 @@ checkit() {
|
||||
eval "$1"
|
||||
status=$?
|
||||
if [ $status != 0 ]; then
|
||||
failed="YES";
|
||||
failed="$failed status=$status"
|
||||
fi
|
||||
|
||||
echo "-------------"
|
||||
@@ -231,7 +232,7 @@ checkit() {
|
||||
echo ""
|
||||
( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
|
||||
( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
|
||||
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
|
||||
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed="$failed dir-diff"
|
||||
|
||||
echo "-------------"
|
||||
echo "check how the files compare with diff:"
|
||||
@@ -239,15 +240,16 @@ checkit() {
|
||||
if [ "x$4" != x ]; then
|
||||
echo " === Skipping (as directed) ==="
|
||||
else
|
||||
diff -r $diffopt "$2" "$3" || failed=YES
|
||||
diff -r $diffopt "$2" "$3" || failed="$failed file-diff"
|
||||
fi
|
||||
|
||||
echo "-------------"
|
||||
if [ -z "$failed" ] ; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Failed: $failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# Test that rsync handles basic xattr preservation.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
lnkdir="$tmpdir/lnk"
|
||||
|
||||
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync is configured without xattr support"
|
||||
|
||||
@@ -18,8 +19,9 @@ case "`xattr 2>&1`" in
|
||||
xattr -s "$xnam" "$xval" "${@}"
|
||||
}
|
||||
xls() {
|
||||
xattr -l "${@}"
|
||||
xattr -l "${@}" | sed "s/^[ $tab_ch]*//"
|
||||
}
|
||||
RSYNC_PREFIX='rsync'
|
||||
RUSR='rsync.nonuser'
|
||||
;;
|
||||
*)
|
||||
@@ -32,11 +34,12 @@ case "`xattr 2>&1`" in
|
||||
xls() {
|
||||
getfattr -d "${@}"
|
||||
}
|
||||
RSYNC_PREFIX='user.rsync'
|
||||
RUSR='user.rsync'
|
||||
;;
|
||||
esac
|
||||
|
||||
makepath "$fromdir/foo/bar"
|
||||
makepath "$lnkdir" "$fromdir/foo/bar"
|
||||
echo now >"$fromdir/file0"
|
||||
echo something >"$fromdir/file1"
|
||||
echo else >"$fromdir/file2"
|
||||
@@ -48,7 +51,10 @@ makepath "$chkdir/foo"
|
||||
echo wow >"$chkdir/file1"
|
||||
cp_touch "$fromdir/foo/file3" "$chkdir/foo"
|
||||
|
||||
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
|
||||
dirs='foo foo/bar'
|
||||
files='file0 file1 file2 foo/file3 file4 foo/bar/file5'
|
||||
|
||||
uid_gid=`"$TOOLDIR/tls" "$fromdir/foo" | sed 's/^.* \([0-9][0-9]*\)\.\([0-9][0-9]*\) .*/\1:\2/'`
|
||||
|
||||
cd "$fromdir"
|
||||
|
||||
@@ -68,54 +74,101 @@ xset user.dir1 'need to test directory xattrs too' foo
|
||||
xset user.dir2 'another xattr' foo
|
||||
xset user.dir3 'this is one last one for the moment' foo
|
||||
|
||||
xset user.dir4 'another dir test' foo/bar
|
||||
xset user.dir5 'one last one' foo/bar
|
||||
|
||||
xset user.foo 'new foo' foo/file3 foo/bar/file5
|
||||
xset user.bar 'new bar' foo/file3 foo/bar/file5
|
||||
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3 foo/bar/file5
|
||||
xset $RUSR.equal 'this long attribute should remain the same and not need to be transferred' foo/file3 foo/bar/file5
|
||||
|
||||
xset user.dir0 'old extra value' "$chkdir/foo"
|
||||
xset user.dir1 'old dir value' "$chkdir/foo"
|
||||
|
||||
xset user.short 'old short' "$chkdir/file1"
|
||||
xset user.extra 'remove me' "$chkdir/file1"
|
||||
|
||||
xset user.foo 'old foo' "$chkdir/foo/file3"
|
||||
xset $RUSR.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
|
||||
|
||||
xls $files >"$scratchdir/xattrs.txt"
|
||||
case $0 in
|
||||
*hlink*)
|
||||
ln foo/bar/file5 foo/bar/file6 || test_skipped "Can't create hardlink"
|
||||
files="$files foo/bar/file6"
|
||||
dashH='-H'
|
||||
altDest='--link-dest'
|
||||
;;
|
||||
*)
|
||||
dashH=''
|
||||
altDest='--copy-dest'
|
||||
;;
|
||||
esac
|
||||
|
||||
xls $dirs $files >"$scratchdir/xattrs.txt"
|
||||
|
||||
# OK, let's try a simple xattr copy.
|
||||
checkit "$RSYNC -avX --super . '$chkdir/'" "$fromdir" "$chkdir"
|
||||
checkit "$RSYNC -avX $dashH --super . '$chkdir/'" "$fromdir" "$chkdir"
|
||||
|
||||
cd "$chkdir"
|
||||
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
xls $dirs $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
cd "$fromdir"
|
||||
|
||||
checkit "$RSYNC -aiX --super --copy-dest=../chk . ../to" "$fromdir" "$todir"
|
||||
if [ "$dashH" ]; then
|
||||
for fn in $files; do
|
||||
name=`basename $fn`
|
||||
ln $fn ../lnk/$name
|
||||
done
|
||||
fi
|
||||
|
||||
checkit "$RSYNC -aiX $dashH --super $altDest=../chk . ../to" "$fromdir" "$todir"
|
||||
|
||||
cd "$todir"
|
||||
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
xls $dirs $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
[ "$dashH" ] && rm -rf "$lnkdir"
|
||||
|
||||
cd "$fromdir"
|
||||
rm -rf "$todir"
|
||||
|
||||
xset user.nice 'this is nice, but different' file1
|
||||
|
||||
checkit "$RSYNC -aiX --fake-super . ../chk" "$fromdir" "$chkdir"
|
||||
xls $dirs $files >"$scratchdir/xattrs.txt"
|
||||
|
||||
cd "$chkdir"
|
||||
xls $files >"$scratchdir/xattrs.txt"
|
||||
|
||||
cd "$fromdir"
|
||||
checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
|
||||
checkit "$RSYNC -aiX $dashH --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
|
||||
|
||||
cd "$todir"
|
||||
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
xls $dirs $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
sed -n -e '/\.\/file1$/d' -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff"
|
||||
sed -n -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff-all"
|
||||
fgrep -v './file1' "$scratchdir/ls-diff-all" >"$scratchdir/ls-diff" || :
|
||||
if [ -s "$scratchdir/ls-diff" ]; then
|
||||
echo "Missing hard links on:"
|
||||
cat "$scratchdir/ls-diff"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -s "$scratchdir/ls-diff-all" ]; then
|
||||
echo "Too many hard links on file1!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$chkdir"
|
||||
chmod go-rwx . $dirs $files
|
||||
|
||||
xset user.nice 'this is nice, but different' file1
|
||||
xset $RSYNC_PREFIX.%stat "40000 0,0 $uid_gid" $dirs
|
||||
xset $RSYNC_PREFIX.%stat "100000 0,0 $uid_gid" $files
|
||||
|
||||
xls $dirs $files >"$scratchdir/xattrs.txt"
|
||||
|
||||
cd "$fromdir"
|
||||
rm -rf "$todir"
|
||||
|
||||
# When run by a non-root tester, this checks if no-user-perm files/dirs can be copied.
|
||||
checkit "$RSYNC -aiX $dashH --fake-super --chmod=a= . ../to" "$chkdir" "$todir" # 2>"$scratchdir/errors.txt"
|
||||
|
||||
cd "$todir"
|
||||
xls $dirs $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
cd "$fromdir"
|
||||
rm -rf "$todir" "$chkdir"
|
||||
@@ -124,10 +177,13 @@ $RSYNC -aX file1 file2
|
||||
$RSYNC -aX file1 file2 ../chk/
|
||||
$RSYNC -aX --del ../chk/ .
|
||||
$RSYNC -aX file1 ../lnk/
|
||||
[ "$dashH" ] && ln "$chkdir/file1" ../lnk/extra-link
|
||||
|
||||
xls file1 file2 >"$scratchdir/xattrs.txt"
|
||||
|
||||
checkit "$RSYNC -aiiX --copy-dest=../lnk . ../to" "$chkdir" "$todir"
|
||||
checkit "$RSYNC -aiiX $dashH $altDest=../lnk . ../to" "$chkdir" "$todir"
|
||||
|
||||
[ "$dashH" ] && rm ../lnk/extra-link
|
||||
|
||||
cd "$todir"
|
||||
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
2
token.c
2
token.c
@@ -192,6 +192,8 @@ void set_compression(const char *fname)
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
if (isUpper(<r))
|
||||
ltr = toLower(<r);
|
||||
while (node->letter != ltr) {
|
||||
if (node->letter > ltr)
|
||||
return;
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
#!/usr/bin/perl -i -p
|
||||
|
||||
# Make some hyphens unbreakable.
|
||||
s{(--\w[-\w]+)}{ $x = $1; $x =~ s/-/\\-/g; $x }eg;
|
||||
s/(?<!\\)-(['"\d*])/\\-$1/g;
|
||||
s#(['"(= /,])-(?!-)#$1\\-#g;
|
||||
s/(\\fB)-/$1\\-/g;
|
||||
s/(\[\w)-(\w\])/$1\\-$2/g;
|
||||
s{(\\f\(CW.*?\\fP)}{ $x = $1; $x =~ s/(?<!\\)-/\\-/g; $x }eg;
|
||||
s/(\.\w+)-/$1\\-/g;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# We only need to use "\&'" or "\&." at the start of a line.
|
||||
s/(?<=.)\\\&(['.])/$1$2/g;
|
||||
|
||||
# Use an em-dash where appropriate.
|
||||
s/ \\?-{1,2} / \\(em /g;
|
||||
s/(?<=.)\\\&(['.])/$1/g;
|
||||
|
||||
# Some quotes turn into open/close quotes.
|
||||
s/'(.)'/\\(oq$1\\(cq/g;
|
||||
|
||||
@@ -39,8 +39,6 @@ extern int numeric_ids;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define GID_NONE ((gid_t)-1)
|
||||
|
||||
struct idlist {
|
||||
struct idlist *next;
|
||||
const char *name;
|
||||
@@ -103,12 +101,12 @@ static gid_t map_gid(gid_t id, const char *name)
|
||||
static int is_in_group(gid_t gid)
|
||||
{
|
||||
#ifdef HAVE_GETGROUPS
|
||||
static gid_t last_in = GID_NONE, last_out;
|
||||
static int ngroups = -2;
|
||||
static gid_t last_in;
|
||||
static int ngroups = -2, last_out = -1;
|
||||
static GETGROUPS_T *gidset;
|
||||
int n;
|
||||
|
||||
if (gid == last_in)
|
||||
if (gid == last_in && last_out >= 0)
|
||||
return last_out;
|
||||
if (ngroups < -1) {
|
||||
gid_t mygid = MY_GID();
|
||||
|
||||
85
util.c
85
util.c
@@ -24,10 +24,10 @@
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int module_id;
|
||||
extern int modify_window;
|
||||
extern int relative_paths;
|
||||
extern int preserve_times;
|
||||
extern int human_readable;
|
||||
extern int preserve_xattrs;
|
||||
extern char *module_dir;
|
||||
@@ -123,12 +123,11 @@ NORETURN void overflow_exit(const char *str)
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
}
|
||||
|
||||
/* This returns 0 for success, 1 for a symlink if symlink time-setting
|
||||
* is not possible, or -1 for any other error. */
|
||||
int set_modtime(const char *fname, time_t modtime, mode_t mode)
|
||||
{
|
||||
#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
|
||||
if (S_ISLNK(mode))
|
||||
return 1;
|
||||
#endif
|
||||
static int switch_step = 0;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "set modtime of %s to (%ld) %s",
|
||||
@@ -136,38 +135,49 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
|
||||
asctime(localtime(&modtime)));
|
||||
}
|
||||
|
||||
if (dry_run)
|
||||
return 0;
|
||||
|
||||
{
|
||||
#ifdef HAVE_UTIMES
|
||||
struct timeval t[2];
|
||||
t[0].tv_sec = time(NULL);
|
||||
t[0].tv_usec = 0;
|
||||
t[1].tv_sec = modtime;
|
||||
t[1].tv_usec = 0;
|
||||
# ifdef HAVE_LUTIMES
|
||||
if (S_ISLNK(mode)) {
|
||||
if (lutimes(fname, t) < 0)
|
||||
return errno == ENOSYS ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
return utimes(fname, t);
|
||||
#elif defined HAVE_STRUCT_UTIMBUF
|
||||
struct utimbuf tbuf;
|
||||
tbuf.actime = time(NULL);
|
||||
tbuf.modtime = modtime;
|
||||
return utime(fname,&tbuf);
|
||||
#elif defined HAVE_UTIME
|
||||
time_t t[2];
|
||||
t[0] = time(NULL);
|
||||
t[1] = modtime;
|
||||
return utime(fname,t);
|
||||
#else
|
||||
#error No file-time-modification routine found!
|
||||
switch (switch_step) {
|
||||
#ifdef HAVE_UTIMENSAT
|
||||
#include "case_N.h"
|
||||
if (do_utimensat(fname, modtime, 0) == 0)
|
||||
break;
|
||||
if (errno != ENOSYS)
|
||||
return -1;
|
||||
switch_step++;
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LUTIMES
|
||||
#include "case_N.h"
|
||||
if (do_lutimes(fname, modtime, 0) == 0)
|
||||
break;
|
||||
if (errno != ENOSYS)
|
||||
return -1;
|
||||
switch_step++;
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
|
||||
#include "case_N.h"
|
||||
switch_step++;
|
||||
if (preserve_times & PRESERVE_LINK_TIMES) {
|
||||
preserve_times &= ~PRESERVE_LINK_TIMES;
|
||||
if (S_ISLNK(mode))
|
||||
return 1;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
#include "case_N.h"
|
||||
#ifdef HAVE_UTIMES
|
||||
if (do_utimes(fname, modtime, 0) == 0)
|
||||
break;
|
||||
#else
|
||||
if (do_utime(fname, modtime, 0) == 0)
|
||||
break;
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This creates a new directory with default permissions. Since there
|
||||
@@ -1014,8 +1024,9 @@ int change_dir(const char *dir, int set_path_only)
|
||||
errno = ENAMETOOLONG;
|
||||
return 0;
|
||||
}
|
||||
curr_dir[curr_dir_len] = '/';
|
||||
memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
|
||||
if (!(curr_dir_len && curr_dir[curr_dir_len-1] == '/'))
|
||||
curr_dir[curr_dir_len++] = '/';
|
||||
memcpy(curr_dir + curr_dir_len, dir, len + 1);
|
||||
|
||||
if (!set_path_only && chdir(curr_dir)) {
|
||||
curr_dir[curr_dir_len] = '\0';
|
||||
|
||||
13
wildtest.c
13
wildtest.c
@@ -50,15 +50,16 @@ static struct poptOption long_options[] = {
|
||||
|
||||
/* match just at the start of string (anchored tests) */
|
||||
static void
|
||||
run_test(int line, bool matches, bool same_as_fnmatch,
|
||||
run_test(int line, bool matches,
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
bool same_as_fnmatch,
|
||||
#endif
|
||||
const char *text, const char *pattern)
|
||||
{
|
||||
bool matched;
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
bool fn_matched;
|
||||
int flags = strstr(pattern, "**")? 0 : FNM_PATHNAME;
|
||||
#else
|
||||
same_as_fnmatch = 0; /* Get rid of unused-variable compiler warning. */
|
||||
#endif
|
||||
|
||||
if (explode_mod) {
|
||||
@@ -194,7 +195,11 @@ main(int argc, char **argv)
|
||||
while (*++s == ' ' || *s == '\t') {}
|
||||
}
|
||||
*end[0] = *end[1] = '\0';
|
||||
run_test(line, flag[0], flag[1], string[0], string[1]);
|
||||
run_test(line, flag[0],
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
flag[1],
|
||||
#endif
|
||||
string[0], string[1]);
|
||||
}
|
||||
|
||||
if (!wildmatch_errors)
|
||||
|
||||
87
xattrs.c
87
xattrs.c
@@ -32,6 +32,9 @@ extern int am_generator;
|
||||
extern int read_only;
|
||||
extern int list_only;
|
||||
extern int preserve_xattrs;
|
||||
extern int preserve_links;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_specials;
|
||||
extern int checksum_seed;
|
||||
|
||||
#define RSYNC_XAL_INITIAL 5
|
||||
@@ -90,11 +93,14 @@ static void rsync_xal_free(item_list *xalp)
|
||||
size_t i;
|
||||
rsync_xa *rxas = xalp->items;
|
||||
|
||||
if (!xalp->malloced)
|
||||
return;
|
||||
|
||||
for (i = 0; i < xalp->count; i++) {
|
||||
free(rxas[i].datum);
|
||||
/*free(rxas[i].name);*/
|
||||
}
|
||||
xalp->count = 0;
|
||||
free(xalp->items);
|
||||
}
|
||||
|
||||
void free_xattr(stat_x *sxp)
|
||||
@@ -138,7 +144,7 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
got_error:
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
|
||||
fname, arg);
|
||||
full_fname(fname), arg);
|
||||
return -1;
|
||||
}
|
||||
list_len = sys_llistxattr(fname, NULL, 0);
|
||||
@@ -174,7 +180,7 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
|
||||
return NULL;
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
|
||||
fname, name);
|
||||
full_fname(fname), name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -191,11 +197,11 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
|
||||
if (len == (size_t)-1) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
|
||||
" failed", fname, name, (long)datum_len);
|
||||
" failed", full_fname(fname), name, (long)datum_len);
|
||||
} else {
|
||||
rprintf(FERROR_XFER,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
|
||||
" returned %ld\n", fname, name,
|
||||
" returned %ld\n", full_fname(fname), name,
|
||||
(long)datum_len, (long)len);
|
||||
}
|
||||
free(ptr);
|
||||
@@ -283,6 +289,26 @@ int get_xattr(const char *fname, stat_x *sxp)
|
||||
{
|
||||
sxp->xattr = new(item_list);
|
||||
*sxp->xattr = empty_xattr;
|
||||
|
||||
if (S_ISREG(sxp->st.st_mode) || S_ISDIR(sxp->st.st_mode)) {
|
||||
/* Everyone supports this. */
|
||||
} else if (S_ISLNK(sxp->st.st_mode)) {
|
||||
#ifndef NO_SYMLINK_XATTRS
|
||||
if (!preserve_links)
|
||||
#endif
|
||||
return 0;
|
||||
} else if (IS_SPECIAL(sxp->st.st_mode)) {
|
||||
#ifndef NO_SPECIAL_XATTRS
|
||||
if (!preserve_specials)
|
||||
#endif
|
||||
return 0;
|
||||
} else if (IS_DEVICE(sxp->st.st_mode)) {
|
||||
#ifndef NO_DEVICE_XATTRS
|
||||
if (!preserve_devices)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rsync_xal_get(fname, sxp->xattr) < 0) {
|
||||
free_xattr(sxp);
|
||||
return -1;
|
||||
@@ -321,8 +347,8 @@ int copy_xattrs(const char *source, const char *dest)
|
||||
if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
|
||||
int save_errno = errno ? errno : EINVAL;
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
dest, name);
|
||||
"copy_xattrs: lsetxattr(\"%s\",\"%s\") failed",
|
||||
full_fname(dest), name);
|
||||
errno = save_errno;
|
||||
return -1;
|
||||
}
|
||||
@@ -383,7 +409,7 @@ static void rsync_xal_store(item_list *xalp)
|
||||
}
|
||||
|
||||
/* Send the make_xattr()-generated xattr list for this flist entry. */
|
||||
int send_xattr(stat_x *sxp, int f)
|
||||
int send_xattr(int f, stat_x *sxp)
|
||||
{
|
||||
int ndx = find_matching_xattr(sxp->xattr);
|
||||
|
||||
@@ -574,7 +600,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
|
||||
|
||||
if (F_XATTR(file) < 0) {
|
||||
rprintf(FERROR, "recv_xattr_request: internal data error!\n");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
lst += F_XATTR(file);
|
||||
|
||||
@@ -590,12 +616,12 @@ int recv_xattr_request(struct file_struct *file, int f_in)
|
||||
if (!cnt || rxa->num != num) {
|
||||
rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",
|
||||
who_am_i(), num, f_name(file, NULL));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (!XATTR_ABBREV(*rxa) || rxa->datum[0] != XSTATE_ABBREV) {
|
||||
rprintf(FERROR, "[%s] internal abbrev error on %s (%s, len=%ld)!\n",
|
||||
who_am_i(), f_name(file, NULL), rxa->name, (long)rxa->datum_len);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (am_sender) {
|
||||
@@ -625,7 +651,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* receive and build the rsync_xattr_lists */
|
||||
void receive_xattr(struct file_struct *file, int f)
|
||||
void receive_xattr(int f, struct file_struct *file)
|
||||
{
|
||||
static item_list temp_xattr = EMPTY_ITEM_LIST;
|
||||
int count, num;
|
||||
@@ -639,14 +665,14 @@ void receive_xattr(struct file_struct *file, int f)
|
||||
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
|
||||
rprintf(FERROR, "receive_xattr: xa index %d out of"
|
||||
" range for %s\n", ndx, f_name(file, NULL));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (ndx != 0) {
|
||||
F_XATTR(file) = ndx - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((count = read_varint(f)) != 0) {
|
||||
(void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
|
||||
temp_xattr.count = 0;
|
||||
@@ -749,10 +775,8 @@ void uncache_tmp_xattrs(void)
|
||||
item_list *xattr_start = xattr_item + prior_xattr_count;
|
||||
xattr_item += rsync_xal_l.count;
|
||||
rsync_xal_l.count = prior_xattr_count;
|
||||
while (xattr_item-- > xattr_start) {
|
||||
while (xattr_item-- > xattr_start)
|
||||
rsync_xal_free(xattr_item);
|
||||
free(xattr_item->items);
|
||||
}
|
||||
prior_xattr_count = (size_t)-1;
|
||||
}
|
||||
}
|
||||
@@ -807,7 +831,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
else if (sys_lsetxattr(fname, name, ptr, len) < 0) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
full_fname(fname), name);
|
||||
ret = -1;
|
||||
} else /* make sure caller sets mtime */
|
||||
sxp->st.st_mtime = (time_t)-1;
|
||||
@@ -828,7 +852,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
full_fname(fname), name);
|
||||
ret = -1;
|
||||
} else /* make sure caller sets mtime */
|
||||
sxp->st.st_mtime = (time_t)-1;
|
||||
@@ -857,8 +881,8 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
if (i == xalp->count) {
|
||||
if (sys_lremovexattr(fname, name) < 0) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
"rsync_xal_set: lremovexattr(\"%s\",\"%s\") failed",
|
||||
full_fname(fname), name);
|
||||
ret = -1;
|
||||
} else /* make sure caller sets mtime */
|
||||
sxp->st.st_mtime = (time_t)-1;
|
||||
@@ -883,6 +907,25 @@ int set_xattr(const char *fname, const struct file_struct *file,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef NO_SPECIAL_XATTRS
|
||||
if (IS_SPECIAL(sxp->st.st_mode)) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef NO_DEVICE_XATTRS
|
||||
if (IS_DEVICE(sxp->st.st_mode)) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#ifdef NO_SYMLINK_XATTRS
|
||||
if (S_ISLNK(sxp->st.st_mode)) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ndx = F_XATTR(file);
|
||||
return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp);
|
||||
}
|
||||
@@ -901,7 +944,7 @@ int set_xattr_acl(const char *fname, int is_access_acl, const char *buf, size_t
|
||||
if (sys_lsetxattr(fname, name, buf, buf_len) < 0) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"set_xattr_acl: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
full_fname(fname), name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user