Compare commits

...

133 Commits

Author SHA1 Message Date
Wayne Davison
40afd365cc Preparing for release of 3.0.9 2011-09-23 09:13:53 -07:00
Wayne Davison
d702b97838 Mention the latest changes. 2011-09-22 23:33:51 -07:00
Wayne Davison
53a46d9e09 Fix two unused-variable compiler warnings. 2011-09-22 23:33:47 -07:00
Wayne Davison
510c5ab7ff Fix xattr memory leak. Fixes bug 8475. 2011-09-22 09:02:21 -07:00
Wayne Davison
033697d96d Make --delete-excluded work better with --filter=merge. 2011-09-15 07:48:31 -07:00
Wayne Davison
abc796661d When modifying PATH, export it (for Solaris). 2011-09-15 07:27:23 -07:00
Wayne Davison
998df4b0c0 Added "SORTED TRANSFER ORDER" manpage section. 2011-09-13 16:03:59 -07:00
Wayne Davison
675f864c6d Cleanup some manpage & --help info. 2011-09-13 15:41:26 -07:00
Wayne Davison
dbd58bb2d0 Improve the usage for --help. 2011-09-11 22:48:11 -07:00
Wayne Davison
a5ef696953 Preparing for release of 3.0.9pre2 2011-09-10 14:52:19 -07:00
Wayne Davison
ae6dea711d Mention the latest changes in the NEWS. 2011-09-10 13:40:48 -07:00
Wayne Davison
5a9933c85c Error out if --password-file specifed and it fails.
Fixes bug 8440.
2011-09-10 13:38:17 -07:00
Wayne Davison
b91ab5f9c8 Dirs need +rx as well as +w for non-super xfers.
Partial fix for bug 8242.
2011-09-10 13:38:11 -07:00
Wayne Davison
5340571ab6 Move implied_dot_dir=1, just to be safe. 2011-08-27 14:58:04 -07:00
Wayne Davison
e7dd0e5004 Fix sending of "." attributes for implied-dot-dir. 2011-08-27 12:08:19 -07:00
Wayne Davison
5822f988f5 Fix bwlimit multiplication overflow. Fixes bug 8375. 2011-08-27 12:08:19 -07:00
Wayne Davison
881455f7b2 Some option-parsing clarifiation in the intro. 2011-08-27 12:06:23 -07:00
Wayne Davison
fe2c165fca Fix misplaced parens on getnameinfo() call. 2011-08-06 11:23:09 -07:00
Wayne Davison
4c0055ecbb Ignore socketpair() on cygwin. Fixes bug 8356. 2011-08-06 11:23:04 -07:00
Wayne Davison
d706e888fc Fix Minix build errors. Fixes bug 8313. 2011-07-22 11:20:20 -07:00
Wayne Davison
c0d07c0987 Replace another inet_ntop() call with getnameinfo(). 2011-07-16 16:14:50 -07:00
Wayne Davison
606c603943 Add more connect debug info, as Carlos suggested. 2011-07-12 16:01:59 -07:00
Wayne Davison
5fed6c076a Move freeaddrinfo() call after failure-reporting loop. 2011-07-11 18:16:48 -07:00
Wayne Davison
30fb28cc97 Mention the latest fixes. 2011-07-04 16:38:14 -07:00
Wayne Davison
3a2495cb22 Fix a comment. 2011-07-04 16:31:58 -07:00
Wayne Davison
1916a7a2a6 Handle FES_NO_SEND properly on a hard-linked file.
Fixes bug 8246.
2011-07-04 16:14:04 -07:00
Wayne Davison
121082fa9b Fix #ifdef in unchanged_attrs(). Fixes bug 8268. 2011-06-26 09:53:31 -07:00
Wayne Davison
c6bed2d9ee Explicitly mention spaces in the "path" setting. 2011-06-24 15:17:56 -07:00
Wayne Davison
ecae885a51 Improve lsh's handling of -l user option w/cd. 2011-06-24 15:11:25 -07:00
Wayne Davison
f350413814 Move var declaration for older C compilers. 2011-06-24 15:09:55 -07:00
Wayne Davison
93bdc6478e Preparing for release of 3.0.9pre1 2011-06-22 08:00:35 -07:00
Wayne Davison
2d07fa6350 Mention latest fix. 2011-06-22 07:58:23 -07:00
Wayne Davison
33e37a49ba Make daemon-exclude errors more error-like.
Fixes bug 7765.
2011-06-18 12:44:47 -07:00
Wayne Davison
5782ac04d7 Prepare for 3.0.9pre1 release. 2011-06-18 10:31:30 -07:00
Wayne Davison
fc41c32159 Mention coming Solaris support. 2011-06-18 10:22:24 -07:00
Wayne Davison
365124a214 Don't force \(em in the manpages. Fixes bug 7941. 2011-06-04 12:53:22 -07:00
Wayne Davison
dbf68ca4c1 Linux needs symlink xattrs. Fixes bug 8201. 2011-06-04 09:46:06 -07:00
Wayne Davison
ba35ba06c9 Fix unwritable directory issue due to misordered chmod call. 2011-05-30 08:41:02 -07:00
Wayne Davison
0b519262c6 Expand NO_ENTRY items from fake-super ACLs in get_rsync_acl(). 2011-05-30 08:39:07 -07:00
Wayne Davison
3ef38b0d1b Avoid adding a slash to path '/'. 2011-04-22 15:51:55 -07:00
Wayne Davison
5a1d092ae1 Fix a potential crash when trying to find a better block match. 2011-04-22 11:27:16 -07:00
Wayne Davison
1ddcdaf3f6 Preparing for release of 3.0.8 2011-03-26 14:34:18 -07:00
Wayne Davison
93562b1941 Mention CVE-2011-1097. 2011-03-26 14:31:45 -07:00
Wayne Davison
959bd70820 Tweak dir xattrs after the writability fudging. 2011-03-26 10:17:14 -07:00
Wayne Davison
a7271fb30f Avoid re-setting xattrs on a hard-linked file w/the same xattrs.
Improved the xattrs testing to include hard-linking.
2011-03-26 10:01:37 -07:00
Wayne Davison
277036153a Mention the latest changes. 2011-03-20 19:46:27 -07:00
Wayne Davison
bc6363f9ab Enhance the -liconv check for OS X. Fixes bug 8018. 2011-03-20 19:31:58 -07:00
Wayne Davison
e71130fd77 Don't send user/group names for ACLs with --numeric-ids.
Fixes bug 8020.
2011-03-18 14:42:28 -07:00
Wayne Davison
38c9f1becf Get rid of an unused extern. 2011-03-17 11:25:12 -07:00
Wayne Davison
779663fc6c Fix xattrs test on OS X. 2011-03-13 20:48:55 -07:00
Wayne Davison
9562cc8925 A few minor NEWS improvements. 2011-02-26 08:10:27 -08:00
Wayne Davison
a945aa19d9 Clarify what extraneous hard link are. 2011-02-23 07:19:23 -08:00
Wayne Davison
2a1d251750 Get rid of obsolete tempfs warning. 2011-02-22 15:37:13 -08:00
Wayne Davison
8750f64ec7 Preparing for release of 3.0.8pre1 2011-02-22 11:03:42 -08:00
Wayne Davison
922895d9a3 Mention even more fixes. 2011-02-22 10:58:33 -08:00
Wayne Davison
72193c82a6 Some uid/gid fixes for (id_t)-1.
The code now avoids any special internal meaning for gid -1.  If chown()
is called with a uid or gid of -1, complain that the ID is not settable
and signal a transfer error.
2011-02-22 10:48:13 -08:00
Wayne Davison
b178eb04d3 Allow a failure of EINVAL to mean no ACLs are available.
(If our POSIX types aren't valid, we can't handle the ACLs.)
2011-02-22 08:51:14 -08:00
Wayne Davison
3158b8df6c Fix --force with --one-file-system w/o --delete. 2011-02-22 08:21:08 -08:00
Wayne Davison
aa3640c09b Fix issue with devices-fake test. 2011-02-22 07:59:08 -08:00
Wayne Davison
07b5c770db Fix test 5's failure message. 2011-02-22 07:41:02 -08:00
Wayne Davison
8b7f20b6d3 Mention latest changes. 2011-02-21 11:32:51 -08:00
Wayne Davison
1dabd5dc9a A few more xattr-support fixes from the master branch. 2011-02-21 11:32:51 -08:00
Wayne Davison
58d657c98f Be clear on which part(s) of testsuite's checkit() failed. 2011-02-21 11:32:51 -08:00
Wayne Davison
e46262f36d Fix issues with unchanged_attrs() for symlinks. 2011-02-21 11:32:51 -08:00
Wayne Davison
4d92246a54 Use ftruncate() at the end of a --sparse file.
Fixes bug 7337.
2011-02-21 11:32:51 -08:00
Wayne Davison
8f48ba03b5 Integrate time-setting fixes/improvements from the master branch. 2011-02-21 11:32:48 -08:00
Wayne Davison
eb8058577d Make case_N.h more generic. 2011-02-21 10:20:58 -08:00
Wayne Davison
3c624bba85 Better mask handling, including some changes to help solaris. 2011-02-21 10:20:58 -08:00
Wayne Davison
24e76f840e Pass "new_mode" to set_acl() and change its return values. 2011-02-21 10:20:58 -08:00
Wayne Davison
b62ea517f6 Put file descriptor arg at the start of the arg list for consistency. 2011-02-21 10:20:58 -08:00
Wayne Davison
a6b3c2b512 Added more missing NEWS items. 2011-02-20 23:51:25 -08:00
Wayne Davison
4e95f91f27 Some manpage enhancements. 2011-02-20 23:48:19 -08:00
Wayne Davison
fad4ab9d0b Suggest a better solution for a make without wildcard support. 2011-02-20 23:48:19 -08:00
Wayne Davison
f91b15fbd6 Add .hg dir exclude to default_cvsignore list.
Fixes bug 7957.
2011-02-20 23:48:19 -08:00
Wayne Davison
83b94efa6b Switch over to Matt's idea of using FLAG_OWNED_BY_US. 2011-01-29 22:19:14 -08:00
Wayne Davison
2064c28d6d Move FLAG_DEL_NEEDS_UID into the "not stored" section. 2011-01-29 20:52:38 -08:00
Wayne Davison
c499002e51 Fix a random flist data bug w/delete, inc-recurse, and no -o.
Fixes bug 7936.
2011-01-29 19:25:53 -08:00
Wayne Davison
c8255147b0 Optimize finding the sum that matches our --inplace position. 2011-01-16 17:23:55 -08:00
Wayne Davison
eee85e3c36 Make sure an alternate --inplace sum has the right length
and add missing break in --inplace same-offset loop.
2011-01-14 15:45:12 -08:00
Wayne Davison
0c0219fe84 Some fixes and improvements from the master branch. 2011-01-13 23:03:59 -08:00
Wayne Davison
a92edcbf5c Avoid splitting a multi-byte character when trimming a name.
Fixes bug 7816.  Also makes the get_tmpname() code and comments
more like the master.
2011-01-03 20:07:28 -08:00
Wayne Davison
17549c95de Mention that sorting the --files-from input is helpful. 2011-01-03 19:49:29 -08:00
Wayne Davison
9d6fe1a6f0 Avoid reading ACL/xattr info on filetypes not being copied.
Make Linux avoid xattr access on symlinks.
Make OS X avoid xattr access on device/special files.
Fixes bug 5458.
2011-01-03 11:23:19 -08:00
Wayne Davison
c43624c575 Mention the latest changes. 2011-01-01 21:24:36 -08:00
Wayne Davison
4baef8d663 Make xattrs.test more like the master version. 2011-01-01 21:24:27 -08:00
Wayne Davison
c3ee6ac369 Avoid directory permission issues with --fake-super.
Fixes bug 7070.
2011-01-01 16:57:08 -08:00
Wayne Davison
63c5ac38a2 Report all socket connection errors if we fail.
Fixes bug 6588.
2011-01-01 13:55:03 -08:00
Wayne Davison
ce41e68995 Itemize xattrs of a missing dir from an alt-dest dir.
Fixes bug 6576.
2011-01-01 13:03:23 -08:00
Wayne Davison
8538db7829 Use full_fname() for system error messages. 2011-01-01 12:33:53 -08:00
Wayne Davison
559bd2ff31 Tweak the year. 2011-01-01 11:51:29 -08:00
Wayne Davison
485a40318c Protect a remote filename that starts with a dash. 2010-12-23 22:08:34 -08:00
Wayne Davison
ede8cae34b Tweak some apostrophes to make editor highlighting less problematic. 2010-12-19 09:11:46 -08:00
Wayne Davison
58ab32037d Optimize --inplace chunck search to avoid a non-aligned search. 2010-12-18 08:27:03 -08:00
Wayne Davison
00cde6582c Mention seek effect of an unmoved --inplace chunk. 2010-12-18 08:17:03 -08:00
Wayne Davison
e6ba6e1107 Improve description of --chmod example. 2010-12-18 08:13:52 -08:00
Wayne Davison
efad2e85ea Fix crash when --backup-dir is excessively long. 2010-12-16 22:20:10 -08:00
Wayne Davison
c463617443 Some quoting fixes/improvements. 2010-09-06 08:42:02 -07:00
Wayne Davison
6abb59adf6 If we create an off_t type, define SIZEOF_OFF_T. 2010-09-06 08:26:50 -07:00
Wayne Davison
d79bc5c791 Fix rsync_xal_set reference in an error. 2010-09-06 08:09:20 -07:00
Wayne Davison
10cd07c225 Avoid infinite loop if the file's length is negative.
Fixes bug 4664.
2010-09-06 08:05:26 -07:00
Wayne Davison
62e9eb7bc2 Mention need of wildcard support in make.
See bug 7625.
2010-08-28 18:05:20 -07:00
Wayne Davison
de20d72541 Remove duplication for -x option. 2010-08-28 18:04:09 -07:00
Wayne Davison
f8cd1c4730 A couple more NEWS items. 2010-07-03 09:30:44 -07:00
Wayne Davison
5de3fe19b6 Always use lchmod() if it is available. 2010-07-03 09:22:50 -07:00
Wayne Davison
0ac2d243bf Mention what -XX (repeated --xattrs) does. 2010-07-03 09:22:13 -07:00
Matt McCutchen
14556a30b3 Document the "copy-some-dirlinks" trick in the man page.
Originally explained at:

