Compare commits

...

342 Commits

Author SHA1 Message Date
Wayne Davison
54f00c3f89 Preparing for release of 3.0.7 2009-12-31 13:08:07 -08:00
Wayne Davison
1fc8c51705 Allow any gcc to make use of __builtin_alloca for alloca. 2009-12-30 20:03:49 -08:00
Wayne Davison
b04604945d Configure check for -Wno-unused-parameter now tries to link too. 2009-12-30 19:57:47 -08:00
Wayne Davison
808b1d61c0 Fixed the passing of a '/' modifier for an absolute-path filter rule. 2009-12-30 12:25:33 -08:00
Wayne Davison
2f01fb1152 Preparing for release of 3.0.7pre2 2009-12-24 08:31:37 -08:00
Wayne Davison
ae358c1960 Revert to having the receiver handle timeouts on the receiving side.
This will give 3.0.7 the standard timeout handling with just a few
improvements: a fix for the detection of recent sender I/O, the use
of MSG_DATA for really old rsync versions, and better setting of
select_timeout for shorter timeout settings.
2009-12-23 11:36:27 -08:00
Wayne Davison
212dfdb960 Preparing for release of 3.0.7pre1 2009-12-21 18:25:00 -08:00
Wayne Davison
c11a77894b Ensure that the generator gets notified about an I/O error for the dir
that generated the error.  This ensures that a --delete-during avoids
deleting in a newly transferred inc-recurse directory.  Requires 3.0.7
or greater on both sides of the transfer.
2009-12-21 14:40:41 -08:00
Wayne Davison
96cce18ce6 Defer forwarding messages during the forwarding of flist data. 2009-12-21 13:48:44 -08:00
Wayne Davison
a21264a8b9 Mention the compress fix. 2009-12-21 10:52:54 -08:00
Wayne Davison
96486cc534 Mention latest --timeout fixes. 2009-12-21 10:25:15 -08:00
Wayne Davison
e0b1b82d84 Don't die if inflate() returns Z_BUF_ERROR in see_deflate_token(). 2009-12-21 10:15:39 -08:00
Wayne Davison
d94b958400 Improve --timeout method to take into account all socket I/O that is
going on.  The receiving side also switches timeout handling from the
receiver to the generator.  Given this setup, all keep-alive messages
are now sent as empty MSG_DATA messages, with MSG_NOOP messages only
being understood and (when necessary) acted upon to forward a keep-alive
event to an older receiver.  This is both safer and more compatible with
older versions.
2009-12-19 13:39:49 -08:00
Wayne Davison
79731940bb Added an am_receiver variable. 2009-12-19 12:04:25 -08:00
Wayne Davison
bdc038fce0 Use 0-length MSG_DATA when MSG_NOOP is not available
(is both safer and supports older rsyncs).
2009-12-16 13:32:03 -08:00
Wayne Davison
2eacba9c41 Avoid -u option to id since solaris doesn't support it. 2009-12-13 19:35:01 -08:00
Wayne Davison
0c5853c32e Get rid of some unused externs. 2009-12-12 22:43:51 -08:00
Wayne Davison
3baa4d2b31 Include info on who is exiting. 2009-12-12 22:42:35 -08:00
Wayne Davison
018dc6f998 Mention the newly cherry-picked changes. 2009-12-12 17:26:11 -08:00
Wayne Davison
523dad4bb3 Use seteuid() (if available) when using setuid(). 2009-12-12 17:26:05 -08:00
Wayne Davison
e0c17aa3b7 Beginning work on a 3.0.7 release. 2009-12-12 17:25:48 -08:00
Wayne Davison
79870bd269 Don't (wrongly) retouch dir permissions with --fake-super.
(Patch from Matt.)
2009-12-12 17:25:19 -08:00
Wayne Davison
e4368e37fe Add IPv6 detection on cygwin. 2009-12-12 17:25:12 -08:00
Wayne Davison
eee529f571 Save first filename and linenum in case exit_cleanup() recurses. 2009-12-12 17:25:06 -08:00
Wayne Davison
ff4715a7c2 Moved some --iconv text that was supposed to be in --files-from. 2009-12-12 17:24:45 -08:00
Wayne Davison
855983b434 Make sure daemon's io_timeout is used as a maximum value. 2009-12-12 17:24:39 -08:00
Wayne Davison
2455140b04 Fix some man page problems Scott Kostyshak pointed out. 2009-12-12 17:24:33 -08:00
Wayne Davison
ae4d4205e3 Avoid type-punned compiler warnings for the byteorder.h macros
by using inline functions for the 4-char <-> uint32 conversions.
2009-12-12 17:24:29 -08:00
Wayne Davison
9523670032 Improve the "--delete does not work without -r or -d" message. 2009-12-12 17:23:55 -08:00
Wayne Davison
01e57e926c Improve error handling and get rid of a lingering fprintf(). 2009-12-12 17:23:45 -08:00
Wayne Davison
ebbab3788f Fix daemon's conveyance of io_error value from sender. 2009-12-12 17:23:03 -08:00
Wayne Davison
d041c17c40 Avoid an dry-run error trying to stat a prior hard-link
file that hasn't really been created.
2009-12-12 17:22:55 -08:00
Wayne Davison
b2b1af40c2 Rebuild proto.h if config.h changes. 2009-12-12 17:22:43 -08:00
Wayne Davison
c5759a2817 Fix the chmod-temp-dir test if /var/tmp doesn't exist.
Fixes bug 6569.
2009-12-12 17:22:12 -08:00
Wayne Davison
5ef08b8c39 Get section reference right. Fixes bug #6573. 2009-12-12 17:22:05 -08:00
Wayne Davison
03f907e386 Added solaris IPv6 checking to configure. Fixes #6438.
Patch from Tim Spriggs.
2009-12-12 17:21:25 -08:00
Wayne Davison
573e24346c Mention that --whole-file is not the default for a local transfer when
writing a batch file.
2009-12-12 17:21:08 -08:00
Wayne Davison
a415379037 Support an older AIX system that doesn't have ENOTSUP. 2009-12-12 17:20:42 -08:00
Wayne Davison
cc4edc2d78 Switch from inet_aton() to inet_pton() (since we supply a compatibility
function for the latter, it will always exist).
2009-12-12 17:20:35 -08:00
Wayne Davison
07bd6618b9 Allow $RSYNC_TEST_TMP to indicate a good tmp dir for our tests. 2009-12-12 17:19:59 -08:00
Wayne Davison
2daed024b1 Fix a bogus free in uncache_tmp_xattrs(). 2009-08-14 07:04:24 -07:00
Wayne Davison
6622816eff Preparing for release of 3.0.6 2009-05-08 10:07:14 -07:00
Wayne Davison
3f137ce0e2 Fix typo pointed out by Chris Pepper. 2009-05-07 08:04:24 -07:00
Matt McCutchen
d616bff57f Move the description of include/exclude modifiers to a better place
in the man page.
2009-05-05 08:18:36 -07:00
Wayne Davison
40b3a59fc8 Clarify which options are transfer rules, and what that means. 2009-04-27 07:26:04 -07:00
Wayne Davison
4640ae85fe Change sending/receiving/storing of the rdev value for special files.
Since the value is not needed, the (superfluous) sending of the value
is optimized so that a valid rdev value is sent as efficiently as
possible.  The receiver no longer caches an rdev value for special
files, and the generator will always pass a 0 rdev value to do_mknod()
for special files. Fixes bug #6280.
2009-04-26 07:51:50 -07:00
Wayne Davison
24f739c118 Clarify the read-batch fix. 2009-04-13 07:42:20 -07:00
Wayne Davison
996824825f Preparing for release of 3.0.6pre1 2009-04-12 15:28:34 -07:00
Wayne Davison
bbef6566cd Changed the commands used to "make gen" without any stoppage. 2009-04-12 15:19:30 -07:00
Wayne Davison
9be5093726 Don't allow --remove-s*-files with --read-batch. 2009-04-12 13:01:14 -07:00
Wayne Davison
feb8dacc14 Fixed the use of --xattrs with --only-write-batch. 2009-04-12 12:48:59 -07:00
Wayne Davison
ff908116ef Allow a "make reconfigure" to continue, even if the Makefile changes. 2009-04-10 16:24:49 -07:00
Wayne Davison
ea53d161be Fixed an ACL/xattr corruption issue where the --backup option could cause
rsync to associate the wrong ACL/xattr information with received files.
2009-04-10 16:09:39 -07:00
Wayne Davison
7875e6fe63 Don't try to simplify an ACL that has a mask w/o any named values. 2009-04-09 22:52:26 -07:00
Wayne Davison
8e2771aa6e Some improvements to the rsync.yo manpage:
- Mention the switch from MD4 to MD5.
- Mention the default for the --log-file-format option.
2009-04-07 07:40:30 -07:00
Wayne Davison
386f22cec6 Make sure that config.h.in is up-to-date before allowing the
Makefile-updating rule to run ./config.status.
2009-04-04 07:53:14 -07:00
Wayne Davison
272adea36b Fixed --dry-run with --read-batch:
- Avoid sending MSG_NO_SEND to the generator.
- Check if the file is wanted before discarding the batched data.
2009-04-04 07:38:37 -07:00
Wayne Davison
a69b165524 Fixed improper deletion of mount-point hierarchies.
Fixes bug #6240.
2009-03-31 20:26:10 -07:00
Wayne Davison
bf350d7b31 Fixed a word ending that Jesse Weinstein and revamp some of the text
to make it clearer.
2009-03-31 14:35:53 -07:00
Wayne Davison
70a9cd5752 Make symlink iconv work for a local copy.
Fixes issue mention in bug #5615.
2009-03-29 13:25:43 -07:00
Matt McCutchen
42560e2e53 Give a meaningful error message when we fail to write to a batch file. 2009-03-13 09:46:39 -07:00
Wayne Davison
d058d0aecd Simplify an "if" in ssh-basic.test. Fixes bug #6169; 2009-03-06 07:08:49 -08:00
Wayne Davison
af00666a40 Mention the fix to --safe-links/--copy-unsafe-links. 2009-03-03 09:00:29 -08:00
Wayne Davison
2517f5440d Improved the unsafe_symlink() code to not get fooled by extra '/' chars
in the symlink's path.  Added test cases.  This fixes bug #6151.
2009-03-03 08:57:43 -08:00
Wayne Davison
f2522e3f53 Make the backup code call unsafe_symlink() correctly. 2009-03-03 08:57:39 -08:00
Wayne Davison
8fba76d5c3 Mention vanishing-directory fix. 2009-02-14 08:38:24 -08:00
Wayne Davison
782b96d3e2 Handle a link_stat() failure with errno ENOENT as a vanished file. 2009-02-14 08:37:10 -08:00
Wayne Davison
1f6b697f28 Mention the latest configure fixes. 2009-02-14 08:05:07 -08:00
Wayne Davison
919491948e Added --disable-iconv-open option for configure to turn off all use
of the iconv_open() function.  Implies --disable-iconv (which turns
off the --iconv option).  Fixes bug #6107.
2009-02-14 07:57:50 -08:00
Wayne Davison
0ea6f486d9 Moved the --disable-debug check sooner in configure.in so that it
happens prior to checking for the compiler.  Switched no-debug code
to setting ac_cv_prog_cc_g=no.  Fixes bug #6106.
2009-02-14 07:57:36 -08:00
Wayne Davison
9493048c10 Ensure that the sender turns off any msg_fd_in use earlier.
This avoids a problem where an extra message from the sender
could give the generator time to start sending data that will
not be understood by the sender's use of read_msg_fd().
2009-02-04 18:27:07 -08:00
Wayne Davison
4dea1a9492 Do not try to send a symlink with a 0-length value.
This avoids a transfer error in the receiver.
2009-02-04 18:16:16 -08:00
Wayne Davison
650bca3770 A few more improvements to the hostspec-parsing code. 2009-01-28 23:18:45 -08:00
Wayne Davison
794f38099a Fixed the parsing of IPv6 literal addresses with a username
prefixed.  Fixes bug #6067.
2009-01-28 15:58:48 -08:00
Wayne Davison
8250d8a1c6 Fixed a hang in the inc_recurse batch-reading code. 2009-01-17 13:54:52 -08:00
Matt McCutchen
1fb6163c51 Handle simultaneous arrival of multiple connections. 2009-01-17 13:46:11 -08:00
Wayne Davison
7f51d0e849 Avoid a server-side problem with -e is at the start of the short options.
(Bug #6020)
2009-01-17 13:44:06 -08:00
Wayne Davison
ece2d0e415 Fixed bug #6011: use of target in configure. 2009-01-17 13:43:48 -08:00
Wayne Davison
445640e803 Update the copyright year. 2009-01-17 13:41:35 -08:00
Wayne Davison
5ea7c8aae3 Beginning work on a 3.0.6 release. 2009-01-17 13:37:20 -08:00
Wayne Davison
7221063019 Preparing for release of 3.0.5 2008-12-28 18:02:17 -08:00
Wayne Davison
b64ae8b3b4 Avoid a hang when using at least 3 --verbose options on a transfer with
a client sender (which includes local copying).
2008-12-28 17:51:36 -08:00
Wayne Davison
9938bad34a Allow opendir() in send_directory() to fail with ENOENT. 2008-12-27 11:22:02 -08:00
Wayne Davison
1ff3e90507 Make it clearer which configure files changed. 2008-11-15 15:32:02 -08:00
Wayne Davison
b292021e45 Mention a few NEWS items that hadn't been mentioned yet. 2008-11-15 15:25:30 -08:00
Wayne Davison
13e40ca0c6 Preparing for release of 3.0.5pre2 2008-11-15 14:55:30 -08:00
Wayne Davison
8e85627fb3 An ftruncate() failure should result in FERROR_XFER. 2008-11-15 14:49:28 -08:00
Wayne Davison
d552250fbb Tweaked the month guess in OLDNEWS. 2008-11-15 14:38:14 -08:00
Wayne Davison
5436b64557 Change clean_fname() to keep "//" at the start for cygwin. 2008-11-15 14:17:49 -08:00
Wayne Davison
b325dd0326 Change some size_t vars to ints. 2008-11-15 13:29:03 -08:00
Wayne Davison
49818a8378 Make sparse_seek an OFF_T (pointed out by Pedro Valasco). 2008-11-11 18:06:50 -08:00
Wayne Davison
af03a7049c A "make reconfigure" doesn't stop if configure changes. 2008-11-11 15:55:53 -08:00
Wayne Davison
e401b30403 Mention Matt's -K --delete fix. 2008-11-10 07:48:00 -08:00
Matt McCutchen
e512826786 Add flist_find_ignore_dirness() and change delete_in_dir() to use it.
This fixes an issue with -K noticed by eric casteleijn, avoids some
inconsistent itemizing when a file/dir is replaced by a dir/file,
and removes a now-obsolete chunk of code from make_file().
2008-11-10 07:46:41 -08:00
Wayne Davison
ccdc2efd67 Mention the fix for --files-from dot/./paths. 2008-11-09 21:48:21 -08:00
Wayne Davison
b8a1fd6404 Fixed the use of a dot-dir path (foo/./bar) inside of a files-from file. 2008-11-09 21:39:08 -08:00
Wayne Davison
3082dffbe2 Fixed a bunch of "warn_unused_result" compiler warnings. 2008-11-09 18:55:14 -08:00
Wayne Davison
42130f9cb0 Mention hang fix in the NEWS. 2008-11-09 18:07:30 -08:00
Wayne Davison
c6c339cd18 Avoid a potential hang when --remove-*-files is active. 2008-11-09 18:02:11 -08:00
Matt McCutchen
6767ca617b The protect filter automatically added with --backup is not perishable
(see f41152d393), so remove the inaccurate
"p" from the man page.  Noticed by Jacob Balazer:

http://lists.samba.org/archive/rsync/2008-November/022022.html
2008-11-02 20:53:01 -08:00
Wayne Davison
7d9e30d383 Mention the getnameinfo() fix in the NEWS. 2008-10-25 09:47:08 -07:00
Wayne Davison
3f81ad6060 Mention rsync's definition of client and server. 2008-10-25 09:44:21 -07:00
Wayne Davison
723e9f856d Fixed our supplied getnameinfo()'s ability to do a reverse lookup,
as reported in bug 5851.
2008-10-25 08:39:41 -07:00
Wayne Davison
9189e41f6e Added another file-list filter to handle odd-ball systems that don't
seem to size their sprintf() fields correctly.
2008-10-14 07:27:56 -07:00
Wayne Davison
6f6f9d1020 Preparing for release of 3.0.5pre1 2008-10-11 11:41:05 -07:00
Wayne Davison
a76ba8b425 Mention the latest NEWS. 2008-10-11 11:40:40 -07:00
Wayne Davison
b8fd528794 Fixed a glitch when using -s with a remote-shell daemon. 2008-10-11 11:14:43 -07:00
Wayne Davison
0ea5d30479 Don't lookup address "0.0.0.0" when we're a remote-shell daemon.
Gets rid of a DNS delay waiting for a lookup failure.
2008-10-11 11:13:43 -07:00
Wayne Davison
cf1b292201 Fixed send_protected_args() to send "." in place of an empty arg. 2008-10-11 10:16:47 -07:00
Wayne Davison
f3721ed133 Added a fully atomic update if the user has setup a symlink
to a *-1 or *-2 directory.  A few other minor improvements.
2008-10-11 09:29:23 -07:00
Wayne Davison
b1220d62f4 Fix the error message on one of the rename operations. 2008-10-10 06:55:21 -07:00
Wayne Davison
5df89a1a44 Remove bogus "non-empty" qualifier in '*' discussion. 2008-09-26 21:47:53 -07:00
Wayne Davison
d47ac91209 Properly ignore source args on a --read-batch command. 2008-09-26 21:34:40 -07:00
Wayne Davison
7c573428a9 Fixed skipping of unneeded updates in a batch file when incremental
recursion is active.  Added a test for this.  Made batch-mode handle
redos properly (and without hanging).
2008-09-26 21:32:43 -07:00
Wayne Davison
f7e65c7b61 Moved the flist_ndx_{push,pop}() routines from io.c into util.c. 2008-09-26 21:21:52 -07:00
Wayne Davison
fe62d30de8 Fix the %P logfile escape inside a chroot. 2008-09-26 21:19:51 -07:00
Wayne Davison
494895fb4b Initialize xattr data in a couple spots in the hlink code, which avoids
a crash when the xattr pointer's memory happens to start out non-zero.
Also fixed the itemizing of an alt-dest file's xattrs when hard-linking.
2008-09-26 21:10:58 -07:00
Wayne Davison
ac68345a34 Don't send a bogus "-" option to an older server if there were
no short options specified.
2008-09-26 21:09:41 -07:00
Wayne Davison
6a9ade2ded Beginning work on a 3.0.5 release. 2008-09-26 21:07:56 -07:00
Wayne Davison
d596d389fe Preparing for release of 3.0.4 2008-09-06 09:32:26 -07:00
Wayne Davison
bc2337717e A few more improvements and a mention of the latest fix. 2008-09-06 08:03:52 -07:00
Wayne Davison
3df40f044a Changed some "rsync" commands into proper "$RSYNC" commands. 2008-09-03 12:14:13 -07:00
Wayne Davison
d11a5b80c1 Made human_num() and human_dnum() able to output negative numbers. 2008-09-01 13:25:41 -07:00
Wayne Davison
deea1f70bd Got rid of the check_for_io_err code, as it could cause a hang.
The io_error issue will be fixed in a better way in 3.1.0.
2008-08-31 09:51:29 -07:00
Wayne Davison
a91e678324 Some minor improvements to the flushing code to try to make it
even more solid.
2008-08-24 13:39:44 -07:00
Wayne Davison
25a22d8501 Make the !flist_eof assumption explicit before the check_for_io_err
code calls wait_for_receiver().
2008-08-24 12:33:22 -07:00
Wayne Davison
fac9e234ae Added /support/savetransfer to .gitignore. 2008-08-17 09:28:06 -07:00
Wayne Davison
f3d87ee972 An improved RERR_PARTIAL message. 2008-08-17 09:25:34 -07:00
Wayne Davison
9bed85542c Changed flist_for_ndx() to optionally die with an error
if the index isn't found.
2008-08-14 07:32:18 -07:00
Wayne Davison
5b979530a7 Made an error of readlink_stat() use the right function name. 2008-08-10 07:31:45 -07:00
Wayne Davison
7ec8baaa7e Make sure that the hlink node->data allocation doesn't fail. 2008-08-08 07:47:31 -07:00
Wayne Davison
8c2c008984 Improved a couple NEWS items. 2008-08-05 18:43:51 -07:00
Wayne Davison
719a29e1cf Preparing for release of 3.0.4pre2 2008-08-02 14:06:31 -07:00
Wayne Davison
4a95d61251 Tweaked the symlink iconv buffer size and fixed a comment. 2008-08-02 13:45:15 -07:00
Wayne Davison
fc088e30c8 When using --iconv, if a server-side receiver can't convert a filename,
it now outputs the name back to the client without mangling the charset.
2008-08-02 10:25:17 -07:00
Wayne Davison
aef51b4c68 Refer to the symlink's contents as "symlink data", not "symlink name". 2008-08-02 10:18:10 -07:00
Wayne Davison
7790ee3684 Added logic to the receiving side to ensure that the --delete-during
code will not delete in a directory prior to receiving an I/O error
for that directory (or not receiving it, as the case may be).
2008-08-02 09:03:49 -07:00
Wayne Davison
ed12c8eb21 Skip new symlink conversion step if the remote rsync is not
new enough to do symlink content conversions.
2008-08-02 07:04:54 -07:00
Wayne Davison
91dd3d0d48 The --iconv option now converts the content of a symlink too. 2008-08-01 19:20:41 -07:00
Wayne Davison
95d1d2a9a4 Fixed a problem with checking for the '.' dir in the first file
list that is transferred.  This fixes a glitch where a failed
--iconv conversion on the receiving side could prevent deletions
from happening in the root-dir of the transfer.
2008-08-01 19:00:21 -07:00
Wayne Davison
a808346dbe Fixed a couple minor problems in util.c:
- Make sure that handle_partial_dir() never returns a truncated fname.
- Make robust_rename() return that it failed to do a cross-device
  copy if the partial-dir could not be created.
2008-08-01 18:00:18 -07:00
Wayne Davison
fa181223d8 Properly handle a failure to create a partial directory, which is
especially important for --delay-updates, particularly when
--remove-source-files was also specified.
2008-08-01 18:00:09 -07:00
Wayne Davison
9ed569486f Output an FERROR* for a general io_error, and an FWARNING for other
io_error flags.
2008-07-31 07:57:55 -07:00
Wayne Davison
2fa069d85f Mention a missing sender-side hash improvment that went out in 3.0.0. 2008-07-30 08:33:35 -07:00
Wayne Davison
a25aed50e6 Make hard-linking work when a device has an st_dev of 0. 2008-07-29 18:08:51 -07:00
Wayne Davison
302e4346c2 Mention some mount options that can interfere with --link-dest. 2008-07-28 18:24:25 -07:00
Wayne Davison
8e5eafccdf Back-porting some manpage improvements. 2008-07-28 17:07:38 -07:00
Wayne Davison
e88b92bade Preparing for release of 3.0.4pre1 2008-07-24 17:03:26 -07:00
Wayne Davison
f8722dba56 Fixed the --fake-super test in the xattrs testsuite when there are
root-level xattrs on the files (e.g. selinux values).
2008-07-24 07:57:57 -07:00
Wayne Davison
ee03cb99d9 Fixed the timeout/flush loop-check logic to work properly with
incremental recursion.
2008-07-23 23:37:11 -07:00
Wayne Davison
92d706a274 Don't interrupt the make if a generated build file didn't really change. 2008-07-23 23:28:57 -07:00
Wayne Davison
581c830c56 A couple xattr fixes for --fake-super. 2008-07-23 23:12:39 -07:00
Wayne Davison
9e58ef45f3 If the user specifies --protocol=29, rsync will avoid sending an -e
option to the server (which is only useful for protocols 30 and above
anyway).  This gives the user an easy way to talk to a restricted
server that has overly restrictive option-checking.
2008-07-23 23:09:15 -07:00
Wayne Davison
05bd05a7a1 Pass --branch option to patch-update script. 2008-07-23 17:13:29 -07:00
Wayne Davison
89b6b4ce4b We only need to deal with local patch branches now. 2008-07-23 14:32:58 -07:00
Wayne Davison
68cdc3b791 Fixed a potential alignment issue in the IRIX ACL code when allocating
the initial struct acl object.  Also, cast mallocs to avoid warnings.
2008-07-22 21:35:21 -07:00
Wayne Davison
209371b891 Fixed a bug in match_hard_links() where an empty directory would try
to allocate 0 bytes of memory (which can fail on some OSes).
2008-07-22 21:34:20 -07:00
Wayne Davison
6fd2662982 Allow a release from a non-master branch. 2008-07-22 09:11:34 -07:00
Wayne Davison
1fdf0302c0 Start the 3.0.4 branch. 2008-07-22 09:11:22 -07:00
Wayne Davison
db8f3f7350 Preparing for release of 3.0.3 2008-06-29 20:15:37 -07:00
Wayne Davison
85fd80ce10 Mention the addition of the deny-rsync script, and tweak some comments. 2008-06-28 10:12:57 -07:00
Wayne Davison
a24d64bfaa Fixed a problem with a file descriptor being left open in the
generator when handling an empty file.
2008-06-26 08:14:11 -07:00
Wayne Davison
33cc92a63a Some deny-rsync fixes:
- Fixed messages longer than 63 chars.
- Don't require the presence of a "bc" program.
- Append a newline to the message to make the script easier to call.
- Make extra sure the message outputs without escape interpretation.
- Stick around long enough for a client to reliably get the message.
2008-06-23 23:10:12 -07:00
Matt McCutchen
5e7f63f0bf The deny-rsync script from bug 3945. 2008-06-23 23:04:21 -07:00
Wayne Davison
8bd77e7098 Fixed the sending of large files with older rsync versions by
handling the old block-size limit for protocols < 29.
2008-06-23 09:17:55 -07:00
Wayne Davison
13074c982b Preparing for release of 3.0.3pre3 2008-06-22 19:03:46 -07:00
Matt McCutchen
2171b9395b The sender now sets IOERR_GENERAL in more skipped-file instances. 2008-06-22 19:00:51 -07:00
Wayne Davison
20bb1eb7ae Mention more fixes in the NEWS. 2008-06-22 18:45:07 -07:00
Wayne Davison
7ee7bcd4e9 Improved the build rules for rsync.1 and rsyncd.conf.5 when building
in a separate build directory from the source.
2008-06-22 18:26:15 -07:00
Wayne Davison
844810d609 Avoid problems with timestamp rounding that cp -p and touch -r may do. 2008-06-17 15:59:47 -07:00
Wayne Davison
67347196b1 Fix the problem with setting xattrs on a directory that has an
identical match found in a --link-dest/--copy-dest hierarchy.
2008-06-12 23:08:43 -07:00
Wayne Davison
e424e26128 Cast the datum_len value to a long for rprintf(). 2008-06-12 06:59:51 -07:00
Wayne Davison
ca7d17e41d Handle a solo_file of a directory for --delete-during. 2008-06-09 07:42:03 -07:00
Wayne Davison
6283e9ef43 A couple more xattr improvements:
- Made the XSTATE_* defines avoid using 0.
- Call !XATTR_ABBREV() in recv_xattr_request().
- Improved the "internal abbrev" error message.
- Fixed the potential for a directory time glitch in xattrs.diff.
2008-06-08 21:14:46 -07:00
Wayne Davison
7462c6ac39 Fixed an "Internal abbrev error" when dealing with an xattr value
that is unchanged on an early file, and changed on a later file.
Added 2 new test cases to ensure this stays fixed.
2008-06-08 20:40:11 -07:00
Wayne Davison
f31850966f Improved the progress_is_active code to not overwrite the progress
output in more circumstances.
2008-06-04 09:01:02 -07:00
Wayne Davison
4ecf3e0671 Improved handling of a system that doesn't have a 64-bit offset type. 2008-06-04 08:15:51 -07:00
Wayne Davison
60a986f504 Improved the proto.h target so that a build in a different dir from the
srcdir will ensure that the builddir has a copy of the proto.h file when
the Makefile found it to be out of date.  This prevents the repeated
building of all the targets when the srcdir's proto.h file is accurate,
but older than the newest .c file.
2008-06-04 07:13:22 -07:00
Wayne Davison
0e9c3564c6 Improved the daemon testing, including adding a test to ensure that
daemon excludes can't exclude a dot dir.
2008-05-31 14:52:24 -07:00
Wayne Davison
164cb66add Fixed the destination path check so that it cannot exclude a
dot dir.
2008-05-31 14:51:38 -07:00
Wayne Davison
0d9eba0312 Have send_file_list() check is_excluded() (but only on non-dot-dirs)
and then call send_file_name() with NO_FILTERS.  This gets rid of
the need for a FLAG_DOTDIR_NAME flag (used only by make_file()).
2008-05-31 14:41:20 -07:00
Wayne Davison
d1f66d8d79 If an arg is excluded, don't include its implied dirs. 2008-05-31 11:29:24 -07:00
Wayne Davison
cc911409d6 Make sure the generator doesn't try to send a negative checksum count to
the sender (which would cause it to die with a cryptic error).  Instead,
warn the user when the file's size is too large for checksum processing.
2008-05-31 10:13:28 -07:00
Wayne Davison
a64f19e24b Fixed the backing up of a device or socket. 2008-05-22 16:44:01 -07:00
Wayne Davison
4337eeb754 A cuple more fixes for --xattrs combined with --backup, this time to
handle when --link-dest is also used.
2008-05-22 07:32:11 -07:00
Wayne Davison
928da42359 Fixed the "src" symlink in each testtmp subdir. 2008-05-18 07:00:48 -07:00
Wayne Davison
e717fa4d37 Fix some path problems when the build dir is not the
source dir.
2008-05-17 15:07:24 -07:00
Wayne Davison
cc56eb2acc Preparing for release of 3.0.3pre2 2008-05-17 10:02:19 -07:00
Wayne Davison
88e05f8489 Fixed an "else" in the device-making part of keep_backup(). 2008-05-17 09:57:08 -07:00
Wayne Davison
9ec8583ef5 Mention the latest fixes in the NEWS. 2008-05-17 09:45:13 -07:00
Wayne Davison
e9489cd6cb Fixed several issues with preserving xattrs when using --backup. 2008-05-17 09:35:46 -07:00
Wayne Davison
f1ca7c4429 Preserve the right errno value when trying adjunct functions during
robust backup, copy, and renaming activities.
2008-05-17 08:25:22 -07:00
Wayne Davison
adc4ebdd76 Improved the docs for --inplace and made the mentions of
rsync's delta-transfer algorithm more consistent.
2008-05-09 23:49:41 -07:00
Wayne Davison
9a30c0cc3c Preparing for release of 3.0.3pre1 2008-05-07 22:12:57 -07:00
Wayne Davison
47f43c023b The test of HAVE_LUTIMES accidentally omitted the 'L'. 2008-05-07 22:11:17 -07:00
Wayne Davison
5b385336b9 Added options to tls.c to allow us to ask for mtime and ownership info
on symlinks.  The testsuite will now pass these options to tls if rsync
is configured to affect such attributes on symlinks.
2008-05-06 10:39:19 -07:00
Wayne Davison
c3a2d95cfa Adding missing entry for 3.0.3 protocol-history list. 2008-05-01 16:14:39 -07:00
Wayne Davison
6b19df680a Mention all the latest changes in the NEWS. 2008-04-28 21:29:30 -07:00
Wayne Davison
fdf74bede0 - Changed prev_name into a buffer so that there is no chance that its
contents can be overwritten by other calls to f_name().
- Changed an hlink assert into a check that provides more debug info.
2008-04-28 21:17:36 -07:00
Wayne Davison
876ad10ccc Fixed a crash if a non-incremental-recursion transfer has a
skipped file in a set of hard-links.
2008-04-27 18:45:13 -07:00
Wayne Davison
34a2b39165 Reorder the filenames to touch to try to avoid a weird error on Solaris
5.8.  Also, use lsh in one of the runs in order to try a hard-link run
that uses a (pretend) remote shell.
2008-04-18 19:55:08 -07:00
Wayne Davison
276cc45571 Added a --no-cd option to support/lsh so that the script can be used by
the testsuite.  Improved the home-directory-changing code and added an
error message when "localhost" is not the hostname specified.  Use the
updated script in the testsuite instead of creating a pretend-ssh script
in a couple spots.
2008-04-18 19:41:57 -07:00
Wayne Davison
311676ed21 Fixed a problem with how the daemon filters deal with
a destination directory with a trailing slash.
2008-04-16 09:32:22 -07:00
Wayne Davison
4616867b0d Don't allow '.' dir to be excluded by the daemon's filter rules. 2008-04-16 09:30:28 -07:00
Wayne Davison
8a5ae84efd A few $last_touch tweaks. 2008-04-16 09:11:15 -07:00
Wayne Davison
59d2cd5a7f When running in --progress mode with a progress message active, the
client now outputs a newline prior to an error message, which avoids
overwriting the active file's last progress line.
2008-04-15 08:50:14 -07:00
Wayne Davison
1c3e6e8b26 Moved the setting of the socket options before the connect(). 2008-04-15 08:34:17 -07:00
Wayne Davison
f2681d42ff Fixed the %M escape, which was munging the wrong spaces. 2008-04-15 08:32:41 -07:00
Wayne Davison
774d1c367b Use overflow_exit() for overflows, not out_of_memory(). 2008-04-15 08:27:38 -07:00
Wayne Davison
1b8e0e876b Consistently call the daemon parameters "parameters", not "options",
which allows us to distinguish them from rsync's command-line options.
2008-04-15 08:26:00 -07:00
Wayne Davison
1502f4f58f Updated the README and the NEWS file. 2008-04-15 08:12:56 -07:00
Wayne Davison
6db1db5488 Fix a file-globbing bug in the daemon when chroot is on. 2008-04-11 22:32:38 -07:00
Wayne Davison
09ad90537d If the daemon test is run as root, use a --config option. 2008-04-11 21:57:17 -07:00
Wayne Davison
da9aefa6b4 Prepare repository for more development. 2008-04-11 21:55:43 -07:00
Wayne Davison
8ba802f3b4 Preparing for release of 3.0.2 2008-04-08 08:16:05 -07:00
Wayne Davison
e53f49d1af Call patch-update in its new location. 2008-04-08 08:15:39 -07:00
Wayne Davison
0917f581bc Roll over the NEWS files for the next release. 2008-04-08 08:03:20 -07:00
Wayne Davison
1fe2a3533f Fixed a potential overflow issue with realloc() that Sebastian Krahmer
pointed out.
2008-04-08 08:01:43 -07:00
Wayne Davison
237e9a178f Have the spec file put more useful stuff into the doc dir. 2008-04-05 22:46:48 -07:00
Wayne Davison
0668bfe077 Moving some files from support into packaging. 2008-04-05 22:45:12 -07:00
Wayne Davison
214af6ad83 Comment out the Source1 tar file by default in the spec file. 2008-04-04 00:27:14 -07:00
Wayne Davison
2551c47eb7 Fixed the code that removes old file versions for a final release. 2008-04-04 00:05:44 -07:00
Wayne Davison
83d22fd7f9 Bump the repository version to 3.0.2dev. 2008-04-04 00:04:58 -07:00
Wayne Davison
325c243210 Preparing for release of 3.0.1 2008-04-03 22:37:01 -07:00
Wayne Davison
4e90cfbfed A few more spec-file tweaks. 2008-04-01 20:00:08 -07:00
Wayne Davison
6fd2c27f38 Define a "srcdir" in the spec file and use it in the URLs for the
source files so that they use the unchanging src or src-preview
subdirectory location for the file.
2008-04-01 12:55:27 -07:00
Wayne Davison
19173d224a Tweaked rsync.spec to use "rsync" in place of "%{name}" in a few
places (which allows for easier creation of adjunct RPMs).
2008-03-31 14:10:07 -07:00
Wayne Davison
5b83829669 A simple change to change_pathname() to ensure that the error output
mentions the right path when dir == NULL.
2008-03-31 07:46:47 -07:00
Wayne Davison
8cd3c6dccf Preparing for release of 3.0.1pre3 2008-03-30 23:29:43 -07:00
Wayne Davison
29a89172f7 Improved the chdir() code:
- Renamed push_dir() to change_dir() and revised it a little so that it
  can chdir() to a relative path without an intervening chdir() back to
  the staring path.
- Renamed push_pathname() to change_pathname() and revised it to take
  different args and to only call path_is_daemon_excluded() on a new
  path (not a revisit of a file's already-checked path).
- Fixed change_pathname() to set the right pathname value when a chdir()
  call fails.
- Set orig_dir once outside of the change_pathname() function.
- Got rid of pop_dir().
2008-03-30 15:44:46 -07:00
Wayne Davison
2089375179 Some argc-based actions in parse_arguments() shouldn't happen on
the server side.
2008-03-30 08:05:50 -07:00
Wayne Davison
f8949e7647 Fixed a path-exclusion glitch when checking more than one arg. 2008-03-30 08:05:42 -07:00
Wayne Davison
84ecaa0eca Improved the code that protects a '.' dir from exclusion.
This fixed a glitch in the daemon-exclusion code that allowed
an exclude rule such as ".*" or "*/" to affect a '.' dir.
2008-03-29 23:06:18 -07:00
Wayne Davison
3f2d8d683a Extended a test to ensure that hard-linked distant files continues
to work in incremental-recursion mode.
2008-03-28 10:40:17 -07:00
Wayne Davison
fd2598022c Allow the file-list sending code to set XMIT_SAME_UID/XMIT_SAME_GID
when owner/group info isn't being preserved.  This helps to ensure
that the lower 8 bits of the xflags aren't 0, and is what older
rsync versions did.
2008-03-28 10:40:10 -07:00
Wayne Davison
b05c58cce6 Dump an extraneous empty line. 2008-03-28 10:30:11 -07:00
Wayne Davison
05805cd6b7 Preparing for release of 3.0.1pre2 2008-03-26 17:12:07 -07:00
Wayne Davison
a165be754b Mention two more NEWS items. 2008-03-26 17:04:29 -07:00
Wayne Davison
af3172c148 Ensure that a per-dir merge file is also loaded from implied directories
in the sender (was working in incremental mode).
2008-03-26 16:49:12 -07:00
Wayne Davison
487cb52615 Fixed the discovery of a prior finished hard-link when the entry
is old enough that it is no longer in the flist data.
2008-03-26 16:12:39 -07:00
Wayne Davison
9793bbb364 Improved a length check in parse_merge_name(). 2008-03-26 14:01:52 -07:00
Wayne Davison
f6f74b93ef Ensure that a per-dir merge file is also loaded from implied directories
in the generator (for protocol 30, at least).
2008-03-26 14:01:26 -07:00
Wayne Davison
7568ff448a Fixed the way rsync handles iconv-conversion problems in the file-list:
- If the sender cannot convert a name, the discarding of the entry now
  occurs soon enough to avoid affecting the sender's list (which was
  causing the file-list on the receiving side to be out of sync).
- If the receiver cannot convert a name, its transformation of the name
  into an empty name (which indicates that the entry should be skipped)
  is no longer thwarted by the clean_fname() call (which was changing
  the name into a ".").
2008-03-25 10:46:06 -07:00
Wayne Davison
56158b7e04 Preparing for release of 3.0.1pre1 2008-03-24 21:15:51 -07:00
Wayne Davison
798a9e4e74 Some more improvements for the packaging/release-rsync script:
- Check early if the version tag already exists, so it aborts right
  away if the release script can't do its work.
- Update the files in the "patches" dir while merging the master branch
  into the patch branches (done before creating the release patches for
  the rsync-patches tar file).
- Allow the user to ask to visit each patch when updating them.
- Pause after initial patch updating so that any extra patch changes
  can be done before the creating of the tar files.
- Ask for the GPG signing passphrase once for all signing commands.
2008-03-24 21:15:30 -07:00
Wayne Davison
c202b4fa96 Some improvements for support/patch-update:
- Added a --shell option which starts a sub-shell on each patch branch.
- Don't allow the user to exit a sub-shell if the branch is not clean.
- If the sub-shell exited with a non-zero exit status, prompt to see if
  the user wanted to abort rather than assuming that.
- Wait to start the new patch-file output until after the shell runs.
- Always return to the starting branch on exit.
2008-03-24 20:30:09 -07:00
Wayne Davison
1df02d13d3 Don't send daemon-config filter-action messages back to the user. 2008-03-24 10:14:59 -07:00
Wayne Davison
73cb6738b3 Improved --dirs/--no-dirs/--list-only option handling:
- Moved setting of list_only and xfer_dirs from main.c to options.c.
- Fixed the ability of the user to force --no-dirs.
- Added the --old-dirs/--old-d option to make it easier to interact
  in list-only mode with an older rsync.
- Suggest the use of --old-d instead of "-r --exclude='/*/*'".
2008-03-24 09:54:04 -07:00
Wayne Davison
ba8672dfab Added a couple more NEWS items. 2008-03-23 10:06:53 -07:00
Wayne Davison
a5e0bf3579 Properly handle a new patch-branch that is only available locally. 2008-03-23 09:53:15 -07:00
Wayne Davison
99ba99c74c Changed the way version numbering of pre-releases will be done in
the RPM spec file so that they order prior to the final release.
2008-03-23 00:10:12 -07:00
Wayne Davison
469ff84e29 More NEWS updates and improvements. 2008-03-22 22:33:04 -07:00
Wayne Davison
b5daf5300f Made the filename arg-parsing code skip args that have excluded path
components, returning the same errors that would occur if the path
elements didn't actually exist.  The glob_match() code was also
changed to no longer truncate an arg with an excluded path element
(it just omits excluded items from glob matching).
2008-03-22 15:33:18 -07:00
Wayne Davison
f5aeb6ff9b Added XFLG_DIR2WILD3 flag that the daemon uses to transform any
config-file dir/ exclude rule into a dir/*** rule.
2008-03-22 14:02:34 -07:00
Wayne Davison
4c74d44dab A couple fixes in add_rule() for XFLG_ABS_IF_SLASH:
- Remove the trailing slash earlier, so that it doesn't
  affect the XFLG_ABS_IF_SLASH check.
- Count the slashes earlier so that the XFLG_ABS_IF_SLASH
  can use it instead of using a strchr() all that could
  scan past the end of the input.
2008-03-22 12:30:43 -07:00
Wayne Davison
4a86fbcda0 Change ex_len to pre_len in add_rule(). 2008-03-22 12:21:41 -07:00
Wayne Davison
bc267e0f57 Improved ENSURE_MEMSPACE() macro and use it in more places in glob code. 2008-03-22 08:13:04 -07:00
Wayne Davison
fc05137846 Mention the most recent changes in the NEWS. 2008-03-21 17:50:01 -07:00
Wayne Davison
c085ece623 Some RPM spec file improvements:
- Added installation of new /etc/xinetd.d/rsync config file.
- Added commented-out lines to demonstrate how to use rsync-patches.
2008-03-21 17:11:20 -07:00
Wayne Davison
91f625cee0 Make glob_expand() return an indicator if the glob had no matches. 2008-03-21 15:00:28 -07:00
Wayne Davison
27b067f87b Changed d_name() to be a static inline function. 2008-03-21 07:26:25 -07:00
Wayne Davison
987a546756 A couple improvements to the new arg-globbing code:
- Put all the state variables into a single struct.
- Reuse the buffer memory for each glob_expand() call until a final
  call with a NULL pointer tells us to free it.
2008-03-21 07:22:34 -07:00
Wayne Davison
4d30f17671 Changed the arg-globbing routine to use a custom arg-globbing algorithm
that does not include any daemon-excluded items in the matches.  It is
also not subverted by the presence of one or more dot-dir elements in
an arg.
2008-03-20 23:30:09 -07:00
Wayne Davison
d48810ba5b Some improvements to the file-name cleaning code:
- Removed the CFN_KEEP_LEADING_DOT_DIR flag for clean_fname().
- Explicitly add an implied dot-dir to the transfer rather than keeping
  a leading a "./" prefix as a part of a relative pathname.
- Added the CFN_KEEP_DOT_DIRS flag for clean_fname().
- Added the SP_KEEP_DOT_DIRS flag for sanitize_path().
- Call clean_fname() a couple more times.
2008-03-20 22:39:29 -07:00
Wayne Davison
819bfe4599 Changed the name of the server_filter_list to be
daemon_filter_list, for improved clarity.
2008-03-20 10:42:43 -07:00
Wayne Davison
d2f6e19262 Fixed a bug in the truncating of daemon-excluded paths. 2008-03-20 10:35:53 -07:00
Wayne Davison
e889e0c43b A couple more support/rrsync tweaks:
- Die if the --server option is not first on the command-line.
- Don't allow the --daemon option by default.
2008-03-19 16:44:11 -07:00
Wayne Davison
6e0bf4d840 Some more minor changes for the skip/missing/dry_run code. 2008-03-19 08:59:44 -07:00
Matt McCutchen
83a8ca7b14 Unsnarl missing_below/dry_run logic.
The generator can skip a directory's contents altogether due to
--ignore-non-existing, a daemon exclude, or a mkdir failure.  On a
--dry-run, the generator can also note the missingness of a directory
while still scanning its contents.  These two scenarios were conflated
using a single set of missing_below/missing_dir variables in combination
with transient increments in dry_run; this caused at least three bugs.

Now recv_generator has separate variables for the two scenarios, called
skip_dir and dry_missing_dir, respectively.  For simplicity, we take the
F_DEPTH instead of having separate *_below variables.  We mark both
kinds of missing dirs with FLAG_MISSING_DIR.  (dry_run > 1) iff the
*root* of the destination does not exist; it is no longer incremented
for missing subdirs.  I added tests for the three fixed bugs in
missing.test.
2008-03-19 07:45:58 -07:00
Matt McCutchen
100200d0d2 Fix a poorly placed sentence in rsyncd.conf.yo. 2008-03-18 15:28:36 -04:00
Wayne Davison
f28bf7f401 My modified version of Matt's improvements to the sections on
the various filter parameters.
2008-03-18 11:41:00 -07:00
Wayne Davison
e0fd68f5ce Improved arg-path checking so that wildcards can't be used to
avoid a daemon-exclude.
2008-03-18 10:57:54 -07:00
Wayne Davison
cc12c488aa Use the missing_below code to make the daemon-exclusions
work better.
2008-03-18 10:10:13 -07:00
Wayne Davison
99c3e591b2 Reject a daemon-excluded destination. 2008-03-18 09:44:42 -07:00
Wayne Davison
1aefb7ef73 Output a non-existent-file error for server-excluded files instead of
silently ignoring them.
2008-03-18 09:16:24 -07:00
Matt McCutchen
d7b6774d82 More typo fixes. 2008-03-17 15:32:07 -04:00
Wayne Davison
d4c5cb2b01 A couple more changes for dealing with "checker" warnings. 2008-03-17 10:50:11 -07:00
Matt McCutchen
df476bfcff Fix typo in rsyncd.conf man page. 2008-03-17 11:30:08 -04:00
Wayne Davison
aa0e6b9977 Attempting to silence some more "checker" warnings. 2008-03-17 07:35:19 -07:00
Wayne Davison
1ba6468f1b Mention all the latest changes in the NEWS file. 2008-03-16 22:43:35 -07:00
Wayne Davison
f490102454 If we're not compiling one or more major options (ACLs, xattrs, & iconv),
try to turn off unused-parameter compiler warnings.
2008-03-16 21:51:07 -07:00
Wayne Davison
18f3cb6957 Changed stat() call to do_stat(). 2008-03-16 21:44:33 -07:00
Wayne Davison
7abcfd85b7 Moved declaration of "int i" outside the ifdef in send_protected_args(). 2008-03-16 20:39:16 -07:00
Wayne Davison
6de417d9d4 If the system's popt.h file is not found, use our provided popt code. 2008-03-16 20:35:18 -07:00
Wayne Davison
ffe8feb265 Added "const" to a couple more char * args. 2008-03-16 19:50:35 -07:00
Wayne Davison
c9b62cf375 Fixed hard-linking when some of the files can get skipped. This adds
the FLAG_SKIP_HLINK flag, which gets set on any hard-linked file that
the user wants to skip (e.g. via --ignore-existing, --append, etc.).
The code in hlink.c now deals with the skipped files instead of
triggering an assert() error.
2008-03-16 19:47:35 -07:00
Wayne Davison
7bc595785e Made the FLAG_MOUNT_DIR bit only honored on a directory. 2008-03-16 17:52:31 -07:00
Wayne Davison
022dec7aba Moved the --append check so that files that don't need to be transferred
still get their non-content attributes updated, and combining --append
with --hard-links will not prevent the discovery of unchanged files.
2008-03-16 17:50:28 -07:00
Wayne Davison
ddaef70ced Make the --ignore-existing option not overwrite a regular file with
a dir/symlink/device/special-file, just like it already refuses to
overwrite a non-regular file with a regular file.
2008-03-16 17:17:38 -07:00
Wayne Davison
2357a51e09 A daemon no longer tries to refuse the iconv option when it is not enabled. 2008-03-16 12:11:19 -07:00
Wayne Davison
24ded29ff6 Fixed a hang when using --remove-source-files in dry-run mode. 2008-03-16 06:56:26 -07:00
Wayne Davison
ddff23a7f9 Added missing $(CPPFLAGS) from the building of rounding.h. 2008-03-15 14:09:20 -07:00
Wayne Davison
53936ef935 Fixed the use of --protect-args (-s) with a daemon. 2008-03-15 11:56:18 -07:00
Wayne Davison
7f9bf6b710 Generate a helpful message when we get an option-error from a daemon
while requesting a file-listing and we suspect that the remote rsync
is complaining about the -d option.
2008-03-15 11:24:38 -07:00
Wayne Davison
cfdb27b0c1 Another optimization of "bp" adding when creating a file_struct. 2008-03-15 07:27:33 -07:00
Wayne Davison
fc3ca11040 Got rid of some useless uses of the -t option. 2008-03-15 07:26:46 -07:00
Wayne Davison
d6c9c3319b - Fixed a crash bug when backing up files with ACLs enabled and we
create a directory in the backup-path area.
- Fixed a bug where make_file() was setting F_PATHNAME() on the
  receiving side.
- A non-pool (temp-memory) file structure now stores the size of
  its extra_cnt value in the F_DEPTH() int so that unmake_file()
  can always be sure of how to free() the memory.
- The ACL-preserving code no longer allocates 4 more bytes per
  file entry than it needs.
- Got rid of a useless adding of the symlink length to "bp".
2008-03-15 00:44:53 -07:00
Wayne Davison
8afaef4219 Have configure check to see if /usr/include/popt/popt.h is around
(rather than /usr/include/popt.h), and use the included popt lib
if it is (to avoid a potential conflict due to our use of -I.).
2008-03-14 22:55:59 -07:00
Wayne Davison
11faa893ca (Matt) More itemize clarifications. 2008-03-13 17:45:13 -07:00
Wayne Davison
600b56b316 Clarify that the change/checksum itemize flag can be missing
when talking to older rsync versions.
2008-03-12 16:51:13 -07:00
Wayne Davison
ee39281d14 Fixed the 'T' itemized output for a symlink the right way this time. 2008-03-11 17:35:49 -07:00
Wayne Davison
0607c30700 - One more fix for the 'T' itemized output for a symlink when we're
the client on the receiving side of a protocol-29 connection.
2008-03-11 07:26:37 -07:00
Wayne Davison
492ad04277 (Matt) Add missing --no-y option. 2008-03-10 21:40:04 -07:00
Wayne Davison
1ed9018e69 Fixed some itemized logging failures:
- If a symlink/device/special-file changes its value without any
  attribute changes, the itemized event no longer gets dropped.
- We put a 'c' into the checksum/change field now to indicate when
  a symlink/device/special-file changes its value without changing
  its type.  This lets us properly interpret the --copy-links output
  to know which items are getting copied without changes and which
  are getting created with new content.
- Fixed the 'T' itemized output for a symlink when rsync tries to
  set the right time but fails due to lack of OS/disk support.
2008-03-10 21:39:01 -07:00
Wayne Davison
ff0e15804f Fixed the itemizing of perms with -E. 2008-03-09 19:50:51 -07:00
Wayne Davison
894e6299c1 Some popt improvements:
- Fixed a bug in short-opt parsing when an abutting arg has an '='.
- Allow a short-opt to be separated from its arg by an '='.
- Avoid an IBM-checker warning about an impossible case in a switch
  and a warning about a potential NULL-pointer dereference.
- Fixed a memory leak.
2008-03-08 11:02:40 -08:00
Wayne Davison
c080190365 Fixed the latest xattrs tests on OS X. 2008-03-07 17:13:38 -08:00
Wayne Davison
26f0e56587 Restore a long-attribute test that was temporarily disabled. 2008-03-07 16:45:26 -08:00
Wayne Davison
b4e6aac985 Fixed a syntax problem for non-HAVE_LINUX_ATTRS systems. 2008-03-07 16:41:09 -08:00
Wayne Davison
7c21776e54 Handle the very latest spot for the nightly dir. 2008-03-07 16:25:05 -08:00
Wayne Davison
d724dd186e Fixed the interaction of --fake-super with --link-dest & --xattrs.
Fixed the munging of non-user namespace xattrs w/--fake-super.
Fixed the sorting of received xattrs when name-munging occurs.
Added xattr tests to verify that these things stay fixed.
2008-03-07 16:23:21 -08:00
Wayne Davison
cbbd8e2e8b The --fake-super option conflicts with -XX (which copies internal
rsync xattrs literally).
2008-03-07 15:23:39 -08:00
Wayne Davison
af6241f7ad Simplify the description of what we're doing. 2008-03-06 09:40:46 -08:00
Wayne Davison
852e763b89 Added even more no-OPTION overrides. 2008-03-06 09:38:48 -08:00
Wayne Davison
0f71592015 Made the description of ignored symlink errors more accurate. 2008-03-06 09:37:26 -08:00
Wayne Davison
e63d3a29e2 Updated nightly-rsync and release-rsync to handle the new
ftp directory layout.
2008-03-05 00:22:55 -08:00
Wayne Davison
38cef641a5 Updated rrsync to deal with the latest 3.0.0's use of the -e option.
Added a couple more long options that might get passed.
2008-03-04 22:51:56 -08:00
Wayne Davison
6226396c4a Don't call utimes() on a dir that doesn't need its mtime changed. 2008-03-04 22:48:01 -08:00
Wayne Davison
89b47d43de - Made the itemize test check for CAN_HARDLINK_SYMLINK define instead
of running its own test using ln.
- Made the merge test call checkit with absolute paths so that some
  folk's cd command won't foul things up with extra output.
2008-03-04 21:46:27 -08:00
Wayne Davison
d1c06c2180 Fixing a problem with a NULL config_file pointer when accessing
a single-use daemon without no --config option specified.  Added
a test to ensure that this doesn't break in the future.
2008-03-03 18:33:11 -08:00
Wayne Davison
800a4485f3 Improved the error-checking when tweaking the files for a new release. 2008-03-03 12:33:15 -08:00
Wayne Davison
fede378577 Updated copyright year in --version output and improved the release
script to look for year changes in options.c and to get the version
defaults totally right in the prompts.
2008-03-03 11:19:48 -08:00
Wayne Davison
3bc207b9dd Fixed a thinko and a typo in the --append option. 2008-03-03 07:16:38 -08:00
Wayne Davison
ebac031925 Show the last compile error if we failed to create rounding.h. 2008-03-01 21:00:41 -08:00
Wayne Davison
3cbe640d3c Tweak the files to start work on the next release.
The work-in-progress version is 3.0.1dev.
2008-03-01 20:35:18 -08:00
Wayne Davison
4cb6197b21 Preparing for release of 3.0.0 2008-03-01 12:12:04 -08:00
Wayne Davison
d3d07a5e86 Include 2008 in the copyright years. 2008-03-01 12:01:41 -08:00
Wayne Davison
62ca38262f Fixed the lastversion default when changing from a pre-release
to a final release.  Ensure that newly-created "extra files"
get included in the diff.
2008-03-01 12:00:13 -08:00
Wayne Davison
d62fb8894f Mention a couple more items of note. 2008-03-01 09:48:55 -08:00
Wayne Davison
fc29efc38d Use variables to hold the constant itemized strings so
that future changes are easier to make.
2008-02-27 17:57:29 -08:00
Wayne Davison
c4c9bb944b Temporarily set uid_ndx in the delete code if the transfer is not
preserving ownership, but we want to know what the UIDs are on the
files we're deleting.  Changed the DEL_OWNED_BY_US flag to be
DEL_NO_UID_WRITE, which is only set when a file is owned by us and
we can't write to it.  Fixed a glitch in the error handling of the
--delete-delay code where it might try to enable delete-after in
incremental-transfer mode.  Made a simple (well tested) optimization
in the --delete-delay code and a few other readability changes.
2008-02-27 16:25:29 -08:00
Wayne Davison
236adddc18 Use preserve_[ug]id values for send/recv checking, which will
allow the delete code to temporarily set [ug]id_ndx during
delete processing, as needed.  Got rid of a couple duplicate
tests.
2008-02-27 16:15:14 -08:00
Wayne Davison
5b3aa8028b Added missing init_iconv() call when initiating a daemon transfer. 2008-02-27 07:19:13 -08:00
Wayne Davison
16e24c2043 Don't force the user to start from the master branch when any
clean starting branch will do.  Return to the starting branch.
2008-02-24 13:19:51 -08:00
Wayne Davison
7869953bbf Fixed the description of the 'x' in the itemized output. 2008-02-23 20:55:39 -08:00
Wayne Davison
d07edfc895 Added a default to the new switch in str_acl_type(). 2008-02-23 08:14:56 -08:00
Wayne Davison
85b057cccf Check the return code from mbr_uid_to_uuid()/mbr_gid_to_uuid() so
that the user sees the right error if they failed.
2008-02-23 07:44:55 -08:00
Wayne Davison
a2c473bb59 Tweaked the ACL type-names returned by str_acl_type()
so that error messages are a little clearer.
2008-02-23 07:33:32 -08:00
Wayne Davison
f587061a5b Cast ai->ai_addrlen to int for an rprintf() call using %d. 2008-02-22 15:15:32 -08:00
Wayne Davison
d9e92804a5 The code expects id_t and mode_t to be unsigned, so the code now defines
each one to be unsigned int (instead of int) when the type is missing.
2008-02-21 20:51:54 -08:00
Wayne Davison
46e858a631 Improved several things in the NEWS files, including some typos
that Matt fixed.
2008-02-20 10:32:35 -08:00
Wayne Davison
e0fe5231c2 Output info on what's being signed to make it clearer
what is happening.  Improved the final admonition.
2008-02-19 19:18:20 -08:00
95 changed files with 5013 additions and 2519 deletions

4
.gitignore vendored
View File

@@ -3,10 +3,13 @@
dummy
ID
Makefile
Makefile.old
configure.sh
configure.sh.old
config.cache
config.h
config.h.in
config.h.in.old
config.log
config.status
/proto.h
@@ -32,6 +35,7 @@ config.status
/rounding.h
/doc/rsync.pdf
/doc/rsync.ps
/support/savetransfer
/testsuite/chown-fake.test
/testsuite/devices-fake.test
/patches

View File

@@ -59,15 +59,15 @@ CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: conf_stop make_stop rsync$(EXEEXT) @MAKE_MAN@
all: Makefile rsync$(EXEEXT) @MAKE_MAN@
install: all
-mkdir -p ${DESTDIR}${bindir}
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
-mkdir -p ${DESTDIR}${mandir}/man1
-mkdir -p ${DESTDIR}${mandir}/man5
if test -f $(srcdir)/rsync.1; then ${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1; fi
if test -f $(srcdir)/rsyncd.conf.5; then ${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
install-strip:
$(MAKE) INSTALL_STRIP='-s' install
@@ -82,7 +82,7 @@ flist.o: rounding.h
rounding.h: rounding.c rsync.h
@for r in 0 1 3; do \
if $(CC) $(CFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >/dev/null 2>&1; then \
if $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >rounding.out 2>&1; then \
echo "#define EXTRA_ROUNDING $$r" >rounding.h; \
if test -f "$$HOME/build_farm/build_test.fns"; then \
echo "EXTRA_ROUNDING is $$r" >&2; \
@@ -92,9 +92,11 @@ rounding.h: rounding.c rsync.h
done
@rm -f rounding
@if test -f rounding.h; then : ; else \
echo "Failed to create rounding.h!"; \
cat rounding.out 1>&2; \
echo "Failed to create rounding.h!" 1>&2; \
exit 1; \
fi
@rm -f rounding.out
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
@@ -109,7 +111,7 @@ TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
@@ -121,35 +123,63 @@ gensend: gen
conf:
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
conf_stop: configure.sh config.h.in
configure.sh config.h.in: configure.in 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
autoheader && touch config.h.in
@echo 'Configure files changed -- perhaps run:'
@echo ' make reconfigure'
@exit 1
@if diff configure.sh configure.sh.old >/dev/null 2>&1; then \
echo "configure.sh is unchanged."; \
rm configure.sh.old; \
else \
echo "configure.sh has CHANGED."; \
fi
@if diff config.h.in config.h.in.old >/dev/null 2>&1; then \
echo "config.h.in is unchanged."; \
rm config.h.in.old; \
else \
echo "config.h.in has CHANGED."; \
fi
@if test -f configure.sh.old -o -f config.h.in.old; then \
if test "$(MAKECMDGOALS)" = reconfigure; then \
echo 'Continuing with "make reconfigure".'; \
else \
echo 'You may need to run:'; \
echo ' make reconfigure'; \
exit 1; \
fi \
fi
reconfigure: configure.sh
./config.status --recheck
./config.status
make_stop: Makefile
Makefile: Makefile.in config.status
Makefile: Makefile.in config.status configure.sh config.h.in
@if test -f Makefile; then cp -p Makefile Makefile.old; else touch Makefile.old; fi
@./config.status
@echo "Makefile updated -- rerun your make command."
@exit 1
@if diff Makefile Makefile.old >/dev/null 2>&1; then \
echo "Makefile is unchanged."; \
rm Makefile.old; \
else \
if test "$(MAKECMDGOALS)" = reconfigure; then \
echo 'Continuing with "make reconfigure".'; \
else \
echo "Makefile updated -- rerun your make command."; \
exit 1; \
fi \
fi
proto: proto.h-tstamp
proto.h: proto.h-tstamp
@echo ' ' >/dev/null
@if test -f proto.h; then :; else cp -p $(srcdir)/proto.h .; fi
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c config.h
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
man: rsync.1 rsyncd.conf.5
@if test -f rsync.1; then :; else cp -p $(srcdir)/rsync.1 .; fi
@if test -f rsyncd.conf.5; then :; else cp -p $(srcdir)/rsyncd.conf.5 .; fi
rsync.1: rsync.yo
yodl2man -o rsync.1 $(srcdir)/rsync.yo
@@ -161,7 +191,7 @@ rsyncd.conf.5: rsyncd.conf.yo
clean: cleantests
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h
rounding rounding.h *.old
cleantests:
rm -rf ./testtmp*

342
NEWS
View File

@@ -1,330 +1,64 @@
NEWS for rsync 3.0.0 (UNRELEASED)
Protocol: 30 (changed)
Changes since 2.6.9:
NOTABLE CHANGES IN BEHAVIOR:
- The handling of implied directories when using --relative has changed to
send them as directories (e.g. no implied dir is ever sent as a symlink).
This avoids unexpected behavior and should not adversely affect most
people. If you're one of those rare individuals who relied upon having
an implied dir be duplicated as a symlink, you should specify the
transfer of the symlink and the transfer of the referent directory as
separate args. (See also --keep-dirlinks and --no-implied-dirs.)
Also, exclude rules no longer have a partial effect on implied dirs.
- Requesting a remote file list without specifying -r (--recursive) now
sends the -d (--dirs) option to the remote rsync rather than sending -r
along with an extra exclude of /*/*. If the remote rsync does not
understand the -d option (i.e. it is 2.6.3 or older), you will need to
either turn off -d (--no-d), or specify -r --exclude='/*/*' manually.
- In --dry-run mode, the last line of the verbose summary text is output
with a "(DRY RUN)" suffix to help remind you that no updates were made.
Similarly, --only-write-batch outputs "(BATCH ONLY)".
- A writable rsync daemon with "use chroot" disabled now defaults to a
symlink-munging behavior designed to make symlinks safer while also
allowing absolute symlinks to be stored and retrieved. This also has
the effect of making symlinks unusable while they're in the daemon's
hierarchy. See the daemon's "munge symlinks" parameter for details.
NEWS for rsync 3.0.7 (31 Dec 2009)
Protocol: 30 (unchanged)
Changes since 3.0.6:
BUG FIXES:
- A daemon with "use chroot = no" and excluded items listed in the daemon
config file now properly checks an absolute-path arg specified for these
options: --compare-dest, --link-dest, --copy-dest, --partial-dir,
--backup-dir, --temp-dir, and --files-from.
- Fixed a bogus free when using --xattrs with --backup.
- A daemon can now be told to disable all user- and group-name translation
on a per-module basis. This avoids a potential problem with a writable
daemon module that has "use chroot" enabled -- if precautions weren't
taken, a user could try to add a missing library and get rsync to use
it. This makes rsync safer by default, and more configurable when id-
translation is not desired. See the daemon's "numeric ids" parameter
for full details.
- Avoid an error when --dry-run was trying to stat a prior hard-link file
that hasn't really been created.
- A chroot daemon can now indicate which part of its path should affect the
chroot call, and which part should become an inside-chroot path for the
module. This allows you to have outside-the-transfer paths (such as for
libraries) even when you enable chroot protection.
- Fixed a problem with --compress (-z) where the receiving side could
return the error "inflate (token) returned -5".
- If a file's data arrived successfully on the receiving side but the
rename of the temporary file to the destination file failed AND the
--remove-source-files (or the deprecated --remove-sent-files) option
was specified, rsync no longer erroneously removes the associated
source file.
- 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).
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
- Improved --skip-compress's error handling of bad character-sets and got
rid of a lingering debug fprintf().
- Made the output of all file types consistent when using a --*-dest
option. Prior versions would output too many creation events for
matching items.
- Fixed the daemon's conveyance of io_error value from the sender.
- The code that waits for a child pid now handles being interrupted by a
signal. This fixes a problem with the pre-xfer exec function not being
able to get the exit status from the script.
- An rsync daemon use seteuid() (when available) if it used setuid().
- A negated filter rule (i.e. with a '!' modifier) no longer loses the
negation when sending the filter rules to the remote rsync.
- Get the permissions right on a --fake-super transferred directory that
needs more owner permissions to emulate root behavior.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
no longer outputs superfluous directory info for a non-daemon rsync.
- An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
its modifier when sending the filter rules to the remote rsync.
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
files (which includes local copies). Version 2.6.9 would complete the
copy, but exit with an error when the receiver output its memory stats.
- Improved the "--delete does not work without -r or -d" message.
- If --password-file is used on a non-daemon transfer, rsync now complains
and exits. This should help users figure out that they can't use this
option to control a remote shell's password prompt.
- 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).
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- Some misc manpage improvements.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- 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.
- The --append option no longer updates a file that has the same size.
- Improved the error-exit reporting when rsync gets an error trying to
cleanup after an error: the initial error is reported.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Improved configure's detection of IPv6 for solaris and cygwin.
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
- Starting up an extra copy of an rsync daemon will not clobber the pidfile
for the running daemon -- if the pidfile exists, the new daemon will exit
with an error.
- Made our (only used if missing) getaddrinfo() routine use inet_pton()
(which we also provide) instead of inet_aton().
- The daemon pidfile is checked and created sooner in the startup sequence.
- If a daemon module's "path" value is not an absolute pathname, the code
now makes it absolute internally (making it work properly).
- Ensure that a temporary file always has owner-write permission while we
are writing to it. This avoids problems with some network filesystems.
- Any errors output about password-file reading no longer cause an error at
the end of the run about a partial transfer.
- The --read-batch option for protocol 30 now ensures that several more
options are set correctly for the current batch file: --iconv, --acls,
--xattrs, --inplace, --append, and --append-verify.
- Using --only-write-batch to a daemon receiver now work properly (older
versions would update some files while writing the batch).
- Avoid outputting a "file has vanished" message when the file is a broken
symlink and --copy-unsafe-links or --copy-dirlinks are used (the code
already handled this for --copy-links).
- Fixed the combination of --only-write-batch and --dry-run.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
to another 3.x version. This starts the transfer going more quickly
(before all the files have been found), and requires much less memory.
See the --recursive option in the manpage for some restrictions.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.
- Rsync now allows multiple remote-source args to be specified rather than
having to rely on a special space-splitting side-effect of the remote-
shell. Additional remote args must specify the same host or an empty one
(e.g. empty: :file1 or ::module/file2). This means that local use of
brace expansion now works: rsync -av host:dir/{f1,f2} .
- Added the --protect-args (-s) option, that tells rsync to send most of
the command-line args at the start of the transfer rather than as args
to the remote-shell command. This protects them from space-splitting,
and only interprets basic wildcard special shell characters (*?[).
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.
- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available, and it even
supports OS X ACLs. If you need to have backward compatibility with old,
ACL-patched versions of rsync, apply the acls.diff file from the patches
dir.
- Added the --xattrs (-X) option to preserver extended attributes. This is
an improved version of the prior patch that was available, and it even
supports OS X xattrs (which includes their resource fork data). If you
need to have backward compatibility with old, xattr-patched versions of
rsync, apply the xattrs.diff file from the patches dir.
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
It even supports the storing of foreign ACL data on your backup server.
There is also an analogous "fake super" parameter for an rsync daemon.
- Added the --iconv option, which allows rsync to convert filenames from
one character-set to another during the transfer. The default is to make
this feature available as long as your system has iconv_open(). If
compilation fails, specify --disable-iconv to configure, and then
rebuild. If you want rsync to perform character-set conversions by
default, you can specify --enable-iconv=CONVERT_STRING with the default
value for the --iconv option that you wish to use. For example,
"--enable-iconv=." is a good choice. See the rsync manpage for an
explanation of the --iconv option's settings.
- A new daemon config parameter, "charset", lets you control the character-
set that is used during an --iconv transfer to/from a daemon module.
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress.
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
The matching routine was also optimized to run more quickly.
- The --max-delete option now outputs a warning if it skipped any file
deletions, including a count of how many deletions were skipped. (Older
versions just silently stopped deleting things.)
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
about extraneous files without deleting anything. If you're not sure
what version the client is, you can use the less-obvious --max-delete=-1,
as both old and new versions will treat that as the same request (though
older versions don't warn).
- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).
- The filter rules now support a perishable ("p") modifier that marks rules
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- Rsync checks all the alternate-destination args for validity (e.g.
--link-dest). This lets the user know when they specified a directory
that does not exist.
- If we get an error setting the time on a symlink, we don't complain about
it anymore (since some operating systems don't support that, and it's not
that important).
- Protocol 30 now uses MD5 checksums instead of MD4.
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --append-verify option, which works like the older --append
option (verifying the existing data in the destination file). For
compatibility with older rsync versions, any use of --append that is
talking protocol 29 or older will revert to the --append-verify method.
- Added the --contimeout=SECONDS option that lets the user specify a
connection timeout for rsync daemon access.
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
that can be used to enhance the client side of a daemon connection.
- Improved the dashes and double-quotes in the nroff manpage output.
- We now support a lot more --no-OPTION override options.
INTERNAL:
- The file-list sorting algorithm now uses a sort that keeps any same-
named items in the same order as they were specified. This allows
rsync to always ensure that the first of the duplicates is the one
that will be included in the copy. The new sort was also faster
than the glibc version of qsort() and mergesort() in my testing.
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Made the file-deletion code use a little less stack when recursing
through a directory hierarchy of extraneous files.
- Fixed a build problem with older (2.x) versions of gcc.
- Added some isType() functions that make dealing with signed characters
easier without forcing variables via casts.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Added missing prototypes for compatibility functions from the lib dir.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Made the sending of some numbers more efficient for protocol 30.
- Make sure that a daemon process doesn't mind if the client was weird and
omitted the --server option.
- There are more internal logging categories available in protocol 30 than
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
categories allow some errors and warnings to go to stderr without causing
an erroneous end-of-run warning about some files not being able to be
transferred.
- Improved the use of "const" on pointers.
- Improved J.W.'s pool_alloc routines to add a way of freeing older
sections of a pool's memory.
- The getaddrinfo.c compatibility code in the "lib" dir was replaced with
some new code (derived from samba, derived from PostgreSQL) that has a
better license than the old code.
- The exit-related debug messages now mention the program's role so it is
clear who output what message.
DEVELOPER RELATED:
- Rsync is now licensed under the GPLv3 or later.
- Got rid of type-punned compiler warnings output by newer gcc versions.
- Rsync is now being maintained in a "git" repository instead of CVS
(though the old CVS repository still exists). Several maintenance
scripts were updated to work with git.
- The Makefile now ensures that proto.h will be rebuilt if config.h changes.
- Generated files are no longer committed into the source repository. The
autoconf and autoheader commands are now automatically run during the
normal use of "configure" and "make". The latest dev versions of all
generated files can also be copied from the samba.org web site (see the
"magic" configure script that now comes with rsync for its location).
- The "patches" directory of diff files is now built from branches in the
rsync git repository (branch patch/FOO creates file patches/FOO.diff).
- The proto.h file is now built using a simple perl script rather than a
complex awk script, which proved to be more widely compatible.
- When running the tests, we now put our per-test temp dirs into a sub-
directory named testtmp (which is created, if missing). This allows
someone to symlink the testtmp directory to another filesystem (which is
useful if the build dir's filesystem does not support ACLs and xattrs,
but another file system does).
- Rsync now has a way of handling protocol-version changes during the
development of a new protocol version. This causes any out-of-sync
versions to speak an older protocol rather than fail in a cryptic manner.
This addition makes it safe to deploy a pre-release version that may
interact with the public. This new exchange of sub-version info does not
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
does not have enough range to allow the main protocol number to be
incremented for every minor tweak in that happens during development).
- The csprotocol.txt file was updated to mention the daemon protocol change
in the 3.0.0 release.
- The testsuite no longer uses "id -u", so it works better on solaris.

793
OLDNEWS
View File

@@ -1,3 +1,787 @@
NEWS for rsync 3.0.6 (8 May 2009)
Protocol: 30 (unchanged)
Changes since 3.0.5:
BUG FIXES:
- Fixed a --read-batch hang when rsync is reading a batch file that was
created from an incremental-recursion transfer.
- Fixed the daemon's socket code to handle the simultaneous arrival of
multiple connections.
- Fix --safe-links/--copy-unsafe-links to properly handle symlinks that
have consecutive slashes in the value.
- Fixed the parsing of an [IPv6_LITERAL_ADDR] when a USER@ is prefixed.
- The sender now skips a (bogus) symlink that has a 0-length value, which
avoids a transfer error in the receiver.
- Fixed a case where the sender could die with a tag-0 error if there was
an I/O during the sending of the file list.
- Fixed the rrsync script to avoid a server-side problem when -e is at the
start of the short options.
- Fixed a problem where a vanished directory could turn into an exit code
23 instead of the proper exit code 24.
- Fixed the --iconv conversion of symlinks when doing a local copy.
- Fixed a problem where --one-file-system was not stopping deletions on the
receiving side when a mount-point directory did not match a directory in
the transfer.
- Fixed the dropping of an ACL mask when no named ACL values were present.
- Fixed an ACL/xattr corruption issue where the --backup option could cause
rsync to associate the wrong ACL/xattr information with received files.
- Fixed the use of --xattrs with --only-write-batch.
- Fixed the use of --dry-run with --read-batch.
- Fixed configure's erroneous use of target.
- Fixed configure's --disable-debug option.
- Fixed a run-time issue for systems that can't find iconv_open() by adding
the --disable-iconv-open configure option.
- Complain and die if the user tries to combine --remove-source-files (or
the deprecated --remove-sent-files) with --read-batch.
- Fixed an failure transferring special files from Solaris to Linux.
NEWS for rsync 3.0.5 (28 Dec 2008)
Protocol: 30 (unchanged)
Changes since 3.0.4:
BUG FIXES:
- Initialize xattr data in a couple spots in the hlink code, which avoids a
crash when the xattr pointer's memory happens to start out non-zero.
Also fixed the itemizing of an alt-dest file's xattrs when hard-linking.
- Don't send a bogus "-" option to an older server if there were no short
options specified.
- Fixed skipping of unneeded updates in a batch file when incremental
recursion is active. Added a test for this. Made batch-mode handle
"redo" files properly (and without hanging).
- Fix the %P logfile escape when the daemon logs from inside a chroot.
- Fixed the use of -s (--protect-args) when used with a remote source or
destination that had an empty path (e.g. "host:"). Also fixed a problem
when -s was used when accessing a daemon via a remote-shell.
- Fixed the use of a dot-dir path (e.g. foo/./bar) inside a --files-from
file when the root of the transfer isn't the current directory.
- Fixed a bug with "-K --delete" removing symlinks to directories when
incremental recursion is active.
- Fixed a hard to trigger hang when using --remove-source-files.
- Got rid of an annoying delay when accessing a daemon via a remote-shell.
- Properly ignore (superfluous) source args on a --read-batch command.
- Improved the manpage's description of the '*' wildcard to remove the
confusing "non-empty" qualifier.
- Fixed reverse lookups in the compatibility-library version of
getnameinfo().
- Fixed a bug when using --sparse on a sparse file that has over 2GB of
consecutive sparse data.
- Avoid a hang when using at least 3 --verbose options on a transfer with a
client sender (which includes local copying).
- Fixed a problem with --delete-delay reporting an error when it was ready
to remove a directory that was now gone.
- Got rid of a bunch of "warn_unused_result" compiler warnings.
- If an ftruncate() on a received file fails, it now causes a partial-
transfer warning.
- Allow a path with a leading "//" to be preserved (CYGWIN only).
ENHANCEMENTS:
- Made the support/atomic-rsync script able to perform a fully atomic
update of the copied hierarchy when the destination is setup using a
particular symlink idiom.
NEWS for rsync 3.0.4 (6 Sep 2008)
Protocol: 30 (unchanged)
Changes since 3.0.3:
BUG FIXES:
- Fixed a bug in the hard-linking code where it would sometimes try to
allocate 0 bytes of memory (which fails on some OSes, such as AIX).
- Fixed the hard-linking of files from a device that has a device number
of 0 (which seems to be a common device number on NetBSD).
- Fixed the handling of a --partial-dir that cannot be created. This
particularly impacts the --delay-updates option (since the files cannot
be delayed without a partial-dir), and was potentially destructive if
the --remove-source-files was also specified.
- Fixed a couple issues in the --fake-super handling of xattrs when the
destination files have root-level attributes (e.g. selinux values) that
a non-root copy can't affect.
- Improved the keep-alive check in the generator to fire consistently in
incremental-recursion mode when --timeout is enabled.
- The --iconv option now converts the content of a symlink too, instead
of leaving it in the wrong character-set (requires 3.0.4 on both sides
of the transfer).
- When using --iconv, if a filename fails to convert on the receiving side,
this no longer makes deletions in the root-dir of the transfer fail
silently (the user now gets a warning about deletions being disabled
due to IO error as long as --ignore-errors was not specified).
- When using --iconv, if a server-side receiver can't convert a filename,
the error message sent back to the client no longer mangles the name
with the wrong charset conversion.
- Fixed a potential alignment issue in the IRIX ACL code when allocating
the initial "struct acl" object. Also, cast mallocs to avoid warnings.
- Changed some errors that were going to stdout to go to stderr.
- Made human_num() and human_dnum() able to output a negative number
(rather than outputting a cryptic string of punctuation).
ENHANCEMENTS:
- Rsync will avoid sending an -e option to the server if an older protocol
is requested (and thus the option would not be useful). This lets the
user specify the --protocol=29 option to access an overly-restrictive
server that is rejecting the protocol-30 use of -e to the server.
- Improved the message output for an RERR_PARTIAL exit.
DEVELOPER RELATED:
- The Makefile will not halt for just a timestamp change on the Makefile
or the configure files, only for actual changes in content.
- Changed some commands in the testsuite's xattrs.test that called "rsync"
instead of "$RSYNC".
- Enhanced the release scripts to be able to handle a branch release and
to do even more consistency checks on the files.
NEWS for rsync 3.0.3 (29 Jun 2008)
Protocol: 30 (unchanged)
Changes since 3.0.2:
BUG FIXES:
- Fixed a wildcard matching problem in the daemon when a module has
"use chroot" enabled.
- Fixed a crash bug in the hard-link code.
- Fixed the sending of xattr directory information when the code finds a
--link-dest or --copy-dest directory with unchanged xattrs -- the
destination directory now gets these unchanged xattrs properly applied.
- Fixed an xattr-sending glitch that could cause an "Internal abbrev"
error.
- Fixed the combination of --xattrs and --backup.
- The generator no longer allows a '.' dir to be excluded by a daemon-
exclude rule.
- Fixed deletion handling when copying a single, empty directory (with no
files) to a differently named, non-existent directory.
- Fixed the conversion of spaces into dashes in the %M log escape.
- Fixed several places in the code that were not returning the right
errno when a function failed.
- Fixed the backing up of a device or special file into a backup dir.
- Moved the setting of the socket options prior to the connect().
- If rsync exits in the middle of a --progress output, it now outputs a
newline to help prevent the progress line from being overwritten.
- Fixed a problem with how a destination path with a trailing slash or
a trailing dot-dir was compared against the daemon excludes.
- Fixed the sending of large (size > 16GB) files when talking to an older
rsync (protocols < 30): we now use a compatible block size limit.
- If a file's length is so huge that we overflow a checksum buffer count
(i.e. several hundred TB), warn the user and avoid sending an invalid
checksum struct over the wire.
- If a source arg is excluded, --relative no longer adds the excluded
arg's implied dirs to the transfer. This fix also made the exclude
check happen in the better place in the sending code.
- Use the overflow_exit() function for overflows, not out_of_memory().
- Improved the code to better handle a system that has only 32-bit file
offsets.
ENHANCEMENTS:
- The rsyncd.conf manpage now consistently refers to the parameters in
the daemon config file as "parameters".
- The description of the --inplace option was improved.
EXTRAS:
- Added a new script in the support directory, deny-rsync, which allows
an admin to (temporarily) replace the rsync command with a script that
sends an error message to the remote client via the rsync protocol.
DEVELOPER RELATED:
- Fixed a testcase failure if the tests are run as root and made some
compatibility improvements.
- Improved the daemon tests, including checking module comments, the
listing of files, and the ensuring that daemon excludes can't affect
a dot-dir arg.
- Improved some build rules for those that build in a separate directory
from the source, including better install rules for the man pages, and
the fixing of a proto.h-tstamp rule that could make the binaries get
rebuild without cause.
- Improved the testsuite to work around a problem with some utilities
(e.g. cp -p & touch -r) rounding sub-second timestamps.
- Ensure that the early patches don't cause any generated-file hunks to
bleed-over into patches that follow.
NEWS for rsync 3.0.2 (8 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.1:
BUG FIXES:
- Fixed a potential buffer overflow in the xattr code.
ENHANCEMENTS:
- None.
DEVELOPER RELATED:
- The RPM spec file was improved to install more useful files.
- A few developer-oriented scripts were moved from the support dir
to the packaging dir.
NEWS for rsync 3.0.1 (3 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.0:
NOTABLE CHANGES IN BEHAVIOR:
- Added the 'c'-flag to the itemizing of non-regular files so that the
itemized output doesn't get hidden if there were no attribute changes,
and also so that the itemizing of a --copy-links run will distinguish
between copying an identical non-regular file and the creation of a
revised version with a new value (e.g. a changed symlink referent, a
new device number, etc.).
BUG FIXES:
- Fixed a crash bug when a single-use rsync daemon (via remote shell) was
run without specifying a --config=FILE option.
- Fixed a crash when backing up a directory that has a default ACL.
- Fixed a bug in the handling of xattr values that could cause rsync to
not think that a file's extended attributes are up-to-date.
- Fixed the working of --fake-super with --link-dest and --xattrs.
- Fixed a hang when combining --dry-run with --remove-source-files.
- Fixed a bug with --iconv's handling of files that cannot be converted:
a failed name can no longer cause a transfer failure.
- Fixed the building of the rounding.h file on systems that need custom
CPPFLAGS to be used. Also improved the error reporting if the building
of rounding.h fails.
- Fixed the use of the --protect-args (-s) option when talking to a daemon.
- Fixed the --ignore-existing option's protection of files on the receiver
that are non-regular files on the sender (e.g. if a symlink or a dir on
the sender is trying to replace a file on the receiver). The reverse
protection (protecting a dir/symlink/device from being replaced by a
file) was already working.
- Fixed an assert failure if --hard-links is combined with an option that
can skip a file in a set of hard-linked files (i.e. --ignore-existing,
--append, etc.), without skipping all the files in the set.
- Avoid setting the modify time on a directory that already has the right
modify time set. This avoids tweaking the dir's ctime.
- Improved the daemon-exclude handling to do a better job of applying the
exclude rules to path entries. It also sends the user an error just as
if the files were actually missing (instead of silently ignoring the
user's args), and avoids sending the user the filter-action messages
for these non-user-initiated rules.
- Fixed some glitches with the dry-run code's missing-directory
handling, including a problem when combined with --fuzzy.
- Fixed some glitches with the skipped-directory handling.
- Fixed the 'T'-flag itemizing of symlinks when --time isn't preserved.
- Fixed a glitch in the itemizing of permissions with the -E option.
- The --append option's restricting of transfers to those that add data no
longer prevents the updating of non-content changes to otherwise up-to-
date files (i.e. those with the same content but differing permissions,
ownership, xattrs, etc.).
- Don't allow --fake-super to be specified with -XX (double --xattrs)
because the options conflict. If a daemon has "fake super" enabled,
it automatically downgrades a -XX request to -X.
- Fixed a couple bugs in the parsing of daemon-config excludes that could
make a floating exclude rule get treated as matching an absolute path.
- A daemon doesn't try to auto-refuse the "iconv" option if iconv-support
wasn't compiled in to the daemon (avoiding a warning in the logs).
- Fixed the inclusion of per-dir merge files from implied dirs.
- Fixed the support/rrsync script to work with the latest options that
rsync sends (including its flag-specifying use of -e to the server).
ENHANCEMENTS:
- Added the --old-dirs (--old-d) option to make it easier for a user to
ask for file-listings with older rsync versions (this is easier than
having to type "-r --exclude='/*/*'" manually).
- When getting an error while asking an older rsync daemon for a file
listing, rsync will try to notice if the error is a rejection of the
--dirs (-d) option and let the user know how to work around the issue.
- Added a few more --no-OPTION overrides.
- Improved the documentation of the --append option.
- Improved the documentation of the filter/exclude/include daemon
parameters.
INTERNAL:
- Fixed a couple minor bugs in the included popt library (ones which I
sent to the official popt project for inclusion in the 1.14 release).
- Fixed a stat() call that should have been do_stat() so that the proper
normal/64-bit stat() function gets called. (Was in an area that should
not have caused problems, though.)
- Changed the file-glob code to do a directory scan without using the
"glob" and "glob.h". This lets us do the globbing with less memory
churn, and also avoid adding daemon-excluded items to the returned
args.
DEVELOPER RELATED:
- The configure script tries to get the user's compiler to not warn about
unused function parameters if the build is not including one or more of
the ACL/xattrs/iconv features.
- The configure script now has better checks for figuring out if the
included popt code should be used or not.
- Fixed two testsuite glitches: avoid a failure if someone's "cd" command
outputs the current directory when cd-ing to a relative path, and made
the itemized test query how rsync was built to determine if it should
expect hard-linked symlinks or not.
- Updated the testsuite to verify that various bug fixes remain fixed.
- The RPM spec file was updated to have: (1) comments for how to use the
rsync-patch tar file, and (2) an /etc/xinetd.d/rsync file.
- Updated the build scripts to work with a revised FTP directory
structure.
NEWS for rsync 3.0.0 (1 Mar 2008)
Protocol: 30 (changed)
Changes since 2.6.9:
NOTABLE CHANGES IN BEHAVIOR:
- The handling of implied directories when using --relative has changed to
send them as directories (e.g. no implied dir is ever sent as a symlink).
This avoids unexpected behavior and should not adversely affect most
people. If you're one of those rare individuals who relied upon having
an implied dir be duplicated as a symlink, you should specify the
transfer of the symlink and the transfer of the referent directory as
separate args. (See also --keep-dirlinks and --no-implied-dirs.)
Also, exclude rules no longer have a partial effect on implied dirs.
- Requesting a remote file-listing without specifying -r (--recursive) now
sends the -d (--dirs) option to the remote rsync rather than sending -r
along with an extra exclude of /*/*. If the remote rsync does not
understand the -d option (i.e. it is 2.6.3 or older), you will need to
either turn off -d (--no-d), or specify -r --exclude='/*/*' manually.
- In --dry-run mode, the last line of the verbose summary text is output
with a "(DRY RUN)" suffix to help remind you that no updates were made.
Similarly, --only-write-batch outputs "(BATCH ONLY)".
- A writable rsync daemon with "use chroot" disabled now defaults to a
symlink-munging behavior designed to make symlinks safer while also
allowing absolute symlinks to be stored and retrieved. This also has
the effect of making symlinks unusable while they're in the daemon's
hierarchy. See the daemon's "munge symlinks" parameter for details.
- Starting up an extra copy of an rsync daemon will not clobber the pidfile
for the running daemon -- if the pidfile exists, the new daemon will exit
with an error. This means that your wrapper script that starts the rsync
daemon should be made to handle lock-breaking (if you want any automatic
breaking of locks to be done).
BUG FIXES:
- A daemon with "use chroot = no" and excluded items listed in the daemon
config file now properly checks an absolute-path arg specified for these
options: --compare-dest, --link-dest, --copy-dest, --partial-dir,
--backup-dir, --temp-dir, and --files-from.
- A daemon can now be told to disable all user- and group-name translation
on a per-module basis. This avoids a potential problem with a writable
daemon module that has "use chroot" enabled -- if precautions weren't
taken, a user could try to add a missing library and get rsync to use
it. This makes rsync safer by default, and more configurable when id-
translation is not desired. See the daemon's "numeric ids" parameter
for full details.
- A chroot daemon can now indicate which part of its path should affect the
chroot call, and which part should become an inside-chroot path for the
module. This allows you to have outside-the-transfer paths (such as for
libraries) even when you enable chroot protection. The idiom used in the
rsyncd.conf file is: path = /chroot/dirs/./dirs/inside
- If a file's data arrived successfully on the receiving side but the
rename of the temporary file to the destination file failed AND the
--remove-source-files (or the deprecated --remove-sent-files) option
was specified, rsync no longer erroneously removes the associated
source file.
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
- Made the output of all file types consistent when using a --*-dest
option. Prior versions would output too many creation events for
matching items.
- The code that waits for a child pid now handles being interrupted by a
signal. This fixes a problem with the pre-xfer exec function not being
able to get the exit status from the script.
- A negated filter rule (i.e. with a '!' modifier) no longer loses the
negation when sending the filter rules to the remote rsync.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
no longer outputs superfluous directory info for a non-daemon rsync.
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
files (which includes local copies). Version 2.6.9 would complete the
copy, but exit with an error when the receiver output its memory stats.
- If --password-file is used on a non-daemon transfer, rsync now complains
and exits. This should help users figure out that they can't use this
option to control a remote shell's password prompt.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- The --append option no longer updates a file that has the same size.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- The daemon pidfile is checked and created sooner in the startup sequence.
- If a daemon module's "path" value is not an absolute pathname, the code
now makes it absolute internally (making it work properly).
- Ensure that a temporary file always has owner-write permission while we
are writing to it. This avoids problems with some network filesystems
when transfering read-only files.
- Any errors output about password-file reading no longer cause an error at
the end of the run about a partial transfer.
- The --read-batch option for protocol 30 now ensures that several more
options are set correctly for the current batch file: --iconv, --acls,
--xattrs, --inplace, --append, and --append-verify.
- Using --only-write-batch to a daemon receiver now works properly (older
versions would update some files while writing the batch).
- Avoid outputting a "file has vanished" message when the file is a broken
symlink and --copy-unsafe-links or --copy-dirlinks is used (the code
already handled this for --copy-links).
- Fixed the combination of --only-write-batch and --dry-run.
- Fixed rsync's ability to remove files that are not writable by the file's
owner when rsync is running as the same user.
- When transferring large files, the sender's hashtable of checksums is
kept at a more reasonable state of fullness (no more than 80% full) so
that the scanning of the hashtable will not bog down as the number of
blocks increases.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
to another 3.x version. This starts the transfer going more quickly
(before all the files have been found), and requires much less memory.
See the --recursive option in the manpage for some restrictions.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.
- Rsync now allows multiple remote-source args to be specified rather than
having to rely on a special space-splitting side-effect of the remote-
shell. Additional remote args must specify the same host or an empty one
(e.g. empty: :file1 or ::module/file2). For example, this means that
local use of brace expansion now works: rsync -av host:dir/{f1,f2} .
- Added the --protect-args (-s) option, that tells rsync to send most of
the command-line args at the start of the transfer rather than as args
to the remote-shell command. This protects them from space-splitting,
and only interprets basic wildcard special shell characters (*?[).
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.
- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available, and it even
supports OS X ACLs. If you need to have backward compatibility with old,
ACL-patched versions of rsync, apply the acls.diff file from the patches
dir.
- Added the --xattrs (-X) option to preserve extended attributes. This is
an improved version of the prior patch that was available, and it even
supports OS X xattrs (which includes their resource fork data). If you
need to have backward compatibility with old, xattr-patched versions of
rsync, apply the xattrs.diff file from the patches dir.
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
It even supports the storing of foreign ACL data on your backup server.
There is also an analogous "fake super" parameter for an rsync daemon.
- Added the --iconv option, which allows rsync to convert filenames from
one character-set to another during the transfer. The default is to
make this feature available as long as your system has iconv_open().
If compilation fails, specify --disable-iconv to configure, and then
rebuild. If you want rsync to perform character-set conversions by
default, you can specify --enable-iconv=CONVERT_STRING with the default
value for the --iconv option that you wish to use. For example,
"--enable-iconv=." is a good choice. See the rsync manpage for an
explanation of the --iconv option's settings.
- A new daemon config parameter, "charset", lets you control the character-
set that is used during an --iconv transfer to/from a daemon module. You
can also set your daemon to refuse "no-iconv" if you want to force the
client to use an --iconv transfer (requiring an rsync 3.x client).
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress (-z).
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
The name-matching routine was also optimized to run more quickly.
- The --max-delete option now outputs a warning if it skipped any file
deletions, including a count of how many deletions were skipped. (Older
versions just silently stopped deleting things.)
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
about extraneous files without deleting anything. If you're not sure
what version the client is, you can use the less-obvious --max-delete=-1,
as both old and new versions will treat that as the same request (though
older versions don't warn).
- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).
- The filter rules now support a perishable ("p") modifier that marks rules
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- Rsync checks all the alternate-destination args for validity (e.g.
--link-dest). This lets the user know when they specified a directory
that does not exist.
- If we get an ENOSYS error setting the time on a symlink, we don't
complain about it anymore (for those systems that even support the
setting of the modify-time on a symlink).
- Protocol 30 now uses MD5 checksums instead of MD4.
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --append-verify option, which works like the older --append
option (verifying the existing data in the destination file). For
compatibility with older rsync versions, any use of --append that is
talking protocol 29 or older will revert to the --append-verify method.
- Added the --contimeout=SECONDS option that lets the user specify a
connection timeout for rsync daemon access.
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
that can be used to enhance the client side of a daemon connection.
- Improved the dashes and double-quotes in the nroff manpage output.
- Rsync now supports a lot more --no-OPTION override options.
INTERNAL:
- The file-list sorting algorithm now uses a sort that keeps any same-
named items in the same order as they were specified. This allows
rsync to always ensure that the first of the duplicates is the one
that will be included in the copy. The new sort is also faster
than the glibc version of qsort() and mergesort().
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Made the file-deletion code use a little less stack when recursing
through a directory hierarchy of extraneous files.
- Fixed a build problem with older (2.x) versions of gcc.
- Added some isType() functions that make dealing with signed characters
easier without forcing variables via casts.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Added missing prototypes for compatibility functions from the lib dir.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Made the sending of some numbers more efficient for protocol 30.
- Make sure that a daemon process doesn't mind if the client was weird and
omitted the --server option.
- There are more internal logging categories available in protocol 30 than
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
categories allow some errors and warnings to go to stderr without causing
an erroneous end-of-run warning about some files not being able to be
transferred.
- Improved the use of "const" on pointers.
- Improved J.W.'s pool_alloc routines to add a way of incrementally freeing
older sections of a pool's memory.
- The getaddrinfo.c compatibility code in the "lib" dir was replaced with
some new code (derived from samba, derived from PostgreSQL) that has a
better license than the old code.
DEVELOPER RELATED:
- Rsync is now licensed under the GPLv3 or later.
- Rsync is now being maintained in a "git" repository instead of CVS
(though the old CVS repository still exists for historical access).
Several maintenance scripts were updated to work with git.
- Generated files are no longer committed into the source repository. The
autoconf and autoheader commands are now automatically run during the
normal use of "configure" and "make". The latest dev versions of all
generated files can also be copied from the samba.org web site (see the
prepare-source script's fetch option).
- The "patches" directory of diff files is now built from branches in the
rsync git repository (branch patch/FOO creates file patches/FOO.diff).
This directory is now distributed in a separate separate tar file named
rsync-patches-VERSION.tar.gz instead of the main rsync-VERSION.tar.gz.
- The proto.h file is now built using a simple perl script rather than a
complex awk script, which proved to be more widely compatible.
- When running the tests, we now put our per-test temp dirs into a sub-
directory named testtmp (which is created, if missing). This allows
someone to symlink the testtmp directory to another filesystem (which is
useful if the build dir's filesystem does not support ACLs and xattrs,
but another filesystem does).
- Rsync now has a way of handling protocol-version changes during the
development of a new protocol version. This causes any out-of-sync
versions to speak an older protocol rather than fail in a cryptic manner.
This addition makes it safer to deploy a pre-release version that may
interact with the public. This new exchange of sub-version info does not
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
does not have enough range to allow the main protocol number to be
incremented for every minor tweak in that happens during development).
- The csprotocol.txt file was updated to mention the daemon protocol change
in the 3.0.0 release.
NEWS for rsync 2.6.9 (6 Nov 2006)
Protocol: 29 (unchanged)
Changes since 2.6.8:
@@ -2244,7 +3028,14 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? ??? 2008 3.0.0 11 Nov 2006 30
31 Dec 2009 3.0.7 30
08 May 2009 3.0.6 30
28 Dec 2008 3.0.5 30
06 Sep 2008 3.0.4 30
29 Jun 2008 3.0.3 30
08 Apr 2008 3.0.2 30
03 Apr 2008 3.0.1 30
01 Mar 2008 3.0.0 11 Nov 2006 30
06 Nov 2006 2.6.9 29
22 Apr 2006 2.6.8 29
11 Mar 2006 2.6.7 29

123
README
View File

@@ -1,122 +1,135 @@
WHAT IS RSYNC?
--------------
rsync is a replacement for scp/rcp that has many more features.
Rsync is a fast and extraordinarily versatile file copying tool for
both remote and local files.
rsync uses the "rsync algorithm" which provides a very fast method for
bringing remote files into sync. It does this by sending just the
Rsync uses a delta-transfer algorithm which provides a very fast method
for bringing remote files into sync. It does this by sending just the
differences in the files across the link, without requiring that both
sets of files are present at one of the ends of the link beforehand.
At first glance this may seem impossible because the calculation of
diffs between two files normally requires local access to both
files.
sets of files are present at one of the ends of the link beforehand. At
first glance this may seem impossible because the calculation of diffs
between two files normally requires local access to both files.
A technical report describing the rsync algorithm is included with
this package.
A technical report describing the rsync algorithm is included with this
package.
USAGE
-----
Basically you use rsync just like rcp, but rsync has many additional
options. To get a complete list of supported options type
Basically you use rsync just like scp, but rsync has many additional
options. To get a complete list of supported options type:
rsync --help
rsync --help
and see the manual for more information.
See the manpage for more detailed information.
SETUP
-----
Rsync normally uses ssh or rsh for communication. It does not need to
be setuid and requires no special privileges for installation. You
must, however, have a working ssh or rsh system. Using ssh is
recommended for its security features.
Rsync normally uses ssh or rsh for communication with remote systems.
It does not need to be setuid and requires no special privileges for
installation. You must, however, have a working ssh or rsh system.
Using ssh is recommended for its security features.
Alternatively, rsync can run in `daemon' mode, listening on a socket.
This is generally used for public file distribution, although
authentication and access control are available.
To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type
"make".
To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type "make".
Note that on some systems you will have to force configure not to use
gcc because gcc may not support some features (such as 64 bit file
offsets) that your system may support. Set the environment variable CC
offsets) that your system may support. Set the environment variable CC
to the name of your native compiler before running configure in this
case.
case.
Once built put a copy of rsync in your search path on the local and
remote systems (or use "make install"). That's it!
remote systems (or use "make install"). That's it!
RSYNC DAEMONS
-------------
rsync can also talk to "rsync daemons" which can provide anonymous or
authenticated rsync. See the rsyncd.conf(5) man page for details on how
to setup an rsync daemon. See the rsync(1) man page for info on how to
Rsync can also talk to "rsync daemons" which can provide anonymous or
authenticated rsync. See the rsyncd.conf(5) man page for details on how
to setup an rsync daemon. See the rsync(1) man page for info on how to
connect to an rsync daemon.
MAILING LIST
------------
WEB SITE
--------
There is a mailing list for the discussion of rsync and its
applications. It is open to anyone to join. I will announce new
versions on this list.
The main rsync web site is here:
To join the mailing list see the web page at http://lists.samba.org/
http://rsync.samba.org/
To send mail to everyone on the list send it to rsync@lists.samba.org
You'll find a FAQ list, downloads, resources, HTML versions of the
manpages, etc.
MAILING LISTS
-------------
There is a mailing list for the discussion of rsync and its applications
that is open to anyone to join. New releases are announced on this
list, and there is also an announcement-only mailing list for those that
want official announcements. See the mailing-list page for full
details:
http://rsync.samba.org/lists.html
BUG REPORTS
-----------
If you have web access then please look at
To visit this web page for full the details on bug reporting:
http://rsync.samba.org/
http://rsync.samba.org/bugzilla.html
That page contains links to the current bug list, and information on
how to report a bug well. You might also like to try searching the
internet for the error message you've received, or looking in the
mailing list archives at
That page contains links to the current bug list, and information on how
to report a bug well. You might also like to try searching the Internet
for the error message you've received, or looking in the mailing list
archives at:
http://mail-archive.com/rsync@lists.samba.org/
http://mail-archive.com/rsync@lists.samba.org/
To send a bug report, follow the instructions on the bug-tracking
page of the web site.
If you don't have web access, email your bug report to
rsync@lists.samba.org.
Alternately, email your bug report to rsync@lists.samba.org .
CVS TREE
--------
GIT REPOSITORY
--------------
If you want to get the very latest version of rsync direct from the
source code repository then you can use anonymous cvs. You will need a
recent version of cvs then use the following commands:
source code repository then you can use git:
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login
Password: cvs
git clone git://git.samba.org/rsync.git
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co rsync
See the download page for full details on all the ways to grab the
source, including nightly tar files, web-browsing of the git repository,
etc.:
Look at the cvs documentation for more details.
http://rsync.samba.org/download.html
COPYRIGHT
---------
rsync was originally written by Andrew Tridgell and has been improved
by many developers around the world. rsync may be used, modified and
redistributed only under the terms of the GNU General Public License,
found in the file COPYING in this distribution, or at
Rsync was originally written by Andrew Tridgell and is currently
maintained by Wayne Davison. It has been improved by many developers
from around the world.
http://www.fsf.org/licenses/gpl.html
Rsync may be used, modified and redistributed only under the terms of
the GNU General Public License, found in the file COPYING in this
distribution, or at:
http://www.fsf.org/licenses/gpl.html
AVAILABILITY

View File

@@ -2,7 +2,7 @@
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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

70
acls.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2006 Wayne Davison
* Copyright (C) 2006-2009 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
@@ -88,13 +88,26 @@ static const rsync_acl empty_rsync_acl = {
static item_list access_acl_list = EMPTY_ITEM_LIST;
static item_list default_acl_list = EMPTY_ITEM_LIST;
static size_t prior_access_count = (size_t)-1;
static size_t prior_default_count = (size_t)-1;
/* === Calculations on ACL types === */
static const char *str_acl_type(SMB_ACL_TYPE_T type)
{
return type == SMB_ACL_TYPE_ACCESS ? "SMB_ACL_TYPE_ACCESS"
: type == SMB_ACL_TYPE_DEFAULT ? "SMB_ACL_TYPE_DEFAULT"
: "unknown SMB_ACL_TYPE_T";
switch (type) {
case SMB_ACL_TYPE_ACCESS:
#ifdef HAVE_OSX_ACLS
return "ACL_TYPE_EXTENDED";
#else
return "ACL_TYPE_ACCESS";
#endif
case SMB_ACL_TYPE_DEFAULT:
return "ACL_TYPE_DEFAULT";
default:
break;
}
return "unknown ACL type!";
}
static int calc_sacl_entries(const rsync_acl *racl)
@@ -127,7 +140,8 @@ static void rsync_acl_strip_perms(rsync_acl *racl)
else {
if (racl->group_obj == racl->mask_obj)
racl->group_obj = NO_ENTRY;
racl->mask_obj = NO_ENTRY;
if (racl->names.count != 0)
racl->mask_obj = NO_ENTRY;
}
racl->other_obj = NO_ENTRY;
}
@@ -739,14 +753,7 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
/* If we received a superfluous mask, throw it away. */
duo_item->racl.mask_obj = NO_ENTRY;
#else
if (!duo_item->racl.names.count) {
/* If we received a superfluous mask, throw it away. */
if (duo_item->racl.mask_obj != NO_ENTRY) {
/* Mask off the group perms with it first. */
duo_item->racl.group_obj &= duo_item->racl.mask_obj | NO_ENTRY;
duo_item->racl.mask_obj = NO_ENTRY;
}
} else if (duo_item->racl.mask_obj == NO_ENTRY) /* Must be non-empty with lists. */
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;
#endif
@@ -784,17 +791,50 @@ static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl
/* Turn the ACL data in stat_x into cached ACL data, setting the index
* values in the file struct. */
void cache_acl(struct file_struct *file, stat_x *sxp)
void cache_tmp_acl(struct file_struct *file, stat_x *sxp)
{
if (prior_access_count == (size_t)-1)
prior_access_count = access_acl_list.count;
F_ACL(file) = cache_rsync_acl(sxp->acc_acl,
SMB_ACL_TYPE_ACCESS, &access_acl_list);
if (S_ISDIR(sxp->st.st_mode)) {
if (prior_default_count == (size_t)-1)
prior_default_count = default_acl_list.count;
F_DIR_DEFACL(file) = cache_rsync_acl(sxp->def_acl,
SMB_ACL_TYPE_DEFAULT, &default_acl_list);
}
}
static void uncache_duo_acls(item_list *duo_list, size_t start)
{
acl_duo *duo_item = duo_list->items;
acl_duo *duo_start = duo_item + start;
duo_item += duo_list->count;
duo_list->count = start;
while (duo_item-- > duo_start) {
rsync_acl_free(&duo_item->racl);
if (duo_item->sacl)
sys_acl_free_acl(duo_item->sacl);
}
}
void uncache_tmp_acls(void)
{
if (prior_access_count != (size_t)-1) {
uncache_duo_acls(&access_acl_list, prior_access_count);
prior_access_count = (size_t)-1;
}
if (prior_default_count != (size_t)-1) {
uncache_duo_acls(&default_acl_list, prior_default_count);
prior_default_count = (size_t)-1;
}
}
#ifndef HAVE_OSX_ACLS
static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode, mode_t mode)
{
@@ -933,7 +973,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
#endif
if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
fname, str_acl_type(type));
fname, str_acl_type(type));
return -1;
}
if (type == SMB_ACL_TYPE_ACCESS)

View File

@@ -2,7 +2,7 @@
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2009 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

114
backup.c
View File

@@ -2,7 +2,7 @@
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -148,19 +148,25 @@ int make_bak_dir(const char *fullpath)
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(rel, &sx);
cache_acl(file, &sx);
cache_tmp_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(rel, &sx);
cache_xattr(file, &sx);
cache_tmp_xattr(file, &sx);
free_xattr(&sx);
}
#endif
set_file_attrs(fbuf, file, NULL, NULL, 0);
unmake_file(file);
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
}
}
*p = '/';
@@ -180,10 +186,19 @@ int make_bak_dir(const char *fullpath)
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(const char *src, char *dst)
{
if (robust_rename(src, dst, NULL, 0755) < 0
&& (errno != ENOENT || make_bak_dir(dst) < 0
|| robust_rename(src, dst, NULL, 0755) < 0))
return -1;
if (robust_rename(src, dst, NULL, 0755) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(dst) == 0) {
if (robust_rename(src, dst, NULL, 0755) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
errno = save_errno;
return -1;
}
}
return 0;
}
@@ -195,6 +210,7 @@ static int keep_backup(const char *fname)
stat_x sx;
struct file_struct *file;
char *buf;
int save_preserve_xattrs = preserve_xattrs;
int kept = 0;
int ret_code;
@@ -213,20 +229,26 @@ static int keep_backup(const char *fname)
if (!(buf = get_backup_name(fname))) {
unmake_file(file);
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return 0;
}
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(fname, &sx);
cache_acl(file, &sx);
cache_tmp_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(fname, &sx);
cache_xattr(file, &sx);
cache_tmp_xattr(file, &sx);
free_xattr(&sx);
}
#endif
@@ -234,15 +256,23 @@ static int keep_backup(const char *fname)
/* Check to see if this is a device file, or link */
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
uint32 *devp = F_RDEV_P(file);
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
int save_errno;
do_unlink(buf);
if (do_mknod(buf, file->mode, rdev) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mknod(buf, file->mode, rdev) < 0)) {
rsyserr(FERROR, errno, "mknod %s failed",
full_fname(buf));
} else if (verbose > 2) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0) {
save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "mknod %s failed",
full_fname(buf));
}
} else
save_errno = 0;
if (verbose > 2 && save_errno == 0) {
rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
fname);
}
@@ -252,11 +282,18 @@ static int keep_backup(const char *fname)
if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */
if (do_mkdir(buf, file->mode) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mkdir(buf, file->mode) < 0)) {
rsyserr(FINFO, errno, "mkdir %s failed",
full_fname(buf));
if (do_mkdir(buf, file->mode) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_mkdir(buf, file->mode) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FINFO, save_errno, "mkdir %s failed",
full_fname(buf));
}
}
ret_code = do_rmdir(fname);
@@ -270,7 +307,7 @@ static int keep_backup(const char *fname)
#ifdef SUPPORT_LINKS
if (!kept && preserve_links && S_ISLNK(file->mode)) {
const char *sl = F_SYMLINK(file);
if (safe_symlinks && unsafe_symlink(sl, buf)) {
if (safe_symlinks && unsafe_symlink(sl, fname)) {
if (verbose) {
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
full_fname(buf), sl);
@@ -278,11 +315,18 @@ static int keep_backup(const char *fname)
kept = 1;
} else {
do_unlink(buf);
if (do_symlink(sl, buf) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_symlink(sl, buf) < 0)) {
rsyserr(FERROR, errno, "link %s -> \"%s\"",
full_fname(buf), sl);
if (do_symlink(sl, buf) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_symlink(sl, buf) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
full_fname(buf), sl);
}
}
do_unlink(fname);
kept = 1;
@@ -294,6 +338,12 @@ static int keep_backup(const char *fname)
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
fname);
unmake_file(file);
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return 1;
}
@@ -308,8 +358,16 @@ static int keep_backup(const char *fname)
robust_unlink(fname); /* Just in case... */
}
}
preserve_xattrs = 0;
set_file_attrs(buf, file, NULL, fname, 0);
preserve_xattrs = save_preserve_xattrs;
unmake_file(file);
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",

59
batch.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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
@@ -156,27 +156,37 @@ void check_batch_flags(void)
append_mode = 2;
}
static void write_arg(int fd, char *arg)
static int write_arg(int fd, char *arg)
{
char *x, *s;
int len, ret = 0;
if (*arg == '-' && (x = strchr(arg, '=')) != NULL) {
write(fd, arg, x - arg + 1);
if (write(fd, arg, x - arg + 1) != x - arg + 1)
ret = -1;
arg += x - arg + 1;
}
if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) {
write(fd, "'", 1);
if (write(fd, "'", 1) != 1)
ret = -1;
for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) {
write(fd, s, x - s + 1);
write(fd, "'", 1);
if (write(fd, s, x - s + 1) != x - s + 1
|| write(fd, "'", 1) != 1)
ret = -1;
}
write(fd, s, strlen(s));
write(fd, "'", 1);
return;
len = strlen(s);
if (write(fd, s, len) != len
|| write(fd, "'", 1) != 1)
ret = -1;
return ret;
}
write(fd, arg, strlen(arg));
len = strlen(arg);
if (write(fd, arg, len) != len)
ret = -1;
return ret;
}
static void write_filter_rules(int fd)
@@ -205,7 +215,7 @@ static void write_filter_rules(int fd)
* (hopefully) work. */
void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
{
int fd, i, len;
int fd, i, len, err = 0;
char *p, filename[MAXPATHLEN];
stringjoin(filename, sizeof filename,
@@ -219,7 +229,8 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
}
/* Write argvs info to BATCH.sh file */
write_arg(fd, argv[0]);
if (write_arg(fd, argv[0]) < 0)
err = 1;
if (filter_list.head) {
if (protocol_version >= 29)
write_sbuf(fd, " --filter=._-");
@@ -240,25 +251,31 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
i++;
continue;
}
write(fd, " ", 1);
if (write(fd, " ", 1) != 1)
err = 1;
if (strncmp(p, "--write-batch", len = 13) == 0
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
write(fd, "--read-batch", 12);
if (write(fd, "--read-batch", 12) != 12)
err = 1;
if (p[len] == '=') {
write(fd, "=", 1);
write_arg(fd, p + len + 1);
if (write(fd, "=", 1) != 1
|| write_arg(fd, p + len + 1) < 0)
err = 1;
}
} else
write_arg(fd, p);
} else {
if (write_arg(fd, p) < 0)
err = 1;
}
}
if (!(p = check_for_hostspec(argv[argc - 1], &p, &i)))
p = argv[argc - 1];
write(fd, " ${1:-", 6);
write_arg(fd, p);
if (write(fd, " ${1:-", 6) != 6
|| write_arg(fd, p) < 0)
err = 1;
write_byte(fd, '}');
if (filter_list.head)
write_filter_rules(fd);
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
if (write(fd, "\n", 1) != 1 || close(fd) < 0 || err) {
rsyserr(FERROR, errno, "Batch file %s write error",
filename);
exit_cleanup(RERR_FILEIO);

View File

@@ -2,7 +2,7 @@
* Simple byteorder handling.
*
* Copyright (C) 1992-1995 Andrew Tridgell
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 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
@@ -19,6 +19,7 @@
*/
#undef CAREFUL_ALIGNMENT
#undef AVOID_BYTEORDER_INLINE
/* We know that the x86 can handle misalignment and has the same
* byte order (LSB-first) as the 32-bit numbers we transmit. */
@@ -32,21 +33,68 @@
#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
#define UVAL(buf,pos) ((uint32)CVAL(buf,pos))
#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
#if CAREFUL_ALIGNMENT
#define PVAL(buf,pos) (UVAL(buf,pos)|UVAL(buf,(pos)+1)<<8)
#define IVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+2)<<16)
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
#else
/* this handles things for architectures like the 386 that can handle
alignment errors */
/*
WARNING: This section is dependent on the length of int32
being correct. set CAREFUL_ALIGNMENT if it is not.
*/
#define IVALu(buf,pos) IVAL(buf,pos)
#define SIVALu(buf,pos,val) SIVAL(buf,pos,val)
#else /* !CAREFUL_ALIGNMENT */
/* This handles things for architectures like the 386 that can handle alignment errors.
* WARNING: This section is dependent on the length of an int32 (and thus a uint32)
* being correct (4 bytes)! Set CAREFUL_ALIGNMENT if it is not. */
# ifdef AVOID_BYTEORDER_INLINE
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
#endif
#define IVALu(buf,pos) IVAL(buf,pos)
#define SIVALu(buf,pos,val) SIVAL(buf,pos,val)
# else /* !AVOID_BYTEORDER_INLINE */
static inline uint32
IVALu(const uchar *buf, int pos)
{
union {
const uchar *b;
const uint32 *num;
} u;
u.b = buf + pos;
return *u.num;
}
static inline void
SIVALu(uchar *buf, int pos, uint32 val)
{
union {
uchar *b;
uint32 *num;
} u;
u.b = buf + pos;
*u.num = val;
}
static inline uint32
IVAL(const char *buf, int pos)
{
return IVALu((uchar*)buf, pos);
}
static inline void
SIVAL(char *buf, int pos, uint32 val)
{
SIVALu((uchar*)buf, pos, val);
}
# endif /* !AVOID_BYTEORDER_INLINE */
#endif /* !CAREFUL_ALIGNMENT */

View File

@@ -1,7 +1,7 @@
/*
* End-of-run cleanup helper code used by cleanup.c.
*
* Copyright (C) 2006-2007 Wayne Davison
* Copyright (C) 2006-2008 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

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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
@@ -58,7 +58,7 @@ void get_checksum2(char *buf, int32 len, char *sum)
md5_begin(&m);
md5_update(&m, (uchar *)buf, len);
if (checksum_seed) {
SIVAL(seedbuf, 0, checksum_seed);
SIVALu(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
}
md5_result(&m, (uchar *)sum);

View File

@@ -2,7 +2,7 @@
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* Copyright (C) 2005-2007 Wayne Davison
* Copyright (C) 2005-2009 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

View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -24,6 +24,7 @@
extern int am_server;
extern int am_daemon;
extern int am_receiver;
extern int io_error;
extern int keep_partial;
extern int got_xfer_error;
@@ -94,17 +95,21 @@ pid_t cleanup_child_pid = -1;
NORETURN void _exit_cleanup(int code, const char *file, int line)
{
static int cleanup_step = 0;
static int exit_code = 0;
static int exit_code = 0, exit_line = 0;
static const char *exit_file = NULL;
static int unmodified_code = 0;
SIGACTION(SIGUSR1, SIG_IGN);
SIGACTION(SIGUSR2, SIG_IGN);
if (exit_code) /* Preserve first error code when recursing. */
if (exit_code) { /* Preserve first exit info when recursing. */
code = exit_code;
file = exit_file;
line = exit_line;
}
/* If this is the exit at the end of the run, the server side
* should not attempt to output a message (see log.c). */
* should not attempt to output a message (see log_exit()). */
if (am_server && code == 0)
am_server = 2;
@@ -114,11 +119,13 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
#include "case_N.h" /* case 0: cleanup_step++; */
exit_code = unmodified_code = code;
exit_file = file;
exit_line = line;
if (verbose > 3) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, file, line);
"[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n",
who_am_i(), code, file, line);
}
/* FALLTHROUGH */
@@ -154,7 +161,8 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
/* FALLTHROUGH */
#include "case_N.h"
io_flush(FULL_FLUSH);
if (!code || am_server || am_receiver)
io_flush(FULL_FLUSH);
/* FALLTHROUGH */
#include "case_N.h"
@@ -186,9 +194,9 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
if (verbose > 2) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): "
"[%s] _exit_cleanup(code=%d, file=%s, line=%d): "
"about to call exit(%d)\n",
unmodified_code, file, line, code);
who_am_i(), unmodified_code, file, line, code);
}
/* FALLTHROUGH */

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2009 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
@@ -108,6 +108,9 @@ char *client_name(int fd)
struct addrinfo hint, *answer;
int err;
if (strcmp(addr, "0.0.0.0") == 0)
return name_buf;
memset(&hint, 0, sizeof hint);
#ifdef AI_NUMERICHOST
@@ -266,7 +269,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
fn, ai->ai_addrlen);
fn, (int)ai->ai_addrlen);
return 1;
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2009 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
@@ -22,6 +22,7 @@
#include "rsync.h"
#include "ifuncs.h"
extern int quiet;
extern int verbose;
extern int dry_run;
extern int output_motd;
@@ -31,7 +32,9 @@ extern int am_server;
extern int am_daemon;
extern int am_root;
extern int rsync_port;
extern int protect_args;
extern int ignore_errors;
extern int preserve_xattrs;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int sanitize_paths;
@@ -47,14 +50,12 @@ extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern mode_t orig_umask;
extern char *bind_address;
extern char *sockopts;
extern char *config_file;
extern char *logfile_format;
extern char *files_from;
extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
extern char curr_dir[];
extern struct filter_list_struct daemon_filter_list;
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
@@ -72,6 +73,8 @@ struct chmod_mode_struct *daemon_chmod_modes;
char *module_dir = NULL;
unsigned int module_dirlen = 0;
char *full_module_path;
static int rl_nulls = 0;
#ifdef HAVE_SIGACTION
@@ -118,7 +121,9 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
if (fd == -1)
exit_cleanup(RERR_SOCKETIO);
set_socket_options(fd, sockopts);
#ifdef ICONV_CONST
setup_iconv();
#endif
ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
@@ -207,7 +212,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
int sargc = 0;
char *p, *modname;
assert(argc > 0);
assert(argc > 0 && *argv != NULL);
if (**argv == '/') {
rprintf(FERROR,
@@ -309,6 +314,8 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
if (rl_nulls) {
for (i = 0; i < sargc; i++) {
if (!sargs[i]) /* stop at --protect-args NULL */
break;
write_sbuf(f_out, sargs[i]);
write_byte(f_out, 0);
}
@@ -319,6 +326,9 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
write_sbuf(f_out, "\n");
}
if (protect_args)
send_protected_args(f_out, sargs);
if (protocol_version < 23) {
if (protocol_version == 22 || !am_sender)
io_start_multiplex_in();
@@ -330,16 +340,24 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
}
static char *finish_pre_exec(pid_t pid, int fd, char *request,
int argc, char *argv[])
char **early_argv, char **argv)
{
int j, status = -1;
int j = 0, status = -1;
if (!request)
request = "(NONE)";
write_buf(fd, request, strlen(request)+1);
for (j = 0; j < argc; j++)
if (early_argv) {
for ( ; *early_argv; early_argv++)
write_buf(fd, *early_argv, strlen(*early_argv)+1);
j = 1; /* Skip arg0 name in argv. */
}
for ( ; argv[j]; j++) {
write_buf(fd, argv[j], strlen(argv[j])+1);
if (argv[j][0] == '.' && argv[j][1] == '\0')
break;
}
write_byte(fd, 0);
close(fd);
@@ -377,10 +395,20 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
return bp - buf;
}
static int path_failure(int f_out, const char *dir, BOOL was_chdir)
{
if (was_chdir)
rsyserr(FLOG, errno, "chdir %s failed\n", dir);
else
rprintf(FLOG, "normalize_path(%s) failed\n", dir);
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
{
int argc, opt_cnt;
char **argv, *chroot_path = NULL;
int argc;
char **argv, **orig_argv, **orig_early_argv, *module_chdir;
char line[BIGPATHBUFLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
@@ -483,28 +511,28 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
module_dir = lp_path(i);
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0';
p += 2;
} else if ((p = strdup("/")) == NULL)
out_of_memory("rsync_module");
*p = '\0'; /* Temporary... */
if (!(module_chdir = normalize_path(module_dir, True, NULL)))
return path_failure(f_out, module_dir, False);
*p = '/';
if (!(p = normalize_path(p + 2, True, &module_dirlen)))
return path_failure(f_out, strstr(module_dir, "/./"), False);
if (!(full_module_path = normalize_path(module_dir, False, NULL)))
full_module_path = module_dir;
module_dir = p;
} else {
if (!(module_chdir = normalize_path(module_dir, False, NULL)))
return path_failure(f_out, module_dir, False);
full_module_path = module_chdir;
module_dir = "/";
module_dirlen = 1;
}
} else {
if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
return path_failure(f_out, module_dir, False);
full_module_path = module_dir = module_chdir;
}
/* We do a push_dir() that doesn't actually call chdir()
* just to make a relative path absolute. */
strlcpy(line, curr_dir, sizeof line);
if (!push_dir(module_dir, 1))
goto chdir_failed;
if (strcmp(curr_dir, module_dir) != 0
&& (module_dir = strdup(curr_dir)) == NULL)
out_of_memory("rsync_module");
push_dir(line, 1); /* Restore curr_dir. */
if (use_chroot) {
chroot_path = module_dir;
module_dir = p; /* p is "/" or our inside-chroot path */
}
module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
if (module_dirlen == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
@@ -512,25 +540,25 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
set_filter_dir(module_dir, module_dirlen);
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH);
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
p = lp_include_from(i);
parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
parse_filter_file(&daemon_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
parse_rule(&server_filter_list, p,
parse_rule(&daemon_filter_list, p,
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
parse_filter_file(&server_filter_list, p, 0,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
parse_filter_file(&daemon_filter_list, p, 0,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
log_init(1);
@@ -539,16 +567,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (!use_chroot)
p = module_dir;
else if (module_dirlen) {
pathjoin(line, sizeof line, chroot_path, module_dir+1);
p = line;
} else
p = chroot_path;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", p) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", full_module_path) < 0
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
@@ -582,7 +602,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
status = -1;
if (asprintf(&p, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(p);
system(lp_postxfer_exec(i));
if (system(lp_postxfer_exec(i)) < 0)
status = -1;
_exit(status);
}
}
@@ -648,30 +669,24 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(chroot_path)) {
rsyserr(FLOG, errno, "chroot %s failed", chroot_path);
if (chroot(module_chdir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir(module_dir, 0))
goto chdir_failed;
if (module_dirlen)
sanitize_paths = 1;
} else {
if (!push_dir(module_dir, 0)) {
chdir_failed:
rsyserr(FLOG, errno, "chdir %s failed\n", module_dir);
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
sanitize_paths = 1;
module_chdir = module_dir;
}
if (!change_dir(module_chdir, CD_NORMAL))
return path_failure(f_out, module_chdir, True);
if (module_dirlen || !use_chroot)
sanitize_paths = 1;
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
munge_symlinks = !use_chroot || module_dirlen;
if (munge_symlinks) {
STRUCT_STAT st;
if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
if (do_stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
SYMLINK_PREFIX);
io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
@@ -705,7 +720,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
}
#endif
if (setuid(uid)) {
if (setuid(uid) < 0
#ifdef HAVE_SETEUID
|| seteuid(uid) < 0
#endif
) {
rsyserr(FLOG, errno, "setuid %d failed", (int)uid);
io_printf(f_out, "@ERROR: setuid failed\n");
return -1;
@@ -726,24 +745,40 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
io_printf(f_out, "@RSYNCD: OK\n");
opt_cnt = read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
orig_argv = argv;
verbose = 0; /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv);
if (protect_args && ret) {
orig_early_argv = orig_argv;
protect_args = 2;
read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request);
orig_argv = argv;
ret = parse_arguments(&argc, (const char ***) &argv);
} else
orig_early_argv = NULL;
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
opt_cnt, argv);
orig_early_argv, orig_argv);
}
verbose = 0; /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv, 0);
if (orig_early_argv)
free(orig_early_argv);
am_server = 1; /* Don't let someone try to be tricky. */
quiet = 0;
if (lp_ignore_errors(module_id))
ignore_errors = 1;
if (write_batch < 0)
dry_run = 1;
if (lp_fake_super(i))
if (lp_fake_super(i)) {
if (preserve_xattrs > 1)
preserve_xattrs = 1;
am_root = -1;
else if (am_root < 0) /* Treat --fake-super from client as --super. */
} else if (am_root < 0) /* Treat --fake-super from client as --super. */
am_root = 2;
if (filesfrom_fd == 0)
@@ -823,7 +858,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
if (lp_timeout(i) && (!io_timeout || lp_timeout(i) < io_timeout))
set_io_timeout(lp_timeout(i));
/* If we have some incoming/outgoing chmod changes, append them to
@@ -860,6 +895,17 @@ static void send_listing(int fd)
io_printf(fd,"@RSYNCD: EXIT\n");
}
static int load_config(int globals_only)
{
if (!config_file) {
if (am_server && am_root <= 0)
config_file = RSYNCD_USERCONF;
else
config_file = RSYNCD_SYSCONF;
}
return lp_load(config_file, globals_only);
}
/* this is called when a connection is established to a client
and we want to start talking. The setup of the system is done from
here */
@@ -875,7 +921,7 @@ int start_daemon(int f_in, int f_out)
* might cause log-file output to occur. This ensures that the
* "log file" param gets honored for the 2 non-forked use-cases
* (when rsync is run by init and run by a remote shell). */
if (!lp_load(config_file, 0))
if (!load_config(0))
exit_cleanup(RERR_SYNTAX);
addr = client_addr(f_in);
@@ -884,10 +930,6 @@ int start_daemon(int f_in, int f_out)
if (!am_server) {
set_socket_options(f_in, "SO_KEEPALIVE");
if (sockopts)
set_socket_options(f_in, sockopts);
else
set_socket_options(f_in, lp_socket_options());
set_nonblocking(f_in);
}
@@ -931,20 +973,23 @@ static void create_pid_file(void)
char *pid_file = lp_pid_file();
char pidbuf[16];
pid_t pid = getpid();
int fd;
int fd, len;
if (!pid_file || !*pid_file)
return;
cleanup_set_pid(pid);
if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666 & ~orig_umask)) == -1) {
failure:
cleanup_set_pid(0);
fprintf(stderr, "failed to create pid file %s: %s\n", pid_file, strerror(errno));
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
write(fd, pidbuf, strlen(pidbuf));
len = strlen(pidbuf);
if (write(fd, pidbuf, len) != len)
goto failure;
close(fd);
}
@@ -984,13 +1029,6 @@ static void become_daemon(void)
int daemon_main(void)
{
if (!config_file) {
if (am_server && am_root <= 0)
config_file = RSYNCD_USERCONF;
else
config_file = RSYNCD_SYSCONF;
}
if (is_a_socket(STDIN_FILENO)) {
int i;
@@ -1005,7 +1043,7 @@ int daemon_main(void)
return start_daemon(STDIN_FILENO, STDIN_FILENO);
}
if (!lp_load(config_file, 1)) {
if (!load_config(1)) {
fprintf(stderr, "Failed to parse config file: %s\n", config_file);
exit_cleanup(RERR_SYNTAX);
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) Andrew Tridgell 1996
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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
@@ -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 use_safe_inc_flist = 0;
extern int verbose;
extern int am_server;
@@ -57,12 +58,14 @@ extern struct filter_list_struct filter_list;
extern int need_unsorted_flist;
#ifdef ICONV_OPTION
extern iconv_t ic_send, ic_recv;
extern char *iconv_opt;
#endif
/* These index values are for the file-list's extra-attribute array. */
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
int sender_symlink_iconv = 0; /* sender should convert symlink content */
#ifdef ICONV_OPTION
int filesfrom_convert = 0;
@@ -70,6 +73,8 @@ int filesfrom_convert = 0;
#define CF_INC_RECURSE (1<<0)
#define CF_SYMLINK_TIMES (1<<1)
#define CF_SYMLINK_ICONV (1<<2)
#define CF_SAFE_FLIST (1<<3)
static const char *client_info;
@@ -249,6 +254,11 @@ void setup_protocol(int f_out,int f_in)
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
#ifdef ICONV_OPTION
compat_flags |= CF_SYMLINK_ICONV;
#endif
if (local_server || strchr(client_info, 'f') != NULL)
compat_flags |= CF_SAFE_FLIST;
write_byte(f_out, compat_flags);
} else
compat_flags = read_byte(f_in);
@@ -262,6 +272,11 @@ void setup_protocol(int f_out,int f_in)
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
else
receiver_symlink_times = 1;
#endif
#ifdef ICONV_OPTION
sender_symlink_iconv = iconv_opt && (am_server
? local_server || strchr(client_info, 's') != NULL
: !!(compat_flags & CF_SYMLINK_ICONV));
#endif
if (inc_recurse && !allow_inc_recurse) {
/* This should only be able to happen in a batch. */
@@ -270,7 +285,12 @@ void setup_protocol(int f_out,int f_in)
read_batch ? "batch file" : "connection");
exit_cleanup(RERR_SYNTAX);
}
use_safe_inc_flist = !!(compat_flags & CF_SAFE_FLIST);
need_messages_from_generator = 1;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
} else if (!am_sender) {
receiver_symlink_times = 1;
#endif
}
if (need_unsorted_flist && (!am_sender || inc_recurse))

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=3.0.0pre10
RSYNC_VERSION=3.0.7
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -13,7 +13,26 @@ AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
LDFLAGS=${LDFLAGS-""}
AC_CANONICAL_TARGET([])
AC_CANONICAL_HOST
# We must decide this before testing the compiler.
# Please allow this to default to yes, so that your users have more
# chance of getting a useful stack trace if problems occur.
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--disable-debug],
[disable debugging symbols and features]))
if test x"$enable_debug" = x"no"; then
AC_MSG_RESULT(no)
ac_cv_prog_cc_g=no
else
AC_MSG_RESULT([yes])
dnl AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
# leave ac_cv_prog_cc_g alone; AC_PROG_CC will try to include -g if it can
fi
dnl Checks for programs.
AC_PROG_CC
@@ -30,27 +49,6 @@ 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])
fi
# We must decide this before testing the compiler.
# Please allow this to default to yes, so that your users have more
# chance of getting a useful stack trace if problems occur.
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--disable-debug],
[disable debugging symbols and features]))
if test x"$enable_debug" = x"no"; then
AC_MSG_RESULT(no)
CFLAGS=${CFLAGS-"-O"}
else
AC_MSG_RESULT([yes])
# leave CFLAGS alone; AC_PROG_CC will try to include -g if it can
dnl AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
dnl CFLAGS=${CFLAGS-"-g"}
fi
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],
[turn on CPU profiling]))
@@ -198,7 +196,7 @@ AC_ARG_ENABLE(ipv6,
[don't 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 toshiba v6d zeta; do
for i in inria kame linux-glibc linux-inet6 solaris toshiba v6d zeta cygwin; do
case $i in
inria)
# http://www.kame.net/
@@ -242,6 +240,16 @@ AC_DEFINE(INET6, 1, [true if you have IPv6])])
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
solaris)
# http://www.sun.com
AC_EGREP_CPP(yes, [
#include <netinet/ip6.h>
#ifdef __sun
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
toshiba)
AC_EGREP_CPP(yes, [
#include <sys/param.h>
@@ -275,6 +283,15 @@ yes
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
cygwin)
AC_EGREP_CPP(yes, [
#include <netinet/in.h>
#ifdef _CYGWIN_IN6_H
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
esac
if test "$ipv6type" != "unknown"; then
break
@@ -311,8 +328,10 @@ AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
sys/un.h sys/attr.h glob.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/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)
AC_HEADER_MAJOR
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
@@ -548,10 +567,10 @@ AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask setattrlist)
dnl cygwin iconv.h defines iconv_open as libiconv_open
@@ -564,10 +583,19 @@ if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
fi
AC_ARG_ENABLE(iconv-open,
AC_HELP_STRING([--disable-iconv-open],
[disable all use of iconv_open() function]),
[], [enable_iconv_open=$ac_cv_func_iconv_open])
if test x"$enable_iconv_open" != x"no"; then
AC_DEFINE(USE_ICONV_OPEN, 1, [Define to 1 if you want rsync to make use of iconv_open()])
fi
AC_ARG_ENABLE(iconv,
AC_HELP_STRING([--disable-iconv],
[disable rsync's --iconv option]),
[], [enable_iconv=$ac_cv_func_iconv_open])
[], [enable_iconv=$enable_iconv_open])
AH_TEMPLATE([ICONV_OPTION],
[Define if you want the --iconv option. Specifing a value will set the
default iconv setting (a NULL means no --iconv processing by default).])
@@ -654,6 +682,15 @@ fi
if test x"$with_included_popt" != x"yes"; then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
fi
if test x"$ac_cv_header_popt_popt_h" = x"yes"; then
# If the system has /usr/include/popt/popt.h, we enable the
# included popt because an attempt to "#include <popt/popt.h>"
# would use our included header file anyway (due to -I.), and
# might conflict with the system popt.
with_included_popt=yes
elif test x"$ac_cv_header_popt_h" != x"yes"; then
with_included_popt=yes
fi
AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"; then
@@ -751,7 +788,7 @@ rsync_cv_HAVE_SECURE_MKSTEMP=yes,
rsync_cv_HAVE_SECURE_MKSTEMP=no,
rsync_cv_HAVE_SECURE_MKSTEMP=cross)])
if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
case $target_os in
case $host_os in
hpux*)
dnl HP-UX has a broken mkstemp() implementation they refuse to fix,
dnl so we noisily skip using it. See HP change request JAGaf34426
@@ -825,7 +862,6 @@ AC_SUBST(CC_SHOBJ_FLAG)
AC_SUBST(BUILD_POPT)
AC_SUBST(MAKE_MAN)
AC_CHECK_HEADERS(sys/acl.h acl/libacl.h)
AC_CHECK_FUNCS(_acl __acl _facl __facl)
#################################################
# check for ACL support
@@ -907,10 +943,6 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
esac
fi
AC_CHECK_HEADERS(attr/xattr.h)
AC_CHECK_HEADERS(sys/xattr.h)
AC_CHECK_HEADERS(sys/extattr.h)
#################################################
# check for extended attribute support
AC_MSG_CHECKING(whether to support extended attributes)
@@ -952,6 +984,23 @@ else
esac
fi
if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"$enable_iconv" = x"no"; then
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wno-unused-parameter"
AC_TRY_LINK([#include <stdio.h>], [printf("hello\n");], [rsync_warn_flag=yes], [rsync_warn_flag=no])
AC_MSG_RESULT([$rsync_warn_flag])
if test x"$rsync_warn_flag" = x"no"; then
CFLAGS="$OLD_CFLAGS"
fi
fi
case "$CC" in
' checker'*|checker*)
AC_DEFINE(FORCE_FD_ZERO_MEMSET, 1, [Used to make "checker" understand that FD_ZERO() clears memory.])
;;
esac
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT

View File

@@ -2,7 +2,7 @@
* Error codes returned by rsync.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 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

102
exclude.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -43,7 +43,7 @@ extern unsigned int module_dirlen;
struct filter_list_struct filter_list = { 0, 0, "" };
struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" };
struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
struct filter_list_struct daemon_filter_list = { 0, 0, " [daemon]" };
/* Need room enough for ":MODS " prefix plus some room to grow. */
#define MAX_RULE_PREFIX (16)
@@ -52,6 +52,8 @@ struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
#define MODIFIERS_INCL_EXCL "/!Crsp"
#define MODIFIERS_HIDE_PROTECT "/!p"
#define SLASH_WILD3_SUFFIX "/***"
/* The dirbuf is set by push_local_filters() to the current subdirectory
* relative to curr_dir that is being processed. The path always has a
* trailing slash appended, and the variable dirbuf_len contains the length
@@ -119,7 +121,7 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
{
struct filter_struct *ret;
const char *cp;
unsigned int ex_len;
unsigned int pre_len, suf_len, slash_cnt = 0;
if (verbose > 2) {
rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n",
@@ -145,22 +147,51 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
if (!(ret = new0(struct filter_struct)))
out_of_memory("add_rule");
if (pat_len > 1 && pat[pat_len-1] == '/') {
pat_len--;
mflags |= MATCHFLG_DIRECTORY;
}
for (cp = pat; cp < pat + pat_len; cp++) {
if (*cp == '/')
slash_cnt++;
}
if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
&& ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
|| (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) {
|| (xflags & XFLG_ABS_IF_SLASH && slash_cnt))) {
mflags |= MATCHFLG_ABS_PATH;
if (*pat == '/')
ex_len = dirbuf_len - module_dirlen - 1;
pre_len = dirbuf_len - module_dirlen - 1;
else
ex_len = 0;
pre_len = 0;
} else
ex_len = 0;
if (!(ret->pattern = new_array(char, ex_len + pat_len + 1)))
pre_len = 0;
/* The daemon wants dir-exclude rules to get an appended "/" + "***". */
if (xflags & XFLG_DIR2WILD3
&& BITS_SETnUNSET(mflags, MATCHFLG_DIRECTORY, MATCHFLG_INCLUDE)) {
mflags &= ~MATCHFLG_DIRECTORY;
suf_len = sizeof SLASH_WILD3_SUFFIX - 1;
} else
suf_len = 0;
if (!(ret->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
out_of_memory("add_rule");
if (ex_len)
memcpy(ret->pattern, dirbuf + module_dirlen, ex_len);
strlcpy(ret->pattern + ex_len, pat, pat_len + 1);
pat_len += ex_len;
if (pre_len) {
memcpy(ret->pattern, dirbuf + module_dirlen, pre_len);
for (cp = ret->pattern; cp < ret->pattern + pre_len; cp++) {
if (*cp == '/')
slash_cnt++;
}
}
strlcpy(ret->pattern + pre_len, pat, pat_len + 1);
pat_len += pre_len;
if (suf_len) {
memcpy(ret->pattern + pat_len, SLASH_WILD3_SUFFIX, suf_len+1);
pat_len += suf_len;
slash_cnt++;
}
if (strpbrk(ret->pattern, "*[?")) {
mflags |= MATCHFLG_WILD;
@@ -178,11 +209,6 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
}
}
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
ret->pattern[pat_len-1] = 0;
mflags |= MATCHFLG_DIRECTORY;
}
if (mflags & MATCHFLG_PERDIR_MERGE) {
struct filter_list_struct *lp;
unsigned int len;
@@ -226,10 +252,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
out_of_memory("add_rule");
}
mergelist_parents[mergelist_cnt++] = ret;
} else {
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
ret->u.slash_cnt++;
}
} else
ret->u.slash_cnt = slash_cnt;
ret->match_flags = mflags;
@@ -295,7 +319,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
strlcpy(to, merge_file, *len_ptr + 1);
merge_file = to;
}
if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, SP_DEFAULT)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
return NULL;
@@ -308,12 +332,13 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
/* If the name isn't in buf yet, it's wasn't absolute. */
if (fn != buf) {
if (dirbuf_len + fn_len >= MAXPATHLEN) {
int d_len = dirbuf_len - prefix_skip;
if (d_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
return NULL;
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
memcpy(buf, dirbuf + prefix_skip, d_len);
memcpy(buf + d_len, fn, fn_len + 1);
fn_len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
}
@@ -451,7 +476,7 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
XFLG_ANCHORED2ABS);
} else {
io_error |= IOERR_GENERAL;
rprintf(FINFO,
rprintf(FERROR,
"cannot add local filter rules in long-named directory: %s\n",
full_fname(dirbuf));
}
@@ -517,13 +542,13 @@ void change_local_filter_dir(const char *dname, int dlen, int dir_depth)
filt_array[cur_depth] = push_local_filters(dname, dlen);
}
static int rule_matches(char *fname, struct filter_struct *ex, int name_is_dir)
static int rule_matches(const char *fname, struct filter_struct *ex, int name_is_dir)
{
int slash_handling, str_cnt = 0, anchored_match = 0;
int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
char *p, *pattern = ex->pattern;
const char *strings[16]; /* more than enough */
char *name = fname + (*fname == '/');
const char *name = fname + (*fname == '/');
if (!*name)
return 0;
@@ -596,7 +621,7 @@ static int rule_matches(char *fname, struct filter_struct *ex, int name_is_dir)
}
static void report_filter_result(char const *name,
static void report_filter_result(enum logcode code, char const *name,
struct filter_struct const *ent,
int name_is_dir, const char *type)
{
@@ -608,7 +633,7 @@ static void report_filter_result(char const *name,
static char *actions[2][2]
= { {"show", "hid"}, {"risk", "protect"} };
const char *w = who_am_i();
rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n",
rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
name_is_dir ? "directory" : "file", name, ent->pattern,
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
@@ -620,7 +645,8 @@ static void report_filter_result(char const *name,
* Return -1 if file "name" is defined to be excluded by the specified
* exclude list, 1 if it is included, and 0 if it was not matched.
*/
int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
int check_filter(struct filter_list_struct *listp, enum logcode code,
const char *name, int name_is_dir)
{
struct filter_struct *ent;
@@ -628,22 +654,22 @@ int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
continue;
if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
int rc = check_filter(ent->u.mergelist, name,
int rc = check_filter(ent->u.mergelist, code, name,
name_is_dir);
if (rc)
return rc;
continue;
}
if (ent->match_flags & MATCHFLG_CVS_IGNORE) {
int rc = check_filter(&cvs_filter_list, name,
int rc = check_filter(&cvs_filter_list, code, name,
name_is_dir);
if (rc)
return rc;
continue;
}
if (rule_matches(name, ent, name_is_dir)) {
report_filter_result(name, ent, name_is_dir,
listp->debug_type);
report_filter_result(code, name, ent, name_is_dir,
listp->debug_type);
return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1;
}
}
@@ -1009,10 +1035,10 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
return;
if (*fname != '-' || fname[1] || am_server) {
if (server_filter_list.head) {
if (daemon_filter_list.head) {
strlcpy(line, fname, sizeof line);
clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&server_filter_list, line, 0) < 0)
if (check_filter(&daemon_filter_list, FLOG, line, 0) < 0)
fp = NULL;
else
fp = fopen(line, "rb");
@@ -1095,6 +1121,8 @@ char *get_rule_prefix(int match_flags, const char *pat, int for_xfer,
else
legal_len = 0;
if (match_flags & MATCHFLG_ABS_PATH)
*op++ = '/';
if (match_flags & MATCHFLG_NEGATE)
*op++ = '!';
if (match_flags & MATCHFLG_CVS_IGNORE)

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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
@@ -28,7 +28,7 @@
extern int sparse_files;
static char last_byte;
static size_t sparse_seek = 0;
static OFF_T sparse_seek = 0;
int sparse_end(int f)
{
@@ -48,9 +48,9 @@ int sparse_end(int f)
}
static int write_sparse(int f, char *buf, size_t len)
static int write_sparse(int f, char *buf, int len)
{
size_t l1 = 0, l2 = 0;
int l1 = 0, l2 = 0;
int ret;
for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
@@ -108,7 +108,7 @@ int flush_write_file(int f)
* write_file does not allow incomplete writes. It loops internally
* until len bytes are written or errno is set.
*/
int write_file(int f,char *buf,size_t len)
int write_file(int f, char *buf, int len)
{
int ret = 0;
@@ -125,7 +125,7 @@ int write_file(int f,char *buf,size_t len)
if (!wf_writeBuf)
out_of_memory("write_file");
}
r1 = MIN(len, wf_writeBufSize - wf_writeBufCnt);
r1 = (int)MIN((size_t)len, wf_writeBufSize - wf_writeBufCnt);
if (r1) {
memcpy(wf_writeBuf + wf_writeBufCnt, buf, r1);
wf_writeBufCnt += r1;

777
flist.c
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
* `id -G` on Linux, but it's too hard to find a portable equivalent.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as

View File

@@ -1,7 +1,7 @@
/*
* Routines to provide a memory-efficient hashtable.
*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2009 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
@@ -87,7 +87,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
uchar buf[4], *keyp = buf;
int i;
SIVAL(buf, 0, key);
SIVALu(buf, 0, key);
for (ndx = 0, i = 0; i < 4; i++) {
ndx += keyp[i];
ndx += (ndx << 10);
@@ -104,7 +104,9 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
a = b = c = 0xdeadbeef + (8 << 2);
#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
#if SIZEOF_INT64 >= 8
b += (uint32)(key >> 32);
#endif
a += (uint32)key;
c ^= b; c -= rot(b, 14);
a ^= c; a -= rot(c, 11);

159
hlink.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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
@@ -30,6 +30,7 @@ extern int inc_recurse;
extern int do_xfers;
extern int link_dest;
extern int preserve_acls;
extern int preserve_xattrs;
extern int make_backups;
extern int protocol_version;
extern int remove_source_files;
@@ -119,18 +120,23 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
if (inc_recurse) {
node = hashtable_find(prior_hlinks, gnum, 1);
if (!node->data) {
node->data = new_array0(char, 5);
if (!(node->data = new_array0(char, 5)))
out_of_memory("match_gnums");
assert(gnum >= hlink_flist->ndx_start);
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
} else if (CVAL(node->data, 0) == 0) {
struct file_list *flist;
struct file_struct *fp;
prev = IVAL(node->data, 1);
flist = flist_for_ndx(prev);
assert(flist != NULL);
fp = flist->files[prev - flist->ndx_start];
fp->flags &= ~FLAG_HLINK_LAST;
flist = flist_for_ndx(prev, NULL);
if (flist)
flist->files[prev - flist->ndx_start]->flags &= ~FLAG_HLINK_LAST;
else {
/* We skipped all prior files in this
* group, so mark this as a "first". */
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
}
} else
prev = -1;
} else {
@@ -175,7 +181,7 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
if (!list_only) {
if (!list_only && flist->used) {
int i, ndx_count = 0;
int32 *ndx_list;
@@ -240,21 +246,43 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
}
/* Figure out if a prior entry is still there or if we just have a
* cached name for it. Never called with a FLAG_HLINK_FIRST entry. */
static char *check_prior(int prev_ndx, int gnum, struct file_list **flist_p)
* cached name for it. */
static char *check_prior(struct file_struct *file, int gnum,
int *prev_ndx_p, struct file_list **flist_p)
{
struct file_list *flist = flist_for_ndx(prev_ndx);
struct file_struct *fp;
struct ht_int32_node *node;
int prev_ndx = F_HL_PREV(file);
if (flist) {
*flist_p = flist;
return NULL;
while (1) {
struct file_list *flist;
if (prev_ndx < 0
|| (flist = flist_for_ndx(prev_ndx, NULL)) == NULL)
break;
fp = flist->files[prev_ndx - flist->ndx_start];
if (!(fp->flags & FLAG_SKIP_HLINK)) {
*prev_ndx_p = prev_ndx;
*flist_p = flist;
return NULL;
}
F_HL_PREV(file) = prev_ndx = F_HL_PREV(fp);
}
node = hashtable_find(prior_hlinks, gnum, 0);
assert(node != NULL && node->data);
assert(CVAL(node->data, 0) != 0);
return node->data;
if (inc_recurse
&& (node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
assert(node->data != NULL);
if (CVAL(node->data, 0) != 0) {
*prev_ndx_p = -1;
*flist_p = NULL;
return node->data;
}
/* The prior file must have been skipped. */
F_HL_PREV(file) = -1;
}
*prev_ndx_p = -1;
*flist_p = NULL;
return NULL;
}
/* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns:
@@ -268,12 +296,20 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
char *realname, *prev_name;
struct file_list *flist;
int gnum = inc_recurse ? F_HL_GNUM(file) : -1;
int prev_ndx = F_HL_PREV(file);
int prev_ndx;
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
prev_name = realname = check_prior(file, gnum, &prev_ndx, &flist);
if (!prev_name) {
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
struct file_struct *prev_file;
if (!flist) {
/* The previous file was skipped, so this one is
* treated as if it were the first in its group. */
return 0;
}
prev_file = flist->files[prev_ndx - flist->ndx_start];
/* Is the previous link not complete yet? */
if (!(prev_file->flags & FLAG_HLINK_DONE)) {
@@ -294,8 +330,8 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
/* There is a finished file to link with! */
if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
/* The previous previous is FIRST when prev is not. */
prev_ndx = F_HL_PREV(prev_file);
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
prev_name = realname = check_prior(prev_file, gnum, &prev_ndx, &flist);
assert(prev_name != NULL || flist != NULL);
/* Update our previous pointer to point to the FIRST. */
F_HL_PREV(file) = prev_ndx;
}
@@ -320,9 +356,13 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
}
if (link_stat(prev_name, &prev_st, 0) < 0) {
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(prev_name));
return -1;
if (!dry_run || errno != ENOENT) {
rsyserr(FERROR_XFER, errno, "stat %s failed", full_fname(prev_name));
return -1;
}
/* A new hard-link will get a new dev & inode, so approximate
* those values in dry-run mode by zeroing them. */
memset(&prev_st, 0, sizeof prev_st);
}
if (statret < 0 && basis_dir[0] != NULL) {
@@ -332,6 +372,9 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
int j = 0;
#ifdef SUPPORT_ACLS
alt_sx.acc_acl = alt_sx.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
alt_sx.xattr = NULL;
#endif
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
@@ -361,19 +404,37 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
sxp->st = alt_sx.st;
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
if (!ACL_READY(*sxp))
free_acl(sxp);
if (!ACL_READY(alt_sx))
get_acl(cmpbuf, sxp);
else {
sxp->acc_acl = alt_sx.acc_acl;
sxp->def_acl = alt_sx.def_acl;
alt_sx.acc_acl = alt_sx.def_acl = NULL;
}
}
#endif
}
#ifdef SUPPORT_ACLS
else if (preserve_acls)
free_acl(&alt_sx);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
free_xattr(sxp);
if (!XATTR_READY(alt_sx))
get_xattr(cmpbuf, sxp);
else {
sxp->xattr = alt_sx.xattr;
alt_sx.xattr = NULL;
}
}
#endif
} else {
#ifdef SUPPORT_ACLS
if (preserve_acls)
free_acl(&alt_sx);
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
free_xattr(&alt_sx);
#endif
}
}
if (maybe_hard_link(file, ndx, fname, statret, sxp, prev_name, &prev_st,
@@ -413,7 +474,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
{
stat_x prev_sx;
STRUCT_STAT st;
char alt_name[MAXPATHLEN], *prev_name;
char prev_name[MAXPATHLEN], alt_name[MAXPATHLEN];
const char *our_name;
struct file_list *flist;
int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
@@ -440,23 +501,28 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
#ifdef SUPPORT_ACLS
prev_sx.acc_acl = prev_sx.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
prev_sx.xattr = NULL;
#endif
while ((ndx = prev_ndx) >= 0) {
int val;
flist = flist_for_ndx(ndx);
assert(flist != NULL);
flist = flist_for_ndx(ndx, "finish_hard_link");
file = flist->files[ndx - flist->ndx_start];
file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE;
prev_ndx = F_HL_PREV(file);
F_HL_PREV(file) = fin_ndx;
prev_name = f_name(file, NULL);
prev_statret = link_stat(prev_name, &prev_sx.st, 0);
prev_statret = link_stat(f_name(file, prev_name), &prev_sx.st, 0);
val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx,
our_name, stp, fname, itemizing, code);
flist->in_progress--;
#ifdef SUPPORT_ACLS
if (preserve_acls)
free_acl(&prev_sx);
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
free_xattr(&prev_sx);
#endif
if (val < 0)
continue;
@@ -474,4 +540,25 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
out_of_memory("finish_hard_link");
}
}
int skip_hard_link(struct file_struct *file, struct file_list **flist_p)
{
struct file_list *flist;
int prev_ndx;
file->flags |= FLAG_SKIP_HLINK;
if (!(file->flags & FLAG_HLINK_LAST))
return -1;
check_prior(file, F_HL_GNUM(file), &prev_ndx, &flist);
if (prev_ndx >= 0) {
file = flist->files[prev_ndx - flist->ndx_start];
if (file->flags & (FLAG_HLINK_DONE|FLAG_FILE_SENT))
return -1;
file->flags |= FLAG_HLINK_LAST;
*flist_p = flist;
}
return prev_ndx;
}
#endif

View File

@@ -1,6 +1,6 @@
/* Inline functions for rsync.
*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 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
@@ -57,6 +57,16 @@ from_wire_mode(int mode)
return mode;
}
static inline char *
d_name(struct dirent *di)
{
#ifdef HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;
#endif
}
static inline int
isDigit(const char *ptr)
{

300
io.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2001 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -45,6 +45,7 @@ extern int inc_recurse;
extern int io_error;
extern int eol_nulls;
extern int flist_eof;
extern int list_only;
extern int read_batch;
extern int csum_length;
extern int protect_args;
@@ -100,10 +101,11 @@ static char ff_lastchar;
#ifdef ICONV_OPTION
static xbuf iconv_buf = EMPTY_XBUF;
#endif
static int defer_forwarding_messages = 0, defer_forwarding_keep = 0;
static int defer_forwarding_messages = 0, keep_defer_forwarding = 0;
static int select_timeout = SELECT_TIMEOUT;
static int active_filecnt = 0;
static OFF_T active_bytecnt = 0;
static int first_message = 1;
static char int_byte_extra[64] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (00 - 3F)/4 */
@@ -112,23 +114,39 @@ static char int_byte_extra[64] = {
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, /* (C0 - FF)/4 */
};
#define REMOTE_OPTION_ERROR "rsync: on remote machine: -"
#define REMOTE_OPTION_ERROR2 ": unknown option"
enum festatus { FES_SUCCESS, FES_REDO, FES_NO_SEND };
static void check_timeout(void)
{
time_t t, chk;
if (!io_timeout || ignore_timeout)
return;
t = time(NULL);
if (!last_io_in)
last_io_in = t;
chk = MAX(last_io_out, last_io_in);
if (t - chk >= io_timeout) {
if (am_server || am_daemon)
exit_cleanup(RERR_TIMEOUT);
rprintf(FERROR, "[%s] io timeout after %d seconds -- exiting\n",
who_am_i(), (int)(t-chk));
exit_cleanup(RERR_TIMEOUT);
}
}
static void readfd(int fd, char *buffer, size_t N);
static void writefd(int fd, const char *buf, size_t len);
static void writefd_unbuffered(int fd, const char *buf, size_t len);
static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len, int convert);
struct flist_ndx_item {
struct flist_ndx_item *next;
int ndx;
};
struct flist_ndx_list {
struct flist_ndx_item *head, *tail;
};
static struct flist_ndx_list redo_list, hlink_list;
static flist_ndx_list redo_list, hlink_list;
struct msg_list_item {
struct msg_list_item *next;
@@ -142,45 +160,10 @@ struct msg_list {
static struct msg_list msg_queue;
static void flist_ndx_push(struct flist_ndx_list *lp, int ndx)
{
struct flist_ndx_item *item;
if (!(item = new(struct flist_ndx_item)))
out_of_memory("flist_ndx_push");
item->next = NULL;
item->ndx = ndx;
if (lp->tail)
lp->tail->next = item;
else
lp->head = item;
lp->tail = item;
}
static int flist_ndx_pop(struct flist_ndx_list *lp)
{
struct flist_ndx_item *next;
int ndx;
if (!lp->head)
return -1;
ndx = lp->head->ndx;
next = lp->head->next;
free(lp->head);
lp->head = next;
if (!next)
lp->tail = NULL;
return ndx;
}
static void got_flist_entry_status(enum festatus status, const char *buf)
{
int ndx = IVAL(buf, 0);
struct file_list *flist = flist_for_ndx(ndx);
assert(flist != NULL);
struct file_list *flist = flist_for_ndx(ndx, "got_flist_entry_status");
if (remove_source_files) {
active_filecnt--;
@@ -203,6 +186,11 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
}
break;
case FES_REDO:
if (read_batch) {
if (inc_recurse)
flist->in_progress++;
break;
}
if (inc_recurse)
flist->to_redo++;
flist_ndx_push(&redo_list, ndx);
@@ -212,29 +200,6 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
}
}
static void check_timeout(void)
{
time_t t;
if (!io_timeout || ignore_timeout)
return;
if (!last_io_in) {
last_io_in = time(NULL);
return;
}
t = time(NULL);
if (t - last_io_in >= io_timeout) {
if (!am_server && !am_daemon) {
rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
(int)(t-last_io_in));
}
exit_cleanup(RERR_TIMEOUT);
}
}
/* Note the fds used for the main socket (which might really be a pipe
* for a local transfer, but we can ignore that). */
void io_set_sock_fds(int f_in, int f_out)
@@ -246,13 +211,15 @@ void io_set_sock_fds(int f_in, int f_out)
void set_io_timeout(int secs)
{
io_timeout = secs;
allowed_lull = (io_timeout + 1) / 2;
if (!io_timeout || io_timeout > SELECT_TIMEOUT)
if (!io_timeout || allowed_lull > SELECT_TIMEOUT)
select_timeout = SELECT_TIMEOUT;
else
select_timeout = io_timeout;
select_timeout = allowed_lull;
allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
if (read_batch)
allowed_lull = 0;
}
/* Setup the fd used to receive MSG_* messages. Only needed during the
@@ -291,33 +258,62 @@ static void msg_list_add(struct msg_list *lst, int code, const char *buf, int le
lst->tail = m;
}
static inline int flush_a_msg(int fd)
{
struct msg_list_item *m = msg_queue.head;
int len = IVAL(m->buf, 0) & 0xFFFFFF;
int tag = *((uchar*)m->buf+3) - MPLEX_BASE;
if (!(msg_queue.head = m->next))
msg_queue.tail = NULL;
defer_forwarding_messages++;
mplex_write(fd, tag, m->buf + 4, len, m->convert);
defer_forwarding_messages--;
free(m);
return len;
}
static void msg_flush(void)
{
if (am_generator) {
while (msg_queue.head && io_multiplexing_out) {
struct msg_list_item *m = msg_queue.head;
int len = IVAL(m->buf, 0) & 0xFFFFFF;
int tag = *((uchar*)m->buf+3) - MPLEX_BASE;
if (!(msg_queue.head = m->next))
msg_queue.tail = NULL;
stats.total_written += len + 4;
defer_forwarding_messages++;
mplex_write(sock_f_out, tag, m->buf + 4, len, m->convert);
defer_forwarding_messages--;
free(m);
}
while (msg_queue.head && io_multiplexing_out)
stats.total_written += flush_a_msg(sock_f_out) + 4;
} else {
while (msg_queue.head) {
struct msg_list_item *m = msg_queue.head;
int len = IVAL(m->buf, 0) & 0xFFFFFF;
int tag = *((uchar*)m->buf+3) - MPLEX_BASE;
if (!(msg_queue.head = m->next))
msg_queue.tail = NULL;
defer_forwarding_messages++;
mplex_write(msg_fd_out, tag, m->buf + 4, len, m->convert);
defer_forwarding_messages--;
free(m);
}
while (msg_queue.head)
(void)flush_a_msg(msg_fd_out);
}
}
static void check_for_d_option_error(const char *msg)
{
static char rsync263_opts[] = "BCDHIKLPRSTWabceghlnopqrtuvxz";
char *colon;
int saw_d = 0;
if (*msg != 'r'
|| strncmp(msg, REMOTE_OPTION_ERROR, sizeof REMOTE_OPTION_ERROR - 1) != 0)
return;
msg += sizeof REMOTE_OPTION_ERROR - 1;
if (*msg == '-' || (colon = strchr(msg, ':')) == NULL
|| strncmp(colon, REMOTE_OPTION_ERROR2, sizeof REMOTE_OPTION_ERROR2 - 1) != 0)
return;
for ( ; *msg != ':'; msg++) {
if (*msg == 'd')
saw_d = 1;
else if (*msg == 'e')
break;
else if (strchr(rsync263_opts, *msg) == NULL)
return;
}
if (saw_d) {
rprintf(FWARNING,
"*** Try using \"--old-d\" if remote rsync is <= 2.6.3 ***\n");
}
}
@@ -414,6 +410,7 @@ static void read_msg_fd(void)
got_flist_entry_status(FES_NO_SEND, buf);
break;
case MSG_ERROR_SOCKET:
case MSG_ERROR_UTF8:
case MSG_CLIENT:
if (!am_generator)
goto invalid_msg;
@@ -451,9 +448,14 @@ static void read_msg_fd(void)
* this, sender-side deletions were mostly happening at the end. */
void increment_active_files(int ndx, int itemizing, enum logcode code)
{
/* TODO: tune these limits? */
while (active_filecnt >= (active_bytecnt >= 128*1024 ? 10 : 50)) {
while (1) {
/* TODO: tune these limits? */
int limit = active_bytecnt >= 128*1024 ? 10 : 50;
if (active_filecnt < limit)
break;
check_for_finished_files(itemizing, code, 0);
if (active_filecnt < limit)
break;
if (iobuf_out_cnt)
io_flush(NORMAL_FLUSH);
else
@@ -496,9 +498,9 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len,
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
defer_forwarding_keep = 1; /* defer_forwarding_messages++ on return */
keep_defer_forwarding++; /* defer_forwarding_messages++ on return */
writefd_unbuffered(fd, buffer, n+4);
defer_forwarding_keep = 0;
keep_defer_forwarding--;
if (len > n)
writefd_unbuffered(fd, buf+n, len-n);
@@ -533,10 +535,9 @@ void send_msg_int(enum msgcode code, int num)
void wait_for_receiver(void)
{
if (iobuf_out_cnt)
io_flush(NORMAL_FLUSH);
else
read_msg_fd();
if (io_flush(NORMAL_FLUSH))
return;
read_msg_fd();
}
int get_redo_num(void)
@@ -838,8 +839,8 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags)
return s - buf;
}
int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
char ***argv_p, int *argc_p, char **request_p)
void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
char ***argv_p, int *argc_p, char **request_p)
{
int maxargs = MAX_ARGS;
int dot_pos = 0;
@@ -853,14 +854,14 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
if (!(argv = new_array(char *, maxargs)))
out_of_memory("read_args");
if (mod_name)
if (mod_name && !protect_args)
argv[argc++] = "rsyncd";
while (1) {
if (read_line(f_in, buf, bufsiz, rl_flags) == 0)
break;
if (argc == maxargs) {
if (argc == maxargs-1) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("read_args");
@@ -883,11 +884,12 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
dot_pos = argc;
}
}
argv[argc] = NULL;
glob_expand(NULL, NULL, NULL, NULL);
*argc_p = argc;
*argv_p = argv;
return dot_pos ? dot_pos : argc;
}
int io_start_buffering_out(int f_out)
@@ -949,8 +951,8 @@ void maybe_send_keepalive(void)
if (time(NULL) - last_io_out >= allowed_lull) {
if (!iobuf_out || !iobuf_out_cnt) {
if (protocol_version < 29)
return; /* there's nothing we can do */
if (protocol_version >= 30)
send_msg(MSG_DATA, "", 0, 0);
else if (protocol_version >= 30)
send_msg(MSG_NOOP, "", 0, 0);
else {
write_int(sock_f_out, cur_flist->used);
@@ -967,11 +969,13 @@ void start_flist_forward(int f_in)
assert(iobuf_out != NULL);
assert(iobuf_f_out == msg_fd_out);
flist_forward_from = f_in;
defer_forwarding_messages++;
}
void stop_flist_forward()
void stop_flist_forward(void)
{
flist_forward_from = -1;
defer_forwarding_messages--;
io_flush(FULL_FLUSH);
}
@@ -1038,6 +1042,8 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
iobuf_in_ndx = 0;
break;
case MSG_NOOP:
if (msg_bytes != 0)
goto invalid_msg;
if (am_sender)
maybe_send_keepalive();
break;
@@ -1119,6 +1125,13 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
}
read_loop(fd, line, msg_bytes);
rwrite((enum logcode)tag, line, msg_bytes, 1);
if (first_message) {
if (list_only && !am_sender && tag == 1) {
line[msg_bytes] = '\0';
check_for_d_option_error(line);
}
first_message = 0;
}
break;
default:
rprintf(FERROR, "unexpected tag %d [%s]\n",
@@ -1311,6 +1324,7 @@ int read_vstring(int f, char *buf, int bufsize)
* called by both the sender and the receiver. */
void read_sum_head(int f, struct sum_struct *sum)
{
int32 max_blength = protocol_version < 30 ? OLD_MAX_BLOCK_SIZE : MAX_BLOCK_SIZE;
sum->count = read_int(f);
if (sum->count < 0) {
rprintf(FERROR, "Invalid checksum count %ld [%s]\n",
@@ -1318,7 +1332,7 @@ void read_sum_head(int f, struct sum_struct *sum)
exit_cleanup(RERR_PROTOCOL);
}
sum->blength = read_int(f);
if (sum->blength < 0 || sum->blength > MAX_BLOCK_SIZE) {
if (sum->blength < 0 || sum->blength > max_blength) {
rprintf(FERROR, "Invalid block length %ld [%s]\n",
(long)sum->blength, who_am_i());
exit_cleanup(RERR_PROTOCOL);
@@ -1409,6 +1423,22 @@ static void sleep_for_bwlimit(int bytes_written)
total_written = (sleep_usec - elapsed_usec) * bwlimit / (ONE_SEC/1024);
}
static const char *what_fd_is(int fd)
{
static char buf[20];
if (fd == sock_f_out)
return "socket";
else if (fd == msg_fd_out)
return "message fd";
else if (fd == batch_fd)
return "batch file";
else {
snprintf(buf, sizeof buf, "fd %d", fd);
return buf;
}
}
/* Write len bytes to the file descriptor fd, looping as necessary to get
* the job done and also (in certain circumstances) reading any data on
* msg_fd_in to avoid deadlock.
@@ -1487,8 +1517,8 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len)
if (am_server && fd == msg_fd_out)
exit_cleanup(RERR_STREAMIO);
rsyserr(FERROR, errno,
"writefd_unbuffered failed to write %ld bytes [%s]",
(long)len, who_am_i());
"writefd_unbuffered failed to write %ld bytes to %s [%s]",
(long)len, what_fd_is(fd), who_am_i());
/* If the other side is sending us error messages, try
* to grab any messages they sent before they died. */
while (!am_server && fd == sock_f_out && io_multiplexing_in) {
@@ -1511,24 +1541,34 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len)
}
no_flush--;
defer_inc -= defer_forwarding_keep;
if (keep_defer_forwarding)
defer_inc--;
if (!(defer_forwarding_messages -= defer_inc) && !no_flush)
msg_flush();
}
void io_flush(int flush_it_all)
int io_flush(int flush_it_all)
{
if (!iobuf_out_cnt || no_flush)
return;
int flushed_something = 0;
if (io_multiplexing_out)
mplex_write(sock_f_out, MSG_DATA, iobuf_out, iobuf_out_cnt, 0);
else
writefd_unbuffered(iobuf_f_out, iobuf_out, iobuf_out_cnt);
iobuf_out_cnt = 0;
if (no_flush)
return 0;
if (flush_it_all && !defer_forwarding_messages)
if (iobuf_out_cnt) {
if (io_multiplexing_out)
mplex_write(sock_f_out, MSG_DATA, iobuf_out, iobuf_out_cnt, 0);
else
writefd_unbuffered(iobuf_f_out, iobuf_out, iobuf_out_cnt);
iobuf_out_cnt = 0;
flushed_something = 1;
}
if (flush_it_all && !defer_forwarding_messages && msg_queue.head) {
msg_flush();
flushed_something = 1;
}
return flushed_something;
}
static void writefd(int fd, const char *buf, size_t len)
@@ -1536,10 +1576,8 @@ static void writefd(int fd, const char *buf, size_t len)
if (fd == sock_f_out)
stats.total_written += len;
if (fd == write_batch_monitor_out) {
if ((size_t)write(batch_fd, buf, len) != len)
exit_cleanup(RERR_FILEIO);
}
if (fd == write_batch_monitor_out)
writefd_unbuffered(batch_fd, buf, len);
if (!iobuf_out || fd != iobuf_f_out) {
writefd_unbuffered(fd, buf, len);

2
io.h
View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 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

View File

@@ -295,9 +295,8 @@ int getaddrinfo(const char *node,
res);
} else if (hints.ai_flags & AI_NUMERICHOST) {
struct in_addr ip;
if (!inet_aton(node, &ip)) {
if (inet_pton(AF_INET, node, &ip) <= 0)
return EAI_FAIL;
}
return getaddr_info_single_addr(service,
ntohl(ip.s_addr),
&hints,
@@ -492,13 +491,10 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
return EAI_FAIL;
}
/* We don't support those. */
if ((node && !(flags & NI_NUMERICHOST))
|| (service && !(flags & NI_NUMERICSERV)))
return EAI_FAIL;
if (node) {
return gethostnameinfo(sa, node, nodelen, flags);
int ret = gethostnameinfo(sa, node, nodelen, flags);
if (ret)
return ret;
}
if (service) {

View File

@@ -38,22 +38,22 @@ static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
C = ctx->C;
D = ctx->D;
X[0] = IVAL(data, 0);
X[1] = IVAL(data, 4);
X[2] = IVAL(data, 8);
X[3] = IVAL(data, 12);
X[4] = IVAL(data, 16);
X[5] = IVAL(data, 20);
X[6] = IVAL(data, 24);
X[7] = IVAL(data, 28);
X[8] = IVAL(data, 32);
X[9] = IVAL(data, 36);
X[10] = IVAL(data, 40);
X[11] = IVAL(data, 44);
X[12] = IVAL(data, 48);
X[13] = IVAL(data, 52);
X[14] = IVAL(data, 56);
X[15] = IVAL(data, 60);
X[0] = IVALu(data, 0);
X[1] = IVALu(data, 4);
X[2] = IVALu(data, 8);
X[3] = IVALu(data, 12);
X[4] = IVALu(data, 16);
X[5] = IVALu(data, 20);
X[6] = IVALu(data, 24);
X[7] = IVALu(data, 28);
X[8] = IVALu(data, 32);
X[9] = IVALu(data, 36);
X[10] = IVALu(data, 40);
X[11] = IVALu(data, 44);
X[12] = IVALu(data, 48);
X[13] = IVALu(data, 52);
X[14] = IVALu(data, 56);
X[15] = IVALu(data, 60);
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
@@ -192,8 +192,8 @@ void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN])
| (ctx->totalN2 << 3);
low = (ctx->totalN << 3);
SIVAL(msglen, 0, low);
SIVAL(msglen, 4, high);
SIVALu(msglen, 0, low);
SIVALu(msglen, 4, high);
last = ctx->totalN & 0x3F;
padn = last < 56 ? 56 - last : 120 - last;
@@ -201,10 +201,10 @@ void md5_result(md_context *ctx, uchar digest[MD5_DIGEST_LEN])
md5_update(ctx, md5_padding, padn);
md5_update(ctx, msglen, 8);
SIVAL(digest, 0, ctx->A);
SIVAL(digest, 4, ctx->B);
SIVAL(digest, 8, ctx->C);
SIVAL(digest, 12, ctx->D);
SIVALu(digest, 0, ctx->A);
SIVALu(digest, 4, ctx->B);
SIVALu(digest, 8, ctx->C);
SIVALu(digest, 12, ctx->D);
}
void get_md5(uchar *out, const uchar *input, int n)

View File

@@ -4,7 +4,7 @@
* An implementation of MD4 designed for use in the SMB authentication protocol.
*
* Copyright (C) 1997-1998 Andrew Tridgell
* Copyright (C) 2005-2007 Wayne Davison
* Copyright (C) 2005-2008 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

View File

@@ -295,24 +295,30 @@ pool_boundary(alloc_pool_t p, size_t len)
}
#define FDPRINT(label, value) \
snprintf(buf, sizeof buf, label, value), \
write(fd, buf, strlen(buf))
do { \
int len = snprintf(buf, sizeof buf, label, value); \
if (write(fd, buf, len) != len) \
ret = -1; \
} while (0)
#define FDEXTSTAT(ext) \
snprintf(buf, sizeof buf, " %12ld %5ld\n", \
(long) ext->free, \
(long) ext->bound), \
write(fd, buf, strlen(buf))
do { \
int len = snprintf(buf, sizeof buf, " %12ld %5ld\n", \
(long)ext->free, (long)ext->bound); \
if (write(fd, buf, len) != len) \
ret = -1; \
} while (0)
void
int
pool_stats(alloc_pool_t p, int fd, int summarize)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
struct pool_extent *cur;
char buf[BUFSIZ];
int ret = 0;
if (!pool)
return;
return ret;
FDPRINT(" Extent size: %12ld\n", (long) pool->size);
FDPRINT(" Alloc quantum: %12ld\n", (long) pool->quantum);
@@ -324,13 +330,16 @@ pool_stats(alloc_pool_t p, int fd, int summarize)
FDPRINT(" Bytes freed: %12.0f\n", (double) pool->b_freed);
if (summarize)
return;
return ret;
if (!pool->extents)
return;
return ret;
write(fd, "\n", 1);
if (write(fd, "\n", 1) != 1)
ret = -1;
for (cur = pool->extents; cur; cur = cur->next)
FDEXTSTAT(cur);
return ret;
}

View File

@@ -2,6 +2,7 @@
* Unix SMB/CIFS implementation.
* Based on the Samba ACL support code.
* Copyright (C) Jeremy Allison 2000.
* Copyright (C) 2007-2008 Wayne Davison
*
* The permission functions have been changed to get/set all bits via
* one call. Some functions that rsync doesn't need were also removed.
@@ -550,7 +551,7 @@ SMB_ACL_T sys_acl_init(int count)
* acl[] array, this actually allocates an ACL with room
* for (count+1) entries
*/
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof (struct acl))) == NULL) {
errno = ENOMEM;
return NULL;
}
@@ -1006,7 +1007,7 @@ SMB_ACL_T sys_acl_init(int count)
* acl[] array, this actually allocates an ACL with room
* for (count+1) entries
*/
if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof(struct acl))) == NULL) {
errno = ENOMEM;
return NULL;
}
@@ -1637,14 +1638,14 @@ SMB_ACL_T sys_acl_init(int count)
return NULL;
}
if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + sizeof (struct acl))) == NULL) {
errno = ENOMEM;
return NULL;
}
a->next = -1;
a->freeaclp = False;
a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
a->aclp = (struct acl *)((char *)a + sizeof a[0]);
a->aclp->acl_cnt = 0;
return a;
@@ -1814,7 +1815,11 @@ SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
/* AIX has no DEFAULT */
if ( type == SMB_ACL_TYPE_DEFAULT ) {
#ifdef ENOTSUP
errno = ENOTSUP;
#else
errno = ENOSYS;
#endif
return NULL;
}
@@ -2703,6 +2708,8 @@ int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits,
rc = mbr_uid_to_uuid(u_g_id, uu);
else
rc = mbr_gid_to_uuid(u_g_id, uu);
if (rc != 0)
return rc;
if (acl_set_tag_type(entry, tag_type) != 0
|| acl_set_qualifier(entry, &uu) != 0

View File

@@ -3,6 +3,7 @@
* Version 2.2.x
* Portable SMB ACL interface
* Copyright (C) Jeremy Allison 2000
* Copyright (C) 2007-2008 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

View File

@@ -2,6 +2,7 @@
* Extended attribute support for rsync.
*
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2003-2008 Wayne Davison
* Written by Jay Fenlason.
*
* This program is free software; you can redistribute it and/or modify

View File

@@ -1,6 +1,3 @@
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
and Karl Auer */
/*
* 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
@@ -16,13 +13,14 @@
* with this program; if not, visit the http://fsf.org website.
*/
/* some fixes
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
* and Karl Auer. Some of the changes are:
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2009 Wayne Davison <wayned@samba.org>
*/
/*
* Load parameters.
/* Load parameters.
*
* This module provides suitable callback functions for the params
* module. It builds the internal table of service details which is

46
log.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -37,6 +37,7 @@ 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;
extern int logfile_format_has_i;
@@ -54,7 +55,7 @@ extern iconv_t ic_chck;
extern iconv_t ic_send, ic_recv;
#endif
extern char curr_dir[];
extern char *module_dir;
extern char *full_module_path;
extern unsigned int module_dirlen;
static int log_initialised;
@@ -84,7 +85,7 @@ struct {
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
{ RERR_WAITCHILD , "waitpid() failed" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files could not be transferred" },
{ RERR_PARTIAL , "some files/attrs were not transferred (see previous errors)" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
{ RERR_TIMEOUT , "timeout in data send/receive" },
{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
@@ -256,13 +257,17 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
if (am_server && msg_fd_out >= 0) {
assert(!is_utf8);
/* Pass the message to our sibling. */
/* Pass the message to our sibling in native charset. */
send_msg((enum msgcode)code, buf, len, 0);
return;
}
if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */
code = FERROR;
else if (code == FERROR_UTF8) {
is_utf8 = 1;
code = FERROR;
}
if (code == FCLIENT)
code = FINFO;
@@ -320,6 +325,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
exit_cleanup(RERR_MESSAGEIO);
}
if (progress_is_active && !am_server) {
fputc('\n', f);
progress_is_active = 0;
}
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;
@@ -517,7 +527,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
break;
case 'M':
n = c = timestring(file->modtime);
while ((c = strchr(p, ' ')) != NULL)
while ((c = strchr(c, ' ')) != NULL)
*c = '-';
break;
case 'B':
@@ -593,7 +603,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
n = timestring(time(NULL));
break;
case 'P':
n = module_dir;
n = full_module_path;
break;
case 'u':
n = auth_user;
@@ -632,15 +642,21 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
: !(iflags & ITEM_TRANSFER) ? '.'
: !local_server && *op == 's' ? '<' : '>';
c[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: IS_DEVICE(file->mode) ? 'D'
: S_ISLNK(file->mode) ? 'L' : 'f';
c[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || (!receiver_symlink_times && S_ISLNK(file->mode))
? 'T' : 't';
if (S_ISLNK(file->mode)) {
c[1] = 'L';
c[3] = '.';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || !receiver_symlink_times
|| (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't';
} else {
c[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: IS_DEVICE(file->mode) ? 'D' : 'f';
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times ? 'T' : 't';
}
c[2] = !(iflags & ITEM_REPORT_CHANGE) ? '.' : 'c';
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';

136
main.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -33,7 +33,6 @@ extern int list_only;
extern int am_root;
extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_daemon;
extern int inc_recurse;
extern int blocking_io;
@@ -78,12 +77,11 @@ extern char *batch_name;
extern char *password_file;
extern char curr_dir[MAXPATHLEN];
extern struct file_list *first_flist;
extern struct filter_list_struct server_filter_list;
#ifdef ICONV_OPTION
extern iconv_t ic_send;
#endif
extern struct filter_list_struct daemon_filter_list;
uid_t our_uid;
int am_receiver = 0; /* Only set to 1 after the receiver/generator fork. */
int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */
int local_server = 0;
int daemon_over_rsh = 0;
mode_t orig_umask = 0;
@@ -334,7 +332,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
{
int i, argc = 0;
char *args[MAX_ARGS];
pid_t ret;
pid_t pid;
int dash_l_set = 0;
if (!read_batch && !local_server) {
@@ -344,7 +342,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
cmd = rsh_env;
if (!cmd)
cmd = RSYNC_RSH;
cmd = strdup(cmd);
cmd = strdup(cmd); /* MEMORY LEAK */
if (!cmd)
goto oom;
@@ -453,7 +451,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
batch_gen_fd = from_gen_pipe[0];
*f_out_p = from_gen_pipe[1];
*f_in_p = batch_fd;
ret = -1; /* no child pid */
pid = (pid_t)-1; /* no child pid */
#ifdef ICONV_CONST
setup_iconv();
#endif
@@ -463,54 +461,20 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
if (whole_file < 0 && !write_batch)
whole_file = 1;
set_allow_inc_recurse();
ret = local_child(argc, args, f_in_p, f_out_p, child_main);
pid = local_child(argc, args, f_in_p, f_out_p, child_main);
#ifdef ICONV_CONST
setup_iconv();
#endif
} else {
pid = piped_child(args, f_in_p, f_out_p);
#ifdef ICONV_CONST
setup_iconv();
#endif
if (protect_args) {
int fd;
#ifdef ICONV_OPTION
int convert = ic_send != (iconv_t)-1;
xbuf outbuf, inbuf;
if (convert)
alloc_xbuf(&outbuf, 1024);
#endif
ret = piped_child(args, f_in_p, f_out_p);
for (i = 0; args[i]; i++) {} /* find first NULL */
args[i] = "rsync"; /* set a new arg0 */
if (verbose > 1)
print_child_argv("protected args:", args + i + 1);
fd = *f_out_p;
do {
#ifdef ICONV_OPTION
if (convert) {
INIT_XBUF_STRLEN(inbuf, args[i]);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
outbuf.buf[outbuf.len] = '\0';
write_buf(fd, outbuf.buf, outbuf.len + 1);
outbuf.len = 0;
} else
#endif
write_buf(fd, args[i], strlen(args[i]) + 1);
} while (args[++i]);
write_byte(fd, 0);
#ifdef ICONV_OPTION
if (convert)
free(outbuf.buf);
#endif
} else
ret = piped_child(args, f_in_p, f_out_p);
if (protect_args && !daemon_over_rsh)
send_protected_args(*f_out_p, args);
}
return ret;
return pid;
oom:
out_of_memory("do_cmd");
@@ -544,12 +508,29 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (!dest_path || list_only)
return NULL;
if (daemon_filter_list.head) {
char *slash = strrchr(dest_path, '/');
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
*slash = '\0';
else
slash = NULL;
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",
dest_path);
exit_cleanup(RERR_FILESELECT);
}
if (slash)
*slash = '/';
}
/* See what currently exists at the destination. */
if ((statret = do_stat(dest_path, &st)) == 0) {
/* If the destination is a dir, enter it and use mode 1. */
if (S_ISDIR(st.st_mode)) {
if (!push_dir(dest_path, 0)) {
rsyserr(FERROR, errno, "push_dir#1 %s failed",
if (!change_dir(dest_path, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#1 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
@@ -608,8 +589,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
dry_run++;
}
if (!push_dir(dest_path, dry_run > 1)) {
rsyserr(FERROR, errno, "push_dir#2 %s failed",
if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#2 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
@@ -628,8 +609,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
dest_path = "/";
*cp = '\0';
if (!push_dir(dest_path, 0)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
if (!change_dir(dest_path, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#3 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
@@ -721,8 +702,8 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
}
if (!relative_paths) {
if (!push_dir(dir, 0)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
if (!change_dir(dir, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#3 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
@@ -780,6 +761,8 @@ static int do_recv(int f_in, int f_out, char *local_name)
}
if (pid == 0) {
am_receiver = 1;
close(error_pipe[0]);
if (f_in != f_out)
close(f_out);
@@ -891,8 +874,8 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
char *dir = argv[0];
argc--;
argv++;
if (!am_daemon && !push_dir(dir, 0)) {
rsyserr(FERROR, errno, "push_dir#4 %s failed",
if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#4 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
@@ -931,25 +914,25 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
if (sanitize_paths) {
char **dir_p;
for (dir_p = basis_dir; *dir_p; dir_p++)
*dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth);
*dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth, SP_DEFAULT);
if (partial_dir)
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth);
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, SP_DEFAULT);
}
check_alt_basis_dirs();
if (server_filter_list.head) {
if (daemon_filter_list.head) {
char **dir_p;
struct filter_list_struct *elp = &server_filter_list;
struct filter_list_struct *elp = &daemon_filter_list;
for (dir_p = basis_dir; *dir_p; dir_p++) {
char *dir = *dir_p;
if (*dir == '/')
dir += module_dirlen;
if (check_filter(elp, dir, 1) < 0)
if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
&& check_filter(elp, partial_dir + module_dirlen, 1) < 0) {
&& check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
options_rejected:
rprintf(FERROR,
"Your options have been rejected by the server.\n");
@@ -1036,7 +1019,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (write_batch && !am_server)
start_write_batch(f_out);
flist = send_file_list(f_out, argc, argv);
set_msg_fd_in(-1);
if (verbose > 3)
rprintf(FINFO,"file list sent\n");
@@ -1067,11 +1049,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_start_multiplex_out();
}
if (argc == 0) {
list_only |= 1;
xfer_dirs |= 1;
}
send_filter_list(read_batch ? -1 : f_out);
if (filesfrom_fd >= 0) {
@@ -1182,8 +1159,6 @@ static int start_client(int argc, char *argv[])
static char *dotarg[1] = { "." };
p = dotarg[0];
remote_argv = dotarg;
list_only |= 1;
xfer_dirs |= 1;
}
remote_argc = 1;
@@ -1214,8 +1189,8 @@ static int start_client(int argc, char *argv[])
rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
exit_cleanup(RERR_SYNTAX);
}
remote_argv = argv + argc - 1;
remote_argc = 1;
remote_argv = argv += argc - 1;
remote_argc = argc = 1;
}
if (am_sender) {
@@ -1255,10 +1230,6 @@ static int start_client(int argc, char *argv[])
}
remote_argv[i] = arg;
}
if (argc == 0) {
list_only |= 1;
xfer_dirs |= 1;
}
}
if (daemon_over_rsh < 0)
@@ -1447,7 +1418,7 @@ int main(int argc,char *argv[])
setlocale(LC_CTYPE, "");
#endif
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
if (!parse_arguments(&argc, (const char ***) &argv)) {
/* FIXME: We ought to call the same error-handling
* code here, rather than relying on getopt. */
option_error();
@@ -1468,11 +1439,11 @@ int main(int argc,char *argv[])
SIGACTION(SIGXFSZ, SIG_IGN);
#endif
/* Initialize push_dir here because on some old systems getcwd
/* Initialize change_dir() here because on some old systems getcwd
* (implemented by forking "pwd" and reading its output) doesn't
* work when there are other child processes. Also, on all systems
* that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL, 0);
change_dir(NULL, CD_NORMAL);
init_flist();
@@ -1496,7 +1467,6 @@ int main(int argc,char *argv[])
read_stream_flags(batch_fd);
else
write_stream_flags(batch_fd);
}
if (write_batch < 0)
dry_run = 1;
@@ -1512,7 +1482,7 @@ int main(int argc,char *argv[])
char buf[MAXPATHLEN];
protect_args = 2;
read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
if (!parse_arguments(&argc, (const char ***) &argv)) {
option_error();
exit_cleanup(RERR_SYNTAX);
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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

296
options.c
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-2007 Wayne Davison
* Copyright (C) 2002-2009 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
@@ -25,11 +25,12 @@
#include "zlib/zlib.h"
extern int module_id;
extern int local_server;
extern int sanitize_paths;
extern int daemon_over_rsh;
extern unsigned int module_dirlen;
extern struct filter_list_struct filter_list;
extern struct filter_list_struct server_filter_list;
extern struct filter_list_struct daemon_filter_list;
int make_backups = 0;
@@ -77,7 +78,6 @@ int def_compress_level = Z_DEFAULT_COMPRESSION;
int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */
int am_server = 0;
int am_sender = 0;
int am_generator = 0;
int am_starting_up = 1;
int relative_paths = -1;
int implied_dirs = 1;
@@ -227,7 +227,8 @@ static void print_rsync_version(enum logcode f)
STRUCT_STAT *dumstat;
#if SUBPROTOCOL_VERSION != 0
asprintf(&subprotocol, ".PR%d", SUBPROTOCOL_VERSION);
if (asprintf(&subprotocol, ".PR%d", SUBPROTOCOL_VERSION) < 0)
out_of_memory("print_rsync_version");
#endif
#ifdef HAVE_SOCKETPAIR
got_socketpair = "";
@@ -259,7 +260,7 @@ static void print_rsync_version(enum logcode f)
rprintf(f, "%s version %s protocol version %d%s\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
rprintf(f, "Copyright (C) 1996-2007 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "Copyright (C) 1996-2009 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",
@@ -474,6 +475,8 @@ static struct poptOption long_options[] = {
{"dirs", 'd', POPT_ARG_VAL, &xfer_dirs, 2, 0, 0 },
{"no-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 0, 0, 0 },
{"no-d", 0, POPT_ARG_VAL, &xfer_dirs, 0, 0, 0 },
{"old-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 },
{"old-d", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 },
{"perms", 'p', POPT_ARG_VAL, &preserve_perms, 1, 0, 0 },
{"no-perms", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
{"no-p", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
@@ -536,8 +539,11 @@ static struct poptOption long_options[] = {
{"ignore-existing", 0, POPT_ARG_NONE, &ignore_existing, 0, 0, 0 },
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
{"min-size", 0, POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
{"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
{"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
{"sparse", 'S', POPT_ARG_VAL, &sparse_files, 1, 0, 0 },
{"no-sparse", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
{"no-S", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
{"inplace", 0, POPT_ARG_VAL, &inplace, 1, 0, 0 },
{"no-inplace", 0, POPT_ARG_VAL, &inplace, 0, 0, 0 },
{"append", 0, POPT_ARG_NONE, 0, OPT_APPEND, 0, 0 },
{"append-verify", 0, POPT_ARG_VAL, &append_mode, 2, 0, 0 },
{"no-append", 0, POPT_ARG_VAL, &append_mode, 0, 0, 0 },
@@ -550,8 +556,10 @@ static struct poptOption long_options[] = {
{"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 },
{"remove-sent-files",0, POPT_ARG_VAL, &remove_source_files, 2, 0, 0 }, /* deprecated */
{"remove-source-files",0,POPT_ARG_VAL, &remove_source_files, 1, 0, 0 },
{"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
{"force", 0, POPT_ARG_VAL, &force_delete, 1, 0, 0 },
{"no-force", 0, POPT_ARG_VAL, &force_delete, 0, 0, 0 },
{"ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 1, 0, 0 },
{"no-ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 0, 0, 0 },
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
{0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
{"filter", 'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
@@ -570,11 +578,13 @@ static struct poptOption long_options[] = {
{"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
{"fuzzy", 'y', POPT_ARG_NONE, &fuzzy_basis, 0, 0, 0 },
{"fuzzy", 'y', POPT_ARG_VAL, &fuzzy_basis, 1, 0, 0 },
{"no-fuzzy", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 },
{"no-y", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 },
{"compress", 'z', POPT_ARG_NONE, 0, 'z', 0, 0 },
{"no-compress", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 },
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
{"no-z", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 },
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
{"compress-level", 0, POPT_ARG_INT, &def_compress_level, 'z', 0, 0 },
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
{"progress", 0, POPT_ARG_VAL, &do_progress, 1, 0, 0 },
@@ -584,7 +594,9 @@ static struct poptOption long_options[] = {
{"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
{"delay-updates", 0, POPT_ARG_VAL, &delay_updates, 1, 0, 0 },
{"no-delay-updates", 0, POPT_ARG_VAL, &delay_updates, 0, 0, 0 },
{"prune-empty-dirs",'m', POPT_ARG_NONE, &prune_empty_dirs, 0, 0, 0 },
{"prune-empty-dirs",'m', POPT_ARG_VAL, &prune_empty_dirs, 1, 0, 0 },
{"no-prune-empty-dirs",0,POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 },
{"no-m", 0, POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 },
{"log-file", 0, POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
{"log-file-format", 0, POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
{"out-format", 0, POPT_ARG_STRING, &stdout_format, 0, 0, 0 },
@@ -613,6 +625,7 @@ static struct poptOption long_options[] = {
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
{"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 },
{"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 },
{"no-contimeout", 0, POPT_ARG_VAL, &connect_timeout, 0, 0, 0 },
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
@@ -622,7 +635,9 @@ static struct poptOption long_options[] = {
#endif
{"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
{"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
{"8-bit-output", '8', POPT_ARG_NONE, &allow_8bit_chars, 0, 0, 0 },
{"8-bit-output", '8', POPT_ARG_VAL, &allow_8bit_chars, 1, 0, 0 },
{"no-8-bit-output", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
{"no-8", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
{"qsort", 0, POPT_ARG_NONE, &use_qsort, 0, 0, 0 },
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
@@ -877,7 +892,7 @@ static void create_refuse_error(int which)
*
* @retval 0 on error, with err_buf containing an explanation
**/
int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
int parse_arguments(int *argc_p, const char ***argv_p)
{
static poptContext pc;
char *ref = lp_refuse_options(module_id);
@@ -889,8 +904,10 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
set_refuse_options(ref);
if (am_daemon) {
set_refuse_options("log-file*");
#ifdef ICONV_OPTION
if (!*lp_charset(module_id))
set_refuse_options("iconv");
#endif
}
#ifdef ICONV_OPTION
@@ -1017,8 +1034,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
case OPT_INCLUDE_FROM:
arg = poptGetOptArg(pc);
if (sanitize_paths)
arg = sanitize_path(NULL, arg, NULL, 0);
if (server_filter_list.head) {
arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
if (daemon_filter_list.head) {
int rej;
char *dir, *cp = strdup(arg);
if (!cp)
@@ -1027,7 +1044,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
goto options_rejected;
dir = cp + (*cp == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
rej = check_filter(&server_filter_list, dir, 0) < 0;
rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0;
free(cp);
if (rej)
goto options_rejected;
@@ -1080,8 +1097,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
break;
case 'q':
if (frommain)
quiet++;
quiet++;
break;
case 'x':
@@ -1259,7 +1275,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
}
if (human_readable && argc == 2) {
if (human_readable && argc == 2 && !am_server) {
/* Allow the old meaning of 'h' (--help) on its own. */
usage(FINFO);
exit_cleanup(0);
@@ -1278,12 +1294,11 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
#endif
if (protect_args == 1) {
if (!frommain)
protect_args = 0;
else if (am_server)
return 1;
}
if (protect_args == 1 && am_server)
return 1;
*argv_p = argv = poptGetArgs(pc);
*argc_p = argc = count_args(argv);
#ifndef SUPPORT_LINKS
if (preserve_links && !am_sender) {
@@ -1303,7 +1318,13 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
#endif
#ifndef SUPPORT_XATTRS
#ifdef SUPPORT_XATTRS
if (am_root < 0 && preserve_xattrs > 1) {
snprintf(err_buf, sizeof err_buf,
"--fake-super conflicts with -XX\n");
return 0;
}
#else
if (am_root < 0) {
snprintf(err_buf, sizeof err_buf,
"--fake-super requires an rsync with extended attributes enabled\n");
@@ -1335,6 +1356,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
"--read-batch cannot be used with --files-from\n");
return 0;
}
if (read_batch && remove_source_files) {
snprintf(err_buf, sizeof err_buf,
"--read-batch cannot be used with --remove-%s-files\n",
remove_source_files == 1 ? "source" : "sent");
return 0;
}
if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
snprintf(err_buf, sizeof err_buf,
"the batch-file name must be %d characters or less.\n",
@@ -1366,8 +1393,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
xfer_dirs = 1;
}
if (xfer_dirs < 1)
xfer_dirs = recurse || list_only;
if (argc < 2 && !read_batch && !am_server)
list_only |= 1;
if (xfer_dirs >= 4) {
parse_rule(&filter_list, "- /*/*", 0, 0);
recurse = xfer_dirs = 1;
} else if (recurse)
xfer_dirs = 1;
else if (xfer_dirs < 0)
xfer_dirs = list_only ? 1 : 0;
if (relative_paths < 0)
relative_paths = files_from? 1 : 0;
@@ -1396,7 +1431,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
if (!xfer_dirs && delete_mode) {
snprintf(err_buf, sizeof err_buf,
"--delete does not work without -r or -d.\n");
"--delete does not work without --recursive (-r) or --dirs (-d).\n");
return 0;
}
@@ -1416,27 +1451,24 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
need_messages_from_generator = 1;
}
*argv_p = argv = poptGetArgs(pc);
*argc_p = argc = count_args(argv);
if (sanitize_paths) {
int i;
for (i = argc; i-- > 0; )
argv[i] = sanitize_path(NULL, argv[i], "", 0);
argv[i] = sanitize_path(NULL, argv[i], "", 0, SP_KEEP_DOT_DIRS);
if (tmpdir)
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
if (backup_dir)
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
}
if (server_filter_list.head && !am_sender) {
struct filter_list_struct *elp = &server_filter_list;
if (daemon_filter_list.head && !am_sender) {
struct filter_list_struct *elp = &daemon_filter_list;
if (tmpdir) {
char *dir;
if (!*tmpdir)
goto options_rejected;
dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, dir, 1) < 0)
if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
if (backup_dir) {
@@ -1445,7 +1477,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
goto options_rejected;
dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, dir, 1) < 0)
if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
}
@@ -1634,14 +1666,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
} else {
if (sanitize_paths)
files_from = sanitize_path(NULL, files_from, NULL, 0);
if (server_filter_list.head) {
files_from = sanitize_path(NULL, files_from, NULL, 0, SP_DEFAULT);
if (daemon_filter_list.head) {
char *dir;
if (!*files_from)
goto options_rejected;
dir = files_from + (*files_from == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&server_filter_list, dir, 0) < 0)
if (check_filter(&daemon_filter_list, FLOG, dir, 0) < 0)
goto options_rejected;
}
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
@@ -1711,8 +1743,8 @@ void server_options(char **args, int *argc_p)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if ((list_only && !recurse) || xfer_dirs > 1
|| (xfer_dirs && !recurse && delete_mode && am_sender))
if ((xfer_dirs >= 2 && xfer_dirs < 4)
|| (xfer_dirs && !recurse && (list_only || (delete_mode && am_sender))))
argstr[x++] = 'd';
if (am_sender) {
if (keep_dirlinks)
@@ -1782,25 +1814,41 @@ void server_options(char **args, int *argc_p)
if (do_compression)
argstr[x++] = 'z';
/* We make use of the -e option to let the server know about any
* pre-release protocol version && some behavior flags. */
argstr[x++] = 'e';
#if SUBPROTOCOL_VERSION != 0
if (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
} else
#endif
argstr[x++] = '.';
set_allow_inc_recurse();
if (allow_inc_recurse)
argstr[x++] = 'i';
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
argstr[x++] = 'L';
/* Checking the pre-negotiated value allows --protocol=29 override. */
if (protocol_version >= 30) {
/* We make use of the -e option to let the server know about
* any pre-release protocol version && some behavior flags. */
argstr[x++] = 'e';
#if SUBPROTOCOL_VERSION != 0
if (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"%d.%d",
PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
} else
#endif
argstr[x++] = '.';
if (allow_inc_recurse)
argstr[x++] = 'i';
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
argstr[x++] = 'L';
#endif
#ifdef ICONV_OPTION
argstr[x++] = 's';
#endif
argstr[x++] = 'f';
}
if (x >= (int)sizeof argstr) { /* Not possible... */
rprintf(FERROR, "argstr overflow in server_options().\n");
exit_cleanup(RERR_MALLOC);
}
argstr[x] = '\0';
args[ac++] = argstr;
if (x > 1)
args[ac++] = argstr;
#ifdef ICONV_OPTION
if (iconv_opt) {
@@ -1815,7 +1863,7 @@ void server_options(char **args, int *argc_p)
}
#endif
if (protect_args) /* initial args break here */
if (protect_args && !local_server) /* unprotected args stop here */
args[ac++] = NULL;
if (list_only > 1)
@@ -1982,7 +2030,6 @@ void server_options(char **args, int *argc_p)
* and it may be an older version that doesn't know this
* option, so don't send it if client is the sender.
*/
int i;
for (i = 0; i < basis_dir_cnt; i++) {
args[ac++] = dest_option;
args[ac++] = basis_dir[i];
@@ -2022,6 +2069,11 @@ void server_options(char **args, int *argc_p)
else if (remove_source_files)
args[ac++] = "--remove-sent-files";
if (ac > MAX_SERVER_ARGS) { /* Not possible... */
rprintf(FERROR, "argc overflow in server_options().\n");
exit_cleanup(RERR_MALLOC);
}
*argc_p = ac;
return;
@@ -2029,6 +2081,62 @@ void server_options(char **args, int *argc_p)
out_of_memory("server_options");
}
/* If str points to a valid hostspec, return allocated memory containing the
* [USER@]HOST part of the string, and set the path_start_ptr to the part of
* the string after the host part. Otherwise, return NULL. If port_ptr is
* non-NULL, we must be parsing an rsync:// URL hostname, and we will set
* *port_ptr if a port number is found. Note that IPv6 IPs will have their
* (required for parsing) [ and ] chars elided from the returned string. */
static char *parse_hostspec(char *str, char **path_start_ptr, int *port_ptr)
{
char *s, *host_start = str;
int hostlen = 0, userlen = 0;
char *ret;
for (s = str; ; s++) {
if (!*s) {
/* It is only OK if we run out of string with rsync:// */
if (!port_ptr)
return NULL;
if (!hostlen)
hostlen = s - host_start;
break;
}
if (*s == ':' || *s == '/') {
if (!hostlen)
hostlen = s - host_start;
if (*s++ == '/') {
if (!port_ptr)
return NULL;
} else if (port_ptr) {
*port_ptr = atoi(s);
while (isDigit(s)) s++;
if (*s && *s++ != '/')
return NULL;
}
break;
}
if (*s == '@') {
userlen = s - str + 1;
host_start = s + 1;
} else if (*s == '[') {
if (s != host_start++)
return NULL;
while (*s && *s != ']' && *s != '/') s++; /*SHARED ITERATOR*/
hostlen = s - host_start;
if (*s != ']' || (s[1] && s[1] != '/' && s[1] != ':') || !hostlen)
return NULL;
}
}
*path_start_ptr = s;
ret = new_array(char, userlen + hostlen + 1);
if (userlen)
strlcpy(ret, str, userlen + 1);
strlcpy(ret + userlen, host_start, hostlen + 1);
return ret;
}
/* Look for a HOST specfication of the form "HOST:PATH", "HOST::PATH", or
* "rsync://HOST:PORT/PATH". If found, *host_ptr will be set to some allocated
* memory with the HOST. If a daemon-accessing spec was specified, the value
@@ -2038,68 +2146,28 @@ void server_options(char **args, int *argc_p)
* "[::ffff:127.0.0.1]") which is returned without the '[' and ']'. */
char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
{
char *p;
int not_host;
int hostlen;
char *path;
if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
char *path;
s += strlen(URL_PREFIX);
if ((p = strchr(s, '/')) != NULL) {
hostlen = p - s;
path = p + 1;
} else {
hostlen = strlen(s);
path = "";
*host_ptr = parse_hostspec(s + strlen(URL_PREFIX), &path, port_ptr);
if (*host_ptr) {
if (!*port_ptr)
*port_ptr = RSYNC_PORT;
return path;
}
if (*s == '[' && (p = strchr(s, ']')) != NULL) {
s++;
hostlen = p - s;
if (p[1] == ':')
*port_ptr = atoi(p+2);
} else {
if ((p = strchr(s, ':')) != NULL && p < s + hostlen) {
hostlen = p - s;
*port_ptr = atoi(p+1);
}
}
if (!*port_ptr)
*port_ptr = RSYNC_PORT;
*host_ptr = new_array(char, hostlen + 1);
strlcpy(*host_ptr, s, hostlen + 1);
return path;
}
if (*s == '[' && (p = strchr(s, ']')) != NULL && p[1] == ':') {
s++;
hostlen = p - s;
*p = '\0';
not_host = strchr(s, '/') || !strchr(s, ':');
*p = ']';
if (not_host)
return NULL;
p++;
} else {
if (!(p = strchr(s, ':')))
return NULL;
hostlen = p - s;
*p = '\0';
not_host = strchr(s, '/') != NULL;
*p = ':';
if (not_host)
return NULL;
}
*host_ptr = parse_hostspec(s, &path, NULL);
if (!*host_ptr)
return NULL;
*host_ptr = new_array(char, hostlen + 1);
strlcpy(*host_ptr, s, hostlen + 1);
if (p[1] == ':') {
if (*path == ':') {
if (port_ptr && !*port_ptr)
*port_ptr = RSYNC_PORT;
return p + 2;
return path + 1;
}
if (port_ptr)
*port_ptr = 0;
return p + 1;
return path;
}

6
packaging/bin/gpg Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh -e
# This script gets git to run gpg with a --passphrase-file option.
PATH=`echo $PATH | sed 's/^[^:]*://'`
gpg --batch --passphrase-file=$GPG_PASSFILE "${@}"

View File

@@ -4,13 +4,19 @@
# is included in the rrsync script.
use strict;
our(%short_no_arg, %short_with_num, %long_opt);
our %short_no_arg;
our %short_with_num;
our %long_opt = (
'no-i-r' => 0,
'fake-super' => 0,
'log-file' => 3,
);
our $last_long_opt;
open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
while (<IN>) {
if (/\Qargstr[x++]\E = '(.)'/) {
if (/\Qargstr[x++]\E = '([^.ie])'/) {
$short_no_arg{$1} = 1;
undef $last_long_opt;
} elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {

View File

@@ -1,9 +1,12 @@
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.0pre10
Version: 3.0.7
%define fullversion %{version}
Release: 1
%define srcdir src
Group: Applications/Internet
Source: http://rsync.samba.org/ftp/rsync/rsync-%{version}.tar.gz
Source0: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
#Source1: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-patches-%{fullversion}.tar.gz
URL: http://rsync.samba.org/
Prefix: %{_prefix}
@@ -22,9 +25,21 @@ destination. Rsync is widely used for backups and mirroring and as an
improved copy command for everyday use.
%prep
%setup -q
# Choose one -- setup source only, or setup source + rsync-patches:
%setup -q -n rsync-%{fullversion}
#%setup -q -b1 -n rsync-%{fullversion}
# If you you used "%setup -q -b1", choose the patches you wish to apply:
#patch -p1 <patches/acls.diff
#patch -p1 <patches/xattrs.diff
#patch -p1 <patches/remote-option.diff
#patch -p1 <patches/db.diff
# Avoid extra perl dependencies for scripts going into doc dir.
chmod -x support/*
%build
#./prepare-source
%configure
make
@@ -34,16 +49,26 @@ rm -rf $RPM_BUILD_ROOT
%makeinstall
mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d
install -m 644 packaging/lsb/rsync.xinetd $RPM_BUILD_ROOT/etc/xinetd.d/rsync
#install -p -m 755 support/rsyncdb $RPM_BUILD_ROOT/usr/bin/rsyncdb
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc COPYING README tech_report.tex
%{_prefix}/bin/rsync
%doc COPYING NEWS OLDNEWS README support/ tech_report.tex
%config(noreplace) /etc/xinetd.d/rsync
%{_prefix}/bin/rsync*
%{_mandir}/man1/rsync.1*
%{_mandir}/man5/rsyncd.conf.5*
%changelog
* Tue Feb 19 2008 Wayne Davison <wayned@samba.org>
Released 3.0.0pre10.
* Thu Dec 31 2009 Wayne Davison <wayned@samba.org>
Released 3.0.7.
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
Added installation of /etc/xinetd.d/rsync file and some commented-out
lines that demonstrate how to use the rsync-patches tar file.

View File

@@ -0,0 +1,13 @@
# default: off
# description: The rsync server is a good addition to an ftp server, as it
# allows crc checksumming etc.
service rsync
{
disable = yes
socket_type = stream
wait = no
user = root
server = /usr/bin/rsync
server_args = --daemon
log_on_failure += USERID
}

View File

@@ -14,8 +14,8 @@ use strict;
use Getopt::Long;
use Date::Format;
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
our $dest = $ENV{HOME} . '/samba-rsync-ftp/nightly';
# Where the local copy of /home/ftp/pub/rsync/dev/nightly should be updated.
our $dest = $ENV{HOME} . '/samba-rsync-ftp/dev/nightly';
our $nightly_symlink = "$dest/rsync-HEAD.tar.gz";
our($make_tar, $upload, $help_opt);
@@ -104,7 +104,7 @@ if ($upload) {
if (defined $ENV{RSYNC_PARTIAL_DIR}) {
$opt = " -f 'R $ENV{RSYNC_PARTIAL_DIR}'";
}
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/dev/nightly";
}
exit;

View File

@@ -10,10 +10,13 @@ use Getopt::Long;
my $patches_dir = 'patches';
my $tmp_dir = "patches.$$";
my $make_gen_cmd = 'make -f prepare-source.mak conf && ./config.status && make gen';
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'branch|b=s' => \( my $master_branch = 'master' ),
'skip-check' => \( my $skip_branch_check ),
'shell|s' => \( my $launch_shell ),
'gen:s' => \( my $incl_generated_files ),
'help|h' => \( my $help_opt ),
);
@@ -27,12 +30,9 @@ 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';
unless ($skip_branch_check) {
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.\n" unless $status =~ /^# On branch master\n/;
my($status, $is_clean, $starting_branch) = &check_git_status;
if (!$skip_branch_check && !$is_clean) {
die "The checkout is not clean:\n", $status;
}
my @extra_files;
@@ -51,38 +51,42 @@ close IN;
if ($incl_generated_files) {
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/master/" and exit 1;
}
my $last_touch = time;
our $last_touch = time;
my(@patches, %local_patch);
my %patches;
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
while (<PIPE>) {
if (m# origin/patch/(.*)#) {
push(@patches, $1);
} elsif (m# patch/(.*)#) {
$local_patch{$1} = 1;
if (m# patch/(.*)#) {
$patches{$1} = 1;
}
}
close PIPE;
my @patches = sort keys %patches;
my(%parent, %description);
foreach my $patch (@patches) {
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
my $branch = "patch/$patch";
my $desc = '';
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
open(PIPE, '-|', 'git', 'diff', '-U1000', "$master_branch...$branch", '--', "PATCH.$patch") or die $!;
while (<PIPE>) {
last if /^@@ /;
}
while (<PIPE>) {
next unless s/^[ +]//;
if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
$parent{$patch} = $1;
my $parent = $parent{$patch} = $1;
if (!$patches{$parent}) {
die "Parent of $patch is not a local branch: $parent\n";
}
}
$desc .= $_;
}
close PIPE;
$description{$patch} = $desc;
}
@@ -90,8 +94,11 @@ if (@ARGV) {
# Limit the list of patches to actually process based on @ARGV.
@patches = ( );
foreach (@ARGV) {
s{^(patches|patch|origin/patch)/} {};
s{^patch(es)?/} {};
s{\.diff$} {};
if (!$patches{$_}) {
die "Local branch not available for patch: $_\n";
}
push(@patches, $_);
}
}
@@ -99,15 +106,15 @@ if (@ARGV) {
my %completed;
foreach my $patch (@patches) {
next if $completed{$patch}++;
update_patch($patch);
last unless update_patch($patch);
}
if ($incl_generated_files) {
system "rm -rf $tmp_dir";
}
sleep 1 if $last_touch == time;
system "git checkout master" and exit 1;
sleep 1 while $last_touch >= time;
system "git checkout $starting_branch" and exit 1;
exit;
@@ -123,29 +130,36 @@ sub update_patch
}
$parent = "patch/$parent";
} else {
$parent = 'master';
$parent = $master_branch;
}
print "======== $patch ========\n";
sleep 1 if $incl_generated_files && $last_touch == time;
if ($local_patch{$patch}) {
system "git checkout patch/$patch" and exit 1;
} else {
system "git checkout --track -b patch/$patch origin/patch/$patch" and exit 1;
sleep 1 while $incl_generated_files && $last_touch >= time;
system "git checkout patch/$patch" and return 0;
my $ok = system("git merge $parent") == 0;
if (!$ok || $launch_shell) {
print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
$ENV{PS1} = "[$parent] patch/$patch: ";
while (1) {
if (system($ENV{SHELL}) != 0) {
print "Abort? [n/y] ";
$_ = <STDIN>;
next unless /^y/i;
return 0;
}
($status, $is_clean) = &check_git_status;
last if $is_clean;
print $status;
}
}
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
print OUT $description{$patch}, "\n";
if (system("git merge $parent") != 0) {
print qq|"git merge $parent" incomplete -- please fix.\n|;
$ENV{PS1} = "[$parent] patch/$patch: ";
system $ENV{SHELL} and exit 1;
}
if ($incl_generated_files) {
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
@@ -163,8 +177,13 @@ sub update_patch
close PIPE;
if ($incl_generated_files) {
$parent =~ s#.*/##;
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
my $parent_dir;
if ($parent eq $master_branch) {
$parent_dir = 'master';
} else {
($parent_dir) = $parent =~ m{([^/]+)$};
}
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent_dir", "$tmp_dir/$patch") or die $!;
while (<PIPE>) {
s#^(diff -up) $tmp_dir/[^/]+/(.*?) $tmp_dir/[^/]+/(.*)#$1 a/$2 b/$3#o;
s#^\Q---\E $tmp_dir/[^/]+/([^\t]+)\t.*#--- a/$1#o;
@@ -175,16 +194,28 @@ sub update_patch
}
close OUT;
1;
}
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]
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
--skip-check Skip the check that ensures starting with a clean master branch.
--skip-check Skip the check that ensures starting with a clean branch.
EOT
}

View File

@@ -7,16 +7,33 @@ use strict;
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
use Cwd;
use Getopt::Long;
use Term::ReadKey;
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $passfile = $ENV{HOME} . '/.rsyncpass';
my $path = $ENV{PATH};
my $cl_today = time2str('* %a %b %d %Y', time);
my $ztoday = time2str('%d %b %Y', time);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'branch|b=s' => \( my $master_branch = 'master' ),
'help|h' => \( my $help_opt ),
);
&usage if $help_opt;
my $now = time;
my $cl_today = time2str('* %a %b %d %Y', $now);
my $year = time2str('%Y', $now);
my $ztoday = time2str('%d %b %Y', $now);
(my $today = $ztoday) =~ s/^0//;
my $curdir = Cwd::cwd;
END {
unlink($passfile);
}
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
@@ -47,25 +64,25 @@ 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.\n" unless $status =~ /^# On branch master\n/;
die "The checkout is not on the $master_branch branch.\n" unless $status =~ /^# On branch $master_branch\n/;
my $lastversion;
my $confversion;
open(IN, '<', 'configure.in') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$lastversion = $1;
$confversion = $1;
last;
}
}
close IN;
if ($lastversion =~ /dev$/) {
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
($lastversion) = /(\d+\.\d+\.\d+)/;
}
die "Unable to find RSYNC_VERSION in configure.in\n" unless defined $confversion;
my $version = $lastversion;
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
my($lastversion) = /(\d+\.\d+\.\d+)/;
my $version = $confversion;
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
print "Please enter the version number of this release: [$version] ";
@@ -75,31 +92,46 @@ if ($_ eq '.') {
} elsif ($_ ne '') {
$version = $_;
}
$version =~ s/[-.]*pre[-.]*/pre/;
die "Invalid version: `$version'\n" unless $version =~ /^[\d.]+(pre\d+)?$/;
if (`git tag -l v$version` ne '') {
print "Tag v$version already exists.\n\nDelete tag or quit? [q/del] ";
$_ = <STDIN>;
exit 1 unless /^del/i;
system "git tag -d v$version";
}
if ($version =~ s/[-.]*pre[-.]*/pre/ && $confversion !~ /dev$/) {
$lastversion = $confversion;
}
print "Enter the previous version to produce a patch against: [$lastversion] ";
chomp($_ = <STDIN>);
$lastversion = $_ if $_ ne '';
$lastversion =~ s/[-.]*pre[-.]*/pre/;
my $release = 1;
my $pre = $version =~ /(pre\d+)/ ? $1 : '';
my $release = $pre ? '0.1' : '1';
print "Please enter the RPM release number of this release: [$release] ";
chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
$release .= ".$pre" if $pre;
my $diffdir;
my $skipping;
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
if ($lastversion =~ /pre/) {
if ($version !~ /pre/) {
if (!$pre) {
die "You should not diff a release version against a pre-release version.\n";
}
$diffdir = "$dest/old-previews";
$srcdir = $srcdiffdir = $lastsrcdir = 'src-previews';
$skipping = ' ** SKIPPING **';
} elsif ($version =~ /pre/) {
$diffdir = $dest;
} elsif ($pre) {
$srcdir = $srcdiffdir = 'src-previews';
$lastsrcdir = 'src';
$skipping = ' ** SKIPPING **';
} else {
$diffdir = "$dest/old-versions";
$srcdir = $lastsrcdir = 'src';
$srcdiffdir = 'src-diffs';
$skipping = '';
}
@@ -108,14 +140,16 @@ print "\n", $break, <<EOT;
\$lastversion is "$lastversion"
\$dest is "$dest"
\$curdir is "$curdir"
\$diffdir is "$diffdir"
\$srcdir is "$srcdir"
\$srcdiffdir is "$srcdiffdir"
\$lastsrcdir is "$lastsrcdir"
\$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 the date in the *.yo files and generate the man pages
- tweak the date in the *.yo files and generate the manpages
- generate configure.sh, config.h.in, and proto.h
- page through the differences
@@ -123,34 +157,54 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in ) );
(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 ) );
if ($version !~ /pre/) {
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
}
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
if ($fn =~ /configure/) {
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m;
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m
or die "Unable to update RSYNC_VERSION in $fn\n";
} elsif ($fn =~ /\.spec/) {
s/^(Version:) .*/$1 $version/m;
s/^(Release:) .*/$1 $release/m;
s/^(Released) .*/$1 $version./m;
s/^\* \w\w\w \w\w\w \d\d \d\d\d\d (.*)/$cl_today $1/m;
while (my($str, $val) = each %specvars) {
s/^\Q$str\E .*/$str $val/m
or die "Unable to update $str in $fn\n";
}
s/^\* \w\w\w \w\w\w \d\d \d\d\d\d (.*)/$cl_today $1/m
or die "Unable to update ChangeLog header in $fn\n";
} elsif ($fn =~ /\.yo/) {
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
} elsif ($fn eq 'NEWS') {
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
or die "Couldn't update NEWS file with release date!\n";
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m
or die "Unable to update date in manpage() header in $fn\n";
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 0/
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;
} elsif ($fn eq 'OLDNEWS') {
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m
or die "Couldn't update OLDNEWS file with release date!\n";
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$finalversion\E)/\t$ztoday$1/m
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) {
die "Copyright comments need to be updated to $year in all files!\n";
}
# Adjust the year in the --version output.
s/(rprintf\(f, "Copyright \(C\) 1996-)(\d+)/$1$year/
or die "Unable to find Copyright string in --version output of $fn\n";
next if $2 eq $year;
} else {
die "Unrecognized file in \@tweak_files: $fn\n";
}
@@ -165,83 +219,89 @@ system "git diff --color | less -p '^diff .*'";
my $srctar_name = "rsync-$version.tar.gz";
my $pattar_name = "rsync-patches-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $srctar_file = "$dest/$srctar_name";
my $pattar_file = "$dest/$pattar_name";
my $diff_file = "$dest/$diff_name";
my $lasttar_file = "$dest/rsync-$lastversion.tar.gz";
my $srctar_file = "$dest/$srcdir/$srctar_name";
my $pattar_file = "$dest/$srcdir/$pattar_name";
my $diff_file = "$dest/$srcdiffdir/$diff_name";
my $news_file = "$dest/$srcdir/rsync-$version-NEWS";
my $lasttar_file = "$dest/$lastsrcdir/rsync-$lastversion.tar.gz";
print $break, <<EOT;
About to:
- commit all changes
- tag this release as v$version
- move the old tar/diff files into the appropriate old-* dirs
- hard-link the moved tar/diff files on samba.org
- create release tar, "$srctar_name"
- create patches tar, "$pattar_name"
- commit all version changes
- merge the $master_branch branch into the patch/* branches
- update the files in the "patches" dir and OPTIONALLY
(if you type 'y') to launch a shell for each patch
EOT
print "<Press Enter OR 'y' to continue> ";
my $ans = <STDIN>;
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
print "Updating files in \"patches\" dir ...\n";
system "packaging/patch-update --branch=$master_branch";
if ($ans =~ /^y/i) {
print "\nVisiting all \"patch/*\" branches ...\n";
system "packaging/patch-update --branch=$master_branch --shell";
}
print $break, <<EOT;
About to:
- create signed tag for this release: v$version
- create release diffs, "$diff_name"
- update patch branches and generate patch/* files
- update README, *NEWS, TODO, and ChangeLog
- update rsync*.html man pages
- create release tar, "$srctar_name"
- generate rsync-$version/patches/* files
- create patches tar, "$pattar_name"
- update top-level README, *NEWS, TODO, and ChangeLog
- update top-level rsync*.html manpages
- gpg-sign the release files
- update hard-linked top-level release files$skipping
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
system "git tag -s -m 'Version $version.' v$version" and exit 1;
my $passphrase;
while (1) {
ReadMode('noecho');
print "\nEnter your GPG pass-phrase: ";
chomp($passphrase = <STDIN>);
ReadMode(0);
print "\n";
# Extract some files from the old tar before we do the shuffle.
# Briefly create a temp file with the passphrase for git's tagging use.
my $oldmask = umask 077;
unlink($passfile);
open(OUT, '>', $passfile) or die $!;
print OUT $passphrase, "\n";
close OUT;
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;
}
# Extract the generated files from the old tar.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
chdir($dest) or die $!;
print "Shuffling old files ...\n";
# We need to run this regardless of $lastversion's "pre"ness.
my @moved_files;
foreach my $fn (glob('rsync*pre*.tar.gz*'), glob('rsync*pre*-NEWS')) {
link($fn, "old-previews/$fn") or die $!;
push(@moved_files, $fn);
}
if ($version !~ /pre/) {
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
next if $fn =~ /^rsync.*pre/;
link($fn, "old-versions/$fn") or die $!;
push(@moved_files, $fn);
}
foreach my $fn (glob('rsync*pre*.diffs.gz*')) {
unlink($fn);
}
foreach my $fn (glob('rsync*.diffs.gz*')) {
link($fn, "old-patches/$fn") or die $!;
push(@moved_files, $fn);
}
}
# Optimize our future upload (in the absence of --detect-renamed) by
# using rsync to hard-link the above files on samba.org.
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
foreach (@moved_files) {
unlink($_);
}
chdir($curdir) or die $!;
}
print "Creating $diff_file ...\n";
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
system "(git diff v$lastversion v$version; diff -up a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "rm -rf a";
rename('b', "rsync-$version");
@@ -250,24 +310,56 @@ system "git archive --format=tar --prefix=rsync-$version/ v$version | tar xf -";
system "support/git-set-file-times --prefix=rsync-$version/";
system "fakeroot tar czf $srctar_file rsync-$version; rm -rf rsync-$version";
print "Updating files in \"rsync-$version/patches\" dir ...\n";
mkdir("rsync-$version", 0755);
mkdir("rsync-$version/patches", 0755);
system "support/patch-update --skip-check --gen=rsync-$version/patches";
system "packaging/patch-update --skip-check --branch=$master_branch --gen=rsync-$version/patches";
print "Creating $pattar_file ...\n";
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
print "Updating the other files in $dest ...\n";
system "rsync -a README NEWS OLDNEWS TODO $dest";
unlink("$dest/rsync-$version-NEWS");
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
unlink($news_file);
link("$dest/NEWS", $news_file);
system "git log --name-status | gzip -9 >$dest/ChangeLog.gz";
system "yodl2html -o $dest/rsync.html rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsyncd.conf.yo";
chdir($dest) or die $!;
system "gpg -ba $srctar_name; gpg -ba $pattar_name; gpg -ba $diff_name";
print $break, <<EOT;
foreach my $fn ($srctar_file, $pattar_file, $diff_file) {
unlink("$fn.asc");
open(GPG, '|-', "gpg --batch --passphrase-fd=0 -ba $fn") or die $!;
print GPG $passphrase, "\n";
close GPG;
}
All done. Remember to announce the release on *BOTH*
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
if (!$pre) {
system "rm $dest/rsync-*.gz $dest/rsync-*.asc $dest/rsync-*-NEWS $dest/src-previews/rsync-*diffs.gz*";
foreach my $fn ($srctar_file, "$srctar_file.asc",
$pattar_file, "$pattar_file.asc",
$diff_file, "$diff_file.asc", $news_file) {
(my $top_fn = $fn) =~ s#/src(-\w+)?/#/#;
link($fn, $top_fn);
}
}
print $break, <<'EOT';
Local changes are done. When you're satisfied, push the git repository
and rsync the release files. Remember to announce the release on *BOTH*
rsync-announce@lists.samba.org and rsync@lists.samba.org (and the web)!
EOT
exit;
sub usage
{
die <<EOT;
Usage: release-rsync [OPTIONS]
-b, --branch=BRANCH The branch to release (default: master)
-h, --help Display this help message
EOT
}

2
pipe.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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

View File

@@ -809,16 +809,20 @@ int poptGetNextOpt(poptContext con)
*oe++ = '\0';
/* XXX longArg is mapped back to persistent storage. */
longArg = origOptString + (oe - localOptString);
}
} else
oe = NULL;
opt = findOption(con->options, optString, '\0', &cb, &cbData,
singleDash);
if (!opt && !singleDash)
return POPT_ERROR_BADOPT;
if (!opt && oe)
oe[-1] = '='; /* restore overwritten '=' */
}
if (!opt) {
con->os->nextCharArg = origOptString + 1;
longArg = NULL;
} else {
if (con->os == con->optionStack &&
opt->argInfo & POPT_ARGFLAG_STRIP)
@@ -856,7 +860,7 @@ int poptGetNextOpt(poptContext con)
origOptString++;
if (*origOptString != '\0')
con->os->nextCharArg = origOptString;
con->os->nextCharArg = origOptString + (*origOptString == '=');
}
/*@=branchstate@*/

View File

@@ -121,7 +121,7 @@ getArgDescrip(const struct poptOption * opt,
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_NONE: return POPT_("NONE");
/*case POPT_ARG_NONE: return POPT_("NONE");*/ /* impossible */
#ifdef DYING
case POPT_ARG_VAL: return POPT_("VAL");
#else
@@ -767,6 +767,9 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
int len = 0;
if (s == NULL)
return 0;
/*@-boundswrite@*/
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg); opt++) {

View File

@@ -163,8 +163,10 @@ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int fl
p++;
linelen = strlen(p);
if (linelen >= maxlinelen-1)
if (linelen >= maxlinelen-1) {
free(argstr);
return POPT_ERROR_OVERFLOW; /* XXX line too long */
}
if (*p == '\0' || *p == '\n') continue; /* line is empty */
if (*p == '#') continue; /* comment line */

View File

@@ -85,7 +85,7 @@ char *alloca(size_t size);
# endif
# endif
# endif
#elif defined(__GNUC__) && defined(__STRICT_ANSI__)
#elif !defined(alloca)
#define alloca __builtin_alloca
#endif

View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -40,6 +40,8 @@ struct progress_history {
OFF_T ofs;
};
int progress_is_active = 0;
static struct progress_history ph_start;
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
static int newest_hpos, oldest_hpos;
@@ -111,8 +113,11 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
stats.num_files);
} else
strlcpy(eol, "\r", sizeof eol);
progress_is_active = 0;
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %s%s",
human_num(ofs), pct, rate, units, rembuf, eol);
if (!is_last)
progress_is_active = 1;
}
void set_current_file_index(struct file_struct *file, int ndx)

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -55,10 +55,11 @@ extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct server_filter_list;
extern struct filter_list_struct daemon_filter_list;
static struct bitbag *delayed_bits = NULL;
static int phase = 0, redoing = 0;
static flist_ndx_list batch_redo_list;
/* We're either updating the basis file or an identical copy: */
static int updating_basis_or_equiv;
@@ -284,8 +285,11 @@ 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);
if (inplace && fd != -1
&& ftruncate(fd, offset) < 0) {
rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
full_fname(fname));
}
#endif
if (do_progress)
@@ -348,25 +352,68 @@ static void handle_delayed_updates(char *local_name)
}
}
static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
static void no_batched_update(int ndx, BOOL is_redo)
{
while (next_gen_ndx < desired_ndx) {
if (next_gen_ndx >= 0) {
struct file_struct *file = cur_flist->files[next_gen_ndx];
rprintf(FERROR_XFER,
"(No batched update for%s \"%s\")\n",
file->flags & FLAG_FILE_SENT ? " resend of" : "",
f_name(file, NULL));
}
next_gen_ndx = read_int(fd);
if (next_gen_ndx == -1) {
if (inc_recurse)
next_gen_ndx = first_flist->prev->used + first_flist->prev->ndx_start;
else
next_gen_ndx = cur_flist->used;
struct file_list *flist = flist_for_ndx(ndx, "no_batched_update");
struct file_struct *file = flist->files[ndx - flist->ndx_start];
rprintf(FERROR_XFER, "(No batched update for%s \"%s\")\n",
is_redo ? " resend of" : "", f_name(file, NULL));
if (inc_recurse && !dry_run)
send_msg_int(MSG_NO_SEND, ndx);
}
static int we_want_redo(int desired_ndx)
{
static int redo_ndx = -1;
while (redo_ndx < desired_ndx) {
if (redo_ndx >= 0)
no_batched_update(redo_ndx, True);
if ((redo_ndx = flist_ndx_pop(&batch_redo_list)) < 0)
return 0;
}
if (redo_ndx == desired_ndx) {
redo_ndx = -1;
return 1;
}
return 0;
}
static int gen_wants_ndx(int desired_ndx)
{
static int next_ndx = -1;
static int done_cnt = 0;
static BOOL got_eof = False;
int flist_num = first_flist->flist_num;
if (got_eof)
return 0;
while (next_ndx < desired_ndx) {
if (inc_recurse && flist_num <= done_cnt)
return 0;
if (next_ndx >= 0)
no_batched_update(next_ndx, False);
if ((next_ndx = read_int(batch_gen_fd)) < 0) {
if (inc_recurse) {
done_cnt++;
continue;
}
got_eof = True;
return 0;
}
}
return next_gen_ndx;
if (next_ndx == desired_ndx) {
next_ndx = -1;
return 1;
}
return 0;
}
/**
@@ -375,7 +422,6 @@ static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
* Receiver process runs on the same host as the generator process. */
int recv_files(int f_in, char *local_name)
{
int next_gen_ndx = -1;
int fd1,fd2;
STRUCT_STAT st;
int iflags, xlen;
@@ -410,17 +456,13 @@ int recv_files(int f_in, char *local_name)
xname, &xlen);
if (ndx == NDX_DONE) {
if (inc_recurse && first_flist) {
if (read_batch)
gen_wants_ndx(first_flist->used + first_flist->ndx_start);
flist_free(first_flist);
if (first_flist)
continue;
}
if (read_batch && cur_flist) {
int high = inc_recurse
? first_flist->prev->used + first_flist->prev->ndx_start
: cur_flist->used;
get_next_gen_ndx(batch_gen_fd, next_gen_ndx, high);
next_gen_ndx = -1;
}
} else if (read_batch && first_flist)
gen_wants_ndx(first_flist->used);
if (++phase > max_phase)
break;
if (verbose > 2)
@@ -441,14 +483,14 @@ int recv_files(int f_in, char *local_name)
rprintf(FINFO, "recv_files(%s)\n", fname);
#ifdef SUPPORT_XATTRS
if (iflags & ITEM_REPORT_XATTR && !dry_run)
if (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 && !dry_run)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
set_file_attrs(fname, file, NULL, fname, 0);
#endif
continue;
@@ -489,12 +531,27 @@ int recv_files(int f_in, char *local_name)
cleanup_got_literal = 0;
if (server_filter_list.head
&& check_filter(&server_filter_list, fname, 0) < 0) {
if (daemon_filter_list.head
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) {
rprintf(FERROR, "attempt to hack rsync failed.\n");
exit_cleanup(RERR_PROTOCOL);
}
if (read_batch) {
int wanted = redoing
? we_want_redo(ndx)
: gen_wants_ndx(ndx);
if (!wanted) {
rprintf(FINFO,
"(Skipping batched update for%s \"%s\")\n",
redoing ? " resend of" : "",
fname);
discard_receive_data(f_in, F_LENGTH(file));
file->flags |= FLAG_FILE_SENT;
continue;
}
}
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
if (read_batch)
@@ -508,20 +565,6 @@ int recv_files(int f_in, char *local_name)
continue;
}
if (read_batch) {
next_gen_ndx = get_next_gen_ndx(batch_gen_fd, next_gen_ndx, ndx);
if (ndx < next_gen_ndx) {
rprintf(FINFO,
"(Skipping batched update for \"%s\")\n",
fname);
discard_receive_data(f_in, F_LENGTH(file));
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
next_gen_ndx = -1;
}
partialptr = partial_dir ? partial_dir_fname(fname) : fname;
if (protocol_version >= 29) {
@@ -555,8 +598,8 @@ int recv_files(int f_in, char *local_name)
fnamecmp = fnamecmpbuf;
break;
}
if (!fnamecmp || (server_filter_list.head
&& check_filter(&server_filter_list, fname, 0) < 0)) {
if (!fnamecmp || (daemon_filter_list.head
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0)) {
fnamecmp = fname;
fnamecmp_type = FNAMECMP_FNAME;
}
@@ -698,23 +741,33 @@ int recv_files(int f_in, char *local_name)
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
} else if (keep_partial && partialptr) {
if (!handle_partial_dir(partialptr, PDIR_CREATE)) {
rprintf(FERROR,
"Unable to create partial-dir for %s -- discarding %s.\n",
local_name ? local_name : f_name(file, NULL),
recv_ok ? "completed file" : "partial file");
do_unlink(fnametmp);
recv_ok = -1;
} else if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
recv_ok = -1;
else if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
recv_ok = 2;
}
} else {
partialptr = NULL;
} else
partialptr = NULL;
} else
do_unlink(fnametmp);
}
cleanup_disable();
if (read_batch)
file->flags |= FLAG_FILE_SENT;
switch (recv_ok) {
case 2:
break;
case 1:
if (remove_source_files || inc_recurse
|| (preserve_hard_links && F_IS_HLINKED(file)))
@@ -744,6 +797,8 @@ int recv_files(int f_in, char *local_name)
keptstr, redostr);
}
if (!redoing) {
if (read_batch)
flist_ndx_push(&batch_redo_list, ndx);
send_msg_int(MSG_REDO, ndx);
file->flags |= FLAG_FILE_SENT;
} else if (inc_recurse)

View File

@@ -1,7 +1,7 @@
/*
* A pre-compilation helper program to aid in the creation of rounding.h.
*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2009 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

121
rsync.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -37,11 +37,11 @@ extern int preserve_times;
extern int am_root;
extern int am_server;
extern int am_sender;
extern int am_receiver;
extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int protocol_version;
extern int receiver_symlink_times;
extern int uid_ndx;
extern int gid_ndx;
extern int inc_recurse;
@@ -81,7 +81,6 @@ void setup_iconv(void)
# endif
if (!am_server && !allow_8bit_chars) {
/* It's OK if this fails... */
ic_chck = iconv_open(defset, defset);
@@ -206,6 +205,45 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
}
#endif
void send_protected_args(int fd, char *args[])
{
int i;
#ifdef ICONV_OPTION
int convert = ic_send != (iconv_t)-1;
xbuf outbuf, inbuf;
if (convert)
alloc_xbuf(&outbuf, 1024);
#endif
for (i = 0; args[i]; i++) {} /* find first NULL */
args[i] = "rsync"; /* set a new arg0 */
if (verbose > 1)
print_child_argv("protected args:", args + i + 1);
do {
if (!args[i][0])
write_buf(fd, ".", 2);
#ifdef ICONV_OPTION
else if (convert) {
INIT_XBUF_STRLEN(inbuf, args[i]);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
outbuf.buf[outbuf.len] = '\0';
write_buf(fd, outbuf.buf, outbuf.len + 1);
outbuf.len = 0;
}
#endif
else
write_buf(fd, args[i], strlen(args[i]) + 1);
} while (args[++i]);
write_byte(fd, 0);
#ifdef ICONV_OPTION
if (convert)
free(outbuf.buf);
#endif
}
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
char *buf, int *len_ptr)
{
@@ -222,8 +260,17 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
break;
if (ndx == NDX_DONE)
return ndx;
if (!inc_recurse || am_sender)
goto invalid_ndx;
if (!inc_recurse || am_sender) {
int last;
if (first_flist)
last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
else
last = -1;
rprintf(FERROR,
"Invalid file index: %d (%d - %d) [%s]\n",
ndx, NDX_DONE, last, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
if (ndx == NDX_FLIST_EOF) {
flist_eof = 1;
send_msg(MSG_FLIST_EOF, "", 0, 0);
@@ -233,9 +280,10 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
if (ndx < 0 || ndx >= dir_flist->used) {
ndx = NDX_FLIST_OFFSET - ndx;
rprintf(FERROR,
"[%s] Invalid dir index: %d (%d - %d)\n",
who_am_i(), ndx, NDX_FLIST_OFFSET,
NDX_FLIST_OFFSET - dir_flist->used + 1);
"Invalid dir index: %d (%d - %d) [%s]\n",
ndx, NDX_FLIST_OFFSET,
NDX_FLIST_OFFSET - dir_flist->used + 1,
who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
@@ -256,25 +304,14 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
iflags = protocol_version >= 29 ? read_shortint(f_in)
: ITEM_TRANSFER | ITEM_MISSING_DATA;
/* Honor the old-style keep-alive indicator. */
if (protocol_version < 30
&& ndx == cur_flist->used && iflags == ITEM_IS_NEW) {
/* Support the protocol-29 keep-alive style. */
if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) {
if (am_sender)
maybe_send_keepalive();
goto read_loop;
}
if (!(flist = flist_for_ndx(ndx))) {
int start, used;
invalid_ndx:
start = first_flist ? first_flist->ndx_start : 0;
used = first_flist ? first_flist->used : 0;
rprintf(FERROR,
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
ndx, start - 1, start + used -1, iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
cur_flist = flist;
cur_flist = flist_for_ndx(ndx, "read_ndx_and_attrs");
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
@@ -400,7 +437,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
else if (receiver_symlink_times)
else
file->flags |= FLAG_TIME_FAILED;
}
@@ -526,8 +563,12 @@ int finish_transfer(const char *fname, const char *fnametmp,
goto do_set_file_attrs;
}
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return 1;
if (make_backups > 0 && overwriting_basis) {
if (!make_backup(fname))
return 1;
if (fnamecmp == fname)
fnamecmp = get_backup_name(fname);
}
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -571,28 +612,48 @@ int finish_transfer(const char *fname, const char *fnametmp,
return 1;
}
struct file_list *flist_for_ndx(int ndx)
struct file_list *flist_for_ndx(int ndx, const char *fatal_error_loc)
{
struct file_list *flist = cur_flist;
if (!flist && !(flist = first_flist))
return NULL;
goto not_found;
while (ndx < flist->ndx_start-1) {
if (flist == first_flist)
return NULL;
goto not_found;
flist = flist->prev;
}
while (ndx >= flist->ndx_start + flist->used) {
if (!(flist = flist->next))
return NULL;
goto not_found;
}
return flist;
not_found:
if (fatal_error_loc) {
int first, last;
if (first_flist) {
first = first_flist->ndx_start - 1;
last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
} else {
first = 0;
last = -1;
}
rprintf(FERROR,
"File-list index %d not in %d - %d (%s) [%s]\n",
ndx, first, last, fatal_error_loc, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
return NULL;
}
const char *who_am_i(void)
{
if (am_starting_up)
return am_server ? "server" : "client";
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
return am_sender ? "sender"
: am_generator ? "generator"
: am_receiver ? "receiver"
: "Receiver"; /* pre-forked receiver */
}

59
rsync.h
View File

@@ -2,7 +2,7 @@
* Copyright (C) 1996, 2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 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
@@ -32,7 +32,7 @@
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
#define URL_PREFIX "rsync://"
#define SYMLINK_PREFIX "/rsyncd-munged/"
#define SYMLINK_PREFIX "/rsyncd-munged/" /* This MUST have a trailing slash! */
#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
#define BACKUP_SUFFIX "~"
@@ -60,6 +60,7 @@
#define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */
#define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
#define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - now (HLINKED files only) */
#define XMIT_IO_ERROR_ENDLIST (1<<12) /* protocols 31*- now (w/XMIT_EXTENDED_FLAGS) (also protocol 30 w/'f' compat flag) */
/* These flags are used in the live flist data. */
@@ -67,7 +68,8 @@
#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 */
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator */
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator (dirs only) */
#define FLAG_SKIP_HLINK (1<<3) /* receiver/generator (w/FLAG_HLINKED) */
#define FLAG_DUPLICATE (1<<4) /* sender */
#define FLAG_MISSING_DIR (1<<4) /* generator */
#define FLAG_HLINKED (1<<5) /* receiver/generator (checked on all types) */
@@ -94,7 +96,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! */
#define SUBPROTOCOL_VERSION 17
#define SUBPROTOCOL_VERSION 0
/* We refuse to interoperate with versions that are not in this range.
* Note that we assume we'll work with later versions: the onus is on
@@ -128,6 +130,9 @@
#define IO_BUFFER_SIZE (4092)
#define MAX_BLOCK_SIZE ((int32)1 << 17)
/* For compatibility with older rsyncs */
#define OLD_MAX_BLOCK_SIZE ((int32)1 << 29)
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
#define IOERR_VANISHED (1<<1)
#define IOERR_DEL_LIMIT (1<<2)
@@ -144,8 +149,9 @@
#define XFLG_FATAL_ERRORS (1<<0)
#define XFLG_OLD_PREFIXES (1<<1)
#define XFLG_ANCHORED2ABS (1<<2)
#define XFLG_ABS_IF_SLASH (1<<3)
#define XFLG_ANCHORED2ABS (1<<2) /* leading slash indicates absolute */
#define XFLG_ABS_IF_SLASH (1<<3) /* leading or interior slash is absolute */
#define XFLG_DIR2WILD3 (1<<4) /* dir/ match gets trailing *** added */
#define ATTRS_REPORT (1<<0)
#define ATTRS_SKIP_MTIME (1<<1)
@@ -166,8 +172,9 @@
/* For use by the itemize_changes code */
#define ITEM_REPORT_ATIME (1<<0)
#define ITEM_REPORT_CHECKSUM (1<<1)
#define ITEM_REPORT_SIZE (1<<2)
#define ITEM_REPORT_CHANGE (1<<1)
#define ITEM_REPORT_SIZE (1<<2) /* regular files only */
#define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
#define ITEM_REPORT_TIME (1<<3)
#define ITEM_REPORT_PERMS (1<<4)
#define ITEM_REPORT_OWNER (1<<5)
@@ -187,11 +194,17 @@
#define SIGNIFICANT_ITEM_FLAGS (~(\
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
#define CFN_KEEP_LEADING_DOT_DIR (1<<0)
#define CFN_KEEP_DOT_DIRS (1<<0)
#define CFN_KEEP_TRAILING_SLASH (1<<1)
#define CFN_DROP_TRAILING_DOT_DIR (1<<2)
#define CFN_COLLAPSE_DOT_DOT_DIRS (1<<3)
#define SP_DEFAULT 0
#define SP_KEEP_DOT_DIRS (1<<0)
#define CD_NORMAL 0
#define CD_SKIP_CHDIR 1
/* Log-message categories. FLOG only goes to the log file, not the client;
* FCLIENT is the opposite. */
enum logcode {
@@ -199,6 +212,7 @@ enum logcode {
FERROR_XFER=1, FINFO=2, /* sent over socket for any protocol */
FERROR=3, FWARNING=4, /* sent over socket for protocols >= 30 */
FERROR_SOCKET=5, FLOG=6, /* only sent via receiver -> generator pipe */
FERROR_UTF8=8, /* only sent via receiver -> generator pipe */
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
};
@@ -209,6 +223,7 @@ enum msgcode {
MSG_ERROR_XFER=FERROR_XFER, MSG_INFO=FINFO, /* remote logging */
MSG_ERROR=FERROR, MSG_WARNING=FWARNING, /* protocol-30 remote logging */
MSG_ERROR_SOCKET=FERROR_SOCKET, /* sibling logging */
MSG_ERROR_UTF8=FERROR_UTF8, /* sibling logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
MSG_FLIST=20, /* extra file list over sibling socket */
@@ -331,10 +346,6 @@ enum msgcode {
#endif
#endif
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
/* these are needed for the uid/gid mapping code */
#include <pwd.h>
#include <grp.h>
@@ -386,7 +397,7 @@ enum msgcode {
# include <limits.h>
#endif
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#if defined USE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#ifndef ICONV_CONST
#define ICONV_CONST
@@ -409,13 +420,13 @@ enum msgcode {
#include "lib/pool_alloc.h"
#ifndef HAVE_ID_T
typedef int id_t;
typedef unsigned int id_t;
#endif
#ifndef HAVE_PID_T
typedef int pid_t;
#endif
#ifndef HAVE_MODE_T
typedef int mode_t;
typedef unsigned int mode_t;
#endif
#ifndef HAVE_OFF_T
typedef long off_t;
@@ -492,10 +503,12 @@ typedef unsigned int size_t;
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
#define OFF_T off_t
#define STRUCT_STAT struct stat
#define SIZEOF_CAPITAL_OFF_T SIZEOF_OFF_T
#else
#define OFF_T off64_t
#define STRUCT_STAT struct stat64
#define USE_STAT64_FUNCS 1
#define SIZEOF_CAPITAL_OFF_T SIZEOF_OFF64_T
#endif
/* CAVEAT: on some systems, int64 will really be a 32-bit integer IFF
@@ -820,6 +833,15 @@ struct stats {
struct chmod_mode_struct;
struct flist_ndx_item {
struct flist_ndx_item *next;
int ndx;
};
typedef struct {
struct flist_ndx_item *head, *tail;
} flist_ndx_list;
#define EMPTY_ITEM_LIST {NULL, 0, 0}
typedef struct {
@@ -1105,6 +1127,11 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#define MY_GID() getgid()
#endif
#ifdef FORCE_FD_ZERO_MEMSET
#undef FD_ZERO
#define FD_ZERO(fdsetp) memset(fdsetp, 0, sizeof (fd_set))
#endif
extern int verbose;
#ifndef HAVE_INET_NTOP

340
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(19 Feb 2008)()()
manpage(rsync)(1)(31 Dec 2009)()()
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
manpagesynopsis()
@@ -70,6 +70,10 @@ destination, the files are listed in an output format similar to "ls -l".
As expected, if neither the source or destination path specify a remote
host, the copy occurs locally (see also the bf(--list-only) option).
Rsync refers to the local side as the "client" and the remote side as the
"server". Don't confuse "server" with an rsync daemon -- a daemon is always a
server, but a server can be either a daemon or a remote-shell spawned process.
manpagesection(SETUP)
See the file README for installation instructions.
@@ -464,9 +468,9 @@ dit(bf(--version)) print the rsync version number and exit.
dit(bf(-v, --verbose)) This option increases the amount of information you
are given during the transfer. By default, rsync works silently. A
single bf(-v) will give you information about what files are being
transferred and a brief summary at the end. Two bf(-v) flags will give you
transferred and a brief summary at the end. Two bf(-v) options will give you
information on what files are being skipped and slightly more
information at the end. More than two bf(-v) flags should only be used if
information at the end. More than two bf(-v) options should only be used if
you are debugging rsync.
Note that the names of the transferred files that are output are done using
@@ -480,7 +484,7 @@ any way. See the bf(--out-format) option for more details.
dit(bf(-q, --quiet)) This option decreases the amount of information you
are given during the transfer, notably suppressing information messages
from the remote server. This flag is useful when invoking rsync from
from the remote server. This option is useful when invoking rsync from
cron.
dit(bf(--no-motd)) This option affects the information that is output
@@ -514,7 +518,7 @@ dit(bf(-c, --checksum)) This changes the way rsync checks if the files have
been changed and are in need of a transfer. Without this option, rsync
uses a "quick check" that (by default) checks if each file's size and time
of last modification match between the sender and receiver. This option
changes this to compare a 128-bit MD4 checksum for each file that has a
changes this to compare a 128-bit checksum for each file that has a
matching size. Generating the checksums means that both sides will expend
a lot of disk I/O reading all the data in the files in the transfer (and
this is prior to any reading that will be done to transfer changed files),
@@ -532,6 +536,9 @@ checksum that is generated as the file is transferred, but that
automatic after-the-transfer verification has nothing to do with this
option's before-the-transfer "Does this file need to be updated?" check.
For protocol 30 and beyond (first supported in 3.0.0), the checksum used is
MD5. For older protocols, the checksum used is MD4.
dit(bf(-a, --archive)) This is equivalent to bf(-rlptgoD). It is a quick
way of saying you want recursion and want to preserve almost
everything (with -H being a notable omission).
@@ -619,7 +626,7 @@ quote(tt( rsync -avR /foo/./bar/baz.c remote:/tmp/))
That would create /tmp/bar/baz.c on the remote machine. (Note that the
dot must be followed by a slash, so "/foo/." would not be abbreviated.)
(2) For older rsync versions, you would need to use a chdir to limit the
For older rsync versions, you would need to use a chdir to limit the
source path. For example, when pushing files:
quote(tt( (cd /foo; rsync -avR bar/baz.c remote:/tmp/) ))
@@ -667,7 +674,7 @@ Note that if you don't specify bf(--backup-dir), (1) the
bf(--omit-dir-times) option will be implied, and (2) if bf(--delete) is
also in effect (without bf(--delete-excluded)), rsync will add a "protect"
filter-rule for the backup suffix to the end of all your existing excludes
(e.g. bf(-f "Pp *~")). This will prevent previously backed-up files from being
(e.g. bf(-f "P *~")). This will prevent previously backed-up files from being
deleted. Note that if you are supplying your own filter rules, you may
need to manually insert your own exclude/protect rule somewhere higher up
in the list so that it has a high enough priority to be effective (e.g., if
@@ -697,15 +704,31 @@ date is on the objects. In other words, if the source has a directory
where the destination has a file, the transfer would occur regardless of
the timestamps.
dit(bf(--inplace)) This causes rsync not to create a new copy of the file
and then move it into place. Instead rsync will overwrite the existing
file, meaning that the rsync algorithm can't accomplish the full amount of
network reduction it might be able to otherwise (since it does not yet try
to sort data matches). One exception to this is if you combine the option
with bf(--backup), since rsync is smart enough to use the backup file as the
basis file for the transfer.
This option is a transfer rule, not an exclude, so it doesn't affect the
data that goes into the file-lists, and thus it doesn't affect deletions.
It just limits the files that the receiver requests to be transferred.
This option is useful for transfer of large files with block-based changes
dit(bf(--inplace)) This option changes how rsync transfers a file when
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).
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.
@@ -714,18 +737,15 @@ the file), but conflicts with bf(--partial-dir) and bf(--delay-updates).
Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest)
and bf(--link-dest).
WARNING: The file's data will be in an inconsistent state during the
transfer (and possibly afterward if the transfer gets interrupted), so you
should not use this option to update files that are in use. Also note that
rsync will be unable to update a file in-place that is not writable by the
receiving user.
dit(bf(--append)) This causes rsync to update a file by appending data onto
the end of the file, which presumes that the data that already exists on
the receiving side is identical with the start of the file on the sending
side. Any files that are the same size or shorter on the receiving size
are skipped. Files that do not yet exist on the receiving side are also
sent, since they are considered to have 0 length. Implies bf(--inplace),
side. If a file needs to be transferred and its size on the receiver is
the same or longer than the size on the sender, the file is skipped. This
does not interfere with the updating of a file's non-content attributes
(e.g. permissions, ownership, etc.) when the file does not need to be
transferred, nor does it affect the updating of any non-regular files.
Implies bf(--inplace),
but does not conflict with bf(--sparse) (since it is always extending a
file's length).
@@ -748,11 +768,15 @@ bf(--recursive) option, rsync will skip all directories it encounters (and
output a message to that effect for each one). If you specify both
bf(--dirs) and bf(--recursive), bf(--recursive) takes precedence.
This option is implied by the bf(--list-only) option (including an implied
The bf(--dirs) option is implied by the bf(--files-from) option
or the bf(--list-only) option (including an implied
bf(--list-only) usage) if bf(--recursive) wasn't specified (so that
directories are seen in the listing). Specify bf(--no-dirs) (or bf(--no-d))
if you want to override this. This option is also implied by
bf(--files-from).
if you want to turn this off.
There is also a backward-compatibility helper option, bf(--old-dirs) (or
bf(--old-d)) that tells rsync to use a hack of "-r --exclude='/*/*'" to get
an older rsync to list a single directory without recursing.
dit(bf(-l, --links)) When symlinks are encountered, recreate the
symlink on the destination.
@@ -924,7 +948,7 @@ a normal user, see the bf(--fake-super) option.
dit(bf(--chmod)) This option tells rsync to apply one or more
comma-separated "chmod" strings to the permission of the files in the
transfer. The resulting value is treated as though it was the permissions
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.
@@ -979,7 +1003,7 @@ with the files and update them on the remote system. Note that if this
option is not used, the optimization that excludes files that have not been
modified cannot be effective; in other words, a missing bf(-t) or bf(-a) will
cause the next transfer to behave as if it used bf(-I), causing all files to be
updated (though the rsync algorithm will make the update fairly efficient
updated (though rsync's delta-transfer algorithm will make the update fairly efficient
if the files haven't actually changed, you're much better off using bf(-t)).
dit(bf(-O, --omit-dir-times)) This tells rsync to omit directories when
@@ -994,7 +1018,7 @@ all groups (not just the current user's groups) via the bf(--groups)
option, and copying devices via the bf(--devices) option. This is useful
for systems that allow such activities without being the super-user, and
also for ensuring that you will get errors if the receiving side isn't
being running as the super-user. To turn off super-user activities, the
being run as the super-user. To turn off super-user activities, the
super-user can use bf(--no-super).
dit(bf(--fake-super)) When this option is enabled, rsync simulates
@@ -1033,8 +1057,8 @@ 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 doesn't seem to handle seeks over null regions
correctly and ends up corrupting the files.
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
@@ -1044,19 +1068,20 @@ to do before one actually runs it.
The output of bf(--itemize-changes) is supposed to be exactly the same on a
dry run and a subsequent real run (barring intentional trickery and system
call failures); if it isn't, that's a bug. Other output is the same to the
extent practical, but may differ in some areas. Notably, a dry run does not
call failures); if it isn't, that's a bug. Other output should be mostly
unchanged, but may differ in some areas. Notably, a dry run does not
send the actual data for file transfers, so bf(--progress) has no effect,
the "bytes sent", "bytes received", "literal data", and "matched data"
statistics are too small, and the "speedup" value is equivalent to a run
where no file transfers are needed.
where no file transfers were needed.
dit(bf(-W, --whole-file)) With this option the delta-transfer algorithm
dit(bf(-W, --whole-file)) With this option rsync's delta-transfer algorithm
is not used and the whole file is sent as-is instead. The transfer may be
faster if this option is used when the bandwidth between the source and
destination machines is higher than the bandwidth to disk (especially when the
"disk" is actually a networked filesystem). This is the default when both
the source and destination are specified as local paths.
the source and destination are specified as local paths, but only if no
batch-writing option is in effect.
dit(bf(-x, --one-file-system)) This tells rsync to avoid crossing a
filesystem boundary when recursing. This does not limit the user's ability
@@ -1082,10 +1107,18 @@ yet on the destination. If this option is
combined with the bf(--ignore-existing) option, no files will be updated
(which can be useful if all you want to do is delete extraneous files).
This option is a transfer rule, not an exclude, so it doesn't affect the
data that goes into the file-lists, and thus it doesn't affect deletions.
It just limits the files that the receiver requests to be transferred.
dit(bf(--ignore-existing)) This tells rsync to skip updating files that
already exist on the destination (this does em(not) ignore existing
directories, or nothing would get done). See also bf(--existing).
This option is a transfer rule, not an exclude, so it doesn't affect the
data that goes into the file-lists, and thus it doesn't affect deletions.
It just limits the files that the receiver requests to be transferred.
This option can be useful for those doing backups using the bf(--link-dest)
option when they need to continue a backup run that got interrupted. Since
a bf(--link-dest) run is copied into a new directory hierarchy (when it is
@@ -1104,7 +1137,7 @@ directories that are being synchronized. You must have asked rsync to
send the whole directory (e.g. "dir" or "dir/") without using a wildcard
for the directory's contents (e.g. "dir/*") since the wildcard is expanded
by the shell and rsync thus gets a request to transfer individual files, not
the files' parent directory. Files that are excluded from transfer are
the files' parent directory. Files that are excluded from the transfer are
also excluded from being deleted unless you use the bf(--delete-excluded)
option or mark the rules as only matching on the sending side (see the
include/exclude modifiers in the FILTER RULES section).
@@ -1120,13 +1153,13 @@ going to be deleted.
If the sending side detects any I/O errors, then the deletion of any
files at the destination will be automatically disabled. This is to
prevent temporary filesystem failures (such as NFS errors) on the
sending side causing a massive deletion of files on the
sending side from causing a massive deletion of files on the
destination. You can override this with the bf(--ignore-errors) option.
The bf(--delete) option may be combined with one of the --delete-WHEN options
without conflict, as well as bf(--delete-excluded). However, if none of the
--delete-WHEN options are specified, rsync will choose the
bf(--delete-during) algorithm when talking to an rsync 3.0.0 or newer, and
bf(--delete-during) algorithm when talking to rsync 3.0.0 or newer, and
the bf(--delete-before) algorithm when talking to an older rsync. See also
bf(--delete-delay) and bf(--delete-after).
@@ -1143,19 +1176,26 @@ algorithm that requires rsync to scan all the files in the transfer into
memory at once (see bf(--recursive)).
dit(bf(--delete-during, --del)) Request that the file-deletions on the
receiving side be done incrementally as the transfer happens. This is
a faster method than choosing the before- or after-transfer algorithm,
but it is only supported beginning with rsync version 2.6.4.
receiving side be done incrementally as the transfer happens. The
per-directory delete scan is done right before each directory is checked
for updates, so it behaves like a more efficient bf(--delete-before),
including doing the deletions prior to any per-directory filter files
being updated. This option was first added in rsync version 2.6.4.
See bf(--delete) (which is implied) for more details on file-deletion.
dit(bf(--delete-delay)) Request that the file-deletions on the receiving
side be computed during the transfer, and then removed after the transfer
completes. If the number of removed files overflows an internal buffer, a
side be computed during the transfer (like bf(--delete-during)), and then
removed after the transfer completes. This is useful when combined with
bf(--delay-updates) and/or bf(--fuzzy), and is more efficient than using
bf(--delete-after) (but can behave differently, since bf(--delete-after)
computes the deletions in a separate pass after all updates are done).
If the number of removed files overflows an internal buffer, a
temporary file will be created on the receiving side to hold the names (it
is removed while open, so you shouldn't see it during the transfer). If
the creation of the temporary file fails, rsync will try to fall back to
using bf(--delete-after) (which it cannot do if bf(--recursive) is doing an
incremental scan).
See bf(--delete) (which is implied) for more details on file-deletion.
dit(bf(--delete-after)) Request that the file-deletions on the receiving
side be done after the transfer has completed. This is useful if you
@@ -1201,6 +1241,10 @@ file that is larger than the specified SIZE. The SIZE value can be
suffixed with a string to indicate a size multiplier, and
may be a fractional value (e.g. "bf(--max-size=1.5m)").
This option is a transfer rule, not an exclude, so it doesn't affect the
data that goes into the file-lists, and thus it doesn't affect deletions.
It just limits the files that the receiver requests to be transferred.
The suffixes are as follows: "K" (or "KiB") is a kibibyte (1024),
"M" (or "MiB") is a mebibyte (1024*1024), and "G" (or "GiB") is a
gibibyte (1024*1024*1024).
@@ -1215,10 +1259,10 @@ Examples: --max-size=1.5mb-1 is 1499999 bytes, and --max-size=2g+1 is
dit(bf(--min-size=SIZE)) This tells rsync to avoid transferring any
file that is smaller than the specified SIZE, which can help in not
transferring small, junk files.
See the bf(--max-size) option for a description of SIZE.
See the bf(--max-size) option for a description of SIZE and other information.
dit(bf(-B, --block-size=BLOCKSIZE)) This forces the block size used in
the rsync algorithm to a fixed value. It is normally selected based on
rsync's delta-transfer algorithm to a fixed value. It is normally selected based on
the size of each file being updated. See the technical report for details.
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
@@ -1403,6 +1447,11 @@ quote(tt( rsync -a --files-from=:/path/file-list src:/ /tmp/copy))
This would copy all the files specified in the /path/file-list file that
was located on the remote "src" host.
If the bf(--iconv) and bf(--protect-args) options are specified and the
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.
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
@@ -1410,18 +1459,14 @@ merged files specified in a bf(--filter) rule.
It does not affect bf(--cvs-exclude) (since all names read from a .cvsignore
file are split on whitespace).
If the bf(--iconv) and bf(--protect-args) options are specified and the
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.
dit(bf(-s, --protect-args)) This option sends all filenames and some options to
dit(bf(-s, --protect-args)) This option sends all filenames and most options to
the remote rsync without allowing the remote shell to interpret them. This
means that spaces are not split in names, and any non-wildcard special
characters are not translated (such as ~, $, ;, &, etc.). Wildcards are
expanded on the remote host by rsync (instead of the shell doing it).
If you use this option with bf(--iconv), the args will also be translated
If you use this option with bf(--iconv), the args related to the remote
side will also be translated
from the local to the remote character-set. The translation happens before
wild-cards are expanded. See also the bf(--files-from) option.
@@ -1509,6 +1554,11 @@ An example:
quote(tt( rsync -av --link-dest=$PWD/prior_dir host:src_dir/ new_dir/))
If file's aren't linking, double-check their attributes. Also check if some
attributes are getting forced outside of rsync's control, such a mount option
that squishes root to a single user, or mounts a removable drive with generic
ownership (such as OS X's "Ignore ownership on this volume" option).
Beginning in version 2.6.4, multiple bf(--link-dest) directories may be
provided, which will cause rsync to search the list in the order specified
for an exact match.
@@ -1674,26 +1724,29 @@ a "?" (this can happen when talking to an older rsync).
The attribute that is associated with each letter is as follows:
quote(itemization(
it() A bf(c) means the checksum of the file is different and will be
updated by the file transfer (requires bf(--checksum)).
it() A bf(s) means the size of the file is different and will be updated
it() A bf(c) means either that a regular file has a different checksum
(requires bf(--checksum)) or that a symlink, device, or special file has
a changed value.
Note that if you are sending files to an rsync prior to 3.0.1, this
change flag will be present only for checksum-differing regular files.
it() A bf(s) means the size of a regular file is different and will be updated
by the file transfer.
it() A bf(t) means the modification time is different and is being updated
to the sender's value (requires bf(--times)). An alternate value of bf(T)
means that the modification time will be set to the transfer time, which happens
when a file/symlink/device is updated without bf(--times) and when a
symlink is changed and the receiver can't set its time.
(Note: when using an rsync 3.0.0 client, you might see the bf(s) flag combined
with bf(t) instead of the proper bf(T) flag for this time-setting failure.)
it() A bf(p) means the permissions are different and are being updated to
the sender's value (requires bf(--perms)).
it() An bf(o) means the owner is different and is being updated to the
sender's value (requires bf(--owner) and super-user privileges).
it() A bf(g) means the group is different and is being updated to the
sender's value (requires bf(--group) and the authority to set the group).
it() The bf(u) slot is reserved for reporting update (access) time changes
(a feature that is not yet released).
it() The bf(u) slot is reserved for future use.
it() The bf(a) means that the ACL information changed.
it() The bf(x) slot is reserved for reporting extended attribute changes
(a feature that is not yet released).
it() The bf(x) means that the extended attribute information changed.
))
One other output is possible: when deleting files, the "%i" will output
@@ -1702,22 +1755,22 @@ you are talking to a recent enough rsync that it logs deletions instead of
outputting them as a verbose message).
dit(bf(--out-format=FORMAT)) This allows you to specify exactly what the
rsync client outputs to the user on a per-update basis. The format is a text
string containing embedded single-character escape sequences prefixed with
a percent (%) character. For a list of the possible escape characters, see
the "log format" setting in the rsyncd.conf manpage.
rsync client outputs to the user on a per-update basis. The format is a
text string containing embedded single-character escape sequences prefixed
with a percent (%) character. A default format of "%n%L" is assumed if
bf(-v) is specified (which reports the name
of the file and, if the item is a link, where it points). For a full list
of the possible escape characters, see the "log format" setting in the
rsyncd.conf manpage.
Specifying this option will mention each file, dir, etc. that gets updated
in a significant way (a transferred file, a recreated symlink/device, or a
touched directory). In addition, if the itemize-changes escape (%i) is
included in the string, the logging of names increases to mention any
item that is changed in any way (as long as the receiving side is at least
2.6.4). See the bf(--itemize-changes) option for a description of the
output of "%i".
The bf(--verbose) option implies a format of "%n%L", but you can use
bf(--out-format) without bf(--verbose) if you like, or you can override
the format of its per-file output using this option.
Specifying the bf(--out-format) option
will mention each file, dir, etc. that gets updated in a significant
way (a transferred file, a recreated symlink/device, or a touched
directory). In addition, if the itemize-changes escape (%i) is included in
the string (e.g. if the bf(--itemize-changes) option was used), the logging
of names increases to mention any item that is changed in any way (as long
as the receiving side is at least 2.6.4). See the bf(--itemize-changes)
option for a description of the output of "%i".
Rsync will output the out-format string prior to a file's transfer unless
one of the transfer-statistic escapes is requested, in which case the
@@ -1748,15 +1801,18 @@ specify an empty string, updated files will not be mentioned in the log file.
For a list of the possible escape characters, see the "log format" setting
in the rsyncd.conf manpage.
The default FORMAT used if bf(--log-file) is specified and this option is not
is '%i %n%L'.
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
on the file transfer, allowing you to tell how effective the rsync
on the file transfer, allowing you to tell how effective rsync's delta-transfer
algorithm is for your data.
The current statistics are as follows: quote(itemization(
it() bf(Number of files) is the count of all "files" (in the generic
sense), which includes directories, symlinks, etc.
it() bf(Number of files transferred) is the count of normal files that
were updated via the rsync algorithm, which does not include created
were updated via rsync's delta-transfer algorithm, which does not include created
dirs, symlinks, etc.
it() bf(Total file size) is the total sum of all file sizes in the transfer.
This does not count any size for directories or special files, but does
@@ -1817,7 +1873,7 @@ after it has served its purpose.
Note that if bf(--whole-file) is specified (or implied), any partial-dir
file that is found for a file that is being updated will simply be removed
(since
rsync is sending files without using the delta transfer algorithm).
rsync is sending files without using rsync's delta-transfer algorithm).
Rsync will create the em(DIR) if it is missing (just the last dir -- not
the whole path). This makes it easy to use a relative path (such as
@@ -1897,11 +1953,16 @@ creation of a bunch of useless directories when the sending rsync is
recursively scanning a hierarchy of files using include/exclude/filter
rules.
Note that the use of transfer rules, such as the bf(--min-size) option, does
not affect what goes into the file list, and thus does not leave directories
empty, even if none of the files in a directory match the transfer rule.
Because the file-list is actually being pruned, this option also affects
what directories get deleted when a delete is active. However, keep in
mind that excluded files and directories can prevent existing items from
being deleted (because an exclude hides source files and protects
destination files).
being deleted due to an exclude both hiding source files and protecting
destination files. See the perishable filter-rule option for how to avoid
this.
You can prevent the pruning of certain empty directories from the file-list
by using a global "protect" filter. For instance, this option would ensure
@@ -1935,7 +1996,7 @@ sender's file, which is being reconstructed at a rate of 110.64 kilobytes
per second, and the transfer will finish in 4 seconds if the current rate
is maintained until the end.
These statistics can be misleading if the delta transfer algorithm is
These statistics can be misleading if rsync's delta-transfer algorithm is
in use. For example, if the sender's file consists of the basis file
followed by additional data, the reported rate will probably drop
dramatically when the receiver gets to the literal data, and the transfer
@@ -2070,14 +2131,14 @@ If rsync was complied without support for IPv6, the bf(--ipv6) option
will have no effect. The bf(--version) output will tell you if this
is the case.
dit(bf(--checksum-seed=NUM)) Set the MD4 checksum seed to the integer
dit(bf(--checksum-seed=NUM)) Set the checksum seed to the integer
NUM. This 4 byte checksum seed is included in each block and file
MD4 checksum calculation. By default the checksum seed is generated
checksum calculation. By default the checksum seed is generated
by the server and defaults to the current code(time()). This option
is used to set a specific checksum seed, which is useful for
applications that want repeatable block and file checksums, or
in the case where the user wants a more random checksum seed.
Note that setting NUM to 0 causes rsync to use the default of code(time())
Setting NUM to 0 causes rsync to use the default of code(time())
for checksum seed.
enddit()
@@ -2248,7 +2309,7 @@ itemization(
it() rsync chooses between doing a simple string match and wildcard
matching by checking if the pattern contains one of these three wildcard
characters: '*', '?', and '[' .
it() a '*' matches any non-empty path component (it stops at slashes).
it() a '*' matches any path component, but it stops at slashes.
it() use '**' to match anything, including slashes.
it() a '?' matches any character except a slash (/).
it() a '[' introduces a character class, such as [a-z] or [[:alpha:]].
@@ -2321,6 +2382,39 @@ itemization(
explicitly included or it would be excluded by the "*")
)
The following modifiers are accepted after a "+" or "-":
itemization(
it() A bf(/) specifies that the include/exclude rule should be matched
against the absolute pathname of the current item. For example,
"-/ /etc/passwd" would exclude the passwd file any time the transfer
was sending files from the "/etc" directory, and "-/ subdir/foo"
would always exclude "foo" when it is in a dir named "subdir", even
if "foo" is at the root of the current transfer.
it() A bf(!) specifies that the include/exclude should take effect if
the pattern fails to match. For instance, "-! */" would exclude all
non-directories.
it() A bf(C) is used to indicate that all the global CVS-exclude rules
should be inserted as excludes in place of the "-C". No arg should
follow.
it() An bf(s) is used to indicate that the rule applies to the sending
side. When a rule affects the sending side, it prevents files from
being transferred. The default is for a rule to affect both sides
unless bf(--delete-excluded) was specified, in which case default rules
become sender-side only. See also the hide (H) and show (S) rules,
which are an alternate way to specify sending-side includes/excludes.
it() An bf(r) is used to indicate that the rule applies to the receiving
side. When a rule affects the receiving side, it prevents files from
being deleted. See the bf(s) modifier for more info. See also the
protect (P) and risk (R) rules, which are an alternate way to
specify receiver-side includes/excludes.
it() A bf(p) indicates that a rule is perishable, meaning that it is
ignored in directories that are being deleted. For instance, the bf(-C)
option's default rules that exclude things like "CVS" and "*.o" are
marked as perishable, and will not prevent a directory that was removed
on the source from being deleted on the destination.
)
manpagesection(MERGE-FILE FILTER RULES)
You can merge whole files into your filter rules by specifying either a
@@ -2369,46 +2463,13 @@ itemization(
"- foo + bar" is parsed as two rules (assuming that prefix-parsing wasn't
also disabled).
it() You may also specify any of the modifiers for the "+" or "-" rules
(below) in order to have the rules that are read in from the file
(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
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.
)
The following modifiers are accepted after a "+" or "-":
itemization(
it() A bf(/) specifies that the include/exclude rule should be matched
against the absolute pathname of the current item. For example,
"-/ /etc/passwd" would exclude the passwd file any time the transfer
was sending files from the "/etc" directory, and "-/ subdir/foo"
would always exclude "foo" when it is in a dir named "subdir", even
if "foo" is at the root of the current transfer.
it() A bf(!) specifies that the include/exclude should take effect if
the pattern fails to match. For instance, "-! */" would exclude all
non-directories.
it() A bf(C) is used to indicate that all the global CVS-exclude rules
should be inserted as excludes in place of the "-C". No arg should
follow.
it() An bf(s) is used to indicate that the rule applies to the sending
side. When a rule affects the sending side, it prevents files from
being transferred. The default is for a rule to affect both sides
unless bf(--delete-excluded) was specified, in which case default rules
become sender-side only. See also the hide (H) and show (S) rules,
which are an alternate way to specify sending-side includes/excludes.
it() An bf(r) is used to indicate that the rule applies to the receiving
side. When a rule affects the receiving side, it prevents files from
being deleted. See the bf(s) modifier for more info. See also the
protect (P) and risk (R) rules, which are an alternate way to
specify receiver-side includes/excludes.
it() A bf(p) indicates that a rule is perishable, meaning that it is
ignored in directories that are being deleted. For instance, the bf(-C)
option's default rules that exclude things like "CVS" and "*.o" are
marked as perishable, and will not prevent a directory that was removed
on the source from being deleted on the destination.
)
Per-directory rules are inherited in all subdirectories of the directory
where the merge-file was found unless the 'n' modifier was used. Each
subdirectory's rules are prefixed to the inherited per-directory rules
@@ -2618,27 +2679,26 @@ of the destination trees. The write-batch option causes the rsync
client to store in a "batch file" all the information needed to repeat
this operation against other, identical destination trees.
To apply the recorded changes to another destination tree, run rsync
with the read-batch option, specifying the name of the same batch
file, and the destination tree. Rsync updates the destination tree
using the information stored in the batch file.
For convenience, one additional file is creating when the write-batch
option is used. This file's name is created by appending
".sh" to the batch filename. The .sh file contains
a command-line suitable for updating a destination tree using that
batch file. It can be executed using a Bourne (or Bourne-like) shell,
optionally
passing in an alternate destination tree pathname which is then used
instead of the original path. This is useful when the destination tree
path differs from the original destination tree path.
Generating the batch file once saves having to perform the file
status, checksum, and data block generation more than once when
updating multiple destination trees. Multicast transport protocols can
be used to transfer the batch update files in parallel to many hosts
at once, instead of sending the same data to every host individually.
To apply the recorded changes to another destination tree, run rsync
with the read-batch option, specifying the name of the same batch
file, and the destination tree. Rsync updates the destination tree
using the information stored in the batch file.
For your convenience, a script file is also created when the write-batch
option is used: it will be named the same as the batch file with ".sh"
appended. This script file contains a command-line suitable for updating a
destination tree using the associated batch file. It can be executed using
a Bourne (or Bourne-like) shell, optionally passing in an alternate
destination tree pathname which is then used instead of the original
destination path. This is useful when the destination tree path on the
current host differs from the one used to create the batch file.
Examples:
quote(
@@ -2730,9 +2790,9 @@ bf(--links).
If bf(--copy-links) is specified, then symlinks are "collapsed" by
copying their referent, rather than the symlink.
rsync also distinguishes "safe" and "unsafe" symbolic links. An
example where this might be used is a web site mirror that wishes
ensure the rsync module they copy does not include symbolic links to
Rsync can also distinguish "safe" and "unsafe" symbolic links. An
example where this might be used is a web site mirror that wishes to
ensure that the rsync module that is copied does not include symbolic links to
bf(/etc/passwd) in the public section of the site. Using
bf(--copy-unsafe-links) will cause any links to be copied as the file
they point to on the destination. Using bf(--safe-links) will cause
@@ -2866,7 +2926,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre10 of rsync.
This man page is current for version 3.0.7 of rsync.
manpagesection(INTERNAL OPTIONS)
@@ -2899,7 +2959,7 @@ Jean-loup Gailly and Mark Adler.
manpagesection(THANKS)
Especial thanks go out to: John Van Essen, Matt McCutchen, Wesley W. Terpstra,
Special thanks go out to: John Van Essen, Matt McCutchen, Wesley W. Terpstra,
David Dykstra, Jos Backus, Sebastian Krahmer, Martin Pool, and our
gone-but-not-forgotten compadre, J.W. Schultz.

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(19 Feb 2008)()()
manpage(rsyncd.conf)(5)(31 Dec 2009)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -69,7 +69,7 @@ Note that you should bf(not) send the rsync daemon a HUP signal to force
it to reread the tt(rsyncd.conf) file. The file is re-read on each client
connection.
manpagesection(GLOBAL OPTIONS)
manpagesection(GLOBAL PARAMETERS)
The first parameters in the file (before a [module] header) are the
global parameters.
@@ -79,12 +79,12 @@ config file in which case the supplied value will override the
default for that parameter.
startdit()
dit(bf(motd file)) The "motd file" option allows you to specify a
dit(bf(motd file)) This parameter allows you to specify a
"message of the day" to display to clients on each connect. This
usually contains site information and any legal notices. The default
is no motd file.
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
dit(bf(pid file)) This parameter tells the rsync daemon to write
its process ID to that file. If the file already exists, the rsync
daemon will abort rather than overwrite the file.
@@ -96,23 +96,22 @@ dit(bf(address)) You can override the default IP address the daemon
will listen on by specifying this value. This is ignored if the daemon is
being run by inetd, and is superseded by the bf(--address) command-line option.
dit(bf(socket options)) This option can provide endless fun for people
dit(bf(socket options)) This parameter can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
slower!). Read the man page for the code(setsockopt()) system call for
details on some of the options you may be able to set. By default no
special socket options are set. These settings are superseded by the
bf(--sockopts) command-line option.
special socket options are set. These settings can also be specified
via the bf(--sockopts) command-line option.
enddit()
manpagesection(MODULE PARAMETERS)
manpagesection(MODULE OPTIONS)
After the global options you should define a number of modules, each
After the global parameters you should define a number of modules, each
module exports a directory tree as a symbolic name. Modules are
exported by specifying a module name in square brackets [module]
followed by the options for that module.
followed by the parameters for that module.
The module name cannot contain a slash or a closing square bracket. If the
name contains whitespace, each internal sequence of whitespace will be
changed into a single space, while leading or trailing whitespace will be
@@ -120,12 +119,12 @@ discarded.
startdit()
dit(bf(comment)) The "comment" option specifies a description string
dit(bf(comment)) This parameter specifies a description string
that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the daemon's
filesystem to make available in this module. You must specify this option
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).
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
@@ -158,7 +157,7 @@ args if rsync believes they would escape the module hierarchy.
The default for "use chroot" is true, and is the safer choice (especially
if the module is not read-only).
When this option is enabled, rsync will not attempt to map users and groups
When this parameter is enabled, rsync will not attempt to map users and groups
by name (by default), but instead copy IDs as though bf(--numeric-ids) had
been specified. In order to enable name-mapping, rsync needs to be able to
use the standard library functions for looking up names and IDs (i.e.
@@ -172,32 +171,32 @@ If you copy the necessary resources into the module's chroot area, you
should protect them through your OS's normal user/group or ACL settings (to
prevent the rsync module's user from being able to change them), and then
hide them from the user's view via "exclude" (see how in the discussion of
that option). At that point it will be safe to enable the mapping of users
and groups by name using the "numeric ids" daemon option (see below).
that parameter). At that point it will be safe to enable the mapping of users
and groups by name using the "numeric ids" daemon parameter (see below).
Note also that you are free to setup custom user/group information in the
chroot area that is different from your normal system. For example, you
could abbreviate the list of users and groups.
dit(bf(numeric ids)) Enabling the "numeric ids" option disables the mapping
dit(bf(numeric ids)) Enabling this parameter disables the mapping
of users and groups by name for the current daemon module. This prevents
the daemon from trying to load any user/group-related files or libraries.
Enabling this option makes the transfer behave as if the client had passed
This enabling makes the transfer behave as if the client had passed
the bf(--numeric-ids) command-line option. By default, this parameter is
enabled for chroot modules and disabled for non-chroot modules.
A chroot-enabled module should not have this option enabled unless you've
A chroot-enabled module should not have this parameter enabled unless you've
taken steps to ensure that the module has the necessary resources it needs
to translate names, and that it is not possible for a user to change those
resources.
dit(bf(munge symlinks)) The "munge symlinks" option tells rsync to modify
dit(bf(munge symlinks)) This parameter tells rsync to modify
all incoming symlinks in a way that makes them unusable but recoverable
(see below). This should help protect your files from user trickery when
your daemon module is writable. The default is disabled when "use chroot"
is on and the inside-chroot path is "/", otherwise it is enabled.
If you disable this option on a daemon that is not read-only, there
If you disable this parameter on a daemon that is not read-only, there
are tricks that a user can play with uploaded symlinks to access
daemon-excluded items (if your module has any), and, if "use chroot"
is off, rsync can even be tricked into showing or changing data that
@@ -205,27 +204,28 @@ is outside the module's path (as access-permissions allow).
The way rsync disables the use of symlinks is to prefix each one with
the string "/rsyncd-munged/". This prevents the links from being used
as long as that directory does not exist. When this option is enabled,
as long as that directory does not exist. When this parameter is enabled,
rsync will refuse to run if that path is a directory or a symlink to
a directory. When using the "munge symlinks" option in a chroot area
a directory. When using the "munge symlinks" parameter in a chroot area
that has an inside-chroot path of "/", you should add "/rsyncd-munged/"
to the exclude setting for the module so that
a user can't try to create it.
Note: rsync makes no attempt to verify that any pre-existing symlinks in
the hierarchy are as safe as you want them to be. If you setup an rsync
the module's hierarchy are as safe as you want them to be (unless, of
course, it just copied in the whole hierarchy). If you setup an rsync
daemon on a new area or locally add symlinks, you can manually protect your
symlinks from being abused by prefixing "/rsyncd-munged/" to the start of
every symlink's value. There is a perl script in the support directory
of the source code named "munge-symlinks" that can be used to add or remove
this prefix from your symlinks.
When this option is disabled on a writable module and "use chroot" is off
When this parameter is disabled on a writable module and "use chroot" is off
(or the inside-chroot path is not "/"),
incoming symlinks will be modified to drop a leading slash and to remove ".."
path elements that rsync believes will allow a symlink to escape the module's
hierarchy. There are tricky ways to work around this, though, so you had
better trust your users if you choose this combination of options.
better trust your users if you choose this combination of parameters.
dit(bf(charset)) This specifies the name of the character set in which the
module's filenames are stored. If the client uses an bf(--iconv) option,
@@ -240,14 +240,14 @@ If you wish to force users to always use bf(--iconv) for a particular
module, add "no-iconv" to the "refuse options" parameter. Keep in mind
that this will restrict access to your module to very new rsync clients.
dit(bf(max connections)) The "max connections" option allows you to
dit(bf(max connections)) This parameter allows you to
specify the maximum number of simultaneous connections you will allow.
Any clients connecting when the maximum has been reached will receive a
message telling them to try later. The default is 0, which means no limit.
A negative value disables the module.
See also the "lock file" option.
See also the "lock file" parameter.
dit(bf(log file)) When the "log file" option is set to a non-empty
dit(bf(log file)) When the "log file" parameter is set to a non-empty
string, the rsync daemon will log messages to the indicated file rather
than using syslog. This is particularly useful on systems (such as AIX)
where code(syslog()) doesn't work for chrooted programs. The file is
@@ -256,11 +256,11 @@ the transfer. If this value is set on a per-module basis instead of
globally, the global log will still contain any authorization failures
or config-file error messages.
If the daemon fails to open to specified file, it will fall back to
If the daemon fails to open the specified file, it will fall back to
using syslog and output an error about the failure. (Note that the
failure to open the specified log file used to be a fatal error.)
dit(bf(syslog facility)) The "syslog facility" option allows you to
dit(bf(syslog facility)) This parameter allows you to
specify the syslog facility name to use when logging messages from the
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
@@ -270,43 +270,43 @@ is daemon. This setting has no effect if the "log file" setting is a
non-empty string (either set in the per-modules settings, or inherited
from the global settings).
dit(bf(max verbosity)) The "max verbosity" option allows you to control
dit(bf(max verbosity)) This parameter allows you to control
the maximum amount of verbose information that you'll allow the daemon to
generate (since the information goes into the log file). The default is 1,
which allows the client to request one level of verbosity.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync daemon uses record
dit(bf(lock file)) This parameter specifies the file to use to
support the "max connections" parameter. The rsync daemon uses record
locking on this file to ensure that the max connections limit is not
exceeded for the modules sharing the lock file.
The default is tt(/var/run/rsyncd.lock).
dit(bf(read only)) The "read only" option determines whether clients
dit(bf(read only)) This parameter determines whether clients
will be able to upload files or not. If "read only" is true then any
attempted uploads will fail. If "read only" is false then uploads will
be possible if file permissions on the daemon side allow them. The default
is for all modules to be read only.
dit(bf(write only)) The "write only" option determines whether clients
dit(bf(write only)) This parameter determines whether clients
will be able to download files or not. If "write only" is true then any
attempted downloads will fail. If "write only" is false then downloads
will be possible if file permissions on the daemon side allow them. The
default is for this option to be disabled.
default is for this parameter to be disabled.
dit(bf(list)) The "list" option determines if this module should be
dit(bf(list)) This parameter determines if this module should be
listed when the client asks for a listing of available modules. By
setting this to false you can create hidden modules. The default is
for modules to be listable.
dit(bf(uid)) The "uid" option specifies the user name or user ID that
dit(bf(uid)) This parameter specifies the user name or user ID that
file transfers to and from that module should take place as when the daemon
was run as root. In combination with the "gid" option this determines what
was run as root. In combination with the "gid" parameter this determines what
file permissions are available. The default is uid -2, which is normally
the user "nobody".
dit(bf(gid)) The "gid" option specifies the group name or group ID that
dit(bf(gid)) This parameter specifies the group name or group ID that
file transfers to and from that module should take place as when the daemon
was run as root. This complements the "uid" option. The default is gid -2,
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
@@ -314,58 +314,56 @@ daemon side to behave as if the bf(--fake-user) 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.
dit(bf(filter)) The "filter" option allows you to specify a space-separated
list of filter rules that the daemon will not allow to be read or written.
This is only superficially equivalent to the client specifying these
patterns with the bf(--filter) option. Only one "filter" option may be
specified, but it may contain as many rules as you like, including
merge-file rules. Note that per-directory merge-file rules do not provide
as much protection as global rules, but they can be used to make bf(--delete)
work better when a client downloads the daemon's files (if the per-dir
merge files are included in the transfer).
dit(bf(filter)) The daemon has its own filter chain that determines what files
it will let the client access. This chain is not sent to the client and is
independent of any filters the client may have specified. Files excluded by
the daemon filter chain (bf(daemon-excluded) files) are treated as non-existent
if the client tries to pull them, are skipped with an error message if the
client tries to push them (triggering exit code 23), and are never deleted from
the module. You can use daemon filters to prevent clients from downloading or
tampering with private administrative files, such as files you may add to
support uid/gid name translations.
dit(bf(exclude)) The "exclude" option allows you to specify a
space-separated list of patterns that the daemon will not allow to be read
or written. This is only superficially equivalent to the client
specifying these patterns with the bf(--exclude) option. Only one "exclude"
option may be specified, but you can use "-" and "+" before patterns to
specify exclude/include.
The daemon filter chain is built from the "filter", "include from", "include",
"exclude from", and "exclude" parameters, in that order of priority. Anchored
patterns are anchored at the root of the module. To prevent access to an
entire subtree, for example, "/secret", you em(must) exclude everything in the
subtree; the easiest way to do this is with a triple-star pattern like
"/secret/***".
Because this exclude list is not passed to the client it only applies on
the daemon: that is, it excludes files received by a client when receiving
from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a daemon.
The "filter" parameter takes a space-separated list of daemon filter rules,
though it is smart enough to know not to split a token at an internal space in
a rule (e.g. "- /foo - /bar" is parsed as two rules). You may specify one or
more merge-file rules using the normal syntax. Only one "filter" parameter can
apply to a given module in the config file, so put all the rules you want in a
single parameter. Note that per-directory merge-file rules do not provide as
much protection as global rules, but they can be used to make bf(--delete) work
better during a client download operation if the per-dir merge files are
included in the transfer and the client requests that they be used.
When you want to exclude a directory and all its contents, it is safest to
use a rule that does both, such as "/some/dir/***" (the three stars tells
rsync to exclude the directory itself and everything inside it). This is
better than just excluding the directory alone with "/some/dir/", as it
helps to guard against attempts to trick rsync into accessing files deeper
in the hierarchy.
dit(bf(exclude)) This parameter takes a space-separated list of daemon
exclude patterns. As with the client bf(--exclude) option, patterns can be
qualified with "- " or "+ " to explicitly indicate exclude/include. Only one
"exclude" parameter can apply to a given module. See the "filter" parameter
for a description of how excluded files affect the daemon.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the daemon that contains exclude patterns, one per line.
This is only superficially equivalent
to the client specifying the bf(--exclude-from) option with an equivalent file.
See the "exclude" option above.
dit(bf(include)) Use an "include" to override the effects of the "exclude"
parameter. Only one "include" parameter can apply to a given module. See the
"filter" parameter for a description of how excluded files affect the daemon.
dit(bf(include)) The "include" option allows you to specify a
space-separated list of patterns which rsync should not exclude. This is
only superficially equivalent to the client specifying these patterns with
the bf(--include) option because it applies only on the daemon. This is
useful as it allows you to build up quite complex exclude/include rules.
Only one "include" option may be specified, but you can use "+" and "-"
before patterns to switch include/exclude. See the "exclude" option
above.
dit(bf(exclude from)) This parameter specifies the name of a file
on the daemon that contains daemon exclude patterns, one per line. Only one
"exclude from" parameter can apply to a given module; if you have multiple
exclude-from files, you can specify them as a merge file in the "filter"
parameter. See the "filter" parameter for a description of how excluded files
affect the daemon.
dit(bf(include from)) The "include from" option specifies a filename
on the daemon that contains include patterns, one per line. This is
only superficially equivalent to the client specifying the
bf(--include-from) option with a equivalent file.
See the "exclude" option above.
dit(bf(include from)) Analogue of "exclude from" for a file of daemon include
patterns. Only one "include from" parameter can apply to a given module. See
the "filter" parameter for a description of how excluded files affect the
daemon.
dit(bf(incoming chmod)) This option allows you to specify a set of
dit(bf(incoming chmod)) This parameter allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
incoming files (files that are being received by the daemon). These
changes happen after all other permission calculations, and this will
@@ -374,7 +372,7 @@ client does not specify bf(--perms).
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(outgoing chmod)) This option allows you to specify a set of
dit(bf(outgoing chmod)) This parameter allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
outgoing files (files that are being sent out from the daemon). These
changes happen first, making the sent permissions appear to be different
@@ -384,7 +382,7 @@ be on to the clients.
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(auth users)) The "auth users" option specifies a comma and
dit(bf(auth users)) This parameter specifies a comma and
space-separated list of usernames that will be allowed to connect to
this module. The usernames do not need to exist on the local
system. The usernames may also contain shell wildcard characters. If
@@ -392,36 +390,36 @@ system. The usernames may also contain shell wildcard characters. If
username and password to connect to the module. A challenge response
authentication protocol is used for this exchange. The plain text
usernames and passwords are stored in the file specified by the
"secrets file" option. The default is for all users to be able to
"secrets file" parameter. The default is for all users to be able to
connect without a password (this is called "anonymous rsync").
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
PROGRAM" section in bf(rsync)(1) for information on how handle an
See also the section entitled "USING RSYNC-DAEMON FEATURES VIA A REMOTE
SHELL CONNECTION" in bf(rsync)(1) for information on how handle an
rsyncd.conf-level username that differs from the remote-shell-level
username when using a remote shell to connect to an rsync daemon.
dit(bf(secrets file)) The "secrets file" option specifies the name of
dit(bf(secrets file)) This parameter specifies the name of
a file that contains the username:password pairs used for
authenticating this module. This file is only consulted if the "auth
users" option is specified. The file is line based and contains
users" parameter is specified. The file is line based and contains
username:password pairs separated by a single colon. Any line starting
with a hash (#) is considered a comment and is skipped. The passwords
can contain any characters but be warned that many operating systems
limit the length of passwords that can be typed at the client end, so
you may find that passwords longer than 8 characters don't work.
There is no default for the "secrets file" option, you must choose a name
There is no default for the "secrets file" parameter, you must choose a name
(such as tt(/etc/rsyncd.secrets)). The file must normally not be readable
by "other"; see "strict modes".
dit(bf(strict modes)) The "strict modes" option determines whether or not
dit(bf(strict modes)) This parameter determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
true, then the secrets file must not be readable by any user ID other
than the one that the rsync daemon is running under. If "strict modes" is
false, the check is not performed. The default is true. This option
false, the check is not performed. The default is true. This parameter
was added to accommodate rsync running on the Windows operating system.
dit(bf(hosts allow)) The "hosts allow" option allows you to specify a
dit(bf(hosts allow)) This parameter allows you to specify a
list of patterns that are matched against a connecting clients
hostname and IP address. If none of the patterns match then the
connection is rejected.
@@ -456,28 +454,28 @@ tt( fe80::%link1/ffff:ffff:ffff:ffff::)nl()
)
You can also combine "hosts allow" with a separate "hosts deny"
option. If both options are specified then the "hosts allow" option s
parameter. If both parameters are specified then the "hosts allow" parameter is
checked first and a match results in the client being able to
connect. The "hosts deny" option is then checked and a match means
connect. The "hosts deny" parameter is then checked and a match means
that the host is rejected. If the host does not match either the
"hosts allow" or the "hosts deny" patterns then it is allowed to
connect.
The default is no "hosts allow" option, which means all hosts can connect.
The default is no "hosts allow" parameter, which means all hosts can connect.
dit(bf(hosts deny)) The "hosts deny" option allows you to specify a
dit(bf(hosts deny)) This parameter allows you to specify a
list of patterns that are matched against a connecting clients
hostname and IP address. If the pattern matches then the connection is
rejected. See the "hosts allow" option for more information.
rejected. See the "hosts allow" parameter for more information.
The default is no "hosts deny" option, which means all hosts can connect.
The default is no "hosts deny" parameter, which means all hosts can connect.
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
dit(bf(ignore errors)) This parameter tells rsyncd to
ignore I/O errors on the daemon when deciding whether to run the delete
phase of the transfer. Normally rsync skips the bf(--delete) step if any
I/O errors have occurred in order to prevent disastrous deletion due
to a temporary resource shortage or other I/O error. In some cases this
test is counter productive so you can use this option to turn off this
test is counter productive so you can use this parameter to turn off this
behavior.
dit(bf(ignore nonreadable)) This tells the rsync daemon to completely
@@ -485,14 +483,14 @@ ignore files that are not readable by the user. This is useful for
public archives that may have some non-readable files among the
directories, and the sysadmin doesn't want those files to be seen at all.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
dit(bf(transfer logging)) This parameter enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. The daemon always logs the transfer at the end, so
if a transfer is aborted, no mention will be made in the log file.
If you want to customize the log lines, see the "log format" option.
If you want to customize the log lines, see the "log format" parameter.
dit(bf(log format)) The "log format" option allows you to specify the
dit(bf(log format)) This parameter allows you to specify the
format used for logging file transfers when transfer logging is enabled.
The format is a text string containing embedded single-character escape
sequences prefixed with a percent (%) character. An optional numeric
@@ -500,7 +498,7 @@ field width may also be specified between the percent and the escape
letter (e.g. "bf(%-50n %8l %07p)").
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
is always prefixed when using the "log file" option.
is always prefixed when using the "log file" parameter.
(A perl script that will summarize this default log format is included
in the rsync source code distribution in the "support" subdirectory:
rsyncstats.)
@@ -511,7 +509,7 @@ quote(itemization(
it() %a the remote IP address
it() %b the number of bytes actually transferred
it() %B the permission bits of the file (e.g. rwxrwxrwt)
it() %c the checksum bytes received for this file (only when sending)
it() %c the total size of the block checksums received for the basis file (only when sending)
it() %f the filename (long form on sender; no trailing "/")
it() %G the gid of the file (decimal) or "DEFAULT"
it() %h the remote host name
@@ -536,14 +534,14 @@ Note that some of the logged output changes when talking with older
rsync versions. For instance, deleted files were only output as verbose
messages prior to rsync 2.6.4.
dit(bf(timeout)) The "timeout" option allows you to override the
clients choice for I/O timeout for this module. Using this option you
dit(bf(timeout)) This parameter allows you to override the
clients choice for I/O timeout for this module. Using this parameter you
can ensure that rsync won't wait on a dead client forever. The timeout
is specified in seconds. A value of zero means no timeout and is the
default. A good choice for anonymous rsync daemons may be 600 (giving
a 10 minute timeout).
dit(bf(refuse options)) The "refuse options" option allows you to
dit(bf(refuse options)) This parameter allows you to
specify a space-separated list of rsync command line options that will
be refused by your rsync daemon.
You may specify the full option name, its one-letter abbreviation, or a
@@ -566,21 +564,21 @@ you can use "dont compress = *" (see below)
instead of "refuse options = compress" to avoid returning an error to a
client that requests compression.
dit(bf(dont compress)) The "dont compress" option allows you to select
dit(bf(dont compress)) This parameter allows you to select
filenames based on wildcard patterns that should not be compressed
when pulling files from the daemon (no analogous option exists to
when pulling files from the daemon (no analogous parameter exists to
govern the pushing of files to a daemon).
Compression is expensive in terms of CPU usage, so it
is usually good to not try to compress files that won't compress well,
such as already compressed files.
The "dont compress" option takes a space-separated list of
The "dont compress" parameter takes a space-separated list of
case-insensitive wildcard patterns. Any source filename matching one
of the patterns will not be compressed during transfer.
See the bf(--skip-compress) option in the bf(rsync)(1) manpage for the list
See the bf(--skip-compress) parameter in the bf(rsync)(1) manpage for the list
of file suffixes that are not compressed by default. Specifying a value
for the "dont compress" option changes the default when the daemon is
for the "dont compress" parameter changes the default when the daemon is
the sender.
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
@@ -702,7 +700,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre10 of rsync.
This man page is current for version 3.0.7 of rsync.
manpagesection(CREDITS)

View File

@@ -154,12 +154,21 @@ fi
RSYNC="$rsync_bin $*"
#RSYNC="valgrind $rsync_bin $*"
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC
TLS_ARGS=''
if egrep '^#define HAVE_LUTIMES 1' config.h >/dev/null; then
TLS_ARGS="$TLS_ARGS -l"
fi
if egrep '#undef CHOWN_MODIFIES_SYMLINK' config.h >/dev/null; then
TLS_ARGS="$TLS_ARGS -L"
fi
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC TLS_ARGS
echo "============================================================"
echo "$0 running in $TOOLDIR"
echo " rsync_bin=$RSYNC"
echo " srcdir=$srcdir"
echo " TLS_ARGS=$TLS_ARGS"
if [ -f /usr/bin/whoami ]; then
testuser=`/usr/bin/whoami`
@@ -229,7 +238,10 @@ prep_scratch() {
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
$setfacl_nodef "$scratchdir" || true
chmod g-s "$scratchdir"
ln -s "$srcdir" "$scratchdir/src"
case "$srcdir" in
/*) ln -s "$srcdir" "$scratchdir/src" ;;
*) ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
esac
return 0
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -22,7 +22,6 @@
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_server;
extern int am_daemon;
@@ -127,15 +126,9 @@ void successful_send(int ndx)
if (!remove_source_files)
return;
if (!(flist = flist_for_ndx(ndx))) {
rprintf(FERROR,
"INTERNAL ERROR: unable to find flist for item %d\n",
ndx);
return;
}
flist = flist_for_ndx(ndx, "successful_send");
file = flist->files[ndx - flist->ndx_start];
if (!push_pathname(F_PATHNAME(file), -1))
if (!change_pathname(file, NULL, 0))
return;
f_name(file, fname);
@@ -159,7 +152,7 @@ static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
if (iflags & ITEM_XNAME_FOLLOWS)
write_vstring(f_out, buf, len);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
send_xattr_request(fname, file, f_out);
#endif
}
@@ -180,6 +173,7 @@ void send_files(int f_in, int f_out)
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
int f_xfer = write_batch < 0 ? batch_fd : f_out;
int save_io_error = io_error;
int ndx, j;
if (verbose > 2)
@@ -221,7 +215,7 @@ void send_files(int f_in, int f_out)
} else {
path = slash = "";
}
if (!push_pathname(F_PATHNAME(file), -1))
if (!change_pathname(file, NULL, 0))
continue;
f_name(file, fname);
@@ -229,7 +223,7 @@ void send_files(int f_in, int f_out)
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
recv_xattr_request(file, f_in);
#endif
@@ -281,7 +275,7 @@ void send_files(int f_in, int f_out)
if (!(s = receive_sums(f_in))) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "receive_sums failed\n");
rprintf(FERROR_XFER, "receive_sums failed\n");
exit_cleanup(RERR_PROTOCOL);
}
@@ -309,7 +303,7 @@ void send_files(int f_in, int f_out)
/* map the local file */
if (do_fstat(fd, &st) != 0) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "fstat failed");
rsyserr(FERROR_XFER, errno, "fstat failed");
free_sums(s);
close(fd);
exit_cleanup(RERR_PROTOCOL);
@@ -368,6 +362,9 @@ void send_files(int f_in, int f_out)
if (make_backups < 0)
make_backups = -make_backups;
if (io_error != save_io_error && protocol_version >= 30)
send_msg_int(MSG_IO_ERROR, io_error);
if (verbose > 2)
rprintf(FINFO, "send files finished\n");

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -31,6 +31,7 @@
#include <netinet/tcp.h>
extern char *bind_address;
extern char *sockopts;
extern int default_af_hint;
extern int connect_timeout;
@@ -272,6 +273,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
alarm(connect_timeout);
}
set_socket_options(s, sockopts);
while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
if (connect_timeout < 0)
exit_cleanup(RERR_CONTIMEOUT);
@@ -433,6 +435,10 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&one, sizeof one);
if (sockopts)
set_socket_options(s, sockopts);
else
set_socket_options(s, lp_socket_options());
#ifdef IPV6_V6ONLY
if (resp->ai_family == AF_INET6) {
@@ -572,7 +578,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
fds = deffds;
#endif
if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1)
continue;
for (i = 0, fd = -1; sp[i] >= 0; i++) {
@@ -817,6 +823,7 @@ static int socketpair_tcp(int fd[2])
**/
int sock_exec(const char *prog)
{
pid_t pid;
int fd[2];
if (socketpair_tcp(fd) != 0) {
@@ -825,14 +832,23 @@ int sock_exec(const char *prog)
}
if (verbose >= 2)
rprintf(FINFO, "Running socket program: \"%s\"\n", prog);
if (fork() == 0) {
pid = fork();
if (pid < 0) {
rsyserr(FERROR, errno, "fork");
exit_cleanup(RERR_IPC);
}
if (pid == 0) {
close(fd[0]);
close(0);
close(1);
dup(fd[1]);
dup(fd[1]);
if (dup2(fd[1], STDIN_FILENO) < 0
|| dup2(fd[1], STDOUT_FILENO) < 0) {
fprintf(stderr, "Failed to run \"%s\"\n", prog);
exit(1);
}
exit(system(prog));
}
close(fd[1]);
return fd[0];
}

View File

@@ -6,35 +6,49 @@
# more details and some important caveats!**
use strict;
use warnings;
use Cwd 'abs_path';
my $RSYNC_PROG = '/usr/bin/rsync';
my $RM_PROG = '/bin/rm';
my $dest_dir = $ARGV[-1];
usage(1) if $dest_dir eq '' || $dest_dir =~ /^--/;
&usage if !defined $dest_dir || $dest_dir =~ /(^-|^$)/ || grep(/^--help/, @ARGV);
$dest_dir =~ s{(?<=.)/+$} {};
if (!-d $dest_dir) {
print STDERR "$dest_dir is not a directory.\n\n";
usage(1);
die "$dest_dir is not a directory.\nUse --help for help.\n";
}
if (@_ = grep(/^--(link|compare)-dest/, @ARGV)) {
if (@_ = grep(/^--[a-z]+-dest\b/, @ARGV)) {
$_ = join(' or ', @_);
print STDERR "You may not use $_ as an rsync option.\n\n";
usage(1);
die "You cannot use the $_ option with atomic-rsync.\nUse --help for help.\n";
}
my $symlink_content = readlink $dest_dir; # undef when a real dir
my $dest_arg = $dest_dir;
# This gives us the real destination dir, with all symlinks dereferenced.
$dest_dir = abs_path($dest_dir);
if ($dest_dir eq '/') {
print STDERR 'You must not use "/" as the destination directory.', "\n\n";
usage(1);
die qq|You must not use "/" as the destination directory.\nUse --help for help.\n|;
}
my $old_dir = "$dest_dir~old~";
my $new_dir = $ARGV[-1] = "$dest_dir~new~";
my($old_dir, $new_dir);
if (defined $symlink_content && $dest_dir =~ /-([12])$/) {
my $num = 3 - $1;
$old_dir = undef;
($new_dir = $dest_dir) =~ s/-[12]$/-$num/;
$symlink_content =~ s/-[12]$/-$num/;
} else {
$old_dir = "$dest_dir~old~";
$new_dir = "$dest_dir~new~";
}
system($RM_PROG, '-rf', $old_dir) if -d $old_dir;
$ARGV[-1] = "$new_dir/";
system($RM_PROG, '-rf', $old_dir) if defined $old_dir && -d $old_dir;
system($RM_PROG, '-rf', $new_dir) if -d $new_dir;
if (system($RSYNC_PROG, "--link-dest=$dest_dir", @ARGV)) {
if ($? == -1) {
@@ -48,17 +62,30 @@ if (system($RSYNC_PROG, "--link-dest=$dest_dir", @ARGV)) {
exit $?;
}
rename($dest_dir, $old_dir) or die "Unable to rename $new_dir to $old_dir: $!";
if (!defined $old_dir) {
atomic_symlink($symlink_content, $dest_arg);
exit;
}
rename($dest_dir, $old_dir) or die "Unable to rename $dest_dir to $old_dir: $!";
rename($new_dir, $dest_dir) or die "Unable to rename $new_dir to $dest_dir: $!";
exit;
sub atomic_symlink
{
my($target, $link) = @_;
my $newlink = "$link~new~";
unlink($newlink); # Just in case
symlink($target, $newlink) or die "Unable to symlink $newlink -> $target: $!\n";
rename($newlink, $link) or die "Unable to rename $newlink to $link: $!\n";
}
sub usage
{
my($ret) = @_;
my $fh = $ret ? *STDERR : *STDOUT;
print $fh <<EOT;
die <<EOT;
Usage: atomic-rsync [RSYNC-OPTIONS] HOST:/SOURCE/DIR/ /DEST/DIR/
atomic-rsync [RSYNC-OPTIONS] HOST::MOD/DIR/ /DEST/DIR/
@@ -67,24 +94,29 @@ creating a new hierarchy (using hard-links to leverage the existing files),
and then swapping the new hierarchy into place. You must be pulling files
to a local directory, and that directory must already exist. For example:
mkdir /local/files-1
ln -s files-1 /local/files
atomic-rsync -av host:/remote/files/ /local/files/
This would make the transfer to the directory /local/files~new~ and then
swap out /local/files at the end of the transfer by renaming it to
/local/files~old~ and putting the new directory into its place. The
/local/files~old~ directory will be preserved until the next update, at
which point it will be deleted.
If /local/files is a symlink to a directory that ends in -1 or -2, the
copy will go to the alternate suffix and the symlink will be changed to
point to the new dir. This is a fully atomic update. If the destination
is not a symlink (or not a symlink to a *-1 or a *-2 directory), this
will instead create a directory with "~new~" suffixed, move the current
directory to a name with "~old~" suffixed, and then move the ~new~
directory to the original destination name (this double rename is not
fully atomic, but is rapid). In both cases, the prior destintaion
directory will be preserved until the next update, at which point it
will be deleted.
Do NOT specify this command:
In all likelihood, you do NOT want to specify this command:
atomic-rsync -av host:/remote/files /local/
... UNLESS you want the entire /local dir to be swapped out!
See the "rsync" command for its list of options. You may not use the
--link-dest or --compare-dest options (since this script uses --link-dest
to make the transfer efficient). Also, the destination directory cannot
be "/".
--link-dest, --compare-dest, or --copy-dest options (since this script
uses --link-dest to make the transfer efficient).
EOT
exit $ret;
}

36
support/deny-rsync Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
# Send an error message via the rsync-protocol to a non-daemon client rsync.
#
# Usage: deny-rsync "message"
protocol_version=29
exit_code=4 # same as a daemon that refuses an option
# e.g. byte_escape 29 => \035
function byte_escape {
echo -ne "\\0$(printf "%o" $1)"
}
msg="$1"
if [ "${#msg}" -gt 254 ]; then
# truncate a message that is too long for this naive script to handle
msg="${msg:0:251}..."
fi
msglen=$(( ${#msg} + 1 )) # add 1 for the newline we append below
# Send protocol version. All numbers are LSB-first 4-byte ints.
echo -ne "$(byte_escape $protocol_version)\\000\\000\\000"
# Send a zero checksum seed.
echo -ne "\\000\\000\\000\\000"
# The following is equivalent to rprintf(FERROR_XFER, "%s\n", $msg).
# 1. Message header: ((MPLEX_BASE + FERROR_XFER) << 24) + $msglen.
echo -ne "$(byte_escape $msglen)\\000\\000\\010"
# 2. The actual data.
echo -E "$msg"
# Make sure the client gets our message, not a write failure.
sleep 1
exit $exit_code

View File

@@ -6,18 +6,30 @@
# we get a -l USER option, we try to use "sudo -u USER" to run the
# command.
user=''
prefix=''
cd # Default path is home dir, just like ssh.
do_cd=y # Default path is user's home dir, just like ssh.
while : ; do
case "$1" in
-l) shift ; prefix="sudo -u $1"; shift ;;
-l*) prefix=`echo $1 | sed 's/-l/sudo -u /'`; shift ;;
-l) user="$2"; shift; shift ;;
-l*) user=`echo $1 | sed 's/^-l//'`; shift ;;
--no-cd) do_cd=n; shift ;;
-*) shift ;;
localhost) shift; break ;;
*) exit 1 ;;
*) echo "lsh: unable to connect to host $1" 1>&2; exit 1 ;;
esac
done
if [ "$user" ]; then
prefix="sudo -H -u $user"
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
fi
elif [ $do_cd = y ]; then
cd
fi
eval $prefix "${@}"

View File

@@ -39,6 +39,7 @@ die "$0: Restricted directory does not exist!\n" if $subdir ne '/' && !-d $subdi
my $command = $ENV{SSH_ORIGINAL_COMMAND};
die "$0: Not invoked via sshd\n$Usage" unless defined $command;
die "$0: SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ s/^rsync\s+//;
die "$0: --server option is not first\n" unless $command =~ /^--server\s/;
our $am_sender = $command =~ /^--server\s+--sender\s/; # Restrictive on purpose!
die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
@@ -65,7 +66,7 @@ our %long_opt = (
'compress-level' => 1,
'copy-dest' => 2,
'copy-unsafe-links' => 0,
'daemon' => 0,
'daemon' => -1,
'delay-updates' => 0,
'delete' => 0,
'delete-after' => 0,
@@ -74,6 +75,7 @@ our %long_opt = (
'delete-during' => 0,
'delete-excluded' => 0,
'existing' => 0,
'fake-super' => 0,
'files-from' => 3,
'force' => 0,
'from0' => 0,
@@ -84,6 +86,7 @@ our %long_opt = (
'inplace' => 0,
'link-dest' => 2,
'list-only' => 0,
'log-file' => 3,
'log-format' => 1,
'max-delete' => 1,
'max-size' => 1,
@@ -110,6 +113,7 @@ our %long_opt = (
'super' => 0,
'temp-dir' => 2,
'timeout' => 1,
'use-qsort' => 0,
);
### END of options data produced by the cull_options script. ###
@@ -139,7 +143,8 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
if ($_ eq '.') {
$in_options = 0;
} else {
next if /^-$short_no_arg+(e\d+\.\d+)?$/o || /^-$short_with_num\d+$/o;
die "$0: invalid option: '-'\n" if $_ eq '-';
next if /^-$short_no_arg*(e\d*\.\w*)?$/o || /^-$short_with_num\d+$/o;
my($opt,$arg) = /^--([^=]+)(?:=(.*))?$/;
my $disabled;

View File

@@ -4,7 +4,7 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -167,9 +167,9 @@ int do_chmod(const char *path, mode_t mode)
code = 1;
#endif
} else
code = chmod(path, mode & CHMOD_BITS);
code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
if (code != 0 && (preserve_perms || preserve_executability))
return code;
return code;
return 0;
}
#endif
@@ -282,12 +282,3 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
return lseek(fd, offset, whence);
#endif
}
char *d_name(struct dirent *di)
{
#ifdef HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;
#endif
}

View File

@@ -3,7 +3,7 @@
* functions, so that module test harnesses can run standalone.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -26,10 +26,11 @@ int module_id = -1;
int relative_paths = 0;
int human_readable = 0;
int module_dirlen = 0;
int preserve_xattrs = 0;
mode_t orig_umask = 002;
char *partial_dir;
char *module_dir;
struct filter_list_struct server_filter_list;
struct filter_list_struct daemon_filter_list;
void rprintf(UNUSED(enum logcode code), const char *format, ...)
{
@@ -56,8 +57,8 @@ struct filter_list_struct server_filter_list;
exit(code);
}
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(char *name),
UNUSED(int name_is_dir))
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(enum logcode code),
UNUSED(const char *name), UNUSED(int name_is_dir))
{
/* This function doesn't really get called in this test context, so
* just return 0. */
@@ -69,6 +70,11 @@ struct filter_list_struct server_filter_list;
return -1;
}
int copy_xattrs(UNUSED(const char *source), UNUSED(const char *dest))
{
return -1;
}
char *lp_name(UNUSED(int mod))
{
return NULL;

View File

@@ -2,7 +2,7 @@
* Test harness for unsafe_symlink(). Not linked into rsync itself.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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

View File

@@ -36,7 +36,7 @@ for fn in deep/name1 deep/name2; do
done
echo deleted-file >"$todir/dname"
cp -p "$todir/dname" "$chkdir"
cp_touch "$todir/dname" "$chkdir"
checkit "$RSYNC -avv --no-whole-file --delete-delay \
--backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \

View File

@@ -41,6 +41,8 @@ runtest "--read-batch from daemon" 'checkit "$RSYNC -av --read-batch=BATCH \"$to
rm -rf "$todir"
runtest "BATCH.sh use of --read-batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"'
runtest "do-nothing re-run of batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"'
rm -rf "$todir"
mkdir "$todir" || test_fail "failed to restore empty destination directory"
runtest "daemon recv --write-batch" 'checkit "\"$ignore23\" $RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'

View File

@@ -13,12 +13,19 @@
hands_setup
tmpdir2=/tmp
tmpdir2=$RSYNC_TEST_TMP
if [ x"$tmpdir2" = x ]; then
tmpdir2=/tmp
fi
sdev=`$TOOLDIR/getfsdev $scratchdir`
tdev=`$TOOLDIR/getfsdev $tmpdir2`
if [ x$sdev = x$tdev ]; then
tmpdir2=/var/tmp
tdev=`$TOOLDIR/getfsdev $tmpdir2`
if [ -d $tmpdir2 ]; then
tdev=`$TOOLDIR/getfsdev $tmpdir2`
else
tdev="$sdev"
fi
[ x$sdev = x$tdev ] && test_skipped "Can't find a tmp dir on a different file system"
fi

View File

@@ -17,7 +17,7 @@ case $0 in
*fake*)
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
RSYNC="$RSYNC --fake-super"
TLS_ARGS=--fake-super
TLS_ARGS="$TLS_ARGS --fake-super"
case "`xattr 2>&1`" in
*--list:*)
chown() {
@@ -37,7 +37,7 @@ case $0 in
;;
*)
RSYNC="$RSYNC --super"
case `id -u` in
case `get_testuid` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then

View File

@@ -19,14 +19,72 @@
# checking the log file
# password authentication
# TODO: Put the common framework in a common file, so that we can have
# subtests fail and keep going.
. "$suitedir/rsync.fns"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
SSH="src/support/lsh --no-cd"
FILE_REPL='s/^\([^d][^ ]*\) *\(..........[0-9]\) /\1 \2 /'
DIR_REPL='s/^\(d[^ ]*\) *[0-9][0-9]* /\1 DIR /'
LS_REPL='s;[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9];####/##/## ##:##:##;'
build_rsyncd_conf
makepath "$fromdir/foo" "$fromdir/bar/baz"
makepath "$todir"
echo one >"$fromdir/foo/one"
echo two >"$fromdir/bar/two"
echo three >"$fromdir/bar/baz/three"
cd "$scratchdir"
ln -s test-rsyncd.conf rsyncd.conf
confopt=''
case `get_testuid` in
0)
# Root needs to specify the config file, or it uses /etc/rsyncd.conf.
echo "Forcing --config=$conf"
confopt=" --config=$conf"
;;
esac
$RSYNC -ve "$SSH" --rsync-path="$RSYNC$confopt" localhost::
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
$RSYNC -v localhost::
$RSYNC -v localhost:: \
| tee "$outfile"
# These have a space-padded 15-char name, then a tab, then a comment.
sed 's/NOCOMMENT//' <<EOT >"$chkfile"
test-from r/o
test-to r/w
test-scratch NOCOMMENT
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -r localhost::test-hidden \
| sed "$FILE_REPL" | sed "$DIR_REPL" | sed "$LS_REPL" \
| tee "$outfile"
cat <<EOT >"$chkfile"
drwxr-xr-x DIR ####/##/## ##:##:## .
drwxr-xr-x DIR ####/##/## ##:##:## bar
-rw-r--r-- 4 ####/##/## ##:##:## bar/two
drwxr-xr-x DIR ####/##/## ##:##:## bar/baz
-rw-r--r-- 6 ####/##/## ##:##:## bar/baz/three
drwxr-xr-x DIR ####/##/## ##:##:## foo
-rw-r--r-- 4 ####/##/## ##:##:## foo/one
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
$RSYNC -r localhost::test-from/f* \
| sed "$FILE_REPL" | sed "$DIR_REPL" | sed "$LS_REPL" \
| tee "$outfile"
cat <<EOT >"$chkfile"
drwxr-xr-x DIR ####/##/## ##:##:## foo
-rw-r--r-- 4 ####/##/## ##:##:## foo/one
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"

View File

@@ -18,7 +18,7 @@ case $0 in
*fake*)
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
RSYNC="$RSYNC --fake-super"
TLS_ARGS=--fake-super
TLS_ARGS="$TLS_ARGS --fake-super"
case "`xattr 2>&1`" in
*--list:*)
mknod() {
@@ -51,7 +51,7 @@ case $0 in
esac
;;
*)
case `id -u` in
case `get_testuid` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
@@ -76,19 +76,20 @@ mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node"
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo"
touch -r "$fromdir/block" "$fromdir/block2"
# Work around time rounding/truncating issue by touching both files.
touch -r "$fromdir/block" "$fromdir/block" "$fromdir/block2"
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++++ block
cD$all_plus block
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -ai "$fromdir/block2" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++++ block2
cD$all_plus block2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
@@ -97,7 +98,7 @@ sleep 1
$RSYNC -Di "$fromdir/block3" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD..T...... block3
cDc.T.$dots block3
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -105,15 +106,15 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t...... ./
cD..t...... block
cD block2
cD+++++++++ block3
hD+++++++++ block2.5 => block3
cD+++++++++ char
cD+++++++++ char2
cD+++++++++ char3
cS+++++++++ fifo
.d..t.$dots ./
cDc.t.$dots block
cDc...$dots block2
cD$all_plus block3
hD$all_plus block2.5 => block3
cD$all_plus char
cD$all_plus char2
cD$all_plus char3
cS$all_plus fifo
EOT
if test ! -r "$fromdir/block2.5"; then
sed -e '/block2\.5/d' <"$chkfile" >"$chkfile.new"
@@ -132,15 +133,15 @@ if test -b "$fromdir/block2.5"; then
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd ./
hD block
hD block2
hD block2.5
hD block3
hD char
hD char2
hD char3
hS fifo
cd$allspace ./
hD$allspace block
hD$allspace block2
hD$allspace block2.5
hD$allspace block3
hD$allspace char
hD$allspace char2
hD$allspace char3
hS$allspace fifo
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
fi

View File

@@ -153,13 +153,13 @@ checkit "$RSYNC -avvC --filter='merge $excl' --delete-excluded \
rm "$chkdir"/foo/file1
rm "$chkdir"/bar/down/to/bar/baz/*.deep
cp -p "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp -p "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
cp_touch "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp_touch "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
$RSYNC -av --existing -f 'show .filt*' -f 'hide,! */' --del "$fromdir/" "$todir/"
echo retained >"$todir"/bar/down/to/bar/baz/nodel.deep
cp -p "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
cp_touch "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"

30
testsuite/files-from.test Normal file
View File

@@ -0,0 +1,30 @@
#!/bin/sh
# Copyright (C) 2008 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that --files-from=FILE works right.
. "$suitedir/rsync.fns"
hands_setup
# This list of files skips the contents of "subsubdir" but includes
# the contents of "subsubdir2" due to its trailing slash.
cat >"$scratchdir/filelist" <<EOT
from/./
from/./dir/subdir
from/./dir/subdir/subsubdir
from/./dir/subdir/subsubdir2/
from/./dir/subdir/foobar.baz
EOT
# Create a chkdir without the content that we expect to be omitted.
$RSYNC -a --exclude=dir/text --exclude='subsubdir/**' "$fromdir/" "$chkdir/"
checkit "$RSYNC -av --files-from='$scratchdir/filelist' '$scratchdir' '$todir/'" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -13,7 +13,7 @@ mkdir "$fromdir"
mkdir "$todir"
cp -p "$srcdir"/rsync.c "$fromdir"/rsync.c
cp -p "$fromdir"/rsync.c "$todir"/rsync2.c
cp_touch "$fromdir"/rsync.c "$todir"/rsync2.c
sleep 1
# Let's do it!

View File

@@ -11,6 +11,8 @@
. "$suitedir/rsync.fns"
SSH="$scratchdir/src/support/lsh"
outfile="$scratchdir/rsync.out"
# Build some hardlinks
@@ -38,12 +40,23 @@ echo "extra extra" >>"$todir/name1"
checkit "$RSYNC -aHivv --no-whole-file '$fromdir/' '$todir/'" "$fromdir" "$todir"
# Add a new link in a new subdirectory to test that we don't try to link
# the files before the directory gets created.
mkdir "$fromdir/subdir"
ln "$name1" "$fromdir/subdir/new-file"
# the files before the directory gets created. We also create a bunch of
# extra files to ensure that an incremental-recursion transfer works across
# distant files.
makepath "$fromdir/subdir/down/deep"
files=''
for x in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9; do
for y in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9; do
files="$files $x$y"
done
done
(cd "$fromdir/subdir"; touch $files)
ln "$name1" "$fromdir/subdir/down/deep/new-file"
rm "$todir/text"
checkit "$RSYNC -aHivv '$fromdir/' '$todir/'" "$fromdir" "$todir"
checkit "$RSYNC -aHivve '$SSH' --rsync-path='$RSYNC' '$fromdir/' localhost:'$todir/'" "$fromdir" "$todir"
# Do some duplicate copies using --link-dest and --copy-dest to test that
# we hard-link all locally-inherited items.

View File

@@ -25,16 +25,14 @@ umask 0
ln -s ../bar/baz/rsync "$fromdir/foo/sym"
umask 022
ln "$fromdir/foo/config1" "$fromdir/foo/extra"
rm -f "$to2dir"
# Check if the OS can hard-link symlinks or not.
# (Note: the link we check MUST NOT point to a valid file!)
ln -s no-such-dir "$to2dir"
if ln "$to2dir" "$to2dir.test" 2>/dev/null; then
# Check if rsync is set to hard-link symlinks.
if egrep '^#define CAN_HARDLINK_SYMLINK 1' config.h >/dev/null; then
L=hL
else
L=cL
fi
rm -f "$to2dir" "$to2dir.test"
# Check if rsync can preserve time on symlinks
case "$RSYNC" in
@@ -53,15 +51,15 @@ esac
$RSYNC -iplr "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++++ ./
cd+++++++++ bar/
cd+++++++++ bar/baz/
>f+++++++++ bar/baz/rsync
cd+++++++++ foo/
>f+++++++++ foo/config1
>f+++++++++ foo/config2
>f+++++++++ foo/extra
cL+++++++++ foo/sym -> ../bar/baz/rsync
cd$all_plus ./
cd$all_plus bar/
cd$all_plus bar/baz/
>f$all_plus bar/baz/rsync
cd$all_plus foo/
>f$all_plus foo/config1
>f$all_plus foo/config2
>f$all_plus foo/extra
cL$all_plus foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
@@ -73,10 +71,10 @@ chmod 601 "$fromdir/foo/config2"
$RSYNC -iplrH "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
>f..T...... bar/baz/rsync
>f..T...... foo/config1
>f.sTp..... foo/config2
hf..T...... foo/extra => foo/config1
>f..T.$dots bar/baz/rsync
>f..T.$dots foo/config1
>f.sTp$dots foo/config2
hf..T.$dots foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
@@ -93,11 +91,11 @@ chmod 777 "$todir/bar/baz/rsync"
$RSYNC -iplrtc "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.f..tp..... bar/baz/rsync
.d..t...... foo/
.f..t...... foo/config1
>fcstp..... foo/config2
cL.$T...... foo/sym -> ../bar/baz/rsync
.f..tp$dots bar/baz/rsync
.d..t.$dots foo/
.f..t.$dots foo/config1
>fcstp$dots foo/config2
cLc$T.$dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -122,15 +120,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d ./
.d bar/
.d bar/baz/
.f...p..... bar/baz/rsync
.d foo/
.f foo/config1
>f..t...... foo/config2
hf foo/extra
.L foo/sym -> ../bar/baz/rsync
.d$allspace ./
.d$allspace bar/
.d$allspace bar/baz/
.f...p$dots bar/baz/rsync
.d$allspace foo/
.f$allspace foo/config1
>f..t.$dots foo/config2
hf$allspace foo/extra
.L$allspace foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
@@ -149,8 +147,8 @@ touch "$todir/foo/config2"
$RSYNC -iplrtH "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.f...p..... foo/config1
>f..t...... foo/config2
.f...p$dots foo/config1
>f..t.$dots foo/config2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
@@ -158,29 +156,29 @@ $RSYNC -ivvplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
case `tail -1 "$outfile"` in
cL..t*)
sym_dots='..t......'
L_sym_dots='cL..t......'
cLc.t*)
sym_dots="c.t.$dots"
L_sym_dots="cL$sym_dots"
is_uptodate='-> ../bar/baz/rsync'
echo "cL$sym_dots foo/sym $is_uptodate" >"$chkfile.extra"
L=cL
;;
*)
sym_dots=' '
L_sym_dots='.L '
sym_dots="$allspace"
L_sym_dots=".L$allspace"
is_uptodate='is uptodate'
touch "$chkfile.extra"
;;
esac
cat <<EOT >"$chkfile"
cd ./
cd bar/
cd bar/baz/
cf bar/baz/rsync
cd foo/
cf foo/config1
cf foo/config2
hf foo/extra => foo/config1
cd$allspace ./
cd$allspace bar/
cd$allspace bar/baz/
cf$allspace bar/baz/rsync
cd$allspace foo/
cf$allspace foo/config1
cf$allspace foo/config2
hf$allspace foo/extra => foo/config1
cL$sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
@@ -189,7 +187,7 @@ rm -rf "$to2dir"
$RSYNC -iplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
hf foo/extra => foo/config1
hf$allspace foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
@@ -215,14 +213,14 @@ $RSYNC -ivvplrtH --link-dest="$todir" "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
cd ./
cd bar/
cd bar/baz/
hf bar/baz/rsync
cd foo/
hf foo/config1
hf foo/config2
hf foo/extra => foo/config1
cd$allspace ./
cd$allspace bar/
cd$allspace bar/baz/
hf$allspace bar/baz/rsync
cd$allspace foo/
hf$allspace foo/config1
hf$allspace foo/config2
hf$allspace foo/extra => foo/config1
$L$sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
@@ -263,14 +261,14 @@ $RSYNC -ivvplrtH --compare-dest="$todir" "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
cd ./
cd bar/
cd bar/baz/
.f bar/baz/rsync
cd foo/
.f foo/config1
.f foo/config2
.f foo/extra
cd$allspace ./
cd$allspace bar/
cd$allspace bar/baz/
.f$allspace bar/baz/rsync
cd$allspace foo/
.f$allspace foo/config1
.f$allspace foo/config2
.f$allspace foo/extra
$L_sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"

View File

@@ -19,15 +19,15 @@ mkdir from2/sub1 from3/sub1
mkdir from3/sub2 from1/dir-and-not-dir
mkdir chk chk/sub1 chk/sub2 chk/dir-and-not-dir
echo "one" >from1/one
cp -p from1/one from2/one
cp -p from1/one from3/one
cp_touch from1/one from2/one
cp_touch from1/one from3/one
echo "two" >from1/two
echo "three" >from2/three
echo "four" >from3/four
echo "five" >from1/five
echo "six" >from3/six
echo "sub1" >from2/sub1/uno
cp -p from2/sub1/uno from3/sub1/uno
cp_touch from2/sub1/uno from3/sub1/uno
echo "sub2" >from3/sub1/dos
echo "sub3" >from2/sub1/tres
echo "subby" >from3/sub2/subby
@@ -36,11 +36,11 @@ echo "not-dir" >from3/dir-and-not-dir
echo "arg-test" >deep/arg-test
echo "shallow" >shallow
cp -p from1/one from1/two from2/three from3/four from1/five from3/six chk
cp -p deep/arg-test shallow chk
cp -p from1/dir-and-not-dir/inside chk/dir-and-not-dir
cp -p from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1
cp -p from3/sub2/subby chk/sub2
cp_touch from1/one from1/two from2/three from3/four from1/five from3/six chk
cp_touch deep/arg-test shallow chk
cp_touch from1/dir-and-not-dir/inside chk/dir-and-not-dir
cp_touch from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1
cp_touch from3/sub2/subby chk/sub2
# Make sure that time has moved on.
sleep 1
@@ -51,7 +51,7 @@ $RSYNC -av --existing -f 'exclude,! */' from2/ from3/
$RSYNC -av --existing -f 'exclude,! */' from1/ chk/
$RSYNC -av --existing -f 'exclude,! */' from3/ chk/
checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" chk to
checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

27
testsuite/missing.test Normal file
View File

@@ -0,0 +1,27 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test three bugs fixed by my redoing of the missing_below logic.
. $srcdir/testsuite/rsync.fns
makepath "$fromdir/subdir" "$todir"
echo data >"$fromdir/subdir/file"
echo data >"$todir/other"
# Test 1: Too much "not creating new..." output on a dry run
$RSYNC -n -r --ignore-non-existing -vv "$fromdir/" "$todir/" | tee "$scratchdir/out"
if grep 'not creating new.*subdir/file' "$scratchdir/out" >/dev/null; then
test_fail 'test 1 failed'
fi
# Test 2: Attempt to make a fuzzy dirlist for a dir not created on a dry run
$RSYNC -n -r -R --no-implied-dirs -y "$fromdir/./subdir/file" "$todir/" \
|| test_fail 'test 2 failed'
# Test 3: --delete-after pass skipped when last dir is dry-missing
$RSYNC -n -r --delete-after -i "$fromdir/" "$todir/" | tee "$scratchdir/out"
grep '^\*deleting * other' "$scratchdir/out" >/dev/null \
|| test_fail 'test 3 failed'

View File

@@ -23,6 +23,11 @@ fromdir="$tmpdir/from"
todir="$tmpdir/to"
chkdir="$tmpdir/chk"
# For itemized output:
all_plus='+++++++++'
allspace=' '
dots='.....' # trailing dots after changes
# Berkley's nice.
PATH="$PATH:/usr/ucb"
@@ -47,6 +52,29 @@ runtest() {
fi
}
set_cp_destdir() {
while test $# -gt 1; do
shift
done
destdir="$1"
}
# Perform a "cp -p", making sure that timestamps are really the same,
# even if the copy rounded microsecond times on the destination file.
cp_touch() {
cp -p "${@}" || test_fail "cp -p failed"
if test $# -gt 2 -o -d "$2"; then
set_cp_destdir "${@}" # sets destdir var
while test $# -gt 1; do
destname="$destdir/`basename $1`"
touch -r "$destname" "$1" "$destname"
shift
done
else
touch -r "$2" "$1" "$2"
fi
}
# Call this if you want to filter out verbose messages (-v or -vv) from
# the output of an rsync run (whittling the output down to just the file
# messages). This isn't needed if you use -i without -v.
@@ -72,6 +100,10 @@ rsync_ls_lR() {
find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
}
get_testuid() {
id 2>/dev/null | sed 's/^[^0-9]*\([0-9][0-9]*\).*/\1/'
}
check_perms() {
perms=`"$TOOLDIR/tls" "$1" | sed 's/^[-d]\(.........\).*/\1/'`
if test $perms = $2; then
@@ -239,7 +271,7 @@ hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
log file = $logfile
log format = %i %h [%a] %m (%u) %l %f%L
transfer logging = yes
exclude = foobar.baz
exclude = ? foobar.baz
max verbosity = 9
uid = 0
gid = 0
@@ -247,14 +279,20 @@ gid = 0
[test-from]
path = $fromdir
read only = yes
comment = r/o
[test-to]
path = $todir
read only = no
comment = r/w
[test-scratch]
path = $scratchdir
read only = no
[test-hidden]
path = $fromdir
list = no
EOF
# Build a helper script to ignore exit code 23

View File

@@ -10,20 +10,7 @@
. "$suitedir/rsync.fns"
SSH="$scratchdir/pretend-ssh"
cat >"$SSH" <<'EOT'
while : ; do
case "$1" in
-*) shift ;;
localhost) shift; break ;;
*) exit 1 ;;
esac
done
eval "${@}"
EOT
chmod +x "$SSH"
SSH="$scratchdir/src/support/lsh"
if test x"$rsync_enable_ssh_tests" = xyes; then
if type ssh >/dev/null ; then
@@ -31,7 +18,7 @@ if test x"$rsync_enable_ssh_tests" = xyes; then
fi
fi
if ! [ "`"$SSH" -o'BatchMode yes' localhost echo yes`" = "yes" ]; then
if [ "`$SSH -o'BatchMode yes' localhost echo yes`" != "yes" ]; then
test_skipped "Skipping SSH tests because ssh conection to localhost not authorised"
fi

View File

@@ -19,33 +19,41 @@ test_unsafe() {
fi
}
test_unsafe file from safe
test_unsafe dir/file from safe
test_unsafe dir/./file from safe
test_unsafe dir/. from safe
test_unsafe dir/ from safe
test_unsafe file from safe
test_unsafe dir/file from safe
test_unsafe dir/./file from safe
test_unsafe dir/. from safe
test_unsafe dir/ from safe
test_unsafe /etc/passwd from unsafe
test_unsafe //../etc/passwd from unsafe
test_unsafe //./etc/passwd from unsafe
test_unsafe /etc/passwd from unsafe
test_unsafe //../etc/passwd from unsafe
test_unsafe //./etc/passwd from unsafe
test_unsafe ./foo from safe
test_unsafe ../foo from unsafe
test_unsafe ../dest from/dir safe
test_unsafe ./foo from safe
test_unsafe ../foo from unsafe
test_unsafe ./../foo from unsafe
test_unsafe .//../foo from unsafe
test_unsafe ./../foo from/.. unsafe
test_unsafe ../dest from/dir safe
test_unsafe ../../dest from//dir unsafe
test_unsafe ..//../dest from/dir unsafe
test_unsafe .. from/file safe
test_unsafe ../.. from/file unsafe
test_unsafe dir/.. from safe
test_unsafe dir/../.. from unsafe
test_unsafe .. from/file safe
test_unsafe ../.. from/file unsafe
test_unsafe ..//.. from//file unsafe
test_unsafe dir/.. from safe
test_unsafe dir/../.. from unsafe
test_unsafe dir/..//.. from unsafe
test_unsafe '' from unsafe
test_unsafe '' from unsafe
# Based on tests from unsafe-links by Vladim<69>r Michl
test_unsafe ../../unsafe/unsafefile from/safe unsafe
test_unsafe ../files/file1 from/safe safe
test_unsafe ../../unsafe/unsafefile from/safe unsafe
test_unsafe ..//../unsafe/unsafefile from/safe unsafe
test_unsafe ../files/file1 from/safe safe
test_unsafe ../../unsafe/unsafefile safe unsafe
test_unsafe ../files/file1 safe unsafe
test_unsafe ../../unsafe/unsafefile safe unsafe
test_unsafe ../files/file1 safe unsafe
test_unsafe ../../unsafe/unsafefile `pwd`/from/safe safe
test_unsafe ../files/file1 `pwd`/from/safe safe
test_unsafe ../../unsafe/unsafefile `pwd`/from/safe safe
test_unsafe ../files/file1 `pwd`/from/safe safe

View File

@@ -20,6 +20,7 @@ case "`xattr 2>&1`" in
xls() {
xattr -l "${@}"
}
RUSR='rsync.nonuser'
;;
*)
xset() {
@@ -31,6 +32,7 @@ case "`xattr 2>&1`" in
xls() {
getfattr -d "${@}"
}
RUSR='user.rsync'
;;
esac
@@ -44,7 +46,7 @@ echo deeper >"$fromdir/foo/bar/file5"
makepath "$chkdir/foo"
echo wow >"$chkdir/file1"
cp -p "$fromdir/foo/file3" "$chkdir/foo"
cp_touch "$fromdir/foo/file3" "$chkdir/foo"
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
@@ -62,43 +64,84 @@ xset user.foo foo file2
xset user.bar bar file2
xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
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.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 user.equal 'this long attribute should remain the same and not need to be transferred' 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.short 'old short' "$chkdir/file1"
xset user.extra 'remove me' "$chkdir/file1"
xset user.foo 'old foo' "$chkdir/foo/file3"
xset user.equal 'this long attribute should remain the same and not need to be transferred' "$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"
# OK, let's try a simple xattr copy.
checkit "$RSYNC -avX . '$chkdir/'" "$fromdir" "$chkdir"
checkit "$RSYNC -avX --super . '$chkdir/'" "$fromdir" "$chkdir"
cd "$chkdir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
checkit "$RSYNC -aiX --copy-dest=../chk . ../to" "$fromdir" "$todir"
checkit "$RSYNC -aiX --super --copy-dest=../chk . ../to" "$fromdir" "$todir"
cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
xset user.nice 'this is nice, but different' file1
xls $files >"$scratchdir/xattrs.txt"
rm -rf "$todir"
checkit "$RSYNC -aiX --link-dest=../chk . ../to" "$chkdir" "$todir"
xset user.nice 'this is nice, but different' file1
checkit "$RSYNC -aiX --fake-super . ../chk" "$fromdir" "$chkdir"
cd "$chkdir"
xls $files >"$scratchdir/xattrs.txt"
cd "$fromdir"
checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
sed -n -e '/\.\/file1$/d' -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff"
if [ -s "$scratchdir/ls-diff" ]; then
echo "Missing hard links on:"
cat "$scratchdir/ls-diff"
exit 1
fi
cd "$fromdir"
rm -rf "$todir" "$chkdir"
$RSYNC -aX file1 file2
$RSYNC -aX file1 file2 ../chk/
$RSYNC -aX --del ../chk/ .
$RSYNC -aX file1 ../lnk/
xls file1 file2 >"$scratchdir/xattrs.txt"
checkit "$RSYNC -aiiX --copy-dest=../lnk . ../to" "$chkdir" "$todir"
cd "$todir"
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
rm "$todir/file2"
echo extra >file1
$RSYNC -aX . ../chk/
checkit "$RSYNC -aiiX . ../to" "$chkdir" "$todir"
cd "$todir"
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
# The script would have aborted on error, so getting here means we've won.
exit 0

18
tls.c
View File

@@ -2,7 +2,7 @@
* Trivial ls for comparing two directories after running an rsync.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -35,7 +35,7 @@
* change. */
#include "rsync.h"
#include "popt.h"
#include <popt.h>
#include "lib/sysxattrs.h"
#define PROGRAM "tls"
@@ -45,6 +45,8 @@ int dry_run = 0;
int am_root = 0;
int read_only = 1;
int list_only = 0;
int link_times = 0;
int link_owner = 0;
int preserve_perms = 0;
int preserve_executability = 0;
@@ -134,12 +136,14 @@ static void list_file(const char *fname)
/* On some BSD platforms the mode bits of a symlink are
* undefined. Also it tends not to be possible to reset a
* symlink's mtime, so we have to ignore it too. */
* symlink's mtime, so we default to ignoring it too. */
if (S_ISLNK(buf.st_mode)) {
int len;
buf.st_mode &= ~0777;
buf.st_mtime = (time_t)0;
buf.st_uid = buf.st_gid = 0;
if (!link_times)
buf.st_mtime = (time_t)0;
if (!link_owner)
buf.st_uid = buf.st_gid = 0;
strlcpy(linkbuf, " -> ", sizeof linkbuf);
/* const-cast required for silly UNICOS headers */
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
@@ -184,6 +188,8 @@ static void list_file(const char *fname)
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"link-times", 'l', POPT_ARG_NONE, &link_times, 0, 0, 0 },
{"link-owner", 'L', POPT_ARG_NONE, &link_owner, 0, 0, 0 },
#ifdef SUPPORT_XATTRS
{"fake-super", 'f', POPT_ARG_VAL, &am_root, -1, 0, 0 },
#endif
@@ -197,6 +203,8 @@ static void tls_usage(int ret)
fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
fprintf(F,"Trivial file listing program for portably checking rsync\n");
fprintf(F,"\nOptions:\n");
fprintf(F," -l, --link-times display the time on a symlink\n");
fprintf(F," -L, --link-owner display the owner+group on a symlink\n");
#ifdef SUPPORT_XATTRS
fprintf(F," -f, --fake-super display attributes including fake-super xattrs\n");
#endif

15
token.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -45,12 +45,12 @@ static void add_suffix(struct suffix_tree **prior, char ltr, const char *str)
if (ltr == '[') {
const char *after = strchr(str, ']');
/* Just skip bogus character classes. */
if (!after++)
/* Treat "[foo" and "[]" as having a literal '['. */
if (after && after++ != str+1) {
while ((ltr = *str++) != ']')
add_suffix(prior, ltr, after);
return;
while ((ltr = *str++) != ']')
add_suffix(prior, ltr, after);
return;
}
}
for (node = *prior; node; prior = &node->sibling, node = node->sibling) {
@@ -100,7 +100,6 @@ static void add_nocompress_suffixes(const char *str)
} while (*++f != '/' && *f);
*t++ = '\0';
fprintf(stderr, "adding `%s'\n", buf);
add_suffix(&suftree, *buf, buf+1);
}
@@ -599,7 +598,7 @@ static void see_deflate_token(char *buf, int32 len)
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
r = inflate(&rx_strm, Z_SYNC_FLUSH);
if (r != Z_OK) {
if (r != Z_OK && r != Z_BUF_ERROR) {
rprintf(FERROR, "inflate (token) returned %d\n", r);
exit_cleanup(RERR_STREAMIO);
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2009 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

564
util.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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
@@ -29,11 +29,12 @@ extern int module_id;
extern int modify_window;
extern int relative_paths;
extern int human_readable;
extern int preserve_xattrs;
extern char *module_dir;
extern unsigned int module_dirlen;
extern mode_t orig_umask;
extern char *partial_dir;
extern struct filter_list_struct server_filter_list;
extern struct filter_list_struct daemon_filter_list;
int sanitize_paths = 0;
@@ -264,6 +265,8 @@ static int safe_read(int desc, char *ptr, size_t len)
/* Copy a file. If ofd < 0, copy_file unlinks and opens the "dest" file.
* Otherwise, it just writes to and closes the provided file descriptor.
* In either case, if --xattrs are being preserved, the dest file will
* have its xattrs set from the source file.
*
* This is used in conjunction with the --temp-dir, --backup, and
* --copy-dest options. */
@@ -275,38 +278,54 @@ int copy_file(const char *source, const char *dest, int ofd,
int len; /* Number of bytes read into `buf'. */
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
errno = save_errno;
return -1;
}
if (ofd < 0) {
if (robust_unlink(dest) && errno != ENOENT) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
errno = save_errno;
return -1;
}
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest));
close(ifd);
return -1;
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
close(ifd);
errno = save_errno;
return -1;
}
}
}
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
close(ifd);
close(ofd);
errno = save_errno;
return -1;
}
}
if (len < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
close(ifd);
close(ofd);
errno = save_errno;
return -1;
}
@@ -316,11 +335,18 @@ int copy_file(const char *source, const char *dest, int ofd,
}
if (close(ofd) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "close failed on %s",
full_fname(dest));
errno = save_errno;
return -1;
}
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
copy_xattrs(source, dest);
#endif
return 0;
}
@@ -401,14 +427,17 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
switch (errno) {
#ifdef ETXTBSY
case ETXTBSY:
if (robust_unlink(to) != 0)
if (robust_unlink(to) != 0) {
errno = ETXTBSY;
return -1;
}
errno = ETXTBSY;
break;
#endif
case EXDEV:
if (partialptr) {
if (!handle_partial_dir(partialptr,PDIR_CREATE))
return -1;
return -2;
to = partialptr;
}
if (copy_file(from, to, -1, mode, 0) != 0)
@@ -503,82 +532,172 @@ int lock_range(int fd, int offset, int len)
return fcntl(fd,F_SETLK,&lock) == 0;
}
static int filter_server_path(char *arg)
{
char *s;
#define ENSURE_MEMSPACE(buf, type, sz, req) \
if ((req) > sz && !(buf = realloc_array(buf, type, sz = MAX(sz * 2, req)))) \
out_of_memory("glob_expand")
if (server_filter_list.head) {
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
*s = '\0';
if (check_filter(&server_filter_list, arg, 1) < 0) {
/* We must leave arg truncated! */
return 1;
}
*s++ = '/';
static inline void call_glob_match(const char *name, int len, int from_glob,
char *arg, int abpos, int fbpos);
static struct glob_data {
char *arg_buf, *filt_buf, **argv;
int absize, fbsize, maxargs, argc;
} glob;
static void glob_match(char *arg, int abpos, int fbpos)
{
int len;
char *slash;
while (*arg == '.' && arg[1] == '/') {
if (fbpos < 0) {
ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, glob.absize);
memcpy(glob.filt_buf, glob.arg_buf, abpos + 1);
fbpos = abpos;
}
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + 3);
glob.arg_buf[abpos++] = *arg++;
glob.arg_buf[abpos++] = *arg++;
glob.arg_buf[abpos] = '\0';
}
return 0;
if ((slash = strchr(arg, '/')) != NULL) {
*slash = '\0';
len = slash - arg;
} else
len = strlen(arg);
if (strpbrk(arg, "*?[")) {
struct dirent *di;
DIR *d;
if (!(d = opendir(abpos ? glob.arg_buf : ".")))
return;
while ((di = readdir(d)) != NULL) {
char *dname = d_name(di);
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
continue;
if (!wildmatch(arg, dname))
continue;
call_glob_match(dname, strlen(dname), 1,
slash ? arg + len + 1 : NULL,
abpos, fbpos);
}
closedir(d);
} else {
call_glob_match(arg, len, 0,
slash ? arg + len + 1 : NULL,
abpos, fbpos);
}
if (slash)
*slash = '/';
}
void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
static inline void call_glob_match(const char *name, int len, int from_glob,
char *arg, int abpos, int fbpos)
{
char **argv = *argv_ptr;
int argc = *argc_ptr;
int maxargs = *maxargs_ptr;
#if !defined HAVE_GLOB || !defined HAVE_GLOB_H
if (argc == maxargs) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("glob_expand");
*argv_ptr = argv;
*maxargs_ptr = maxargs;
}
if (!*s)
s = ".";
s = argv[argc++] = strdup(s);
filter_server_path(s);
#else
glob_t globbuf;
char *use_buf;
if (maxargs <= argc)
return;
if (!*s)
s = ".";
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + len + 2);
memcpy(glob.arg_buf + abpos, name, len);
abpos += len;
glob.arg_buf[abpos] = '\0';
if (fbpos >= 0) {
ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, fbpos + len + 2);
memcpy(glob.filt_buf + fbpos, name, len);
fbpos += len;
glob.filt_buf[fbpos] = '\0';
use_buf = glob.filt_buf;
} else
use_buf = glob.arg_buf;
if (from_glob || (arg && len)) {
STRUCT_STAT st;
int is_dir;
if (do_stat(glob.arg_buf, &st) != 0)
return;
is_dir = S_ISDIR(st.st_mode) != 0;
if (arg && !is_dir)
return;
if (daemon_filter_list.head
&& check_filter(&daemon_filter_list, FLOG, use_buf, is_dir) < 0)
return;
}
if (arg) {
glob.arg_buf[abpos++] = '/';
glob.arg_buf[abpos] = '\0';
if (fbpos >= 0) {
glob.filt_buf[fbpos++] = '/';
glob.filt_buf[fbpos] = '\0';
}
glob_match(arg, abpos, fbpos);
} else {
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
if (!(glob.argv[glob.argc++] = strdup(glob.arg_buf)))
out_of_memory("glob_match");
}
}
/* This routine performs wild-card expansion of the pathname in "arg". Any
* daemon-excluded files/dirs will not be matched by the wildcards. Returns 0
* if a wild-card string is the only returned item (due to matching nothing). */
int glob_expand(const char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
{
int ret, save_argc;
char *s;
if (!arg) {
if (glob.filt_buf)
free(glob.filt_buf);
free(glob.arg_buf);
memset(&glob, 0, sizeof glob);
return -1;
}
if (sanitize_paths)
s = sanitize_path(NULL, s, "", 0);
else
s = strdup(s);
if (!s)
out_of_memory("glob_expand");
memset(&globbuf, 0, sizeof globbuf);
if (!filter_server_path(s))
glob(s, 0, NULL, &globbuf);
if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) {
maxargs += globbuf.gl_pathc + MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("glob_expand");
*argv_ptr = argv;
*maxargs_ptr = maxargs;
}
if (globbuf.gl_pathc == 0)
argv[argc++] = s;
s = sanitize_path(NULL, arg, "", 0, SP_KEEP_DOT_DIRS);
else {
int i;
free(s);
for (i = 0; i < (int)globbuf.gl_pathc; i++) {
if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
out_of_memory("glob_expand");
}
s = strdup(arg);
if (!s)
out_of_memory("glob_expand");
clean_fname(s, CFN_KEEP_DOT_DIRS
| CFN_KEEP_TRAILING_SLASH
| CFN_COLLAPSE_DOT_DOT_DIRS);
}
globfree(&globbuf);
#endif
*argc_ptr = argc;
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, MAXPATHLEN);
*glob.arg_buf = '\0';
glob.argc = save_argc = *argc_p;
glob.argv = *argv_p;
glob.maxargs = *maxargs_p;
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, 100);
glob_match(s, 0, -1);
/* The arg didn't match anything, so add the failed arg to the list. */
if (glob.argc == save_argc) {
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
glob.argv[glob.argc++] = s;
ret = 0;
} else {
free(s);
ret = 1;
}
*maxargs_p = glob.maxargs;
*argv_p = glob.argv;
*argc_p = glob.argc;
return ret;
}
/* This routine is only used in daemon mode. */
void glob_expand_module(char *base1, char *arg, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
void glob_expand_module(char *base1, char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
{
char *p, *s;
char *base = base1;
@@ -600,7 +719,7 @@ void glob_expand_module(char *base1, char *arg, char ***argv_ptr, int *argc_ptr,
for (s = arg; *s; s = p + base_len) {
if ((p = strstr(s, base)) != NULL)
*p = '\0'; /* split it at this point */
glob_expand(s, argv_ptr, argc_ptr, maxargs_ptr);
glob_expand(s, argv_p, argc_p, maxargs_p);
if (!p)
break;
}
@@ -687,13 +806,14 @@ int count_dir_elements(const char *p)
return cnt;
}
/* Turns multiple adjacent slashes into a single slash, drops interior "."
* elements, drops an intial "./" unless CFN_KEEP_LEADING_DOT_DIR is flagged,
* will even drop a trailing '.' after a '/' if CFN_DROP_TRAILING_DOT_DIR is
* flagged, removes a trailing slash (perhaps after removing the aforementioned
* dot) unless CFN_KEEP_TRAILING_SLASH is flagged, will even collapse ".."
* elements (except at the start of the string) if CFN_COLLAPSE_DOT_DOT_DIRS
* is flagged. If the resulting name would be empty, we return ".". */
/* Turns multiple adjacent slashes into a single slash (possible exception:
* the preserving of two leading slashes at the start), drops all leading or
* interior "." elements unless CFN_KEEP_DOT_DIRS is flagged. Will also drop
* a trailing '.' after a '/' if CFN_DROP_TRAILING_DOT_DIR is flagged, removes
* a trailing slash (perhaps after removing the aforementioned dot) unless
* CFN_KEEP_TRAILING_SLASH is flagged, and will also collapse ".." elements
* (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged. If the
* resulting name would be empty, returns ".". */
unsigned int clean_fname(char *name, int flags)
{
char *limit = name - 1, *t = name, *f = name;
@@ -702,9 +822,16 @@ unsigned int clean_fname(char *name, int flags)
if (!name)
return 0;
if ((anchored = *f == '/') != 0)
if ((anchored = *f == '/') != 0) {
*t++ = *f++;
else if (flags & CFN_KEEP_LEADING_DOT_DIR && *f == '.' && f[1] == '/') {
#ifdef __CYGWIN__
/* If there are exactly 2 slashes at the start, preserve
* them. Would break daemon excludes unless the paths are
* really treated differently, so used this sparingly. */
if (*f == '/' && f[1] != '/')
*t++ = *f++;
#endif
} else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {
*t++ = *f++;
*t++ = *f++;
}
@@ -716,7 +843,7 @@ unsigned int clean_fname(char *name, int flags)
}
if (*f == '.') {
/* discard interior "." dirs */
if (f[1] == '/') {
if (f[1] == '/' && !(flags & CFN_KEEP_DOT_DIRS)) {
f += 2;
continue;
}
@@ -773,10 +900,11 @@ unsigned int clean_fname(char *name, int flags)
* ALWAYS collapses ".." elements (except for those at the start of the
* string up to "depth" deep). If the resulting name would be empty,
* change it into a ".". */
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
int flags)
{
char *start, *sanp;
int rlen = 0, leave_one_dotdir = relative_paths;
int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
if (dest != p) {
int plen = strlen(p);
@@ -799,21 +927,22 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
}
}
if (drop_dot_dirs) {
while (*p == '.' && p[1] == '/')
p += 2;
}
start = sanp = dest + rlen;
/* This loop iterates once per filename component in p, pointing at
* the start of the name (past any prior slash) for each iteration. */
while (*p) {
/* discard leading or extra slashes */
if (*p == '/') {
p++;
continue;
}
/* this loop iterates once per filename component in p.
* both p (and sanp if the original had a slash) should
* always be left pointing after a slash
*/
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
if (leave_one_dotdir && p[1])
leave_one_dotdir = 0;
else {
if (drop_dot_dirs) {
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
p++;
continue;
@@ -826,10 +955,8 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
if (sanp != start) {
/* back up sanp one level */
--sanp; /* now pointing at slash */
while (sanp > start && sanp[-1] != '/') {
/* skip back up to slash */
while (sanp > start && sanp[-1] != '/')
sanp--;
}
}
continue;
}
@@ -853,14 +980,17 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
/* Like chdir(), but it keeps track of the current directory (in the
* global "curr_dir"), and ensures that the path size doesn't overflow.
* Also cleans the path using the clean_fname() function. */
int push_dir(const char *dir, int set_path_only)
int change_dir(const char *dir, int set_path_only)
{
static int initialised;
unsigned int len;
if (!initialised) {
initialised = 1;
getcwd(curr_dir, sizeof curr_dir - 1);
if (getcwd(curr_dir, sizeof curr_dir - 1) == NULL) {
rsyserr(FERROR, errno, "getcwd()");
exit_cleanup(RERR_FILESELECT);
}
curr_dir_len = strlen(curr_dir);
}
@@ -871,21 +1001,26 @@ int push_dir(const char *dir, int set_path_only)
if (len == 1 && *dir == '.')
return 1;
if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir) {
errno = ENAMETOOLONG;
return 0;
}
if (!set_path_only && chdir(dir))
return 0;
if (*dir == '/') {
if (len >= sizeof curr_dir) {
errno = ENAMETOOLONG;
return 0;
}
if (!set_path_only && chdir(dir))
return 0;
memcpy(curr_dir, dir, len + 1);
curr_dir_len = len;
} else {
curr_dir[curr_dir_len++] = '/';
memcpy(curr_dir + curr_dir_len, dir, len + 1);
curr_dir_len += len;
if (curr_dir_len + 1 + len >= sizeof curr_dir) {
errno = ENAMETOOLONG;
return 0;
}
curr_dir[curr_dir_len] = '/';
memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
if (!set_path_only && chdir(curr_dir)) {
curr_dir[curr_dir_len] = '\0';
return 0;
}
}
curr_dir_len = clean_fname(curr_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
@@ -896,30 +1031,37 @@ int push_dir(const char *dir, int set_path_only)
}
if (verbose >= 5 && !set_path_only)
rprintf(FINFO, "[%s] push_dir(%s)\n", who_am_i(), curr_dir);
rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir);
return 1;
}
/**
* Reverse a push_dir() call. You must pass in an absolute path
* that was copied from a prior value of "curr_dir".
**/
int pop_dir(const char *dir)
/* This will make a relative path absolute and clean it up via clean_fname().
* Returns the string, which might be newly allocated, or NULL on error. */
char *normalize_path(char *path, BOOL force_newbuf, unsigned int *len_ptr)
{
if (chdir(dir))
return 0;
unsigned int len;
curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
if (curr_dir_len >= sizeof curr_dir)
curr_dir_len = sizeof curr_dir - 1;
if (sanitize_paths)
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
if (*path != '/') { /* Make path absolute. */
int len = strlen(path);
if (curr_dir_len + 1 + len >= sizeof curr_dir)
return NULL;
curr_dir[curr_dir_len] = '/';
memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
if (!(path = strdup(curr_dir)))
out_of_memory("normalize_path");
curr_dir[curr_dir_len] = '\0';
} else if (force_newbuf) {
if (!(path = strdup(path)))
out_of_memory("normalize_path");
}
if (verbose >= 5)
rprintf(FINFO, "[%s] pop_dir(%s)\n", who_am_i(), curr_dir);
len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
return 1;
if (len_ptr)
*len_ptr = len;
return path;
}
/**
@@ -977,13 +1119,13 @@ char *partial_dir_fname(const char *fname)
fn = fname;
if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
return NULL;
if (server_filter_list.head) {
if (daemon_filter_list.head) {
t = strrchr(partial_fname, '/');
*t = '\0';
if (check_filter(&server_filter_list, partial_fname, 1) < 0)
if (check_filter(&daemon_filter_list, FLOG, partial_fname, 1) < 0)
return NULL;
*t = '/';
if (check_filter(&server_filter_list, partial_fname, 0) < 0)
if (check_filter(&daemon_filter_list, FLOG, partial_fname, 0) < 0)
return NULL;
}
@@ -1009,12 +1151,16 @@ int handle_partial_dir(const char *fname, int create)
STRUCT_STAT st;
int statret = do_lstat(dir, &st);
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (do_unlink(dir) < 0)
if (do_unlink(dir) < 0) {
*fn = '/';
return 0;
}
statret = -1;
}
if (statret < 0 && do_mkdir(dir, 0700) < 0)
if (statret < 0 && do_mkdir(dir, 0700) < 0) {
*fn = '/';
return 0;
}
} else
do_rmdir(dir);
*fn = '/';
@@ -1022,12 +1168,13 @@ int handle_partial_dir(const char *fname, int create)
return 1;
}
/**
* Determine if a symlink points outside the current directory tree.
/* Determine if a symlink points outside the current directory tree.
* This is considered "unsafe" because e.g. when mirroring somebody
* else's machine it might allow them to establish a symlink to
* /etc/passwd, and then read it through a web server.
*
* Returns 1 if unsafe, 0 if safe.
*
* Null symlinks and absolute symlinks are always unsafe.
*
* Basically here we are concerned with symlinks whose target contains
@@ -1035,17 +1182,11 @@ int handle_partial_dir(const char *fname, int create)
* transferred directory. We are not allowed to go back up and
* reenter.
*
* @param dest Target of the symlink in question.
* "dest" is the target of the symlink in question.
*
* @param src Top source directory currently applicable. Basically this
* is the first parameter to rsync in a simple invocation, but it's
* modified by flist.c in slightly complex ways.
*
* @retval True if unsafe
* @retval False is unsafe
*
* @sa t_unsafe.c
**/
* "src" is the top source directory currently applicable at the level
* of the referenced symlink. This is usually the symlink's full path
* (including its name), as referenced from the root of the transfer. */
int unsafe_symlink(const char *dest, const char *src)
{
const char *name, *slash;
@@ -1057,35 +1198,57 @@ int unsafe_symlink(const char *dest, const char *src)
/* find out what our safety margin is */
for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
if (strncmp(name, "../", 3) == 0) {
depth = 0;
} else if (strncmp(name, "./", 2) == 0) {
/* nothing */
} else {
/* ".." segment starts the count over. "." segment is ignored. */
if (*name == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))) {
if (name[1] == '.')
depth = 0;
} else
depth++;
}
while (slash[1] == '/') slash++; /* just in case src isn't clean */
}
if (strcmp(name, "..") == 0)
if (*name == '.' && name[1] == '.' && name[2] == '\0')
depth = 0;
for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
if (strncmp(name, "../", 3) == 0) {
/* if at any point we go outside the current directory
then stop - it is unsafe */
if (--depth < 0)
return 1;
} else if (strncmp(name, "./", 2) == 0) {
/* nothing */
} else {
if (*name == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))) {
if (name[1] == '.') {
/* if at any point we go outside the current directory
then stop - it is unsafe */
if (--depth < 0)
return 1;
}
} else
depth++;
}
while (slash[1] == '/') slash++;
}
if (strcmp(name, "..") == 0)
if (*name == '.' && name[1] == '.' && name[2] == '\0')
depth--;
return (depth < 0);
return depth < 0;
}
#define HUMANIFY(mult) \
do { \
if (num >= mult || num <= -mult) { \
double dnum = (double)num / mult; \
char units; \
if (num < 0) \
dnum = -dnum; \
if (dnum < mult) \
units = 'K'; \
else if ((dnum /= mult) < mult) \
units = 'M'; \
else { \
dnum /= mult; \
units = 'G'; \
} \
if (num < 0) \
dnum = -dnum; \
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \
return bufs[n]; \
} \
} while (0)
/* Return the int64 number as a string. If the --human-readable option was
* specified, we may output the number in K, M, or G units. We can return
* up to 4 buffers at a time. */
@@ -1094,27 +1257,15 @@ char *human_num(int64 num)
static char bufs[4][128]; /* more than enough room */
static unsigned int n;
char *s;
int negated;
n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
if (human_readable) {
char units = '\0';
int mult = human_readable == 1 ? 1000 : 1024;
double dnum = 0;
if (num > mult*mult*mult) {
dnum = (double)num / (mult*mult*mult);
units = 'G';
} else if (num > mult*mult) {
dnum = (double)num / (mult*mult);
units = 'M';
} else if (num > mult) {
dnum = (double)num / mult;
units = 'K';
}
if (units) {
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units);
return bufs[n];
}
if (human_readable == 1)
HUMANIFY(1000);
else
HUMANIFY(1024);
}
s = bufs[n] + sizeof bufs[0] - 1;
@@ -1122,10 +1273,23 @@ char *human_num(int64 num)
if (!num)
*--s = '0';
if (num < 0) {
/* A maximum-size negated number can't fit as a positive,
* so do one digit in negated form to start us off. */
*--s = (char)(-(num % 10)) + '0';
num = -(num / 10);
negated = 1;
} else
negated = 0;
while (num) {
*--s = (char)(num % 10) + '0';
num /= 10;
}
if (negated)
*--s = '-';
return s;
}
@@ -1138,8 +1302,8 @@ char *human_dnum(double dnum, int decimal_digits)
int len = strlen(buf);
if (isDigit(buf + len - 1)) {
/* There's extra room in buf prior to the start of the num. */
buf -= decimal_digits + 1;
snprintf(buf, len + decimal_digits + 2, "%.*f", decimal_digits, dnum);
buf -= decimal_digits + 2;
snprintf(buf, len + decimal_digits + 3, "%.*f", decimal_digits, dnum);
}
return buf;
}
@@ -1255,7 +1419,7 @@ void *_new_array(unsigned long num, unsigned int size, int use_calloc)
return use_calloc ? calloc(num, size) : malloc(num * size);
}
void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
void *_realloc_array(void *ptr, unsigned int size, size_t num)
{
if (num >= MALLOC_MAX/size)
return NULL;
@@ -1463,6 +1627,39 @@ int bitbag_next_bit(struct bitbag *bb, int after)
return -1;
}
void flist_ndx_push(flist_ndx_list *lp, int ndx)
{
struct flist_ndx_item *item;
if (!(item = new(struct flist_ndx_item)))
out_of_memory("flist_ndx_push");
item->next = NULL;
item->ndx = ndx;
if (lp->tail)
lp->tail->next = item;
else
lp->head = item;
lp->tail = item;
}
int flist_ndx_pop(flist_ndx_list *lp)
{
struct flist_ndx_item *next;
int ndx;
if (!lp->head)
return -1;
ndx = lp->head->ndx;
next = lp->head->next;
free(lp->head);
lp->head = next;
if (!next)
lp->tail = NULL;
return ndx;
}
void *expand_item_list(item_list *lp, size_t item_size,
const char *desc, int incr)
{
@@ -1476,7 +1673,10 @@ void *expand_item_list(item_list *lp, size_t item_size,
new_size += incr;
else
new_size *= 2;
new_ptr = realloc_array(lp->items, char, new_size * item_size);
if (new_size < lp->malloced)
overflow_exit("expand_item_list");
/* Using _realloc_array() lets us pass the size, not a type. */
new_ptr = _realloc_array(lp->items, item_size, new_size);
if (verbose >= 4) {
rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n",
who_am_i(), desc, (double)new_size * item_size,

View File

@@ -1,7 +1,7 @@
/*
* Test suite for the wildmatch code.
*
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2009 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

188
xattrs.c
View File

@@ -3,7 +3,7 @@
* Written by Jay Fenlason, vaguely based on the ACLs patch.
*
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2006, 2007 Wayne Davison
* Copyright (C) 2006-2009 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
@@ -44,9 +44,9 @@ extern int checksum_seed;
#define XATTR_ABBREV(x) ((size_t)((x).name - (x).datum) < (x).datum_len)
#define XSTATE_ABBREV 0
#define XSTATE_DONE 1
#define XSTATE_TODO 2
#define XSTATE_ABBREV 1
#define XSTATE_DONE 2
#define XSTATE_TODO 3
#define USER_PREFIX "user."
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
@@ -62,9 +62,12 @@ extern int checksum_seed;
#endif
#define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1)
#define XSTAT_ATTR RSYNC_PREFIX "%stat"
#define XACC_ACL_ATTR RSYNC_PREFIX "%aacl"
#define XDEF_ACL_ATTR RSYNC_PREFIX "%dacl"
#define XSTAT_SUFFIX "stat"
#define XSTAT_ATTR RSYNC_PREFIX "%" XSTAT_SUFFIX
#define XACC_ACL_SUFFIX "aacl"
#define XACC_ACL_ATTR RSYNC_PREFIX "%" XACC_ACL_SUFFIX
#define XDEF_ACL_SUFFIX "dacl"
#define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX
typedef struct {
char *datum, *name;
@@ -78,6 +81,8 @@ static char *namebuf = NULL;
static item_list empty_xattr = EMPTY_ITEM_LIST;
static item_list rsync_xal_l = EMPTY_ITEM_LIST;
static size_t prior_xattr_count = (size_t)-1;
/* ------------------------------------------------------------------------- */
static void rsync_xal_free(item_list *xalp)
@@ -175,8 +180,9 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
if (!datum_len && !extra_len)
extra_len = 1; /* request non-zero amount of memory */
if (datum_len + extra_len < datum_len /* checks for overflow */
|| !(ptr = new_array(char, datum_len + extra_len)))
if (datum_len + extra_len < datum_len)
overflow_exit("get_xattr_data");
if (!(ptr = new_array(char, datum_len + extra_len)))
out_of_memory("get_xattr_data");
if (datum_len) {
@@ -206,7 +212,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
size_t datum_len, name_offset;
char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
int user_only = am_sender ? 0 : !am_root;
int user_only = am_sender ? 0 : am_root <= 0;
#endif
rsync_xa *rxa;
int count;
@@ -231,7 +237,10 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
if (name_len > RPRE_LEN && name[RPRE_LEN] == '%'
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
if ((am_sender && preserve_xattrs < 2)
|| (am_root < 0 && strcmp(name, XSTAT_ATTR) == 0))
|| (am_root < 0
&& (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
|| strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
|| strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
continue;
}
@@ -253,14 +262,6 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
} else
name_offset = datum_len;
#ifdef HAVE_LINUX_XATTRS
if (am_root < 0 && name_len > RPRE_LEN && name[RPRE_LEN] != '%'
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
name += RPRE_LEN;
name_len -= RPRE_LEN;
}
#endif
rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
rxa->name = ptr + name_offset;
memcpy(rxa->name, name, name_len);
@@ -289,6 +290,48 @@ int get_xattr(const char *fname, stat_x *sxp)
return 0;
}
int copy_xattrs(const char *source, const char *dest)
{
ssize_t list_len, name_len;
size_t datum_len;
char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
int user_only = am_root <= 0;
#endif
/* This puts the name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(source)) < 0)
return -1;
for (name = namebuf; list_len > 0; name += name_len) {
name_len = strlen(name) + 1;
list_len -= name_len;
#ifdef HAVE_LINUX_XATTRS
/* We always ignore the system namespace, and non-root
* ignores everything but the user namespace. */
if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
: HAS_PREFIX(name, SYSTEM_PREFIX))
continue;
#endif
datum_len = 0;
if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
return -1;
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);
errno = save_errno;
return -1;
}
free(ptr);
}
return 0;
}
static int find_matching_xattr(item_list *xalp)
{
size_t i, j;
@@ -352,25 +395,32 @@ int send_xattr(stat_x *sxp, int f)
int count = sxp->xattr->count;
write_varint(f, count);
for (rxa = sxp->xattr->items; count--; rxa++) {
size_t name_len = rxa->name_len;
const char *name = rxa->name;
/* Strip the rsync prefix from disguised namespaces. */
if (name_len > RPRE_LEN
#ifdef HAVE_LINUX_XATTRS
write_varint(f, rxa->name_len);
write_varint(f, rxa->datum_len);
write_buf(f, rxa->name, rxa->name_len);
#else
/* We strip the rsync prefix from disguised namespaces
* and put everything else in the user namespace. */
if (HAS_PREFIX(rxa->name, RSYNC_PREFIX)
&& rxa->name[RPRE_LEN] != '%') {
write_varint(f, rxa->name_len - RPRE_LEN);
write_varint(f, rxa->datum_len);
write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN);
} else {
write_varint(f, rxa->name_len + UPRE_LEN);
write_varint(f, rxa->datum_len);
write_buf(f, USER_PREFIX, UPRE_LEN);
write_buf(f, rxa->name, rxa->name_len);
&& am_root < 0
#endif
&& name[RPRE_LEN] != '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
name += RPRE_LEN;
name_len -= RPRE_LEN;
}
#ifndef HAVE_LINUX_XATTRS
else {
/* Put everything else in the user namespace. */
name_len += UPRE_LEN;
}
#endif
write_varint(f, name_len);
write_varint(f, rxa->datum_len);
#ifndef HAVE_LINUX_XATTRS
if (name_len > rxa->name_len) {
write_buf(f, USER_PREFIX, UPRE_LEN);
name_len -= UPRE_LEN;
}
#endif
write_buf(f, name, name_len);
if (rxa->datum_len > MAX_FULL_DATUM)
write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
else
@@ -455,9 +505,11 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
return !xattrs_equal;
}
/* When called by the generator with a NULL fname, this tells the sender
* which abbreviated xattr values we need. When called by the sender
* (with a non-NULL fname), we send all the extra xattr data it needs. */
/* When called by the generator (with a NULL fname), this tells the sender
* all the abbreviated xattr values we need. When called by the sender
* (with a non-NULL fname), we send all the extra xattr data it needs.
* The generator may also call with f_out < 0 to just change all the
* XSTATE_ABBREV states into XSTATE_DONE. */
void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
{
item_list *lst = rsync_xal_l.items;
@@ -476,6 +528,7 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
rxa->datum[0] = XSTATE_DONE;
continue;
case XSTATE_TODO:
assert(f_out >= 0);
break;
default:
continue;
@@ -504,7 +557,8 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
}
}
write_byte(f_out, 0); /* end the list */
if (f_out >= 0)
write_byte(f_out, 0); /* end the list */
}
/* When called by the sender, read the request from the generator and mark
@@ -538,8 +592,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
who_am_i(), num, f_name(file, NULL));
exit_cleanup(RERR_STREAMIO);
}
if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i());
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);
}
@@ -552,7 +607,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
rxa->datum_len = read_varint(f_in);
if (rxa->name_len + rxa->datum_len < rxa->name_len)
out_of_memory("recv_xattr_request"); /* overflow */
overflow_exit("recv_xattr_request");
rxa->datum = new_array(char, rxa->datum_len + rxa->name_len);
if (!rxa->datum)
out_of_memory("recv_xattr_request");
@@ -574,6 +629,11 @@ void receive_xattr(struct file_struct *file, int f)
{
static item_list temp_xattr = EMPTY_ITEM_LIST;
int count, num;
#ifdef HAVE_LINUX_XATTRS
int need_sort = 0;
#else
int need_sort = 1;
#endif
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
@@ -599,10 +659,9 @@ void receive_xattr(struct file_struct *file, int f)
size_t datum_len = read_varint(f);
size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len;
size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0;
if (dget_len + extra_len < dget_len)
out_of_memory("receive_xattr"); /* overflow */
if (dget_len + extra_len + name_len < dget_len)
out_of_memory("receive_xattr"); /* overflow */
if ((dget_len + extra_len < dget_len)
|| (dget_len + extra_len + name_len < dget_len))
overflow_exit("receive_xattr");
ptr = new_array(char, dget_len + extra_len + name_len);
if (!ptr)
out_of_memory("receive_xattr");
@@ -624,6 +683,7 @@ void receive_xattr(struct file_struct *file, int f)
name -= RPRE_LEN;
name_len += RPRE_LEN;
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
need_sort = 1;
}
#else
/* This OS only has a user namespace, so we either
@@ -655,6 +715,9 @@ void receive_xattr(struct file_struct *file, int f)
rxa->num = num;
}
if (need_sort && count > 1)
qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
ndx = rsync_xal_l.count; /* pre-incremented count */
rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
@@ -663,13 +726,15 @@ void receive_xattr(struct file_struct *file, int f)
/* Turn the xattr data in stat_x into cached xattr data, setting the index
* values in the file struct. */
void cache_xattr(struct file_struct *file, stat_x *sxp)
void cache_tmp_xattr(struct file_struct *file, stat_x *sxp)
{
int ndx;
if (!sxp->xattr)
return;
if (prior_xattr_count == (size_t)-1)
prior_xattr_count = rsync_xal_l.count;
ndx = find_matching_xattr(sxp->xattr);
if (ndx < 0)
rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */
@@ -677,6 +742,21 @@ void cache_xattr(struct file_struct *file, stat_x *sxp)
F_XATTR(file) = ndx;
}
void uncache_tmp_xattrs(void)
{
if (prior_xattr_count != (size_t)-1) {
item_list *xattr_item = rsync_xal_l.items;
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) {
rsync_xal_free(xattr_item);
free(xattr_item->items);
}
prior_xattr_count = (size_t)-1;
}
}
static int rsync_xal_set(const char *fname, item_list *xalp,
const char *fnamecmp, stat_x *sxp)
{
@@ -684,7 +764,11 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
ssize_t list_len;
size_t i, len;
char *name, *ptr, sum[MAX_DIGEST_LEN];
int name_len, ret = 0;
#ifdef HAVE_LINUX_XATTRS
int user_only = am_root <= 0;
#endif
size_t name_len;
int ret = 0;
/* This puts the current name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(fname)) < 0)
@@ -758,8 +842,8 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
#ifdef HAVE_LINUX_XATTRS
/* We always ignore the system namespace, and non-root
* ignores everything but the user namespace. */
if (am_root ? HAS_PREFIX(name, SYSTEM_PREFIX)
: !HAS_PREFIX(name, USER_PREFIX))
if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
: HAS_PREFIX(name, SYSTEM_PREFIX))
continue;
#endif
if (am_root < 0 && name_len > RPRE_LEN
@@ -905,7 +989,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
fst.st_mode &= (_S_IFMT | CHMOD_BITS);
fmode = new_mode & (_S_IFMT | CHMOD_BITS);
if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) {
if (IS_DEVICE(fmode)) {
uint32 *devp = F_RDEV_P(file);
rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
} else
@@ -916,7 +1000,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
| (S_ISDIR(fst.st_mode) ? 0700 : 0600);
if (fst.st_mode != mode)
do_chmod(fname, mode);
if (!IS_DEVICE(fst.st_mode) && !IS_SPECIAL(fst.st_mode))
if (!IS_DEVICE(fst.st_mode))
fst.st_rdev = 0; /* just in case */
if (mode == fmode && fst.st_rdev == rdev