http://lists.samba.org/archive/rsync/2006-February/014838.html
2010-07-03 09:21:10 -07:00
Matt McCutchen
8c1f2d53ec Fix erroneous "--fake-user" in the rsyncd.conf(5) man page. 2010-07-03 09:20:07 -07:00
Matt McCutchen
f532cede11 In "ignoring unsafe symlink" messages, show only the file-list path.
Rsync was showing the full destination path, which was confusing because
nothing is created at that path and was especially bogus in combination
with the source name of a solo file.

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=506830
2010-07-03 09:19:01 -07:00
Wayne Davison
05022e00a2 More NEWS. 2010-07-03 08:56:09 -07:00
Wayne Davison
24a743b565 If a module has no path setting, return an error. 2010-07-03 08:54:40 -07:00
Wayne Davison
e36f5c9f6c Mention latest changes. 2010-07-03 08:49:46 -07:00
Wayne Davison
c9c3215698 Refer to the right lsetxattr() caller in a error message. 2010-07-03 08:47:02 -07:00
Wayne Davison
dbfde9e50a Fix compression-ignoring of upper-case suffixes.
Fixes bug 7512.
2010-07-03 08:47:02 -07:00
Wayne Davison
1cdb5e1c86 Fix a couple socketpair_tcp() issues (see bug 7514). 2010-07-03 08:47:02 -07:00
Wayne Davison
24afdc500a Fix a typo that Andrea Gelmini pointed out. 2010-07-03 08:40:23 -07:00
Wayne Davison
303759b803 Get rid of trailing whitespace. 2010-07-03 08:40:23 -07:00
Matt McCutchen
a699f7c6af Man page description of --xattrs should not assume a push. 2010-07-03 08:37:25 -07:00
Wayne Davison
a250fa251b More manpage improvements. 2010-07-03 08:35:44 -07:00
Matt McCutchen
e44aa644c2 Amplify the man page description of --hard-links (see bug 3693), and
improve that of --inplace while I'm at it.
2010-07-03 08:33:24 -07:00
Wayne Davison
ef67c238b5 Reject passing an arg to an option that doesn't take one (bug 6915).
Based on a patch by Matt, but further tweaked to deal with -q=foo.
2010-07-03 08:27:38 -07:00
Wayne Davison
111599be2b Mention 2010 in the main copyright. 2010-07-03 08:24:58 -07:00
Wayne Davison
8e918e1861 Make an empty-string dest-dir the same as "." again. 2010-07-03 08:23:31 -07:00
Wayne Davison
0874fc4872 Setup for 3.0.8dev. 2010-06-30 09:19:01 -07:00
Wayne Davison
55dbbdeafe Fixed inconsistencies reported by packaging/var-checker. 2010-06-30 09:17:26 -07:00
Wayne Davison
cbd27d5e18 Update support/rrsync and some packaging/* scripts. 2010-06-30 09:17:13 -07:00
Matt McCutchen
178ccdde7d Rename configure.in to configure.ac, the current autoconf standard. 2010-06-30 08:29:48 -07:00
Wayne Davison
e51bb8f330 Write out the right compat_flags value into the batch file. 2010-06-26 16:14:15 -07:00
Wayne Davison
6d9207bd38 Turn some asserts into descriptive errors. 2010-06-26 16:13:58 -07:00
Wayne Davison
6b87566744 Make sure our use of idev_find() hashtable is right
while also supporting older rsyncs that send dev == 0.
2010-06-26 16:13:20 -07:00
Wayne Davison
b384d71e53 Make sure that the code doesn't try to use an illegal key. 2010-06-26 11:32:14 -07:00
Wayne Davison
11f4f34ed9 Fix daemon-filter crash issue (bug 7489). 2010-06-04 23:10:47 -07:00
Wayne Davison
fe2c582af8 Removing now-redundant path-size check from send_if_directory(). 2010-03-31 15:00:53 -07:00
Wayne Davison
2ecd8b7cd2 Fix directory-length overflow bug (7057). 2010-03-26 16:56:40 -07:00
61 changed files with 1781 additions and 813 deletions

1
.gitignore vendored
View File

@@ -38,4 +38,5 @@ config.status
/support/savetransfer
/testsuite/chown-fake.test
/testsuite/devices-fake.test
/testsuite/xattrs-hlink.test
/patches

13
INSTALL
View File

@@ -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
---------

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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++;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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
View File

@@ -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)

View File

@@ -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);

View File

@@ -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
View File

@@ -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
View File

@@ -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)

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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
View 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;

View File

@@ -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

View File

@@ -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 -";

View File

@@ -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
}

View File

@@ -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
View 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;
}
}
}

View File

@@ -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:

View File

@@ -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) */

View File

@@ -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

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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)

View File

@@ -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&section=projects
- BitTorrent -- p2p mirroring
http://bitconjurer.org/BitTorrent/
http://bitconjurer.org/BitTorrent/

View File

@@ -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)

View File

@@ -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
View File

@@ -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];

View File

@@ -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 "${@}"

View File

@@ -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;

View File

@@ -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
View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View File

@@ -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"

View File

@@ -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/" \

View File

@@ -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
}

View File

@@ -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" -

View File

@@ -192,6 +192,8 @@ void set_compression(const char *fname)
return;
while (1) {
if (isUpper(&ltr))
ltr = toLower(&ltr);
while (node->letter != ltr) {
if (node->letter > ltr)
return;

View File

@@ -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;

View File

@@ -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
View File

@@ -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';

View File

@@ -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)

View File

@@ -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;