Compare commits

..

681 Commits

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

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

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=506830
2010-07-03 09:19:01 -07:00
Wayne Davison
05022e00a2 More NEWS. 2010-07-03 08:56:09 -07:00
Wayne Davison
24a743b565 If a module has no path setting, return an error. 2010-07-03 08:54:40 -07:00
Wayne Davison
e36f5c9f6c Mention latest changes. 2010-07-03 08:49:46 -07:00
Wayne Davison
c9c3215698 Refer to the right lsetxattr() caller in a error message. 2010-07-03 08:47:02 -07:00
Wayne Davison
dbfde9e50a Fix compression-ignoring of upper-case suffixes.
Fixes bug 7512.
2010-07-03 08:47:02 -07:00
Wayne Davison
1cdb5e1c86 Fix a couple socketpair_tcp() issues (see bug 7514). 2010-07-03 08:47:02 -07:00
Wayne Davison
24afdc500a Fix a typo that Andrea Gelmini pointed out. 2010-07-03 08:40:23 -07:00
Wayne Davison
303759b803 Get rid of trailing whitespace. 2010-07-03 08:40:23 -07:00
Matt McCutchen
a699f7c6af Man page description of --xattrs should not assume a push. 2010-07-03 08:37:25 -07:00
Wayne Davison
a250fa251b More manpage improvements. 2010-07-03 08:35:44 -07:00
Matt McCutchen
e44aa644c2 Amplify the man page description of --hard-links (see bug 3693), and
improve that of --inplace while I'm at it.
2010-07-03 08:33:24 -07:00
Wayne Davison
ef67c238b5 Reject passing an arg to an option that doesn't take one (bug 6915).
Based on a patch by Matt, but further tweaked to deal with -q=foo.
2010-07-03 08:27:38 -07:00
Wayne Davison
111599be2b Mention 2010 in the main copyright. 2010-07-03 08:24:58 -07:00
Wayne Davison
8e918e1861 Make an empty-string dest-dir the same as "." again. 2010-07-03 08:23:31 -07:00
Wayne Davison
0874fc4872 Setup for 3.0.8dev. 2010-06-30 09:19:01 -07:00
Wayne Davison
55dbbdeafe Fixed inconsistencies reported by packaging/var-checker. 2010-06-30 09:17:26 -07:00
Wayne Davison
cbd27d5e18 Update support/rrsync and some packaging/* scripts. 2010-06-30 09:17:13 -07:00
Matt McCutchen
178ccdde7d Rename configure.in to configure.ac, the current autoconf standard. 2010-06-30 08:29:48 -07:00
Wayne Davison
e51bb8f330 Write out the right compat_flags value into the batch file. 2010-06-26 16:14:15 -07:00
Wayne Davison
6d9207bd38 Turn some asserts into descriptive errors. 2010-06-26 16:13:58 -07:00
Wayne Davison
6b87566744 Make sure our use of idev_find() hashtable is right
while also supporting older rsyncs that send dev == 0.
2010-06-26 16:13:20 -07:00
Wayne Davison
b384d71e53 Make sure that the code doesn't try to use an illegal key. 2010-06-26 11:32:14 -07:00
Wayne Davison
11f4f34ed9 Fix daemon-filter crash issue (bug 7489). 2010-06-04 23:10:47 -07:00
Wayne Davison
fe2c582af8 Removing now-redundant path-size check from send_if_directory(). 2010-03-31 15:00:53 -07:00
Wayne Davison
2ecd8b7cd2 Fix directory-length overflow bug (7057). 2010-03-26 16:56:40 -07:00
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
Wayne Davison
698bc16e87 Preparing for release of 3.0.0pre10 2008-02-19 18:28:00 -08:00
Wayne Davison
7b4f48650c Make a few more char pointers const. 2008-02-19 16:35:22 -08:00
Wayne Davison
a43ff267e9 Tweaked a comparison that "checker" was complaining about. 2008-02-19 11:52:00 -08:00
Wayne Davison
717d04669a Fixed the hard-link check again, adding a comment as to
why it is coded the way it is.
2008-02-18 17:16:08 -08:00
Wayne Davison
15dbffc215 Fixed a compilation problem when iconv support is disabled. 2008-02-18 16:48:20 -08:00
Wayne Davison
0099e42332 Only set FLAG_TIME_FAILED if receiver_symlink_times is set. 2008-02-18 16:48:04 -08:00
Wayne Davison
1ed56a05c2 Extended the protocol-30 info-passing code at startup, and use it to
tell the client if the server can set the times on a symlink (both
the server->client byte and the client->server use of -e).  Make use
of this info to allow the proper output of the 't' flag when rsync
can set the time on a symlink (and we're talking protocol >= 30).
Added output of "[no] symtimes" info in the --version message.
Fixed the itemize.test so that it works when rsync believes that it
can set the time of a symlink, but it can't really do it.
2008-02-18 15:57:59 -08:00
Wayne Davison
28fb6365d0 Added --no-one-file-system and --no-x options. 2008-02-18 12:42:04 -08:00
Wayne Davison
8365126b8d Some permssion fixes:
- Changed itemized output to only report 'p' with -p or -E.
 - Fixed a duplicate output of a link-dest file with -vv but no -i.
 - Improved unchanged_attrs() to handle -E.
2008-02-18 10:20:50 -08:00
Wayne Davison
d770837ec0 Fixed a typo reported in a Debian bug report. 2008-02-18 09:59:44 -08:00
Wayne Davison
59658acfec Mention the leading '*'-char rule for itemized output. 2008-02-18 08:25:15 -08:00
Wayne Davison
46f800e8c7 Decided to pad the "*deleting" message to make the names line up. 2008-02-17 23:46:26 -08:00
Wayne Davison
1c65a93d03 The daemon no longer logs a recv entry for a file that is not
actually being updated due to the --only-write-batch option.
2008-02-17 23:44:52 -08:00
Wayne Davison
cae7885e2f Don't output a duplicate warning when the daemon-config excludes a
directory or when a directory is ignored via --ignore-non-existing.
Use a new var, is_dir, to simplify the dir code in recv_generator().
2008-02-17 22:34:08 -08:00
Wayne Davison
eaa28e654f Use the name "ChangeLog" for the ftp copy of the repository history. 2008-02-16 14:45:22 -08:00
Wayne Davison
beef86d0dd A few minor changes, including better push_dir()/pop_dir() verbosity. 2008-02-15 22:19:43 -08:00
Wayne Davison
2fe1feea75 Added a way to specify where the chroot should occur in the module's
path, which allows a daemon admin to have chroot protection and still
have files that are outside the transfer area (such as libraries).
2008-02-15 19:01:35 -08:00
Wayne Davison
0b52f94da7 Some daemon security improvements, including the new parameters
"charset" and "numeric ids".
2008-02-15 17:39:21 -08:00
Wayne Davison
f96bac8468 (Matt) Dropped a superfluous word from a sentence. 2008-02-12 17:30:02 -08:00
Wayne Davison
8444a7c00d (Matt) Needed to remove a few more files for distclean target. 2008-02-12 17:29:09 -08:00
Wayne Davison
c9d3bc3fca A few more NEWS tweaks. 2008-02-10 21:21:24 -08:00
Wayne Davison
8340aa9670 Mention a couple more items. 2008-02-10 21:02:05 -08:00
Wayne Davison
3e2c0024d5 Made reconfigure target check if configure.sh was up-to-date. 2008-02-10 20:39:31 -08:00
Wayne Davison
205393a2b5 Preparing for release of 3.0.0pre9 2008-02-10 20:16:25 -08:00
Wayne Davison
5f0f2e0894 Some improvements for --hard-links and --filter options. 2008-02-10 20:10:13 -08:00
Wayne Davison
a5bb0902b4 One more fix in set_modtime() when we get ENOSYS on a symlink. 2008-02-10 15:39:21 -08:00
Wayne Davison
d348d5fd5f Add a trailing slash to a modname arg that has no path information.
This ensures that the user gets a "skipping" message if they didn't
specify -r or -d.  (A trailing-slash was already being added to a
lone modname for --list-only transfers.)
2008-02-09 22:07:03 -08:00
Wayne Davison
21897ecbed Improved the "symlink has no referent" logic to work with all the
--copy*links options.
2008-02-09 21:41:50 -08:00
Wayne Davison
01103e1870 Make do_recv() reset copy_unsafe_links too (just like it does for
copy_links and copy_dirlinks).
2008-02-09 21:33:13 -08:00
Wayne Davison
2d8f9b1df0 Ignore exit-code 23 when we expect a daemon-excluded file to be excluded. 2008-02-09 21:30:49 -08:00
Wayne Davison
68f1e7e594 (Matt) Made a daemon-refused file an FERROR_XFER with a better message. 2008-02-07 11:24:38 -08:00
Wayne Davison
87629cf2f6 Re-indent some code in set_file_attrs() to make the flow clearer. 2008-02-07 07:24:58 -08:00
Wayne Davison
e7f642cffe Using rebase for the patches has become a failing-hunk
pain in the neck, so I'm switching to using merge.
2008-02-06 16:39:53 -08:00
Wayne Davison
3e8fe565ed A daemon needs to call setup_iconv() after parsing the options
it receives.
2008-02-06 16:13:37 -08:00
Wayne Davison
e96c7777d7 Fixed return code from hard_link_one() when not verbose. 2008-02-06 16:06:33 -08:00
Wayne Davison
71daa07fb1 Make get_xattr_names() even safer at fetching the list of attr names. 2008-02-06 07:52:00 -08:00
Wayne Davison
287bb276d5 Only check F_OWNER() if uid_ndx is non-zero. 2008-02-04 21:17:27 -08:00
Wayne Davison
ddc8110dea Fixed local_child() so that the client side really does handle
the log-file writing.
2008-02-04 12:52:41 -08:00
Wayne Davison
c0f4228d66 Don't try to use recv_xattr_request() with --dry-run. Fixes an
internal abbrev error on the sending side.
2008-02-04 12:34:02 -08:00
Wayne Davison
d6e6333a02 Store the key64 flag from hashtable_create() in the hashtable structure
so that hashtable_find() knows which hashtable is which on a 64-bit
architecture.
2008-02-04 07:29:22 -08:00
Wayne Davison
970ce063ee Fixed finding of parent's description when @ARGV doesn't mention it. 2008-02-04 00:12:01 -08:00
Wayne Davison
dd1f0da818 Improved the usage message. 2008-02-03 23:40:20 -08:00
Wayne Davison
38a4bd432a Fixed a couple DEL_OWNED_BY_US glitches. 2008-02-03 16:40:28 -08:00
Wayne Davison
3eabe6aa41 Dump delete_item()'s "replace" var to reduce recursive stack use. 2008-02-03 15:13:36 -08:00
Wayne Davison
f2b7b64d86 Fixed the diffing of generated files when creating a patch that has
a parent that is not the master branch.
2008-02-02 17:00:25 -08:00
Wayne Davison
b2057d38a9 Some extra password-clarification verbage from Matt. 2008-01-29 17:19:22 -08:00
Wayne Davison
964244b90d Fixed several glitches with failed updates and batch files:
- Correctly identify when a missing batch update is for a resend.
- Made a missing batch update an xfer error.
- Made a failed redo an xfer error.
- Identify a failed transfer file consistently when it is a solo file.
- Have --read-batch say "may try again" instead of "will try again".
2008-01-27 14:40:50 -08:00
Wayne Davison
a7c1fa0049 Moved the batch option checking until after the protocol-version
in the batch file is known.  Also simplified the do_compress
checking, which had some erroneous def_compress_level code.
2008-01-26 11:58:17 -08:00
Wayne Davison
42a28d9d3a Improved a comment. 2008-01-26 09:13:19 -08:00
Wayne Davison
19284e2ef8 When removing a file/dir that is owned by us but does not have
owner-write permission, set it before the removal.
2008-01-26 08:47:02 -08:00
Wayne Davison
2268defe66 Fix some typos and such. 2008-01-25 16:57:54 -08:00
Wayne Davison
643b018cfb Mention iconv --list. 2008-01-25 16:57:26 -08:00
Wayne Davison
e35ad79b1b Make do_chmod() report an error with -E. 2008-01-25 16:57:02 -08:00
Wayne Davison
da01d2e843 Improved option handling for protocol 30 batch files. 2008-01-19 11:21:07 -08:00
Wayne Davison
641dc0c51e Output (BATCH ONLY) rather than (DRY RUN) for --only-write-batch. 2008-01-19 11:20:42 -08:00
Wayne Davison
69e2b4ee3a Fixed the combination of --dry-run and --only-write-batch. 2008-01-19 11:20:17 -08:00
Wayne Davison
75a01a0734 Don't apply filter rules to implied directories. 2008-01-19 10:09:22 -08:00
Wayne Davison
b769ad6a3e Another xattr "internal abbrev" fix for an xattr object that is
shared by multiple files:  handle the case where one file has an
abbreviated item set correctly, but a following item does not.
Also extended testsuite/xattrs.test to verify that this works.
2008-01-12 22:16:37 -08:00
Wayne Davison
6e59b97770 Preparing for release of 3.0.0pre8 2008-01-12 10:53:10 -08:00
Wayne Davison
4da9fcd41d - Make sure the Makefile is up-to-date before running "make gen".
- The release-rsync script now creates the generated patches in a
  separate dir from the normal patches.
2008-01-12 10:52:46 -08:00
Wayne Davison
68ddbaf645 Fixed a bug with truncated xattr data requests when the receiver
needs to discard some of the items from the sender's list.
2008-01-12 09:14:56 -08:00
Wayne Davison
555a081fe2 If "make gensend" fails, abort the script. 2008-01-11 13:20:14 -08:00
Wayne Davison
513d3fd806 Improved check_for_finished_files() to be really, really sure
that we've processed all the items on the hard-linked and redo
queues before we return.
2008-01-11 13:13:15 -08:00
Wayne Davison
34aa616d41 Fixed a length problem parsing an arg of "./". 2008-01-09 11:51:44 -08:00
Wayne Davison
ec8637f367 Don't allow a slash to be specified in a module name.
Document the module-name limitations in rsyncd.conf.yo.
2008-01-09 11:41:23 -08:00
Wayne Davison
62a6b8df72 Made read_arg_from_pipe() handle EINTR. 2008-01-02 17:20:44 -08:00
Wayne Davison
dd6f31f70f Rebuild the Makefile when it is not up-to-date. 2008-01-01 10:43:55 -08:00
Wayne Davison
a5fd4b6e6e Renamed mkrounding.c to rounding.c. 2008-01-01 10:34:27 -08:00
Wayne Davison
eca151d457 Changed the creation of rounding.h to use a set of compile-time checks
similar to how configure determines the size of variables.
2008-01-01 10:27:19 -08:00
Wayne Davison
f859d3ded6 If we're cross-compiling, tell the user to run mkrounding on the
target machine to build the rounding.h file.
2008-01-01 08:59:26 -08:00
Wayne Davison
5288be3af7 Some minor tweaks:
- Improved some comments in hlink.c.
- Changed "the" to "a" in rsyncd.conf.yo.
- Improved the PATCH.name filtering loop in patch-update.
2007-12-31 20:40:51 -08:00
Wayne Davison
83235dbc54 Fixed a case where the receiver indicates a successful update when the
transfer succeeded, but the final rename failed.
2007-12-31 10:31:43 -08:00
Wayne Davison
c78cb8f349 Made some user-/group-name pointers "const". 2007-12-29 22:52:42 -08:00
Wayne Davison
7210dbfd2a Some minor tweaking to name_to_uid() and name_to_gid(). 2007-12-29 22:52:04 -08:00
Wayne Davison
b6800a0b32 Added check for libiconv_open when iconv_open isn't found. 2007-12-29 09:53:37 -08:00
Wayne Davison
14eaa7a53b Added reconfigure target to re-run configure. 2007-12-29 09:44:58 -08:00
Wayne Davison
bc065415b0 Fixed Source URL and changed from ftp to http. 2007-12-19 09:36:05 -08:00
Wayne Davison
9203c8d274 Improved prepare-source to make it more flexible. The script now
lets the user choose which actions to perform and their order.
2007-12-17 23:32:47 -08:00
Wayne Davison
9468cf796d Fixed a FALL THROUGH comment. 2007-12-16 17:51:36 -08:00
Wayne Davison
77d4c400c2 Only ignore ENOSYS error from lutimes(). 2007-12-16 17:18:01 -08:00
Wayne Davison
e3915dac76 Added the 'h' option to the tar command that creates the patches
tar file just in case the patches directory is a symlink.
2007-12-16 15:41:59 -08:00
Wayne Davison
78246d1a09 Preparing for release of 3.0.0pre7 2007-12-16 15:09:43 -08:00
Wayne Davison
4bb319c6a6 Fixed extracting files from old tar file. 2007-12-16 15:09:21 -08:00
Wayne Davison
293b11b8a5 Mention 2 more changes in the NEWS. 2007-12-16 15:04:12 -08:00
Wayne Davison
8f42da0b50 Added a "fetchall" option. 2007-12-16 15:02:42 -08:00
Wayne Davison
a10186910d Fixed the check_filter() calls that might be checking an absolute path
in "use chroot = no" mode against a daemon's exclude restriction.
2007-12-16 14:16:37 -08:00
Wayne Davison
eb7715c1eb Moved the dir_count increment into an even better spot and make sure that
send_file_name() returned a non-NULL pointer before doing any DOT_NAME
processing in inc_recurse mode.
2007-12-16 14:14:35 -08:00
Wayne Davison
a7188cbf48 Fixed a potential memory leak in make_file(). 2007-12-15 11:57:34 -08:00
Wayne Davison
f7a2ac075f Refer to delta-transfer algorithm rather than rsync algorithm. 2007-12-15 08:35:45 -08:00
Wayne Davison
ce27f36d92 Check on the alternate destination dirs and report any problems. 2007-12-15 08:19:56 -08:00
Wayne Davison
af5ed0f257 Make push_dir() output where we are when verbosity is high. 2007-12-15 07:39:33 -08:00
Wayne Davison
e6d05dcfca Move incrementing of dir_count so that it can't get incremented
for a directory that isn't going to be included in the transfer.
2007-12-13 07:00:38 -08:00
Wayne Davison
65b4e4b2a9 Updated indexing for accurate progress and improved raw ndx values.
The sending side now has a sorted file-list in iconv mode so that it
can output progress in sorted order.  Simplified the over-the-wire
index values to ensure both sides will always agree on the values.
Optimized the allocation of the dir_flist->sorted array on the
receiving side with --iconv and incremental recursion.
2007-12-08 11:39:47 -08:00
Wayne Davison
37adeae73e A few more additions of $(srcdir) to Makefile.in. 2007-11-30 19:08:54 -08:00
Wayne Davison
091b3459f6 Fixed a build problem for those building in a different dir from
the srcdir.  Also got rid of "cd" code in configure stub.
2007-11-30 19:02:50 -08:00
Wayne Davison
85cdbb6be3 Reorganize the build-farm "prepare-source" magic a little.
This makes it easier for a user to request a copy of the
configure scripts via rsync ("./prepare-source fetch").
2007-11-30 18:01:18 -08:00
Wayne Davison
fcb1068f72 Improved header-file dependency rules even more. 2007-11-30 07:42:47 -08:00
Wayne Davison
07ad305e8a Make sure that the test programs get rebuilt when a header
file changes.
2007-11-29 23:44:40 -08:00
Wayne Davison
bcfb738c93 One build-farm system needs to fetch the proto.h* files too. 2007-11-29 23:21:51 -08:00
Wayne Davison
b58f5e17ed Simplified the time_t overflow check and moved an extra_len rounding
check into the right spot in recv_file_entry().
2007-11-29 22:52:20 -08:00
Wayne Davison
87de82f2d0 Make sure that the inc_recurse value is always set to
either 0 or 1.
2007-11-29 22:46:43 -08:00
Wayne Davison
87531e6302 Get rid of some compiler warnings in the AIX sysacls code. 2007-11-29 17:12:54 -08:00
Wayne Davison
eb67a6909b Don't try to process hard-link data in list-only mode. 2007-11-29 10:27:16 -08:00
Wayne Davison
9217ce30e3 Revised release-rsync and nightly-rsync code to create a tar files
with the right timestamps.
2007-11-29 09:29:45 -08:00
Wayne Davison
d52607ecd6 Preparing for release of 3.0.0pre6 2007-11-28 01:00:37 -08:00
Wayne Davison
13e4914826 Fixed a problem with extracting the previous release's
generated files (used to create the release diff).
2007-11-28 01:00:02 -08:00
Wayne Davison
932fcfc1aa Mentioned the latest changes in the NEWS. 2007-11-28 00:40:34 -08:00
Wayne Davison
a2c770dc21 Switching over to a dynamic hash method for really large files.
This code has been reported to be better for large files than the
file-chunking code that was included in pre3.
2007-11-28 00:39:02 -08:00
Wayne Davison
ba22c9e219 Adding --contimeout=SECONDS option. 2007-11-28 00:28:26 -08:00
Wayne Davison
6a2456c501 Don't use git-FOO command to call git sub-commands. 2007-11-27 16:06:01 -08:00
Wayne Davison
ef3f14e6a7 When the new "munge symlinks" option is off, a non-chroot
daemon should sanitize its symlinks, as it used to do.
2007-11-27 13:11:49 -08:00
Wayne Davison
9585b27678 Add a new daemon security option: "munge symlinks". 2007-11-27 07:34:59 -08:00
Wayne Davison
5c77266d95 Use a non-printing command for proto.h's build-rule. 2007-11-25 15:12:06 -08:00
Wayne Davison
3db06222af Give proto.h a build rule so that make re-checks its timestamp. 2007-11-25 15:03:19 -08:00
Wayne Davison
aa6865d761 Return to the master branch at the end. 2007-11-25 14:46:33 -08:00
Wayne Davison
67b9b26ff3 Modified the discovery of the generated files & use "make gen". 2007-11-25 14:36:30 -08:00
Wayne Davison
b82ad9507f Re-run autoconf and autoheader, as needed. 2007-11-25 14:08:19 -08:00
Wayne Davison
4d7c8e6b76 We now call set_stat_xattr() before set_xattr(). 2007-11-25 13:49:41 -08:00
Wayne Davison
a685271de3 Various xattr fixes:
- Fake-super mode no longer strips the RSYNC_PREFIX from a "%name" item.
- Make various places skip the fake-super xattr when --fake-super is enabled.
- If we fail to re-read the xattr value of an xattr we are trying to un-
  abbreviate, send a zero for its length (avoiding a protocol problem).
2007-11-25 13:48:54 -08:00
Wayne Davison
613c2d4431 Improved proto.h-tstamp handling, including cleanup. 2007-11-24 11:50:41 -08:00
Wayne Davison
225787a4a4 Made the (re-)building of the proto.h file automatic in the
main Makefile rules, and the (re-)building of the man pages
automatic if yodl2man is present.
2007-11-24 10:54:35 -08:00
Wayne Davison
e107b6b122 Fixed a problem with --fake-super not getting the fully tweaked new_mode
value.  Also fixed the removal of rsync-internal xattr values on the
destination files when we aren't copying rsync-internal xattr values.
2007-11-24 10:50:45 -08:00
Wayne Davison
5223b786ca A daemon needs to set dry_run with --only-write-batch. 2007-11-22 11:19:34 -08:00
Wayne Davison
3f0211b63a New logging categories added to allow differentiation between
transfer errors, normal errors, and warnings.  New messages are
translated into old FERROR/FINFO categories for older protocols.
2007-11-22 10:05:36 -08:00
Wayne Davison
a6c6f8e650 Use FLOG instead of FERROR for config errors. 2007-11-22 09:51:21 -08:00
Wayne Davison
ee6e80c753 Fix two iconv problems that Lennart Lövstrand pointed out in bug 5075. 2007-11-22 07:57:03 -08:00
Wayne Davison
ce72de30ce Don't try to delete when list_only is set. 2007-11-21 07:09:26 -08:00
Wayne Davison
29bca53f9b Got rid of the unused symlink parameter to sanitize_path(). 2007-11-20 17:37:53 -08:00
Wayne Davison
dc2815c1fb Make sure that a failure to build configure.sh or config.h.in
doesn't leave a file lying around that could deceive us on the
next run.
2007-11-20 17:22:47 -08:00
Wayne Davison
3005a12bce Only allow the build farm to rsync the latest generated
configure files when building them fails.
2007-11-20 08:40:15 -08:00
Wayne Davison
fd913297fa Made some code that handles hard-linking of symlinks be
omitted if symlinks can't be hard-linked.
2007-11-18 17:54:35 -08:00
Wayne Davison
90c98cdc39 Adding a support script that can be used to make the checked-out
file-times of an initial clone nicer.
2007-11-17 10:29:13 -08:00
Wayne Davison
b258ebf8ac Improved F_RDEV_P() define to use DEV_EXTRA_CNT count. 2007-11-17 10:26:46 -08:00
Wayne Davison
97f0421523 Make sure we process a parent patch before a dependent patch. 2007-11-16 08:02:26 -08:00
Wayne Davison
ee8a733d6f A couple minor improvments to the tar-creation code. 2007-11-15 14:05:09 -08:00
Wayne Davison
20c7d7fd69 Updated to work with git instead of cvs. 2007-11-15 07:48:13 -08:00
Wayne Davison
49ebb358ab Handle new PATCH-$name files, improved $last_touch code,
fixed handling of dependent patches.
2007-11-12 15:10:52 -08:00
Wayne Davison
1f41d42a91 Getting rid of all .cvsignore files. 2007-11-12 13:32:10 -08:00
Wayne Davison
813d2d101a Mention the change for protocol 30. 2007-11-12 07:12:48 -08:00
Wayne Davison
86eb9f9595 Exit if something goes wrong with commit or tag. 2007-11-12 06:44:16 -08:00
Wayne Davison
18fa91296b Make sure that time has progressed when we need change branches
in order to run prepare-source.
2007-11-12 06:30:24 -08:00
Wayne Davison
8d3211447d If we start a sub-shell to let the user fix a rebase, output a
message and change the prompt.
2007-11-12 00:13:52 -08:00
Wayne Davison
805d8ac43d Updated to work with latest git repository and to package
the patches directory in a separate tar file.
2007-11-11 23:58:01 -08:00
Wayne Davison
d26c7dfdb0 This script transforms one or more patch/* branches into
one or more patches/*.diff files.
2007-11-11 23:15:40 -08:00
Wayne Davison
1e21cde315 Ignore a couple more items. 2007-11-11 22:52:25 -08:00
Wayne Davison
c5d77e9659 Including my extern-squishing script, which just found an
extraneous extern in exclude.c.
2007-11-11 22:51:50 -08:00
Wayne Davison
2909586ede This helper script exists to create the generated files that are needed
for a build.  It pretends to be a configure script so that the build
steps are still the normal sequence of ./configure, make, make install
(which is particularly helpful with the samba build farm).  Once the
generated files are ready, the configure.sh script is called to do the
real configure work.
2007-11-09 21:37:01 -08:00
Wayne Davison
c5435b56bf Switched prototype generation from awk to perl. 2007-11-09 22:57:14 +00:00
Wayne Davison
2c386ff971 Ignore generated files and dirs. 2007-11-09 19:55:00 +00:00
Wayne Davison
7f3b529367 Tweaked gensend to upload man pages too. 2007-11-09 19:31:20 +00:00
Wayne Davison
6228239894 Include the arg name for the lp_*() funtions. 2007-11-09 19:28:27 +00:00
Wayne Davison
4da09a65f8 Simplified script even more for HP-UX. 2007-11-09 19:14:51 +00:00
Wayne Davison
ab96610986 Use older open() style for compatibility with older perl versions. 2007-11-09 18:15:52 +00:00
Wayne Davison
c8dccf8fb4 Improved the manpage install rules. 2007-11-09 18:12:40 +00:00
Wayne Davison
bdc12f41de Don't fail the install if the man pages aren't there. 2007-11-09 18:04:50 +00:00
Wayne Davison
2042c63251 Clean generated files for distclean. 2007-11-09 17:56:00 +00:00
Wayne Davison
6ec47d3d01 Added gensend target. 2007-11-09 17:50:10 +00:00
Wayne Davison
0c270e48af Let's try using perl for building proto.h. 2007-11-09 17:40:56 +00:00
Wayne Davison
8aeac05d98 Improved configure bootstrap to try to build generated files
before fetching them.
2007-11-09 16:56:46 +00:00
Wayne Davison
564dc9941e This is an attempt to remove generated files from the rsync repository
while still supporting the samba build farm.  Let's see if it works.
2007-11-09 16:22:20 +00:00
Wayne Davison
732b391720 Preparing for release of 3.0.0pre5 2007-11-09 04:49:18 +00:00
Wayne Davison
879b6ad05c When performing a --dry-run, output a "(DRY RUN)" reminder on the
last line of the verbose summary text.
2007-11-09 04:48:10 +00:00
Wayne Davison
f153c9c943 Mention latest changes. 2007-11-09 04:32:58 +00:00
Wayne Davison
1b411143e5 Got rid of a compiler warning. 2007-11-08 20:30:17 +00:00
Wayne Davison
9456434688 Some fixes for SCO in new getaddrinfo() code. 2007-11-08 14:54:58 +00:00
Wayne Davison
268da8167a Use uint32, not uint32_t. 2007-11-08 01:31:58 +00:00
Wayne Davison
2213961e8f Add back a define of "struct sockaddr_storage" for systems that
don't have it.
2007-11-08 01:10:34 +00:00
Wayne Davison
d100e733db Improve the man page and --help descriptions of --dry-run. In
particular, make it clear that --dry-run turns off action without
turning on verbosity, and has some incomplete/inaccurate stats.
2007-11-08 00:06:48 +00:00
Wayne Davison
15e4d40184 Tweaked an extern. 2007-11-06 15:32:55 +00:00
Wayne Davison
f7a76b9c45 Some changes to allow an unsorted file list even if the iconv option
was disabled via configure.
2007-11-06 15:25:02 +00:00
Wayne Davison
84e1a34eaa Fixed some typos that Matt pointed out. 2007-11-05 18:33:09 +00:00
Wayne Davison
41979f2518 Make sure that get_xattr_data() never tries to malloc 0 bytes. 2007-11-05 18:15:04 +00:00
Wayne Davison
4b1553e2d4 If the xattr data is bogus in get_rsync_acl(), free the buffer. 2007-11-05 18:15:01 +00:00
Wayne Davison
e516b69ef6 Fixed get_xattr_acl() -- it needed to zero *len_p. 2007-11-05 15:02:30 +00:00
Wayne Davison
7df593f21f Got rid of a redundant mtime check. 2007-11-05 15:02:27 +00:00
Wayne Davison
cac80887a6 Conditional symlink-checking code in unchanged_attrs() should be
checking HAVE_LUTIMES.
2007-11-04 06:43:01 +00:00
Wayne Davison
45a143cd51 Have unchanged_attrs() check the mtime on items where we can
affect the time, even if unchanged_file() might have already
checked it.
2007-11-03 21:14:16 +00:00
Wayne Davison
0379c8eca1 Make sure that the user has write permissions when opening a temp file. 2007-11-03 19:27:49 +00:00
Wayne Davison
c9b16cdaba Stop password errors from getting reported as transfer errors. 2007-11-03 18:14:36 +00:00
Wayne Davison
77943e69aa - Renamed updating_basis -> updating_basis_or_equiv.
- Set updating_basis_or_equiv if we're inplace-updating a
  file using the backup file as the basis.
2007-11-03 16:57:17 +00:00
Wayne Davison
d620219dc4 A better way to count our queued workload. 2007-11-03 16:30:30 +00:00
Wayne Davison
c0685c05f8 Fixed hang when --hard-links was processing a large directory
hierarchy with no files.
2007-11-03 15:27:14 +00:00
Wayne Davison
b7386d23d4 Avoid verbose output during the forwarding of flist data (for now,
at least).
2007-11-03 07:20:09 +00:00
Wayne Davison
17a4977bef In mplex_write(), make extra sure something unexpected doesn't get
put between the split output of a long buffer.
2007-11-03 07:20:05 +00:00
Wayne Davison
4f9b139ab9 The HAVE_UTIMBUF define changed to HAVE_STRUCT_UTIMBUF. 2007-11-02 20:53:04 +00:00
Wayne Davison
9f802c7294 A new version of the getaddrinfo code from the samba source. 2007-11-02 20:52:57 +00:00
Wayne Davison
6e1fa33f67 Make use of the HAVE_NETDB_H define. 2007-11-02 20:52:52 +00:00
Wayne Davison
4021aa455b Changes to handle new getaddrinfo code. 2007-11-02 20:52:46 +00:00
Wayne Davison
6ec0f6977d Added AC_HAVE_TYPE(). 2007-11-02 20:52:33 +00:00
Wayne Davison
8c702798f6 One more SUBPROTOCOL_VERSION increase for iconv change. 2007-10-31 15:01:26 +00:00
Wayne Davison
2ad3c71777 - In --iconv mode, we can't lower the ndx_end value because dirs
aren't sorted to the end.
- Made output_flist() output from "files" instead of "sorted".
2007-10-31 14:02:51 +00:00
Wayne Davison
05bd302ab6 Increment the SUBPROTOCOL_VERSION. 2007-10-31 05:48:56 +00:00
Wayne Davison
2b4d51f2e9 Set ndx_start to 1 only for an inc-recursive transfer. 2007-10-31 05:48:25 +00:00
Wayne Davison
ee279980cc - Handle a dot-dir-containing flist using its parent_ndx value. 2007-10-31 04:43:36 +00:00
Wayne Davison
4e42173508 - Fixed a problem with merging dot dirs with non-dot-dir args
in inc-recursive mode.
- Clean up a relative name to remove interior dot dirs and extra
  slashes.
- Fixed the error output about /../ in a -R path after a /./ cut-off.
- Changed the starting ndx value to 1 so that a dot-dir flist can
  use 0 to refer to its parent (".") directory.
2007-10-31 04:43:32 +00:00
Wayne Davison
b58bfb2f20 Call clean_fname() with new flag arg. 2007-10-31 04:43:29 +00:00
Wayne Davison
6bb82fe0a8 Changed clean_fname() to take a flag int instead of a BOOL. Added
a few extra cleaning options (all off by default).
2007-10-31 04:43:25 +00:00
Wayne Davison
c73f2a3831 - Define the new CFN_* flags for clean_fname().
- Changed struct relnamecache's "is_dot_dir" member to "name_type".
2007-10-31 04:43:22 +00:00
Wayne Davison
b1eca24226 Avoid a crash if we read an index value without a valid first_flist. 2007-10-31 04:43:19 +00:00
Wayne Davison
58b7b3d668 Suggest -Z as a good popt alias letter instead of -s. 2007-10-31 00:51:48 +00:00
Wayne Davison
ce055e863d Mention that --keep-dirlinks can be dangerous if there are
untrusted symlinks in the transfer.
2007-10-30 15:00:40 +00:00
Wayne Davison
53ec55a88e Fixed --one-file-system handling when dealing with multiple
user-specified mount points in inc-recursive mode.
2007-10-30 02:24:03 +00:00
Wayne Davison
2cce75453c My version of Matt's cleanup patch from bug 5051. This makes
--copy-dest use a temp file when not in in-place mode, and has
various improvments for the code.  I have also "#if 0"ed the code
in the receiver that makes missing directories to see if we can
figure out if it is needed (and if so, what for).
2007-10-29 20:43:34 +00:00
Wayne Davison
93204ccae2 Made some more char pointers const. 2007-10-28 21:42:41 +00:00
Wayne Davison
57d617192b Don't call copy_file() for a dry-run. (Thanks, Matt!) 2007-10-28 20:03:00 +00:00
Wayne Davison
ea118be593 Fixed setting of updating_basis value. 2007-10-28 06:51:50 +00:00
120 changed files with 9333 additions and 4145 deletions

View File

@@ -1,25 +0,0 @@
ID
Makefile
autom4te*.cache
confdefs.h
config.cache
config.h
config.log
config.status
conftest*
dox
getgroups
gmon.out
rsync
shconfig
testdir
tests-dont-exist
testtmp
tls
trimslash
t_unsafe
wildtest
getfsdev
.rsync-filter
mkrounding
rounding.h

42
.gitignore vendored Normal file
View File

@@ -0,0 +1,42 @@
*.[oa]
*~
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
/proto.h-tstamp
/rsync.1
/rsyncd.conf.5
/autom4te*.cache
/confdefs.h
/conftest*
/dox
/getgroups
/gmon.out
/rsync
/shconfig
/testdir
/tests-dont-exist
/testtmp
/tls
/trimslash
/t_unsafe
/wildtest
/getfsdev
/rounding.h
/doc/rsync.pdf
/doc/rsync.ps
/support/savetransfer
/testsuite/chown-fake.test
/testsuite/devices-fake.test
/testsuite/xattrs-hlink.test
/patches

13
INSTALL
View File

@@ -17,7 +17,7 @@ for the daemon by editing the NOBODY_USER and NOBODY_GROUP defines in
config.h, or just override them in your /etc/rsyncd.conf file.
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
cut-down copy of release 1.6.4 is included in the rsync distribution,
cut-down copy of a recent release is included in the rsync distribution,
and will be used if there is no popt library on your build host, or if
the --with-included-popt option is passed to ./configure.
@@ -25,6 +25,17 @@ If you configure using --enable-maintainer-mode, then rsync will try
to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
useful, but it should be turned off for production builds.
MAKE COMPATIBILITY
------------------
Note that Makefile.in has a rule that uses a wildcard in a prerequisite. If
your make has a problem with this rule, you will see an error like this:
Don't know how to make ./*.c
You can change the "proto.h-tstamp" target in Makefile.in to list all the *.c
filenames explicitly in order to avoid this issue.
RPM NOTES
---------

View File

@@ -26,6 +26,7 @@ VERSION=@VERSION@
.SUFFIXES:
.SUFFIXES: .c .o
GENFILES=configure.sh config.h.in proto.h proto.h-tstamp rsync.1 rsyncd.conf.5
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h lib/pool_alloc.h
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o @LIBOBJS@
@@ -47,10 +48,10 @@ TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxa
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test testsuite/xattrs-hlink.test
# Objects for CHECK_PROGS to clean
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
@@ -58,15 +59,15 @@ CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: rsync$(EXEEXT)
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
${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1
${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5
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
@@ -75,16 +76,27 @@ rsync$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
$(OBJS): $(HEADERS)
$(CHECK_OBJS): $(HEADERS)
flist.o: rounding.h
rounding.h: mkrounding$(EXEEXT)
./mkrounding$(EXEEXT) >rounding.h
mkrounding$(EXEEXT): mkrounding.c rsync.h
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
@rm mkrounding.h
rounding.h: rounding.c rsync.h
@for r in 0 1 3; do \
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; \
fi; \
break; \
fi; \
done
@rm -f rounding
@if test -f rounding.h; then : ; else \
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)
@@ -99,22 +111,87 @@ 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)
gen:
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
gen: conf proto.h man
man:
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
gensend: gen
rsync -aivzc $(GENFILES) samba.org:/home/ftp/pub/rsync/generated-files/
proto:
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
conf:
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
configure.sh config.h.in: configure.ac aclocal.m4
@if test -f configure.sh; then cp -p configure.sh configure.sh.old; else touch configure.sh.old; fi
@if test -f config.h.in; then cp -p config.h.in config.h.in.old; else touch config.h.in.old; fi
autoconf -o configure.sh
autoheader && touch config.h.in
@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
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
@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
@if test -f proto.h; then :; else cp -p $(srcdir)/proto.h .; fi
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
-$(srcdir)/tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
-$(srcdir)/tweak_manpage rsyncd.conf.5
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
mkrounding mkrounding.h rounding.h
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h *.old
cleantests:
rm -rf ./testtmp*
@@ -124,12 +201,14 @@ cleantests:
# the source directory.
distclean: clean
rm -f Makefile config.h config.status
rm -f lib/dummy popt/dummy zlib/dummy
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
rm -f $(srcdir)/lib/dummy $(srcdir)/popt/dummy $(srcdir)/zlib/dummy
rm -f config.cache config.log
rm -f $(srcdir)/config.cache $(srcdir)/config.log
rm -f shconfig $(srcdir)/shconfig
rm -f $(GENFILES)
rm -rf autom4te.cache
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
@@ -160,7 +239,7 @@ check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
wildtest.o: wildtest.c lib/wildmatch.c rsync.h config.h
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
@@ -170,6 +249,9 @@ testsuite/chown-fake.test:
testsuite/devices-fake.test:
ln -s devices.test $(srcdir)/testsuite/devices-fake.test
testsuite/xattrs-hlink.test:
ln -s xattrs.test $(srcdir)/testsuite/xattrs-hlink.test
# This does *not* depend on building or installing: you can use it to
# check a version installed from a binary or some other source tree,
# if you want.

242
NEWS
View File

@@ -1,234 +1,56 @@
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.)
- 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.
NEWS for rsync 3.0.9 (23 Sep 2011)
Protocol: 30 (unchanged)
Changes since 3.0.8:
BUG FIXES:
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
- Fix a crash bug in checksum scanning when --inplace is used.
- Made the output of all file types consistent when using a --*-dest
option. Prior versions would output too many creation events for
matching items.
- Fix a hang if a hard-linked file cannot be opened by the sender (e.g.
if it has no read permission).
- 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.
- Fix preservation of a symlink's system xattrs (e.g. selinux) on Linux.
- A negated filter rule (i.e. with a '!' modifier) no longer loses the
negation when sending the filter rules to the remote rsync.
- Fix a memory leak in the xattr code.
- 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 bug with --delete-excluded when a filter merge file has a rule
that specifies a receiver-only side restriction.
- 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.
- Fix a bug with the modifying of unwritable directories.
- 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.
- Fix --fake-super's interaction with --link-dest same-file comparisons.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- Fix the updating of the curr_dir buffer to avoid a duplicate slash.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Fix the directory permissions on an implied dot-dir when using --relative
(e.g. /outside/path/././send/path).
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- Fixed some too-long sleeping instances when using --bwlimit.
- The --append option no longer updates a file that has the same size.
- Fixed when symlink ownership difference-checking gets compiled into
unchanged_attrs().
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Improved the socket-error reporting when multiple protocols fail.
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- Fixed a case where a socket error could reference just-freed memory.
- 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.
- Failing to use a password file that was specified on the command-line is
now a fatal error.
- The daemon pidfile is checked and created sooner in the startup sequence.
- Fix the non-root updating of directories that don't have the read and/or
execute permission.
- If a daemon module's "path" value is not an absolute pathname, the code
now makes it absolute internally (making it work properly).
- Make daemon-excluded file errors more error-like.
ENHANCEMENTS:
- Fix a compilation issue on older C compilers (due to a misplaced var
declaration).
- 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.
- Make configure avoid finding socketpair on cygwin.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- Avoid trying to reference SO_BROADCAST if the OS doesn't support it.
- 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.
- Fix some issues with the post-processing of the man pages.
- 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} .
- Fixed the user home-dir handling in the support/lsh script.
- 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" option 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.
- 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.
- 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.
- 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).
- 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.
- 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.
DEVELOPER RELATED:
- Rsync is now licensed under the GPLv3 or later.
- 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).
- Some minor manpage improvements.

1002
OLDNEWS
View File

File diff suppressed because it is too large Load Diff

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

23
aclocal.m4 vendored
View File

@@ -68,4 +68,25 @@ AC_DEFUN([TYPE_SOCKLEN_T],
#include <sys/socket.h>])
])
dnl AC_HAVE_TYPE(TYPE,INCLUDES)
AC_DEFUN([AC_HAVE_TYPE], [
AC_REQUIRE([AC_HEADER_STDC])
cv=`echo "$1" | sed 'y%./+- %__p__%'`
AC_MSG_CHECKING(for $1)
AC_CACHE_VAL([ac_cv_type_$cv],
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
AC_INCLUDES_DEFAULT
$2]],
[[$1 foo;]])],
[eval "ac_cv_type_$cv=yes"],
[eval "ac_cv_type_$cv=no"]))dnl
ac_foo=`eval echo \\$ac_cv_type_$cv`
AC_MSG_RESULT($ac_foo)
if test "$ac_foo" = yes; then
ac_tr_hdr=HAVE_`echo $1 | sed 'y%abcdefghijklmnopqrstuvwxyz./- %ABCDEFGHIJKLMNOPQRSTUVWXYZ____%'`
if false; then
AC_CHECK_TYPES($1)
fi
AC_DEFINE_UNQUOTED($ac_tr_hdr, 1, [Define if you have type `$1'])
fi
])

251
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
@@ -31,6 +31,8 @@ extern int list_only;
extern int orig_umask;
extern int numeric_ids;
extern int inc_recurse;
extern int preserve_devices;
extern int preserve_specials;
/* Flags used to indicate what items are being transmitted for an entry. */
#define XMIT_USER_OBJ (1<<0)
@@ -88,13 +90,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)
@@ -102,10 +117,11 @@ static int calc_sacl_entries(const rsync_acl *racl)
/* A System ACL always gets user/group/other permission entries. */
return racl->names.count
#ifdef ACLS_NEED_MASK
+ 4;
+ 1
#else
+ (racl->mask_obj != NO_ENTRY) + 3;
+ (racl->mask_obj != NO_ENTRY)
#endif
+ 3;
}
/* Extracts and returns the permission bits from the ACL. This cannot be
@@ -119,15 +135,21 @@ static int rsync_acl_get_perms(const rsync_acl *racl)
/* Removes the permission-bit entries from the ACL because these
* can be reconstructed from the file's mode. */
static void rsync_acl_strip_perms(rsync_acl *racl)
static void rsync_acl_strip_perms(stat_x *sxp)
{
rsync_acl *racl = sxp->acc_acl;
racl->user_obj = NO_ENTRY;
if (racl->mask_obj == NO_ENTRY)
racl->group_obj = NO_ENTRY;
else {
if (racl->group_obj == racl->mask_obj)
int group_perms = (sxp->st.st_mode >> 3) & 7;
if (racl->group_obj == group_perms)
racl->group_obj = NO_ENTRY;
racl->mask_obj = NO_ENTRY;
#ifndef HAVE_SOLARIS_ACLS
if (racl->names.count != 0 && racl->mask_obj == group_perms)
racl->mask_obj = NO_ENTRY;
#endif
}
racl->other_obj = NO_ENTRY;
}
@@ -300,7 +322,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
ida->access = access;
}
if (rc) {
rsyserr(FERROR, errno, "unpack_smb_acl: %s()", errfun);
rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
rsync_acl_free(racl);
return False;
}
@@ -326,15 +348,6 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
/* Truncate the temporary list now that its idas have been saved. */
temp_ida_list.count = 0;
#ifdef ACLS_NEED_MASK
if (!racl->names.count && racl->mask_obj != NO_ENTRY) {
/* Throw away a superfluous mask, but mask off the
* group perms with it first. */
racl->group_obj &= racl->mask_obj;
racl->mask_obj = NO_ENTRY;
}
#endif
return True;
}
@@ -356,7 +369,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
static int store_access_in_entry(uint32 access, SMB_ACL_ENTRY_T entry)
{
if (sys_acl_set_access_bits(entry, access)) {
rsyserr(FERROR, errno, "store_access_in_entry sys_acl_set_access_bits()");
rsyserr(FERROR_XFER, errno, "store_access_in_entry sys_acl_set_access_bits()");
return -1;
}
return 0;
@@ -375,7 +388,7 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
SMB_ACL_ENTRY_T entry;
if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
rsyserr(FERROR, errno, "pack_smb_acl: sys_acl_init()");
rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
return False;
}
@@ -424,14 +437,14 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
#ifdef DEBUG
if (sys_acl_valid(*smb_acl) < 0)
rprintf(FERROR, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
rprintf(FERROR_XFER, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
#endif
return True;
error_exit:
if (errfun) {
rsyserr(FERROR, errno, "pack_smb_acl %s()", errfun);
rsyserr(FERROR_XFER, errno, "pack_smb_acl %s()", errfun);
}
sys_acl_free_acl(*smb_acl);
return False;
@@ -476,13 +489,21 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
if ((buf = get_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, &len)) == NULL)
return 0;
cnt = (len - 4*4) / (4+4);
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4)
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4) {
free(buf);
return -1;
}
racl->user_obj = IVAL(buf, 0);
if (racl->user_obj == NO_ENTRY)
racl->user_obj = (mode >> 6) & 7;
racl->group_obj = IVAL(buf, 4);
if (racl->group_obj == NO_ENTRY)
racl->group_obj = (mode >> 3) & 7;
racl->mask_obj = IVAL(buf, 8);
racl->other_obj = IVAL(buf, 12);
if (racl->other_obj == NO_ENTRY)
racl->other_obj = mode & 7;
if (cnt) {
char *bp = buf + 4*4;
@@ -512,7 +533,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
if (type == SMB_ACL_TYPE_ACCESS)
rsync_acl_fake_perms(racl, mode);
} else {
rsyserr(FERROR, errno, "get_acl: sys_acl_get_file(%s, %s)",
rsyserr(FERROR_XFER, errno, "get_acl: sys_acl_get_file(%s, %s)",
fname, str_acl_type(type));
return -1;
}
@@ -524,6 +545,23 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
int get_acl(const char *fname, stat_x *sxp)
{
sxp->acc_acl = create_racl();
if (S_ISREG(sxp->st.st_mode) || S_ISDIR(sxp->st.st_mode)) {
/* Everyone supports this. */
} else if (S_ISLNK(sxp->st.st_mode)) {
return 0;
} else if (IS_SPECIAL(sxp->st.st_mode)) {
#ifndef NO_SPECIAL_ACLS
if (!preserve_specials)
#endif
return 0;
} else if (IS_DEVICE(sxp->st.st_mode)) {
#ifndef NO_DEVICE_ACLS
if (!preserve_devices)
#endif
return 0;
}
if (get_rsync_acl(fname, sxp->acc_acl, SMB_ACL_TYPE_ACCESS,
sxp->st.st_mode) < 0) {
free_acl(sxp);
@@ -545,7 +583,7 @@ int get_acl(const char *fname, stat_x *sxp)
/* === Send functions === */
/* Send the ida list over the file descriptor. */
static void send_ida_entries(const ida_entries *idal, int f)
static void send_ida_entries(int f, const ida_entries *idal)
{
id_access *ida;
size_t count = idal->count;
@@ -554,12 +592,12 @@ static void send_ida_entries(const ida_entries *idal, int f)
for (ida = idal->idas; count--; ida++) {
uint32 xbits = ida->access << 2;
char *name;
const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
name = add_uid(ida->id);
name = numeric_ids ? NULL : add_uid(ida->id);
} else
name = add_gid(ida->id);
name = numeric_ids ? NULL : add_gid(ida->id);
write_varint(f, ida->id);
if (inc_recurse && name) {
int len = strlen(name);
@@ -571,8 +609,8 @@ static void send_ida_entries(const ida_entries *idal, int f)
}
}
static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
item_list *racl_list, int f)
static void send_rsync_acl(int f, rsync_acl *racl, SMB_ACL_TYPE_T type,
item_list *racl_list)
{
int ndx = find_matching_rsync_acl(racl, type, racl_list);
@@ -605,7 +643,7 @@ static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
if (flags & XMIT_OTHER_OBJ)
write_varint(f, racl->other_obj);
if (flags & XMIT_NAME_LIST)
send_ida_entries(&racl->names, f);
send_ida_entries(f, &racl->names);
/* Give the allocated data to the new list object. */
*new_racl = *racl;
@@ -615,28 +653,28 @@ static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
/* Send the ACL from the stat_x structure down the indicated file descriptor.
* This also frees the ACL data. */
void send_acl(stat_x *sxp, int f)
void send_acl(int f, stat_x *sxp)
{
if (!sxp->acc_acl) {
sxp->acc_acl = create_racl();
rsync_acl_fake_perms(sxp->acc_acl, sxp->st.st_mode);
}
/* Avoid sending values that can be inferred from other data. */
rsync_acl_strip_perms(sxp->acc_acl);
rsync_acl_strip_perms(sxp);
send_rsync_acl(sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list, f);
send_rsync_acl(f, sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list);
if (S_ISDIR(sxp->st.st_mode)) {
if (!sxp->def_acl)
sxp->def_acl = create_racl();
send_rsync_acl(sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list, f);
send_rsync_acl(f, sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list);
}
}
/* === Receive functions === */
static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
static uint32 recv_acl_access(int f, uchar *name_follows_ptr)
{
uint32 access = read_varint(f);
@@ -653,7 +691,7 @@ static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
access |= NAME_IS_USER;
} else if (am_root >= 0 && access & ~SMB_ACL_VALID_OBJ_BITS) {
value_error:
rprintf(FERROR, "recv_acl_access: value out of range: %x\n",
rprintf(FERROR_XFER, "recv_acl_access: value out of range: %x\n",
access);
exit_cleanup(RERR_STREAMIO);
}
@@ -661,7 +699,7 @@ static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
return access;
}
static uchar recv_ida_entries(ida_entries *ent, int f)
static uchar recv_ida_entries(int f, ida_entries *ent)
{
uchar computed_mask_bits = 0;
int i, count = read_varint(f);
@@ -677,7 +715,7 @@ static uchar recv_ida_entries(ida_entries *ent, int f)
for (i = 0; i < count; i++) {
uchar has_name;
id_t id = read_varint(f);
uint32 access = recv_acl_access(&has_name, f);
uint32 access = recv_acl_access(f, &has_name);
if (has_name) {
if (access & NAME_IS_USER)
@@ -700,7 +738,7 @@ static uchar recv_ida_entries(ida_entries *ent, int f)
return computed_mask_bits & ~NO_ENTRY;
}
static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
static int recv_rsync_acl(int f, item_list *racl_list, SMB_ACL_TYPE_T type, mode_t mode)
{
uchar computed_mask_bits = 0;
acl_duo *duo_item;
@@ -708,14 +746,14 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > racl_list->count) {
rprintf(FERROR, "recv_acl_index: %s ACL index %d > %d\n",
rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
str_acl_type(type), ndx, (int)racl_list->count);
exit_cleanup(RERR_STREAMIO);
}
if (ndx != 0)
return ndx - 1;
ndx = racl_list->count;
duo_item = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
duo_item->racl = empty_rsync_acl;
@@ -723,29 +761,28 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
flags = read_byte(f);
if (flags & XMIT_USER_OBJ)
duo_item->racl.user_obj = recv_acl_access(NULL, f);
duo_item->racl.user_obj = recv_acl_access(f, NULL);
if (flags & XMIT_GROUP_OBJ)
duo_item->racl.group_obj = recv_acl_access(NULL, f);
duo_item->racl.group_obj = recv_acl_access(f, NULL);
if (flags & XMIT_MASK_OBJ)
duo_item->racl.mask_obj = recv_acl_access(NULL, f);
duo_item->racl.mask_obj = recv_acl_access(f, NULL);
if (flags & XMIT_OTHER_OBJ)
duo_item->racl.other_obj = recv_acl_access(NULL, f);
duo_item->racl.other_obj = recv_acl_access(f, NULL);
if (flags & XMIT_NAME_LIST)
computed_mask_bits |= recv_ida_entries(&duo_item->racl.names, f);
computed_mask_bits |= recv_ida_entries(f, &duo_item->racl.names);
#ifdef HAVE_OSX_ACLS
/* If we received a superfluous mask, throw it away. */
duo_item->racl.mask_obj = NO_ENTRY;
#else
if (!duo_item->racl.names.count) {
/* 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. */
duo_item->racl.mask_obj = (computed_mask_bits | duo_item->racl.group_obj) & ~NO_ENTRY;
if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) {
/* Mask must be non-empty with lists. */
if (type == SMB_ACL_TYPE_ACCESS)
computed_mask_bits = (mode >> 3) & 7;
else
computed_mask_bits |= duo_item->racl.group_obj & ~NO_ENTRY;
duo_item->racl.mask_obj = computed_mask_bits;
}
#endif
duo_item->sacl = NULL;
@@ -754,12 +791,12 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
}
/* Receive the ACL info the sender has included for this file-list entry. */
void receive_acl(struct file_struct *file, int f)
void receive_acl(int f, struct file_struct *file)
{
F_ACL(file) = recv_rsync_acl(&access_acl_list, SMB_ACL_TYPE_ACCESS, f);
F_ACL(file) = recv_rsync_acl(f, &access_acl_list, SMB_ACL_TYPE_ACCESS, file->mode);
if (S_ISDIR(file->mode))
F_DIR_DEFACL(file) = recv_rsync_acl(&default_acl_list, SMB_ACL_TYPE_DEFAULT, f);
F_DIR_DEFACL(file) = recv_rsync_acl(f, &default_acl_list, SMB_ACL_TYPE_DEFAULT, 0);
}
static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl_list)
@@ -782,17 +819,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)
{
@@ -838,12 +908,14 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
break;
case SMB_ACL_MASK:
#ifndef HAVE_SOLARIS_ACLS
#ifndef ACLS_NEED_MASK
/* mask is only empty when we don't need it. */
if (racl->mask_obj == NO_ENTRY)
break;
#endif
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
#endif
break;
case SMB_ACL_OTHER:
COE2( store_access_in_entry,(mode & 7, entry) );
@@ -853,10 +925,10 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
if (rc) {
error_exit:
if (errfun) {
rsyserr(FERROR, errno, "change_sacl_perms: %s()",
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
errfun);
}
return (mode_t)~0;
return (mode_t)-1;
}
#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
@@ -885,7 +957,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
#endif
rc = sys_acl_delete_def_file(fname);
if (rc < 0) {
rsyserr(FERROR, errno, "set_acl: sys_acl_delete_def_file(%s)",
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
fname);
return -1;
}
@@ -925,13 +997,13 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
if (type == SMB_ACL_TYPE_ACCESS) {
cur_mode = change_sacl_perms(duo_item->sacl, &duo_item->racl,
cur_mode, mode);
if (cur_mode == (mode_t)~0)
if (cur_mode == (mode_t)-1)
return 0;
}
#endif
if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
rsyserr(FERROR, errno, "set_acl: sys_acl_set_file(%s, %s)",
fname, str_acl_type(type));
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
fname, str_acl_type(type));
return -1;
}
if (type == SMB_ACL_TYPE_ACCESS)
@@ -941,17 +1013,17 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
return 0;
}
/* Set ACL on indicated filename.
/* Given a fname, this sets extended access ACL entries, the default ACL (for a
* dir), and the regular mode bits on the file. Call this with fname set to
* NULL to just check if the ACL is different.
*
* This sets extended access ACL entries and default ACL. If convenient,
* it sets permission bits along with the access ACL and signals having
* done so by modifying sxp->st.st_mode.
* If the ACL operation has a side-effect of changing the file's mode, the
* sxp->st.st_mode value will be changed to match.
*
* Returns 1 for unchanged, 0 for changed, -1 for failed. Call this
* with fname set to NULL to just check if the ACL is unchanged. */
int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp)
* Returns 0 for an unchanged ACL, 1 for changed, -1 for failed. */
int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp, mode_t new_mode)
{
int unchanged = 1;
int changed = 0;
int32 ndx;
BOOL eq;
@@ -965,18 +1037,18 @@ int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp)
acl_duo *duo_item = access_acl_list.items;
duo_item += ndx;
eq = sxp->acc_acl
&& rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, file->mode);
&& rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, new_mode);
if (!eq) {
unchanged = 0;
changed = 1;
if (!dry_run && fname
&& set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_ACCESS,
sxp, file->mode) < 0)
unchanged = -1;
sxp, new_mode) < 0)
return -1;
}
}
if (!S_ISDIR(sxp->st.st_mode))
return unchanged;
if (!S_ISDIR(new_mode))
return changed;
ndx = F_DIR_DEFACL(file);
if (ndx >= 0 && (size_t)ndx < default_acl_list.count) {
@@ -984,16 +1056,15 @@ int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp)
duo_item += ndx;
eq = sxp->def_acl && rsync_acl_equal(sxp->def_acl, &duo_item->racl);
if (!eq) {
if (unchanged > 0)
unchanged = 0;
changed = 1;
if (!dry_run && fname
&& set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_DEFAULT,
sxp, file->mode) < 0)
unchanged = -1;
sxp, new_mode) < 0)
return -1;
}
}
return unchanged;
return changed;
}
/* Non-incremental recursion needs to convert all the received IDs.
@@ -1036,6 +1107,9 @@ int default_perms_for_dir(const char *dir)
if (sacl == NULL) {
/* Couldn't get an ACL. Darn. */
switch (errno) {
case EINVAL:
/* If SMB_ACL_TYPE_DEFAULT isn't valid, then the ACLs must be non-POSIX. */
break;
#ifdef ENOTSUP
case ENOTSUP:
#endif
@@ -1050,7 +1124,8 @@ int default_perms_for_dir(const char *dir)
}
/* Otherwise fall through. */
default:
rprintf(FERROR, "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
rprintf(FWARNING,
"default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
dir, str_acl_type(SMB_ACL_TYPE_DEFAULT), strerror(errno));
}
return perms;
@@ -1061,7 +1136,7 @@ int default_perms_for_dir(const char *dir)
ok = unpack_smb_acl(sacl, &racl);
sys_acl_free_acl(sacl);
if (!ok) {
rprintf(FERROR, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
rprintf(FWARNING, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
return perms;
}

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
@@ -156,36 +156,27 @@ static const char *getpassf(const char *filename)
{
STRUCT_STAT st;
char buffer[512], *p;
int fd, n, ok = 1;
const char *envpw = getenv("RSYNC_PASSWORD");
int fd, n;
if (!filename)
return NULL;
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FERROR, errno, "could not open password file \"%s\"",
filename);
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
rsyserr(FERROR, errno, "could not open password file %s", filename);
exit_cleanup(RERR_SYNTAX);
}
if (do_stat(filename, &st) == -1) {
rsyserr(FERROR, errno, "stat(%s)", filename);
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FERROR, "password file must not be other-accessible\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FERROR, "password file must be owned by root when running as root\n");
ok = 0;
exit_cleanup(RERR_SYNTAX);
}
if (!ok) {
close(fd);
rprintf(FERROR, "continuing without password file\n");
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
if ((st.st_mode & 06) != 0) {
rprintf(FERROR, "ERROR: password file must not be other-accessible\n");
exit_cleanup(RERR_SYNTAX);
}
if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");
exit_cleanup(RERR_SYNTAX);
}
n = read(fd, buffer, sizeof buffer - 1);
@@ -196,7 +187,8 @@ static const char *getpassf(const char *filename)
return strdup(p);
}
return NULL;
rprintf(FERROR, "ERROR: failed to read a password from %s\n", filename);
exit_cleanup(RERR_SYNTAX);
}
/* Generate an MD4 hash created from the combination of the password

118
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,19 +307,26 @@ 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);
rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
fname, sl);
}
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",

135
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
@@ -31,15 +31,25 @@ extern int preserve_hard_links;
extern int preserve_devices;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_acls;
extern int preserve_xattrs;
extern int always_checksum;
extern int do_compression;
extern int def_compress_level;
extern int inplace;
extern int append_mode;
extern int protocol_version;
extern char *batch_name;
#ifdef ICONV_OPTION
extern char *iconv_opt;
#endif
extern struct filter_list_struct filter_list;
static int tweaked_compress_level;
int batch_stream_flags;
static int tweaked_append;
static int tweaked_append_verify;
static int tweaked_iconv;
static int *flag_ptr[] = {
&recurse, /* 0 */
@@ -50,7 +60,13 @@ static int *flag_ptr[] = {
&preserve_hard_links, /* 5 */
&always_checksum, /* 6 */
&xfer_dirs, /* 7 (protocol 29) */
&tweaked_compress_level,/* 8 (protocol 29) */
&do_compression, /* 8 (protocol 29) */
&tweaked_iconv, /* 9 (protocol 30) */
&preserve_acls, /* 10 (protocol 30) */
&preserve_xattrs, /* 11 (protocol 30) */
&inplace, /* 12 (protocol 30) */
&tweaked_append, /* 13 (protocol 30) */
&tweaked_append_verify, /* 14 (protocol 30) */
NULL
};
@@ -64,6 +80,12 @@ static char *flag_name[] = {
"--checksum (-c)",
"--dirs (-d)",
"--compress (-z)",
"--iconv",
"--acls (-A)",
"--xattrs (-X)",
"--inplace",
"--append",
"--append-verify",
NULL
};
@@ -71,16 +93,14 @@ void write_stream_flags(int fd)
{
int i, flags;
#if Z_DEFAULT_COMPRESSION == -1
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
#else
#error internal logic error! Fix def_compress_level logic above and below too!
tweaked_append = append_mode == 1;
tweaked_append_verify = append_mode == 2;
#ifdef ICONV_OPTION
tweaked_iconv = iconv_opt != NULL;
#endif
/* Start the batch file with a bitmap of data-stream-affecting
* flags. */
if (protocol_version < 29)
flag_ptr[7] = NULL;
for (i = 0, flags = 0; flag_ptr[i]; i++) {
if (*flag_ptr[i])
flags |= 1 << i;
@@ -90,13 +110,31 @@ void write_stream_flags(int fd)
void read_stream_flags(int fd)
{
int i, flags;
batch_stream_flags = read_int(fd);
}
void check_batch_flags(void)
{
int i;
if (protocol_version < 29)
flag_ptr[7] = NULL;
for (i = 0, flags = read_int(fd); flag_ptr[i]; i++) {
int set = flags & (1 << i) ? 1 : 0;
else if (protocol_version < 30)
flag_ptr[9] = NULL;
tweaked_append = append_mode == 1;
tweaked_append_verify = append_mode == 2;
#ifdef ICONV_OPTION
tweaked_iconv = iconv_opt != NULL;
#endif
for (i = 0; flag_ptr[i]; i++) {
int set = batch_stream_flags & (1 << i) ? 1 : 0;
if (*flag_ptr[i] != set) {
if (i == 9) {
rprintf(FERROR,
"%s specify the --iconv option to use this batch file.\n",
set ? "Please" : "Do not");
exit_cleanup(RERR_SYNTAX);
}
if (verbose) {
rprintf(FINFO,
"%sing the %s option to match the batchfile.\n",
@@ -112,35 +150,43 @@ void read_stream_flags(int fd)
xfer_dirs = 0;
}
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
do_compression = 0;
else {
do_compression = 1;
def_compress_level = tweaked_compress_level - 2;
}
if (tweaked_append)
append_mode = 1;
else if (tweaked_append_verify)
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)
@@ -169,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,
@@ -179,11 +225,12 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
filename);
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
/* 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=._-");
@@ -204,27 +251,33 @@ 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(1);
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.
* Allow an arbitrary sequence of case labels.
*
* Copyright (C) 2006-2007 Wayne Davison
* Copyright (C) 2006-2010 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,63 +17,60 @@
* with this program; if not, visit the http://fsf.org website.
*/
/* This is included by cleanup.c multiple times, once for every segement in
* the _exit_cleanup() code. This produces the next "case N:" statement in
* sequence and increments the cleanup_step variable by 1. This ensures that
* our case statements never get out of whack due to added/removed steps. */
/* This is included multiple times, once for every segement in a switch statement.
* This produces the next "case N:" statement in sequence. */
#if !defined EXIT_CLEANUP_CASE_0
#define EXIT_CLEANUP_CASE_0
#if !defined CASE_N_STATE_0
#define CASE_N_STATE_0
case 0:
#elif !defined EXIT_CLEANUP_CASE_1
#define EXIT_CLEANUP_CASE_1
#elif !defined CASE_N_STATE_1
#define CASE_N_STATE_1
case 1:
#elif !defined EXIT_CLEANUP_CASE_2
#define EXIT_CLEANUP_CASE_2
#elif !defined CASE_N_STATE_2
#define CASE_N_STATE_2
case 2:
#elif !defined EXIT_CLEANUP_CASE_3
#define EXIT_CLEANUP_CASE_3
#elif !defined CASE_N_STATE_3
#define CASE_N_STATE_3
case 3:
#elif !defined EXIT_CLEANUP_CASE_4
#define EXIT_CLEANUP_CASE_4
#elif !defined CASE_N_STATE_4
#define CASE_N_STATE_4
case 4:
#elif !defined EXIT_CLEANUP_CASE_5
#define EXIT_CLEANUP_CASE_5
#elif !defined CASE_N_STATE_5
#define CASE_N_STATE_5
case 5:
#elif !defined EXIT_CLEANUP_CASE_6
#define EXIT_CLEANUP_CASE_6
#elif !defined CASE_N_STATE_6
#define CASE_N_STATE_6
case 6:
#elif !defined EXIT_CLEANUP_CASE_7
#define EXIT_CLEANUP_CASE_7
#elif !defined CASE_N_STATE_7
#define CASE_N_STATE_7
case 7:
#elif !defined EXIT_CLEANUP_CASE_8
#define EXIT_CLEANUP_CASE_8
#elif !defined CASE_N_STATE_8
#define CASE_N_STATE_8
case 8:
#elif !defined EXIT_CLEANUP_CASE_9
#define EXIT_CLEANUP_CASE_9
#elif !defined CASE_N_STATE_9
#define CASE_N_STATE_9
case 9:
#elif !defined EXIT_CLEANUP_CASE_10
#define EXIT_CLEANUP_CASE_10
#elif !defined CASE_N_STATE_10
#define CASE_N_STATE_10
case 10:
#elif !defined EXIT_CLEANUP_CASE_11
#define EXIT_CLEANUP_CASE_11
#elif !defined CASE_N_STATE_11
#define CASE_N_STATE_11
case 11:
#elif !defined EXIT_CLEANUP_CASE_12
#define EXIT_CLEANUP_CASE_12
#elif !defined CASE_N_STATE_12
#define CASE_N_STATE_12
case 12:
#elif !defined EXIT_CLEANUP_CASE_13
#define EXIT_CLEANUP_CASE_13
#elif !defined CASE_N_STATE_13
#define CASE_N_STATE_13
case 13:
#elif !defined EXIT_CLEANUP_CASE_14
#define EXIT_CLEANUP_CASE_14
#elif !defined CASE_N_STATE_14
#define CASE_N_STATE_14
case 14:
#elif !defined EXIT_CLEANUP_CASE_15
#define EXIT_CLEANUP_CASE_15
#elif !defined CASE_N_STATE_15
#define CASE_N_STATE_15
case 15:
#elif !defined EXIT_CLEANUP_CASE_16
#define EXIT_CLEANUP_CASE_16
#elif !defined CASE_N_STATE_16
#define CASE_N_STATE_16
case 16:
#else
#error Need to add more case statements!
#endif
cleanup_step++;

View File

@@ -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
@@ -24,8 +24,6 @@
extern int checksum_seed;
extern int protocol_version;
int csum_length = SHORT_SUM_LENGTH; /* initial value */
/*
a simple 32 bit checksum that can be upadted from either end
(inspired by Mark Adler's Adler-32 checksum)
@@ -58,7 +56,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,9 +24,10 @@
extern int am_server;
extern int am_daemon;
extern int am_receiver;
extern int io_error;
extern int keep_partial;
extern int log_got_error;
extern int got_xfer_error;
extern char *partial_dir;
extern char *logfile_name;
@@ -78,8 +79,8 @@ void close_all(void)
**/
int cleanup_got_literal = 0;
static char *cleanup_fname;
static char *cleanup_new_fname;
static const char *cleanup_fname;
static const char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd_r, cleanup_fd_w;
static pid_t cleanup_pid = 0;
@@ -93,36 +94,44 @@ 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 switch_step = 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;
/* Some of our actions might cause a recursive call back here, so we
* keep track of where we are in the cleanup and never repeat a step. */
switch (cleanup_step) {
#include "case_N.h" /* case 0: cleanup_step++; */
switch (switch_step) {
#include "case_N.h" /* case 0: */
switch_step++;
exit_code = unmodified_code = code;
exit_file = file;
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 */
#include "case_N.h"
switch_step++;
if (cleanup_child_pid != -1) {
int status;
@@ -136,10 +145,11 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
const char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
@@ -153,11 +163,14 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
io_flush(FULL_FLUSH);
if (!code || am_server || am_receiver)
io_flush(FULL_FLUSH);
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (cleanup_fname)
do_unlink(cleanup_fname);
@@ -174,7 +187,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
code = exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
if (io_error & IOERR_GENERAL || got_xfer_error)
code = exit_code = RERR_PARTIAL;
}
@@ -183,16 +196,18 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
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 */
#include "case_N.h"
switch_step++;
if (am_server && code)
msleep(100);
@@ -213,7 +228,7 @@ void cleanup_disable(void)
}
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
void cleanup_set(const char *fnametmp, const char *fname, struct file_struct *file,
int fd_r, int fd_w)
{
cleanup_fname = fnametmp;

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,7 +22,9 @@
#include "rsync.h"
#include "ifuncs.h"
extern int quiet;
extern int verbose;
extern int dry_run;
extern int output_motd;
extern int list_only;
extern int am_sender;
@@ -30,39 +32,49 @@ 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;
extern int numeric_ids;
extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern int io_timeout;
extern int no_detach;
extern int write_batch;
extern int default_af_hint;
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;
#endif
char *auth_user;
int read_only = 0;
int module_id = -1;
int munge_symlinks = 0;
struct chmod_mode_struct *daemon_chmod_modes;
/* module_dirlen is the length of the module_dir string when in daemon
* mode, not chrooted, and the path is not "/"; otherwise 0. */
* mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
* enabled module can have a non-"/" module_dir these days.) */
char *module_dir = NULL;
unsigned int module_dirlen = 0;
char *full_module_path;
static int rl_nulls = 0;
#ifdef HAVE_SIGACTION
@@ -109,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);
@@ -198,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,
@@ -242,10 +256,13 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
if (list_only && strncmp(*argv, modname, modlen) == 0
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
else
else if (**argv == '-') {
if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
out_of_memory("start_inband_exchange");
} else
sargs[sargc++] = *argv;
argv++;
argc--;
@@ -300,6 +317,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);
}
@@ -310,6 +329,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();
@@ -321,16 +343,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);
@@ -352,8 +382,12 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
char *bp = buf, *eob = buf + limit - 1;
while (1) {
if (read(fd, bp, 1) != 1)
int got = read(fd, bp, 1);
if (got != 1) {
if (got < 0 && errno == EINTR)
continue;
return -1;
}
if (*bp == '\0')
break;
if (bp < eob)
@@ -364,10 +398,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;
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;
@@ -378,6 +422,13 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
pid_t pre_exec_pid = 0;
char *request = NULL;
#ifdef ICONV_OPTION
iconv_opt = lp_charset(i);
if (*iconv_opt)
setup_iconv();
iconv_opt = NULL;
#endif
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
@@ -460,43 +511,62 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
/* TODO: Perhaps take a list of gids, and make them into the
* supplementary groups. */
/* We do a push_dir() without actually calling chdir() in order
* to make sure that the module's path is absolute. After this
* check, module_dir will be set to an absolute path. */
module_dir = lp_path(i);
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);
push_dir(line, 1); /* Restore curr_dir. */
if (*module_dir == '\0') {
rprintf(FLOG, "No path specified for module %s\n", name);
io_printf(f_out, "@ERROR: no path setting.\n");
return -1;
}
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0'; /* Temporary... */
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;
}
if (use_chroot || (module_dirlen = strlen(module_dir)) == 1) {
if (module_dirlen == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
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);
@@ -504,8 +574,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", module_dir) < 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)
@@ -539,7 +610,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);
}
}
@@ -605,21 +677,29 @@ 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(module_dir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_dir);
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("/", 0))
goto chdir_failed;
} 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;
}
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 (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);
exit_cleanup(RERR_UNSUPPORTED);
}
}
if (am_root) {
@@ -648,7 +728,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;
@@ -669,22 +753,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)
@@ -747,7 +849,24 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
exit_cleanup(RERR_UNSUPPORTED);
}
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
#ifdef ICONV_OPTION
if (!iconv_opt) {
if (ic_send != (iconv_t)-1) {
iconv_close(ic_send);
ic_send = (iconv_t)-1;
}
if (ic_recv != (iconv_t)-1) {
iconv_close(ic_recv);
ic_recv = (iconv_t)-1;
}
}
#endif
if (!numeric_ids
&& (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) && (!io_timeout || lp_timeout(i) < io_timeout))
set_io_timeout(lp_timeout(i));
/* If we have some incoming/outgoing chmod changes, append them to
@@ -784,6 +903,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 */
@@ -799,7 +929,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);
@@ -808,10 +938,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);
}
@@ -855,20 +981,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);
}
@@ -908,13 +1037,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;
@@ -929,7 +1051,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);
}
@@ -949,7 +1071,7 @@ int daemon_main(void)
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
RSYNC_VERSION, rsync_port);
/* TODO: If listening on a particular address, then show that
* address too. In fact, why not just do inet_ntop on the
* address too. In fact, why not just do getnameinfo on the
* local address??? */
start_accept_loop(rsync_port, start_daemon);

View File

@@ -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,8 @@
int remote_protocol = 0;
int file_extra_cnt = 0; /* count of file-list extras that everyone gets */
int inc_recurse = 0;
int compat_flags = 0;
int use_safe_inc_flist = 0;
extern int verbose;
extern int am_server;
@@ -48,25 +50,35 @@ extern int preserve_acls;
extern int preserve_xattrs;
extern int need_messages_from_generator;
extern int delete_mode, delete_before, delete_during, delete_after;
extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */
extern char *shell_cmd;
extern char *partial_dir;
extern char *dest_option;
extern char *files_from;
extern char *filesfrom_host;
extern struct filter_list_struct filter_list;
extern int need_unsorted_flist;
#ifdef ICONV_OPTION
extern char *iconv_opt;
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;
#ifdef ICONV_OPTION
int ic_ndx;
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;
#endif
#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;
/* The server makes sure that if either side only supports a pre-release
* version of a protocol, that both sides must speak a compatible version
* of that protocol for it to be advertised as available. */
@@ -80,8 +92,9 @@ static void check_sub_protocol(void)
int our_sub = 0;
#endif
if (!shell_cmd || !(dot = strchr(shell_cmd, '.'))
|| !(their_protocol = atoi(shell_cmd))
/* client_info starts with VER.SUB string if client is a pre-release. */
if (!(their_protocol = atoi(client_info))
|| !(dot = strchr(client_info, '.'))
|| !(their_sub = atoi(dot+1))) {
#if SUBPROTOCOL_VERSION != 0
if (our_sub)
@@ -104,6 +117,8 @@ static void check_sub_protocol(void)
void set_allow_inc_recurse(void)
{
client_info = shell_cmd ? shell_cmd : "";
if (!recurse || use_qsort)
allow_inc_recurse = 0;
else if (!am_sender
@@ -111,7 +126,7 @@ void set_allow_inc_recurse(void)
|| delay_updates || prune_empty_dirs))
allow_inc_recurse = 0;
else if (am_server && !local_server
&& (!shell_cmd || strchr(shell_cmd, 'i') == NULL))
&& (strchr(client_info, 'i') == NULL))
allow_inc_recurse = 0;
}
@@ -172,6 +187,8 @@ void setup_protocol(int f_out,int f_in)
PROTOCOL_VERSION, am_server? "Server" : "Client");
exit_cleanup(RERR_PROTOCOL);
}
if (read_batch)
check_batch_flags();
if (protocol_version < 30) {
if (append_mode == 1)
@@ -233,10 +250,34 @@ void setup_protocol(int f_out,int f_in)
}
} else if (protocol_version >= 30) {
if (am_server) {
inc_recurse = allow_inc_recurse;
write_byte(f_out, inc_recurse);
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
#ifdef CAN_SET_SYMLINK_TIMES
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
inc_recurse = read_byte(f_in);
compat_flags = read_byte(f_in);
/* The inc_recurse var MUST be set to 0 or 1. */
inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0;
if (am_sender) {
receiver_symlink_times = am_server
? strchr(client_info, 'L') != NULL
: !!(compat_flags & CF_SYMLINK_TIMES);
}
#ifdef CAN_SET_SYMLINK_TIMES
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. */
fprintf(stderr,
@@ -244,13 +285,16 @@ 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;
#ifdef CAN_SET_SYMLINK_TIMES
} else if (!am_sender) {
receiver_symlink_times = 1;
#endif
}
#ifdef ICONV_OPTION
if (iconv_opt && (!am_sender || inc_recurse))
ic_ndx = ++file_extra_cnt;
#endif
if (need_unsorted_flist && (!am_sender || inc_recurse))
unsort_ndx = ++file_extra_cnt;
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;

25
configure vendored Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh -e
# This configure script ensures that the configure.sh script exists, and
# if not, it tries to fetch rsync's generated files or build them. We
# then transfer control to the configure.sh script to do the real work.
dir=`dirname $0`
realconfigure="$dir/configure.sh"
if test ! -f "$realconfigure"; then
if test -f "$HOME/build_farm/build_test.fns"; then
# Allow the build farm to grab latest files via rsync.
actions='build fetch'
else
actions='build'
fi
if "$dir/prepare-source" $actions; then
:
else
echo 'Failed to build configure.sh and/or config.h.in -- giving up.' >&2
rm -f "$realconfigure"
exit 1
fi
fi
exec "$realconfigure" "${@}"

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=3.0.0pre4
RSYNC_VERSION=3.0.9
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -13,22 +13,7 @@ AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
LDFLAGS=${LDFLAGS-""}
AC_CANONICAL_TARGET([])
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
AC_PROG_CC_STDC
AC_SUBST(SHELL)
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
fi
AC_CANONICAL_HOST
# We must decide this before testing the compiler.
@@ -42,14 +27,27 @@ AC_ARG_ENABLE(debug,
if test x"$enable_debug" = x"no"; then
AC_MSG_RESULT(no)
CFLAGS=${CFLAGS-"-O"}
ac_cv_prog_cc_g=no
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"}
# 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
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
AC_PROG_CC_STDC
AC_SUBST(SHELL)
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
AC_MSG_WARN([rsync requires an ANSI C compiler and you do not seem to have one])
fi
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],
@@ -123,6 +121,11 @@ else
fi
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
AC_CHECK_PROG(HAVE_YODL2MAN, yodl2man, 1, 0)
if test x$HAVE_YODL2MAN = x1; then
MAKE_MAN=man
fi
AC_ARG_WITH(nobody-group,
AC_HELP_STRING([--with-nobody-group=GROUP],
[set the default unprivileged group (default nobody or nogroup)]),
@@ -190,10 +193,10 @@ ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6],
[don't even try to use IPv6]))
[do not even try to use IPv6]))
if test x"$enable_ipv6" != x"no"; then
AC_MSG_CHECKING([ipv6 stack type])
for i in inria kame linux-glibc linux-inet6 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/
@@ -237,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>
@@ -270,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
@@ -285,7 +307,7 @@ AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale],
[disable locale features]))
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you don't want locale features. By default this is defined.])
[Undefine if you do not want locale features. By default this is defined.])
if test x"$enable_locale" != x"no"; then
AC_DEFINE(CONFIG_LOCALE)
fi
@@ -306,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 netinet/in_systm.h netinet/ip.h)
AC_HEADER_MAJOR
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
@@ -404,8 +428,10 @@ fi
AC_SEARCH_LIBS(inet_ntop, resolv)
# Solaris and HP-UX weirdness:
# Search for libiconv_open (not iconv_open) to discover if -liconv is needed!
# For OS X, Solaris, HP-UX, etc.: figure out if -liconv is needed. We'll
# accept either iconv_open or libiconv_open, since some include files map
# the former to the latter.
AC_SEARCH_LIBS(iconv_open, iconv)
AC_SEARCH_LIBS(libiconv_open, iconv)
AC_MSG_CHECKING([for iconv declaration])
@@ -435,6 +461,10 @@ dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
AC_CHECK_FUNCS(inet_pton, , [AC_LIBOBJ(lib/inet_pton)])
AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>])
AC_HAVE_TYPE([struct sockaddr_storage], [#include <sys/types.h>
#include <sys/socket.h>])
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
# builtin getaddrinfo if one of the defines don't exist
AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
@@ -448,7 +478,7 @@ AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
#endif],
rsync_cv_HAVE_GETADDR_DEFINES=yes,
rsync_cv_HAVE_GETADDR_DEFINES=no)])
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" -a x"$ac_cv_type_struct_addrinfo" = x"yes"; then
# Tru64 UNIX has getaddrinfo() but has it renamed in libc as
# something else so we must include <netdb.h> to get the
# redefinition.
@@ -459,13 +489,11 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_GETADDRINFO, 1,
[Define to 1 if you have the "getaddrinfo" function.])],
[Define to 1 if you have the "getaddrinfo" function and required types.])],
[AC_MSG_RESULT([no])
AC_LIBOBJ(lib/getaddrinfo)])])
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
else
AC_LIBOBJ(lib/getaddrinfo)
AC_LIBOBJ(lib/getnameinfo)
fi
AC_CHECK_MEMBER([struct sockaddr.sa_len],
@@ -494,15 +522,6 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct sockaddr_storage)
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>],
[struct sockaddr_storage x;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
[Define to 1 if you have struct sockaddr_storage.] ),
AC_MSG_RESULT(no))
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
[],
@@ -512,8 +531,7 @@ AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct stat64)
AC_TRY_COMPILE([#include <stdio.h>
AC_HAVE_TYPE([struct stat64], [#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
@@ -528,10 +546,7 @@ AC_TRY_COMPILE([#include <stdio.h>
# include <stdlib.h>
# endif
#endif
],[struct stat64 st;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STRUCT_STAT64,1,[Define to 1 if you have struct stat64.]),
AC_MSG_RESULT(no))
])
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
#
@@ -554,21 +569,36 @@ 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 \
extattr_get_link sigaction sigprocmask setattrlist)
seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask setattrlist \
utimensat)
dnl cygwin iconv.h defines iconv_open as libiconv_open
if test x"$ac_cv_func_iconv_open" != x"yes"; then
AC_CHECK_FUNC(libiconv_open, [ac_cv_func_iconv_open=yes; AC_DEFINE(HAVE_ICONV_OPEN, 1)])
fi
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
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).])
@@ -645,7 +675,11 @@ AC_TRY_RUN([
main() {
int fd[2];
#ifdef __CYGWIN__
exit(1);
#else
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
#endif
}],
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
@@ -655,6 +689,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
@@ -689,13 +732,13 @@ if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [Define to 1 if readdir() is broken])
fi
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_STRUCT_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
rsync_cv_HAVE_STRUCT_UTIMBUF=yes,rsync_cv_HAVE_STRUCT_UTIMBUF=no)])
if test x"$rsync_cv_HAVE_STRUCT_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_STRUCT_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
@@ -752,7 +795,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
@@ -824,8 +867,8 @@ AC_SUBST(OBJ_SAVE)
AC_SUBST(OBJ_RESTORE)
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 +950,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)
@@ -936,12 +975,18 @@ else
AC_MSG_RESULT(Using OS X xattrs)
AC_DEFINE(HAVE_OSX_XATTRS, 1, [True if you have Mac OS X xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
AC_DEFINE(NO_DEVICE_XATTRS, 1, [True if device files do not support xattrs])
AC_DEFINE(NO_SPECIAL_XATTRS, 1, [True if special files do not support xattrs])
;;
freebsd*)
AC_MSG_RESULT(Using FreeBSD extattrs)
AC_DEFINE(HAVE_FREEBSD_XATTRS, 1, [True if you have FreeBSD xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
;;
solaris*)
# Better Solaris support coming in 3.1.0...
AC_DEFINE(NO_SYMLINK_XATTRS, 1, [True if symlinks do not support xattrs])
;;
*)
if test x"$enable_xattr_support" = x"yes"; then
AC_MSG_ERROR(Failed to find extended attribute support)
@@ -952,6 +997,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

@@ -3,21 +3,22 @@ basically a summary of clientserver.c and authenticate.c.
-- Martin Pool <mbp@samba.org>
$Id$
This is the protocol used for rsync --daemon; i.e. connections to port
873 rather than invocations over a remote shell.
When the server accepts a connection, it prints a greeting
@RSYNCD: <version>
@RSYNCD: <version>.<subprotocol>
where <version> is the numeric version; currently 24. It follows this
with a free text message-of-the-day. It expects to see a similar
greeting back from the client.
where <version> is the numeric version (see PROTOCOL_VERSION in rsync.h)
'.' is a literal period, and <subprotocol> is the numeric subprotocol
version (see SUBPROTOCOL_VERSION -- it will be 0 for final releases).
Protocols prior to 30 only output <version> alone. The daemon expects
to see a similar greeting back from the client. For protocols prior to
30, an absent ".<subprotocol>" value is assumed to be 0. For protocol
30, an absent value is a fatal error. The daemon then follows this line
with a free-format text message-of-the-day (if any is defined).
The server is now in the connected state. The client can either send
the command
@@ -75,8 +76,13 @@ stay tuned (or write it yourself!).
------------
Protocol version changes
25 (2001-08-20, 2.4.7pre2)
30 (2007-10-04, 3.0.0pre1)
Send an explicit "@RSYNC EXIT" command at the end of the
module listing. We never intentionally end the transmission
by just closing the socket anymore.
The use of a ".<subprotocol>" number was added to
@RSYNCD: <version>.<subprotocol>
25 (2001-08-20, 2.4.7pre2)
Send an explicit "@RSYNC EXIT" command at the end of the
module listing. We never intentionally end the transmission
by just closing the socket anymore.

View File

@@ -1,2 +0,0 @@
rsync.pdf
rsync.ps

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
@@ -45,6 +45,7 @@
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
#define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */
/* Although it doesn't seem to be specified anywhere,
* ssh and the shell seem to return these values:

125
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
@@ -26,7 +26,6 @@ extern int verbose;
extern int am_server;
extern int am_sender;
extern int eol_nulls;
extern int recurse;
extern int io_error;
extern int local_server;
extern int prune_empty_dirs;
@@ -38,13 +37,13 @@ extern int sanitize_paths;
extern int protocol_version;
extern int module_id;
extern char curr_dir[];
extern char curr_dir[MAXPATHLEN];
extern unsigned int curr_dir_len;
extern unsigned int module_dirlen;
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)
@@ -53,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
@@ -120,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",
@@ -146,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;
@@ -179,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;
@@ -227,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;
@@ -296,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, NULL)) {
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, SP_DEFAULT)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
return NULL;
@@ -304,18 +327,19 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
fn_len = strlen(fn);
} else {
strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
fn_len = clean_fname(fn, 1);
fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS);
}
/* 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);
fn_len = clean_fname(buf, 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);
}
if (len_ptr)
@@ -337,7 +361,7 @@ void set_filter_dir(const char *dir, unsigned int dirlen)
len = 0;
memcpy(dirbuf + len, dir, dirlen);
dirbuf[dirlen + len] = '\0';
dirbuf_len = clean_fname(dirbuf, 1);
dirbuf_len = clean_fname(dirbuf, CFN_COLLAPSE_DOT_DOT_DIRS);
if (dirbuf_len > 1 && dirbuf[dirbuf_len-1] == '.'
&& dirbuf[dirbuf_len-2] == '/')
dirbuf_len -= 2;
@@ -373,7 +397,7 @@ static BOOL setup_merge_file(struct filter_struct *ex,
else
pathjoin(buf, MAXPATHLEN, dirbuf, x);
len = clean_fname(buf, 1);
len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
if (len != 1 && len < MAXPATHLEN-1) {
buf[len++] = '/';
buf[len] = '\0';
@@ -452,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));
}
@@ -518,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;
@@ -597,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)
{
@@ -609,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);
@@ -621,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;
@@ -629,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;
}
}
@@ -876,13 +901,9 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
exit_cleanup(RERR_SYNTAX);
}
/* --delete-excluded turns an un-modified include/exclude into a
* sender-side rule. We also affect per-dir merge files that take
* no prefixes as a simple optimization. */
/* --delete-excluded turns an un-modified include/exclude into a sender-side rule. */
if (delete_excluded
&& !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE))
&& (!(new_mflags & MATCHFLG_PERDIR_MERGE)
|| new_mflags & MATCHFLG_NO_PREFIXES))
&& !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE|MATCHFLG_MERGE_FILE|MATCHFLG_PERDIR_MERGE)))
new_mflags |= MATCHFLG_SENDER_SIDE;
*len_ptr = len;
@@ -899,7 +920,7 @@ static char default_cvsignore[] =
" *.a *.olb *.o *.obj *.so *.exe"
" *.Z *.elc *.ln core"
/* The rest we added to suit ourself. */
" .svn/ .git/ .bzr/";
" .svn/ .git/ .hg/ .bzr/";
static void get_cvs_excludes(uint32 mflags)
{
@@ -1010,10 +1031,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, 1);
if (check_filter(&server_filter_list, line, 0) < 0)
clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&daemon_filter_list, FLOG, line, 0) < 0)
fp = NULL;
else
fp = fopen(line, "rb");
@@ -1096,6 +1117,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
@@ -27,39 +27,43 @@
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)
int sparse_end(int f, OFF_T size)
{
int ret;
if (!sparse_seek)
return 0;
do_lseek(f, sparse_seek-1, SEEK_CUR);
#ifdef HAVE_FTRUNCATE
ret = do_ftruncate(f, size);
#else
if (do_lseek(f, sparse_seek-1, SEEK_CUR) != size-1)
ret = -1;
else {
do {
ret = write(f, "", 1);
} while (ret < 0 && errno == EINTR);
ret = ret <= 0 ? -1 : 0;
}
#endif
sparse_seek = 0;
do {
ret = write(f, "", 1);
} while (ret < 0 && errno == EINTR);
return ret <= 0 ? -1 : 0;
return ret;
}
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++) {}
for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}
/* XXX Riddle me this: why does this function SLOW DOWN when I
* remove the following (unneeded) line?? Core Duo weirdness? */
last_byte = buf[len-1];
sparse_seek += l1;
if (l1 == len)
@@ -108,7 +112,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 +129,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;

1148
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
@@ -24,7 +24,7 @@
struct hashtable *hashtable_create(int size, int key64)
{
struct hashtable *tbl;
int node_size = key64 ? sizeof (struct ht_int64_node )
int node_size = key64 ? sizeof (struct ht_int64_node)
: sizeof (struct ht_int32_node);
/* Pick a power of 2 that can hold the requested size. */
@@ -41,6 +41,7 @@ struct hashtable *hashtable_create(int size, int key64)
tbl->size = size;
tbl->entries = 0;
tbl->node_size = node_size;
tbl->key64 = key64 ? 1 : 0;
return tbl;
}
@@ -55,10 +56,15 @@ void hashtable_destroy(struct hashtable *tbl)
* already existing. Returns NULL if not allocating and not found. */
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
{
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
int key64 = tbl->key64;
struct ht_int32_node *node;
uint32 ndx;
if (key64 ? key == 0 : (int32)key == 0) {
rprintf(FERROR, "Internal hashtable error: illegal key supplied!\n");
exit_cleanup(RERR_MESSAGEIO);
}
if (allocate_if_missing && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
void *old_nodes = tbl->nodes;
int size = tbl->size * 2;
@@ -86,7 +92,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);
@@ -103,7 +109,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);
@@ -139,7 +147,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
if (key64)
((struct ht_int64_node*)node)->key = key;
else
node->key = key;
node->key = (int32)key;
tbl->entries++;
return node;
}

244
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
@@ -24,21 +24,21 @@
extern int verbose;
extern int dry_run;
extern int list_only;
extern int am_sender;
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;
extern int stdout_format_has_i;
extern int maybe_ATTRS_REPORT;
extern char *basis_dir[];
extern int unsort_ndx;
extern char *basis_dir[MAX_BASIS_DIRS+1];
extern struct file_list *cur_flist;
#ifdef ICONV_OPTION
extern int ic_ndx;
#endif
#ifdef SUPPORT_HARD_LINKS
@@ -57,7 +57,7 @@ static struct file_list *hlink_flist;
void init_hard_links(void)
{
if (am_sender || protocol_version < 30)
dev_tbl = hashtable_create(16, SIZEOF_INT64 == 8);
dev_tbl = hashtable_create(16, 1);
else if (inc_recurse)
prior_hlinks = hashtable_create(1024, 0);
}
@@ -67,11 +67,12 @@ struct ht_int64_node *idev_find(int64 dev, int64 ino)
static struct ht_int64_node *dev_node = NULL;
struct hashtable *tbl;
if (!dev_node || dev_node->key != dev) {
/* Note that some OSes have a dev == 0, so increment to avoid storing a 0. */
if (!dev_node || dev_node->key != dev+1) {
/* We keep a separate hash table of inodes for every device. */
dev_node = hashtable_find(dev_tbl, dev, 1);
dev_node = hashtable_find(dev_tbl, dev+1, 1);
if (!(tbl = dev_node->data))
tbl = dev_node->data = hashtable_create(512, SIZEOF_INT64 == 8);
tbl = dev_node->data = hashtable_create(512, 1);
} else
tbl = dev_node->data;
@@ -120,18 +121,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 {
@@ -144,12 +150,10 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
if (gnum != gnum_next)
break;
F_HL_PREV(file) = prev;
/* The linked list must use raw ndx values. */
#ifdef ICONV_OPTION
if (ic_ndx)
/* The linked list uses over-the-wire ndx values. */
if (unsort_ndx)
prev = F_NDX(file);
else
#endif
prev = ndx_list[from] + hlink_flist->ndx_start;
}
if (prev < 0 && !inc_recurse) {
@@ -163,11 +167,9 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
file->flags |= FLAG_HLINK_LAST;
F_HL_PREV(file) = prev;
if (inc_recurse && CVAL(node->data, 0) == 0) {
#ifdef ICONV_OPTION
if (ic_ndx)
if (unsort_ndx)
prev = F_NDX(file);
else
#endif
prev = ndx_list[from] + hlink_flist->ndx_start;
SIVAL(node->data, 1, prev);
}
@@ -180,23 +182,25 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
int i, ndx_count = 0;
int32 *ndx_list;
if (!list_only && flist->used) {
int i, ndx_count = 0;
int32 *ndx_list;
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
if (protocol_version < 30)
idev_destroy();
}
@@ -223,7 +227,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
if (!make_backup(fname))
return -1;
} else if (robust_unlink(fname)) {
rsyserr(FERROR, errno, "unlink %s failed",
rsyserr(FERROR_XFER, errno, "unlink %s failed",
full_fname(fname));
return -1;
}
@@ -243,21 +247,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:
@@ -271,20 +297,28 @@ 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;
/* Is the previous link is not complete yet? */
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)) {
/* Is the previous link being transferred? */
if (prev_file->flags & FLAG_FILE_SENT) {
/* Add ourselves to the list of files that will be
* updated when the transfer completes, and mark
* ourself as waiting for the transfer. */
/* Add ourselves to the list of files that will
* be updated when the transfer completes, and
* mark ourself as waiting for the transfer. */
F_HL_PREV(file) = F_HL_PREV(prev_file);
F_HL_PREV(prev_file) = ndx;
file->flags |= FLAG_FILE_SENT;
@@ -297,8 +331,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;
}
@@ -323,9 +357,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, 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) {
@@ -335,6 +373,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);
@@ -364,19 +405,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,
@@ -396,10 +455,10 @@ int hard_link_one(struct file_struct *file, const char *fname,
enum logcode code;
if (terse) {
if (!verbose)
return -1;
return 0;
code = FINFO;
} else
code = FERROR;
code = FERROR_XFER;
rsyserr(code, errno, "link %s => %s failed",
full_fname(fname), oldname);
return 0;
@@ -416,14 +475,14 @@ 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);
if (stp == NULL && prev_ndx >= 0) {
if (link_stat(fname, &st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return;
}
@@ -443,23 +502,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;
@@ -470,11 +534,43 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
if (inc_recurse) {
int gnum = F_HL_GNUM(file);
struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
assert(node != NULL && node->data != NULL);
assert(CVAL(node->data, 0) == 0);
if (node == NULL) {
rprintf(FERROR, "Unable to find a hlink node for %d (%s)\n", gnum, f_name(file, prev_name));
exit_cleanup(RERR_MESSAGEIO);
}
if (node->data == NULL) {
rprintf(FERROR, "Hlink node data for %d is NULL (%s)\n", gnum, f_name(file, prev_name));
exit_cleanup(RERR_MESSAGEIO);
}
if (CVAL(node->data, 0) != 0) {
rprintf(FERROR, "Hlink node data for %d already has path=%s (%s)\n",
gnum, (char*)node->data, f_name(file, prev_name));
exit_cleanup(RERR_MESSAGEIO);
}
free(node->data);
if (!(node->data = strdup(our_name)))
out_of_memory("finish_hard_link");
}
}
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)
{

390
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
@@ -36,7 +36,6 @@
extern int bwlimit;
extern size_t bwlimit_writemax;
extern int io_timeout;
extern int allowed_lull;
extern int am_server;
extern int am_daemon;
extern int am_sender;
@@ -45,8 +44,9 @@ 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 compat_flags;
extern int protect_args;
extern int checksum_seed;
extern int protocol_version;
@@ -59,7 +59,8 @@ extern int filesfrom_convert;
extern iconv_t ic_send, ic_recv;
#endif
const char phase_unknown[] = "unknown";
int csum_length = SHORT_SUM_LENGTH; /* initial value */
int allowed_lull = 0;
int ignore_timeout = 0;
int batch_fd = -1;
int msgdone_cnt = 0;
@@ -100,10 +101,11 @@ static char ff_lastchar;
#ifdef ICONV_OPTION
static xbuf iconv_buf = EMPTY_XBUF;
#endif
static int defer_forwarding_messages = 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--;
@@ -194,44 +177,30 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
case FES_SUCCESS:
if (remove_source_files)
send_msg(MSG_SUCCESS, buf, 4, 0);
/* FALL THROUGH */
case FES_NO_SEND:
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links) {
struct file_struct *file = flist->files[ndx - flist->ndx_start];
if (F_IS_HLINKED(file)) {
if (status == FES_NO_SEND)
flist_ndx_push(&hlink_list, -2); /* indicates a failure follows */
flist_ndx_push(&hlink_list, ndx);
flist->in_progress++;
}
}
#endif
break;
case FES_REDO:
if (read_batch) {
if (inc_recurse)
flist->in_progress++;
break;
}
if (inc_recurse)
flist->to_redo++;
flist_ndx_push(&redo_list, ndx);
break;
case FES_NO_SEND:
break;
}
}
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);
}
}
@@ -246,13 +215,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 +262,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");
}
}
@@ -413,15 +413,18 @@ static void read_msg_fd(void)
readfd(fd, buf, 4);
got_flist_entry_status(FES_NO_SEND, buf);
break;
case MSG_SOCKERR:
case MSG_ERROR_SOCKET:
case MSG_ERROR_UTF8:
case MSG_CLIENT:
if (!am_generator)
goto invalid_msg;
if (tag == MSG_SOCKERR)
if (tag == MSG_ERROR_SOCKET)
io_end_multiplex_out();
/* FALL THROUGH */
case MSG_INFO:
case MSG_ERROR:
case MSG_ERROR_XFER:
case MSG_WARNING:
case MSG_LOG:
while (len) {
n = len;
@@ -440,7 +443,7 @@ static void read_msg_fd(void)
no_flush--;
msg_fd_in = fd;
if (!--defer_forwarding_messages)
if (!--defer_forwarding_messages && !no_flush)
msg_flush();
}
@@ -449,9 +452,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
@@ -468,46 +476,41 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len,
char buffer[BIGPATHBUFLEN]; /* Oversized for use by iconv code. */
size_t n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
#ifdef ICONV_OPTION
if (convert && ic_send == (iconv_t)-1)
#endif
convert = 0;
/* We need to convert buf before doing anything else so that we
* can include the (converted) byte length in the message header. */
if (convert && ic_send != (iconv_t)-1) {
xbuf outbuf, inbuf;
if (convert || n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
n = 0;
INIT_XBUF(outbuf, buffer + 4, 0, sizeof buffer - 4);
INIT_XBUF(inbuf, (char*)buf, len, -1);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
if (inbuf.len > 0) {
rprintf(FERROR, "overflowed conversion buffer in mplex_write");
exit_cleanup(RERR_UNSUPPORTED);
}
n = len = outbuf.len;
} else
#endif
if (n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
n = 0; /* We'd rather do 2 writes than too much memcpy(). */
else
memcpy(buffer + 4, buf, n);
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
keep_defer_forwarding++; /* defer_forwarding_messages++ on return */
writefd_unbuffered(fd, buffer, n+4);
keep_defer_forwarding--;
len -= n;
buf += n;
if (len > n)
writefd_unbuffered(fd, buf+n, len-n);
#ifdef ICONV_OPTION
if (convert) {
xbuf outbuf, inbuf;
INIT_CONST_XBUF(outbuf, buffer);
INIT_XBUF(inbuf, (char*)buf, len, -1);
defer_forwarding_messages++;
do {
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
writefd_unbuffered(fd, outbuf.buf, outbuf.len);
} while (inbuf.len);
if (!--defer_forwarding_messages)
msg_flush();
} else
#endif
if (len) {
defer_forwarding_messages++;
writefd_unbuffered(fd, buf, len);
if (!--defer_forwarding_messages)
msg_flush();
}
if (!--defer_forwarding_messages && !no_flush)
msg_flush();
}
int send_msg(enum msgcode code, const char *buf, int len, int convert)
@@ -536,10 +539,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)
@@ -756,7 +758,7 @@ static int read_timeout(int fd, char *buf, size_t len)
/* Don't write errors on a dead socket. */
if (fd == sock_f_in) {
io_end_multiplex_out();
rsyserr(FSOCKERR, errno, "read error");
rsyserr(FERROR_SOCKET, errno, "read error");
} else
rsyserr(FERROR, errno, "read error");
exit_cleanup(RERR_STREAMIO);
@@ -841,8 +843,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;
@@ -856,14 +858,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");
@@ -886,11 +888,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)
@@ -952,8 +955,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);
@@ -970,11 +973,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);
}
@@ -1041,6 +1046,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;
@@ -1059,10 +1066,9 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
xbuf outbuf, inbuf;
char ibuf[512];
int add_null = 0;
int pos = 0;
INIT_CONST_XBUF(outbuf, line);
inbuf.buf = ibuf;
INIT_XBUF(inbuf, ibuf, 0, -1);
while (msg_bytes) {
inbuf.len = msg_bytes > sizeof ibuf
@@ -1074,7 +1080,6 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
if (iconvbufs(ic_send, &inbuf, &outbuf,
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE) < 0)
goto overflow;
pos = -1;
}
if (add_null) {
if (outbuf.len == outbuf.size)
@@ -1111,6 +1116,8 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
break;
case MSG_INFO:
case MSG_ERROR:
case MSG_ERROR_XFER:
case MSG_WARNING:
if (msg_bytes >= sizeof line) {
overflow:
rprintf(FERROR,
@@ -1120,6 +1127,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",
@@ -1312,6 +1326,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",
@@ -1319,7 +1334,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);
@@ -1389,7 +1404,7 @@ static void sleep_for_bwlimit(int bytes_written)
if (prior_tv.tv_sec) {
elapsed_usec = (start_tv.tv_sec - prior_tv.tv_sec) * ONE_SEC
+ (start_tv.tv_usec - prior_tv.tv_usec);
total_written -= elapsed_usec * bwlimit / (ONE_SEC/1024);
total_written -= (int64)elapsed_usec * bwlimit / (ONE_SEC/1024);
if (total_written < 0)
total_written = 0;
}
@@ -1410,6 +1425,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.
@@ -1488,8 +1519,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) {
@@ -1512,23 +1543,34 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len)
}
no_flush--;
if (!(defer_forwarding_messages -= defer_inc))
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 +1578,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);
@@ -1863,7 +1903,7 @@ void start_write_batch(int fd)
* is involved. */
write_int(batch_fd, protocol_version);
if (protocol_version >= 30)
write_byte(batch_fd, inc_recurse);
write_byte(batch_fd, compat_flags);
write_int(batch_fd, checksum_seed);
if (am_sender)

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

@@ -1 +0,0 @@
dummy

180
lib/addrinfo.h Normal file
View File

@@ -0,0 +1,180 @@
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*-------------------------------------------------------------------------
*
* getaddrinfo.h
* Support getaddrinfo() on platforms that don't have it.
*
* Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
* whether or not the library routine getaddrinfo() can be found. This
* policy is needed because on some platforms a manually installed libbind.a
* may provide getaddrinfo(), yet the system headers may not provide the
* struct definitions needed to call it. To avoid conflict with the libbind
* definition in such cases, we rename our routines to pg_xxx() via macros.
*
* This code will also work on platforms where struct addrinfo is defined
* in the system headers but no getaddrinfo() can be located.
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
*
*-------------------------------------------------------------------------
*/
#ifndef ADDRINFO_H
#define ADDRINFO_H
/* Various macros that ought to be in <netdb.h>, but might not be */
#ifndef EAI_FAIL
#define EAI_BADFLAGS (-1)
#define EAI_NONAME (-2)
#define EAI_AGAIN (-3)
#define EAI_FAIL (-4)
#define EAI_FAMILY (-6)
#define EAI_SOCKTYPE (-7)
#define EAI_SERVICE (-8)
#define EAI_MEMORY (-10)
#define EAI_SYSTEM (-11)
#endif /* !EAI_FAIL */
#ifndef AI_PASSIVE
#define AI_PASSIVE 0x0001
#endif
#ifndef AI_NUMERICHOST
/*
* some platforms don't support AI_NUMERICHOST; define as zero if using
* the system version of getaddrinfo...
*/
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_NUMERICHOST 0
#else
#define AI_NUMERICHOST 0x0004
#endif
#endif
#ifndef AI_CANONNAME
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_CANONNAME 0
#else
#define AI_CANONNAME 0x0008
#endif
#endif
#ifndef AI_NUMERICSERV
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_NUMERICSERV 0
#else
#define AI_NUMERICSERV 0x0010
#endif
#endif
#ifndef NI_NUMERICHOST
#define NI_NUMERICHOST 1
#endif
#ifndef NI_NUMERICSERV
#define NI_NUMERICSERV 2
#endif
#ifndef NI_NOFQDN
#define NI_NOFQDN 4
#endif
#ifndef NI_NAMEREQD
#define NI_NAMEREQD 8
#endif
#ifndef NI_DGRAM
#define NI_DGRAM 16
#endif
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif
#ifndef HAVE_STRUCT_ADDRINFO
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
#endif /* !HAVE_STRUCT_ADDRINFO */
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
struct sockaddr_storage {
unsigned short ss_family;
unsigned long ss_align;
char ss_padding[128 - sizeof (unsigned long)];
};
#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
#ifndef HAVE_GETADDRINFO
/* Rename private copies per comments above */
#ifdef getaddrinfo
#undef getaddrinfo
#endif
#define getaddrinfo pg_getaddrinfo
#ifdef freeaddrinfo
#undef freeaddrinfo
#endif
#define freeaddrinfo pg_freeaddrinfo
#ifdef gai_strerror
#undef gai_strerror
#endif
#define gai_strerror pg_gai_strerror
#ifdef getnameinfo
#undef getnameinfo
#endif
#define getnameinfo pg_getnameinfo
extern int getaddrinfo(const char *node, const char *service,
const struct addrinfo * hints, struct addrinfo ** res);
extern void freeaddrinfo(struct addrinfo * res);
extern const char *gai_strerror(int errcode);
extern int getnameinfo(const struct sockaddr * sa, socklen_t salen,
char *node, size_t nodelen,
char *service, size_t servicelen, int flags);
#endif /* !HAVE_GETADDRINFO */
#endif /* ADDRINFO_H */

504
lib/getaddrinfo.c Normal file
View File

@@ -0,0 +1,504 @@
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*-------------------------------------------------------------------------
*
* getaddrinfo.c
* Support getaddrinfo() on platforms that don't have it.
*
* We also supply getnameinfo() here, assuming that the platform will have
* it if and only if it has getaddrinfo(). If this proves false on some
* platform, we'll need to split this file and provide a separate configure
* test for getnameinfo().
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
*
* Copyright (C) 2007 Jeremy Allison.
* Modified to return multiple IPv4 addresses for Samba.
*
*-------------------------------------------------------------------------
*/
#include "rsync.h"
#ifndef SMB_MALLOC
#define SMB_MALLOC(s) malloc(s)
#endif
#ifndef SMB_STRDUP
#define SMB_STRDUP(s) strdup(s)
#endif
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif
static int check_hostent_err(struct hostent *hp)
{
#ifndef INET6
extern int h_errno;
#endif
if (!hp) {
switch (h_errno) {
case HOST_NOT_FOUND:
case NO_DATA:
return EAI_NONAME;
case TRY_AGAIN:
return EAI_AGAIN;
case NO_RECOVERY:
default:
return EAI_FAIL;
}
}
if (!hp->h_name || hp->h_addrtype != AF_INET) {
return EAI_FAIL;
}
return 0;
}
static char *canon_name_from_hostent(struct hostent *hp,
int *perr)
{
char *ret = NULL;
*perr = check_hostent_err(hp);
if (*perr) {
return NULL;
}
ret = SMB_STRDUP(hp->h_name);
if (!ret) {
*perr = EAI_MEMORY;
}
return ret;
}
static char *get_my_canon_name(int *perr)
{
char name[HOST_NAME_MAX+1];
if (gethostname(name, HOST_NAME_MAX) == -1) {
*perr = EAI_FAIL;
return NULL;
}
/* Ensure null termination. */
name[HOST_NAME_MAX] = '\0';
return canon_name_from_hostent(gethostbyname(name), perr);
}
static char *get_canon_name_from_addr(struct in_addr ip,
int *perr)
{
return canon_name_from_hostent(
gethostbyaddr((void *)&ip, sizeof ip, AF_INET),
perr);
}
static struct addrinfo *alloc_entry(const struct addrinfo *hints,
struct in_addr ip,
unsigned short port)
{
struct sockaddr_in *psin = NULL;
struct addrinfo *ai = SMB_MALLOC(sizeof(*ai));
if (!ai) {
return NULL;
}
memset(ai, '\0', sizeof(*ai));
psin = SMB_MALLOC(sizeof(*psin));
if (!psin) {
free(ai);
return NULL;
}
memset(psin, '\0', sizeof(*psin));
psin->sin_family = AF_INET;
psin->sin_port = htons(port);
psin->sin_addr = ip;
ai->ai_flags = 0;
ai->ai_family = AF_INET;
ai->ai_socktype = hints->ai_socktype;
ai->ai_protocol = hints->ai_protocol;
ai->ai_addrlen = sizeof(*psin);
ai->ai_addr = (struct sockaddr *) psin;
ai->ai_canonname = NULL;
ai->ai_next = NULL;
return ai;
}
/*
* get address info for a single ipv4 address.
*
* Bugs: - servname can only be a number, not text.
*/
static int getaddr_info_single_addr(const char *service,
uint32 addr,
const struct addrinfo *hints,
struct addrinfo **res)
{
struct addrinfo *ai = NULL;
struct in_addr ip;
unsigned short port = 0;
if (service) {
port = (unsigned short)atoi(service);
}
ip.s_addr = htonl(addr);
ai = alloc_entry(hints, ip, port);
if (!ai) {
return EAI_MEMORY;
}
/* If we're asked for the canonical name,
* make sure it returns correctly. */
if (!(hints->ai_flags & AI_NUMERICSERV) &&
hints->ai_flags & AI_CANONNAME) {
int err;
if (addr == INADDR_LOOPBACK || addr == INADDR_ANY) {
ai->ai_canonname = get_my_canon_name(&err);
} else {
ai->ai_canonname =
get_canon_name_from_addr(ip,&err);
}
if (ai->ai_canonname == NULL) {
freeaddrinfo(ai);
return err;
}
}
*res = ai;
return 0;
}
/*
* get address info for multiple ipv4 addresses.
*
* Bugs: - servname can only be a number, not text.
*/
static int getaddr_info_name(const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res)
{
struct addrinfo *listp = NULL, *prevp = NULL;
char **pptr = NULL;
int err;
struct hostent *hp = NULL;
unsigned short port = 0;
if (service) {
port = (unsigned short)atoi(service);
}
hp = gethostbyname(node);
err = check_hostent_err(hp);
if (err) {
return err;
}
for(pptr = hp->h_addr_list; *pptr; pptr++) {
struct in_addr ip = *(struct in_addr *)*pptr;
struct addrinfo *ai = alloc_entry(hints, ip, port);
if (!ai) {
freeaddrinfo(listp);
return EAI_MEMORY;
}
if (!listp) {
listp = ai;
prevp = ai;
ai->ai_canonname = SMB_STRDUP(hp->h_name);
if (!ai->ai_canonname) {
freeaddrinfo(listp);
return EAI_MEMORY;
}
} else {
prevp->ai_next = ai;
prevp = ai;
}
}
*res = listp;
return 0;
}
/*
* get address info for ipv4 sockets.
*
* Bugs: - servname can only be a number, not text.
*/
int getaddrinfo(const char *node,
const char *service,
const struct addrinfo * hintp,
struct addrinfo ** res)
{
struct addrinfo hints;
/* Setup the hints struct. */
if (hintp == NULL) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
} else {
memcpy(&hints, hintp, sizeof(hints));
}
if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) {
return EAI_FAMILY;
}
if (hints.ai_socktype == 0) {
hints.ai_socktype = SOCK_STREAM;
}
if (!node && !service) {
return EAI_NONAME;
}
if (node) {
if (node[0] == '\0') {
return getaddr_info_single_addr(service,
INADDR_ANY,
&hints,
res);
} else if (hints.ai_flags & AI_NUMERICHOST) {
struct in_addr ip;
if (inet_pton(AF_INET, node, &ip) <= 0)
return EAI_FAIL;
return getaddr_info_single_addr(service,
ntohl(ip.s_addr),
&hints,
res);
} else {
return getaddr_info_name(node,
service,
&hints,
res);
}
} else if (hints.ai_flags & AI_PASSIVE) {
return getaddr_info_single_addr(service,
INADDR_ANY,
&hints,
res);
}
return getaddr_info_single_addr(service,
INADDR_LOOPBACK,
&hints,
res);
}
void freeaddrinfo(struct addrinfo *res)
{
struct addrinfo *next = NULL;
for (;res; res = next) {
next = res->ai_next;
if (res->ai_canonname) {
free(res->ai_canonname);
}
if (res->ai_addr) {
free(res->ai_addr);
}
free(res);
}
}
const char *gai_strerror(int errcode)
{
#ifdef HAVE_HSTRERROR
int hcode;
switch (errcode)
{
case EAI_NONAME:
hcode = HOST_NOT_FOUND;
break;
case EAI_AGAIN:
hcode = TRY_AGAIN;
break;
case EAI_FAIL:
default:
hcode = NO_RECOVERY;
break;
}
return hstrerror(hcode);
#else /* !HAVE_HSTRERROR */
switch (errcode)
{
case EAI_NONAME:
return "Unknown host";
case EAI_AGAIN:
return "Host name lookup failure";
#ifdef EAI_BADFLAGS
case EAI_BADFLAGS:
return "Invalid argument";
#endif
#ifdef EAI_FAMILY
case EAI_FAMILY:
return "Address family not supported";
#endif
#ifdef EAI_MEMORY
case EAI_MEMORY:
return "Not enough memory";
#endif
#ifdef EAI_NODATA
case EAI_NODATA:
return "No host data of that type was found";
#endif
#ifdef EAI_SERVICE
case EAI_SERVICE:
return "Class type not found";
#endif
#ifdef EAI_SOCKTYPE
case EAI_SOCKTYPE:
return "Socket type not supported";
#endif
default:
return "Unknown server error";
}
#endif /* HAVE_HSTRERROR */
}
static int gethostnameinfo(const struct sockaddr *sa,
char *node,
size_t nodelen,
int flags)
{
int ret = -1;
char *p = NULL;
if (!(flags & NI_NUMERICHOST)) {
struct hostent *hp = gethostbyaddr(
(void *)&((struct sockaddr_in *)sa)->sin_addr,
sizeof (struct in_addr),
sa->sa_family);
ret = check_hostent_err(hp);
if (ret == 0) {
/* Name looked up successfully. */
ret = snprintf(node, nodelen, "%s", hp->h_name);
if (ret < 0 || (size_t)ret >= nodelen) {
return EAI_MEMORY;
}
if (flags & NI_NOFQDN) {
p = strchr(node,'.');
if (p) {
*p = '\0';
}
}
return 0;
}
if (flags & NI_NAMEREQD) {
/* If we require a name and didn't get one,
* automatically fail. */
return ret;
}
/* Otherwise just fall into the numeric host code... */
}
p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
ret = snprintf(node, nodelen, "%s", p);
if (ret < 0 || (size_t)ret >= nodelen) {
return EAI_MEMORY;
}
return 0;
}
static int getservicenameinfo(const struct sockaddr *sa,
char *service,
size_t servicelen,
int flags)
{
int ret = -1;
int port = ntohs(((struct sockaddr_in *)sa)->sin_port);
if (!(flags & NI_NUMERICSERV)) {
struct servent *se = getservbyport(
port,
(flags & NI_DGRAM) ? "udp" : "tcp");
if (se && se->s_name) {
/* Service name looked up successfully. */
ret = snprintf(service, servicelen, "%s", se->s_name);
if (ret < 0 || (size_t)ret >= servicelen) {
return EAI_MEMORY;
}
return 0;
}
/* Otherwise just fall into the numeric service code... */
}
ret = snprintf(service, servicelen, "%d", port);
if (ret < 0 || (size_t)ret >= servicelen) {
return EAI_MEMORY;
}
return 0;
}
/*
* Convert an ipv4 address to a hostname.
*
* Bugs: - No IPv6 support.
*/
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *node, size_t nodelen,
char *service, size_t servicelen, int flags)
{
/* Invalid arguments. */
if (sa == NULL || (node == NULL && service == NULL)) {
return EAI_FAIL;
}
if (sa->sa_family != AF_INET) {
return EAI_FAIL;
}
if (salen < (socklen_t)sizeof (struct sockaddr_in)) {
return EAI_FAIL;
}
if (node) {
int ret = gethostnameinfo(sa, node, nodelen, flags);
if (ret)
return ret;
}
if (service) {
return getservicenameinfo(sa, service, servicelen, flags);
}
return 0;
}

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;
@@ -1735,6 +1736,13 @@ int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
struct new_acl_entry *entry;
int keep_going;
if (entry_id == SMB_ACL_FIRST_ENTRY)
theacl->count = 0;
else if (entry_id != SMB_ACL_NEXT_ENTRY) {
errno = EINVAL;
return -1;
}
DEBUG(10,("This is the count: %d\n",theacl->count));
/* Check if count was previously set to -1. *
@@ -1804,11 +1812,14 @@ SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
struct acl_entry_link *acl_entry_link_head;
int i;
int rc = 0;
uid_t user_id;
/* AIX has no DEFAULT */
if ( type == SMB_ACL_TYPE_DEFAULT ) {
#ifdef ENOTSUP
errno = ENOTSUP;
#else
errno = ENOSYS;
#endif
return NULL;
}
@@ -2025,7 +2036,6 @@ SMB_ACL_T sys_acl_get_fd(int fd)
struct acl_entry_link *acl_entry_link_head;
int i;
int rc = 0;
uid_t user_id;
/* Get the acl using fstatacl */
@@ -2255,6 +2265,11 @@ SMB_ACL_T sys_acl_init( int count)
{
struct acl_entry_link *theacl = NULL;
if (count < 0) {
errno = EINVAL;
return NULL;
}
DEBUG(10,("Entering sys_acl_init\n"));
theacl = SMB_MALLOC_P(struct acl_entry_link);
@@ -2373,7 +2388,6 @@ int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl
struct acl_entry *acl_entry = NULL;
struct ace_id *ace_id = NULL;
uint id_type;
uint ace_access;
uint user_id;
uint acl_length;
uint rc;
@@ -2551,7 +2565,7 @@ int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
}
#endif
int sys_acl_delete_def_file(const char *name)
int sys_acl_delete_def_file(UNUSED(const char *name))
{
/* AIX has no default ACL */
return 0;
@@ -2694,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
@@ -2765,6 +2781,11 @@ int no_acl_syscall_error(int err)
return 1;
}
#endif
if (err == EINVAL) {
/* If the type of SMB_ACL_TYPE_ACCESS or SMB_ACL_TYPE_DEFAULT
* isn't valid, then the ACLs must be non-POSIX. */
return 1;
}
return 0;
}

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
@@ -124,6 +122,7 @@ static global Globals;
typedef struct
{
char *auth_users;
char *charset;
char *comment;
char *dont_compress;
char *exclude;
@@ -157,6 +156,8 @@ typedef struct
BOOL ignore_errors;
BOOL ignore_nonreadable;
BOOL list;
BOOL munge_symlinks;
BOOL numeric_ids;
BOOL read_only;
BOOL strict_modes;
BOOL transfer_logging;
@@ -172,7 +173,8 @@ typedef struct
static service sDefault =
{
/* auth_users; */ NULL,
/* comment; */ NULL,
/* charset; */ NULL,
/* comment; */ NULL,
/* dont_compress; */ DEFAULT_DONT_COMPRESS,
/* exclude; */ NULL,
/* exclude_from; */ NULL,
@@ -205,6 +207,8 @@ static service sDefault =
/* ignore_errors; */ False,
/* ignore_nonreadable; */ False,
/* list; */ True,
/* munge_symlinks; */ (BOOL)-1,
/* numeric_ids; */ (BOOL)-1,
/* read_only; */ True,
/* strict_modes; */ True,
/* transfer_logging; */ False,
@@ -299,6 +303,7 @@ static struct parm_struct parm_table[] =
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
{"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
@@ -319,7 +324,9 @@ static struct parm_struct parm_table[] =
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
{"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
{"numeric ids", P_BOOL, P_LOCAL, &sDefault.numeric_ids, NULL,0},
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
#ifdef HAVE_PUTENV
@@ -389,6 +396,7 @@ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_charset, charset)
FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
FN_LOCAL_STRING(lp_exclude, exclude)
@@ -410,18 +418,20 @@ FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_BOOL(lp_fake_super, fake_super)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
@@ -558,7 +568,7 @@ static int map_parameter(char *parmname)
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
return(iIndex);
rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
rprintf(FLOG, "Unknown Parameter encountered: \"%s\"\n", parmname);
return(-1);
}
@@ -584,7 +594,7 @@ static BOOL set_boolean(BOOL *pb, char *parmvalue)
*pb = False;
else
{
rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n",
parmvalue);
bRetval = False;
}
@@ -671,7 +681,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
if (parmnum < 0)
{
rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
rprintf(FLOG, "IGNORING unknown parameter \"%s\"\n", parmname);
return(True);
}
@@ -682,7 +692,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
parm_ptr = def_ptr;
} else {
if (parm_table[parmnum].class == P_GLOBAL) {
rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
rprintf(FLOG, "Global parameter %s found in service section!\n",parmname);
return(True);
}
parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
@@ -780,6 +790,11 @@ static BOOL do_section(char *sectionname)
return(True);
}
if (strchr(sectionname, '/') != NULL) {
rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
return False;
}
/* if we have a current service, tidy it up before moving on */
bRetval = True;
@@ -794,7 +809,7 @@ static BOOL do_section(char *sectionname)
if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
{
rprintf(FERROR,"Failed to add a new service\n");
rprintf(FLOG, "Failed to add a new service\n");
return(False);
}
}

93
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
@@ -35,12 +35,12 @@ extern int msg_fd_out;
extern int allow_8bit_chars;
extern int protocol_version;
extern int preserve_times;
extern int uid_ndx;
extern int gid_ndx;
extern int progress_is_active;
extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern int receiver_symlink_times;
extern mode_t orig_umask;
extern char *auth_user;
extern char *stdout_format;
@@ -50,10 +50,10 @@ extern char *logfile_name;
extern iconv_t ic_chck;
#endif
#ifdef ICONV_OPTION
extern iconv_t ic_send, ic_recv;
extern iconv_t ic_recv;
#endif
extern char curr_dir[];
extern char *module_dir;
extern char curr_dir[MAXPATHLEN];
extern char *full_module_path;
extern unsigned int module_dirlen;
static int log_initialised;
@@ -61,7 +61,7 @@ static int logfile_was_closed;
static FILE *logfile_fp;
struct stats stats;
int log_got_error = 0;
int got_xfer_error = 0;
struct {
int code;
@@ -83,9 +83,10 @@ 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" },
{ RERR_CMD_FAILED , "remote shell failed" },
{ RERR_CMD_KILLED , "remote shell killed" },
{ RERR_CMD_RUN , "remote command could not be run" },
@@ -235,8 +236,8 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
}
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
* certain fatal conditions. */
* it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT. Note: recursion
* can happen with certain fatal conditions. */
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
{
int trailing_CR_or_NL;
@@ -254,20 +255,24 @@ 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 == FSOCKERR) /* This gets simplified for a non-sibling. */
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;
else if (am_daemon || logfile_name) {
static int in_block;
char msg[2048];
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
int priority = code == FINFO || code == FLOG ? LOG_INFO : LOG_WARNING;
if (in_block)
return;
@@ -283,12 +288,19 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
} else if (code == FLOG)
return;
if (quiet && code != FERROR)
if (quiet && code == FINFO)
return;
if (am_server) {
enum msgcode msg = (enum msgcode)code;
if (protocol_version < 30) {
if (msg == MSG_ERROR)
msg = MSG_ERROR_XFER;
else if (msg == MSG_WARNING)
msg = MSG_INFO;
}
/* Pass the message to the non-server side. */
if (send_msg((enum msgcode)code, buf, len, !is_utf8))
if (send_msg(msg, buf, len, !is_utf8))
return;
if (am_daemon) {
/* TODO: can we send the error to the user somehow? */
@@ -297,8 +309,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
}
switch (code) {
case FERROR_XFER:
got_xfer_error = 1;
/* FALL THROUGH */
case FERROR:
log_got_error = 1;
case FWARNING:
f = stderr;
break;
case FINFO:
@@ -308,6 +323,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;
@@ -342,8 +362,8 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
}
}
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
/* This is the rsync debugging function. Call it with FINFO, FERROR_*,
* FWARNING, FLOG, or FCLIENT. */
void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
@@ -421,10 +441,10 @@ void rflush(enum logcode code)
if (am_daemon || code == FLOG)
return;
if (code == FERROR || am_server)
f = stderr;
else
if (code == FINFO && !am_server)
f = stdout;
else
f = stderr;
fflush(f);
}
@@ -505,7 +525,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':
@@ -581,7 +601,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;
@@ -612,7 +632,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
break;
case 'i':
if (iflags & ITEM_DELETED) {
n = "*deleting";
n = "*deleting ";
break;
}
n = c = buf2 + MAXPATHLEN - 32;
@@ -620,14 +640,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 || 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';
@@ -801,7 +828,7 @@ void log_exit(int code, const char *file, int line)
/* VANISHED is not an error, only a warning */
if (code == RERR_VANISHED) {
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
} else {
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",

262
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;
@@ -41,10 +40,11 @@ extern int remove_source_files;
extern int need_messages_from_generator;
extern int kluge_around_eof;
extern int do_stats;
extern int log_got_error;
extern int got_xfer_error;
extern int module_id;
extern int copy_links;
extern int copy_dirlinks;
extern int copy_unsafe_links;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
@@ -63,22 +63,26 @@ extern int read_batch;
extern int write_batch;
extern int batch_fd;
extern int filesfrom_fd;
extern int connect_timeout;
extern dev_t filesystem_dev;
extern pid_t cleanup_child_pid;
extern unsigned int module_dirlen;
extern struct stats stats;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *basis_dir[];
extern char *dest_option;
extern char *basis_dir[MAX_BASIS_DIRS+1];
extern char *rsync_path;
extern char *shell_cmd;
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;
@@ -272,9 +276,10 @@ static void output_summary(void)
"sent %s bytes received %s bytes %s bytes/sec\n",
human_num(total_written), human_num(total_read),
human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
rprintf(FINFO, "total size is %s speedup is %.2f\n",
rprintf(FINFO, "total size is %s speedup is %.2f%s\n",
human_num(stats.total_size),
(double)stats.total_size / (total_written+total_read));
(double)stats.total_size / (total_written+total_read),
write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
}
fflush(stdout);
@@ -328,8 +333,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;
char *dir = NULL;
pid_t pid;
int dash_l_set = 0;
if (!read_batch && !local_server) {
@@ -339,7 +343,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;
@@ -425,7 +429,11 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
args[argc++] = *remote_argv++;
if (**remote_argv == '-') {
if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
out_of_memory("do_cmd");
} else
args[argc++] = *remote_argv++;
remote_argc--;
}
}
@@ -448,7 +456,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
@@ -458,57 +466,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);
}
if (dir)
free(dir);
return ret;
return pid;
oom:
out_of_memory("do_cmd");
@@ -542,15 +513,37 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (!dest_path || list_only)
return NULL;
/* Treat an empty string as a copy into the current directory. */
if (!*dest_path)
dest_path = ".";
if (daemon_filter_list.head) {
char *slash = strrchr(dest_path, '/');
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
*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, "ERROR: daemon has 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);
}
filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
return NULL;
}
if (file_total > 1) {
@@ -606,8 +599,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);
}
@@ -626,8 +619,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);
}
@@ -636,36 +629,41 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
return cp + 1;
}
/* Call this if the destination dir (which is assumed to be in curr_dir)
* does not yet exist and we can't create it due to being in dry-run
* mode. We'll fix dirs that can be relative to the non-existent dir. */
static void fix_basis_dirs(void)
/* This function checks on our alternate-basis directories. If we're in
* dry-run mode and the destination dir does not yet exist, we'll try to
* tweak any dest-relative paths to make them work for a dry-run (the
* destination dir must be in curr_dir[] when this function is called).
* We also warn about any arg that is non-existent or not a directory. */
static void check_alt_basis_dirs(void)
{
char **dir, *new, *slash;
int len;
STRUCT_STAT st;
char **dir_p, *slash = strrchr(curr_dir, '/');
if (dry_run <= 1)
return;
slash = strrchr(curr_dir, '/');
for (dir = basis_dir; *dir; dir++) {
if (**dir == '/')
continue;
len = curr_dir_len + 1 + strlen(*dir) + 1;
if (!(new = new_array(char, len)))
out_of_memory("fix_basis_dirs");
if (slash && strncmp(*dir, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir);
*dir = new;
for (dir_p = basis_dir; *dir_p; dir_p++) {
if (dry_run > 1 && **dir_p != '/') {
int len = curr_dir_len + 1 + strlen(*dir_p) + 1;
char *new = new_array(char, len);
if (!new)
out_of_memory("check_alt_basis_dirs");
if (slash && strncmp(*dir_p, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir_p + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir_p);
*dir_p = new;
}
if (do_stat(*dir_p, &st) < 0) {
rprintf(FWARNING, "%s arg does not exist: %s\n",
dest_option, *dir_p);
} else if (!S_ISDIR(st.st_mode)) {
rprintf(FWARNING, "%s arg is not a dir: %s\n",
dest_option, *dir_p);
}
}
}
@@ -714,8 +712,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);
}
@@ -753,7 +751,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
/* The receiving side mustn't obey this, or an existing symlink that
* points to an identical file won't be replaced by the referent. */
copy_links = copy_dirlinks = 0;
copy_links = copy_dirlinks = copy_unsafe_links = 0;
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && !inc_recurse)
@@ -773,6 +771,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);
@@ -861,7 +861,6 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
int exit_code;
struct file_list *flist;
char *local_name = NULL;
char *dir = NULL;
int save_verbose = verbose;
if (filesfrom_fd >= 0) {
@@ -882,11 +881,11 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
}
if (argc > 0) {
dir = argv[0];
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);
}
@@ -923,26 +922,27 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
/* Now that we know what our destination directory turned out to be,
* we can sanitize the --link-/copy-/compare-dest args correctly. */
if (sanitize_paths) {
char **dir;
for (dir = basis_dir; *dir; dir++) {
*dir = sanitize_path(NULL, *dir, NULL, curr_dir_depth, NULL);
}
if (partial_dir) {
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, NULL);
}
char **dir_p;
for (dir_p = basis_dir; *dir_p; dir_p++)
*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, SP_DEFAULT);
}
fix_basis_dirs();
check_alt_basis_dirs();
if (server_filter_list.head) {
char **dir;
struct filter_list_struct *elp = &server_filter_list;
if (daemon_filter_list.head) {
char **dir_p;
struct filter_list_struct *elp = &daemon_filter_list;
for (dir = basis_dir; *dir; dir++) {
if (check_filter(elp, *dir, 1) < 0)
for (dir_p = basis_dir; *dir_p; dir_p++) {
char *dir = *dir_p;
if (*dir == '/')
dir += module_dirlen;
if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
&& check_filter(elp, partial_dir, 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");
@@ -1029,7 +1029,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");
@@ -1060,11 +1059,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) {
@@ -1081,7 +1075,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (flist && flist->used > 0) {
local_name = get_local_name(flist, argv[0]);
fix_basis_dirs();
check_alt_basis_dirs();
exit_code2 = do_recv(f_in, f_out, local_name);
} else {
@@ -1175,8 +1169,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;
@@ -1207,8 +1199,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) {
@@ -1248,10 +1240,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)
@@ -1263,6 +1251,12 @@ static int start_client(int argc, char *argv[])
exit_cleanup(RERR_SYNTAX);
}
if (connect_timeout) {
rprintf(FERROR, "The --contimeout option may only be "
"used when connecting to an rsync daemon.\n");
exit_cleanup(RERR_SYNTAX);
}
if (shell_machine) {
p = strrchr(shell_machine,'@');
if (p) {
@@ -1309,7 +1303,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
if (!am_server)
output_summary();
close_all();
if (log_got_error)
if (got_xfer_error)
_exit(RERR_PARTIAL);
_exit(0);
}
@@ -1416,7 +1410,8 @@ int main(int argc,char *argv[])
#endif
starttime = time(NULL);
am_root = (MY_UID() == 0);
our_uid = MY_UID();
am_root = our_uid == 0;
memset(&stats, 0, sizeof(stats));
@@ -1433,7 +1428,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();
@@ -1454,11 +1449,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();
@@ -1482,7 +1477,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;
@@ -1498,7 +1492,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);
}

128
match.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
@@ -39,48 +39,58 @@ static int total_matches;
extern struct stats stats;
#define TABLESIZE (1<<16)
#define TRADITIONAL_TABLESIZE (1<<16)
static uint32 tablesize;
static int32 *hash_table;
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
static int32 build_hash_table(struct sum_struct *s, int32 start)
{
int32 i, end = s->count;
#define BIG_SUM2HASH(sum) ((sum)%tablesize)
if (!hash_table) {
hash_table = new_array(int32, TABLESIZE);
static void build_hash_table(struct sum_struct *s)
{
static uint32 alloc_size;
int32 i;
/* Dynamically calculate the hash table size so that the hash load
* for big files is about 80%. A number greater than the traditional
* size must be odd or s2 will not be able to span the entire set. */
tablesize = (uint32)(s->count/8) * 10 + 11;
if (tablesize < TRADITIONAL_TABLESIZE)
tablesize = TRADITIONAL_TABLESIZE;
if (tablesize > alloc_size || tablesize < alloc_size - 16*1024) {
if (hash_table)
free(hash_table);
hash_table = new_array(int32, tablesize);
if (!hash_table)
out_of_memory("build_hash_table");
alloc_size = tablesize;
}
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
memset(hash_table, 0xFF, tablesize * sizeof hash_table[0]);
if (end - start > TABLESIZE*8/10)
end = start + TABLESIZE*8/10;
for (i = start; i < end; i++) {
uint32 t = SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
if (tablesize == TRADITIONAL_TABLESIZE) {
for (i = 0; i < s->count; i++) {
uint32 t = SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
}
} else {
for (i = 0; i < s->count; i++) {
uint32 t = BIG_SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
}
}
if (verbose > 2) {
rprintf(FINFO, "built hash table for entries %ld - %ld\n",
(long)start, (long)end - 1);
}
return end;
}
static OFF_T last_match;
/**
* Transmit a literal and/or match token.
/* Transmit a literal and/or match token.
*
* This delightfully-named function is called either when we find a
* match and need to transmit all the unmatched data leading up to it,
@@ -88,9 +98,9 @@ static OFF_T last_match;
* transmit it. As a result of this second case, it is called even if
* we have not matched at all!
*
* @param i If >0, the number of a matched token. If 0, indicates we
* have only literal data.
**/
* If i >= 0, the number of a matched token. If < 0, indicates we have
* only literal data. A -1 will send a 0-token-int too, and a -2 sends
* only literal data, w/o any token-int. */
static void matched(int f, struct sum_struct *s, struct map_struct *buf,
OFF_T offset, int32 i)
{
@@ -130,8 +140,8 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf, OFF_T len)
{
OFF_T offset, end, reset = 0;
int32 k, want_i, backup, sum_pos = 0;
OFF_T offset, aligned_offset, end;
int32 k, want_i, aligned_i, backup;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
int more;
@@ -156,7 +166,7 @@ static void hash_search(int f,struct sum_struct *s,
if (verbose > 3)
rprintf(FINFO, "sum=%.8x k=%ld\n", sum, (long)k);
offset = 0;
offset = aligned_offset = aligned_i = 0;
end = len + 1 - s->sums[s->count-1].len;
@@ -169,24 +179,21 @@ static void hash_search(int f,struct sum_struct *s,
int done_csum2 = 0;
int32 i;
if (offset >= reset) {
sum_pos = build_hash_table(s, sum_pos);
if (sum_pos == s->count)
reset = len;
else
reset = sum_pos * s->blength;
}
if (verbose > 4) {
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
}
i = hash_table[SUM2HASH2(s1,s2)];
if (i < 0)
goto null_hash;
if (tablesize == TRADITIONAL_TABLESIZE) {
if ((i = hash_table[SUM2HASH2(s1,s2)]) < 0)
goto null_hash;
sum = (s1 & 0xffff) | (s2 << 16);
} else {
sum = (s1 & 0xffff) | (s2 << 16);
if ((i = hash_table[BIG_SUM2HASH(sum)]) < 0)
goto null_hash;
}
sum = (s1 & 0xffff) | (s2 << 16);
hash_hits++;
do {
int32 l;
@@ -224,27 +231,28 @@ static void hash_search(int f,struct sum_struct *s,
/* When updating in-place, the best possible match is
* one with an identical offset, so we prefer that over
* the following want_i optimization. */
* the adjacent want_i optimization. */
if (updating_basis_file) {
int32 i2;
for (i2 = i; i2 >= 0; i2 = s->sums[i2].chain) {
if (s->sums[i2].offset != offset)
continue;
if (i2 != i) {
if (sum != s->sums[i2].sum1)
break;
if (memcmp(sum2, s->sums[i2].sum2,
s->s2length) != 0)
break;
i = i2;
/* All the generator's chunks start at blength boundaries. */
while (aligned_offset < offset) {
aligned_offset += s->blength;
aligned_i++;
}
if (offset == aligned_offset && aligned_i < s->count) {
if (i != aligned_i) {
if (sum != s->sums[aligned_i].sum1
|| l != s->sums[aligned_i].len
|| memcmp(sum2, s->sums[aligned_i].sum2, s->s2length) != 0)
goto check_want_i;
i = aligned_i;
}
/* This chunk was at the same offset on
* both the sender and the receiver. */
/* This identical chunk is in the same spot in the old and new file. */
s->sums[i].flags |= SUMFLG_SAME_OFFSET;
goto set_want_i;
want_i = i;
}
}
check_want_i:
/* we've found a match, but now check to see
* if want_i can hint at a better match. */
if (i != want_i && want_i < s->count
@@ -256,7 +264,6 @@ static void hash_search(int f,struct sum_struct *s,
* will be happy */
i = want_i;
}
set_want_i:
want_i = i + 1;
matched(f,s,buf,offset,i);
@@ -354,6 +361,11 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
}
if (len > 0 && s->count > 0) {
build_hash_table(s);
if (verbose > 2)
rprintf(FINFO,"built hash table\n");
hash_search(f, s, buf, len);
if (verbose > 2)

View File

@@ -1,74 +0,0 @@
# generate prototypes for Samba C code
# tridge, June 1996
BEGIN {
inheader=0;
print "/* This file is automatically generated with \"make proto\". DO NOT EDIT */"
print ""
}
{
if (inheader) {
if (match($0,"[)][ \t]*$")) {
inheader = 0;
printf "%s;\n",$0;
} else {
printf "%s\n",$0;
}
next;
}
}
/^FN_LOCAL_BOOL/ {
split($0,a,"[,()]")
printf "BOOL %s(int );\n", a[2]
}
/^FN_LOCAL_STRING/ {
split($0,a,"[,()]")
printf "char *%s(int );\n", a[2]
}
/^FN_LOCAL_INT/ {
split($0,a,"[,()]")
printf "int %s(int );\n", a[2]
}
/^FN_LOCAL_CHAR/ {
split($0,a,"[,()]")
printf "char %s(int );\n", a[2]
}
/^FN_GLOBAL_BOOL/ {
split($0,a,"[,()]")
printf "BOOL %s(void);\n", a[2]
}
/^FN_GLOBAL_STRING/ {
split($0,a,"[,()]")
printf "char *%s(void);\n", a[2]
}
/^FN_GLOBAL_INT/ {
split($0,a,"[,()]")
printf "int %s(void);\n", a[2]
}
/^static|^extern/ || /[;]/ {
next;
}
!/^[A-Za-z][A-Za-z0-9_]* / {
next;
}
/[(].*[)][ \t]*$/ {
printf "%s;\n",$0;
next;
}
/[(]/ {
inheader=1;
printf "%s\n",$0;
next;
}

48
mkproto.pl Normal file
View File

@@ -0,0 +1,48 @@
# generate prototypes for rsync
$old_protos = '';
if (open(IN, 'proto.h')) {
$old_protos = join('', <IN>);
close IN;
}
%FN_MAP = (
BOOL => 'BOOL ',
CHAR => 'char ',
INTEGER => 'int ',
STRING => 'char *',
);
$inheader = 0;
$protos = qq|/* This file is automatically generated with "make proto". DO NOT EDIT */\n\n|;
while (<>) {
if ($inheader) {
if (/[)][ \t]*$/) {
$inheader = 0;
s/$/;/;
}
$protos .= $_;
} elsif (/^FN_(LOCAL|GLOBAL)_([^(]+)\(([^,()]+)/) {
$ret = $FN_MAP{$2};
$func = $3;
$arg = $1 eq 'LOCAL' ? 'int module_id' : 'void';
$protos .= "$ret$func($arg);\n";
} elsif (/^static|^extern/ || /[;]/ || !/^[A-Za-z][A-Za-z0-9_]* /) {
;
} elsif (/[(].*[)][ \t]*$/) {
s/$/;/;
$protos .= $_;
} elsif (/[(]/) {
$inheader = 1;
$protos .= $_;
}
}
if ($old_protos ne $protos) {
open(OUT, '>proto.h') or die $!;
print OUT $protos;
close OUT;
}
open(OUT, '>proto.h-tstamp') and close OUT;

View File

@@ -1,66 +0,0 @@
/*
* A pre-compilation helper program to aid in the creation of rounding.h.
*
* Copyright (C) 2007 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
struct test1 {
union file_extras extras1[1];
struct {
# include "mkrounding.h"
} file;
};
struct test2 {
union file_extras extras2[2];
struct {
# include "mkrounding.h"
} file;
};
struct test4 {
union file_extras extras4[4];
struct {
# include "mkrounding.h"
} file;
};
#define SIZE_TEST(n) (sizeof (struct test ## n) == EXTRA_LEN * n + sizeof (struct file_struct))
int main(UNUSED(int argc), UNUSED(char *argv[]))
{
int cnt;
if (SIZE_TEST(1))
cnt = 0;
else if (SIZE_TEST(2))
cnt = 1;
else if (SIZE_TEST(4))
cnt = 3;
else {
fprintf(stderr, "Unable to determine required file_extras rounding!\n");
cnt = 3;
}
if (cnt)
fprintf(stderr, "Rounding file_extras in multiples of %d", cnt + 1);
else
fprintf(stderr, "No rounding needed for file_extras");
fprintf(stderr, " (EXTRA_LEN=%d, FILE_STRUCT_LEN=%d)\n",
(int)EXTRA_LEN, (int)FILE_STRUCT_LEN);
printf("#define EXTRA_ROUNDING %d\n", cnt);
return 0;
}

389
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-2011 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,10 +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;
@@ -76,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;
@@ -84,7 +85,6 @@ int numeric_ids = 0;
int allow_8bit_chars = 0;
int force_delete = 0;
int io_timeout = 0;
int allowed_lull = 0;
int prune_empty_dirs = 0;
int use_qsort = 0;
char *files_from = NULL;
@@ -99,6 +99,7 @@ int xfer_dirs = -1;
int am_daemon = 0;
int do_stats = 0;
int do_progress = 0;
int connect_timeout = 0;
int keep_partial = 0;
int safe_symlinks = 0;
int copy_unsafe_links = 0;
@@ -185,8 +186,8 @@ int list_only = 0;
#define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
char *batch_name = NULL;
#ifdef ICONV_OPTION
int need_unsorted_flist = 0;
#ifdef ICONV_OPTION
char *iconv_opt = ICONV_OPTION;
#endif
@@ -200,7 +201,7 @@ static int itemize_changes = 0;
static int refused_delete, refused_archive_part, refused_compress;
static int refused_partial, refused_progress, refused_delete_before;
static int refused_delete_during;
static int refused_inplace;
static int refused_inplace, refused_no_iconv;
static char *max_size_arg, *min_size_arg;
static char tmp_partialdir[] = ".~tmp~";
@@ -216,6 +217,7 @@ static void print_rsync_version(enum logcode f)
char const *got_socketpair = "no ";
char const *have_inplace = "no ";
char const *hardlinks = "no ";
char const *symtimes = "no ";
char const *acls = "no ";
char const *xattrs = "no ";
char const *links = "no ";
@@ -224,7 +226,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 = "";
@@ -250,10 +253,13 @@ static void print_rsync_version(enum logcode f)
#ifdef ICONV_OPTION
iconv = "";
#endif
#ifdef CAN_SET_SYMLINK_TIMES
symtimes = "";
#endif
rprintf(f, "%s version %s protocol version %d%s\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
rprintf(f, "Copyright (C) 1996-2007 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "Web site: http://rsync.samba.org/\n");
rprintf(f, "Capabilities:\n");
rprintf(f, " %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
@@ -263,8 +269,8 @@ static void print_rsync_version(enum logcode f)
(int)(sizeof (int64) * 8));
rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
got_socketpair, hardlinks, links, ipv6, have_inplace);
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv\n",
have_inplace, acls, xattrs, iconv);
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
have_inplace, acls, xattrs, iconv, symtimes);
#ifdef MAINTAINER_MODE
rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
@@ -351,8 +357,8 @@ void usage(enum logcode F)
rprintf(F," --fake-super store/recover privileged attrs using xattrs\n");
#endif
rprintf(F," -S, --sparse handle sparse files efficiently\n");
rprintf(F," -n, --dry-run show what would have been transferred\n");
rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n");
rprintf(F," -n, --dry-run perform a trial run with no changes made\n");
rprintf(F," -W, --whole-file copy files whole (without delta-xfer algorithm)\n");
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
rprintf(F," -B, --block-size=SIZE force a fixed checksum block-size\n");
rprintf(F," -e, --rsh=COMMAND specify the remote shell to use\n");
@@ -363,7 +369,7 @@ void usage(enum logcode F)
rprintf(F," --del an alias for --delete-during\n");
rprintf(F," --delete delete extraneous files from destination dirs\n");
rprintf(F," --delete-before receiver deletes before transfer, not during\n");
rprintf(F," --delete-during receiver deletes during transfer (default)\n");
rprintf(F," --delete-during receiver deletes during the transfer\n");
rprintf(F," --delete-delay find deletions during, delete after\n");
rprintf(F," --delete-after receiver deletes after transfer, not during\n");
rprintf(F," --delete-excluded also delete excluded files from destination dirs\n");
@@ -377,7 +383,8 @@ void usage(enum logcode F)
rprintf(F," --delay-updates put all updated files into place at transfer's end\n");
rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n");
rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n");
rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n");
rprintf(F," --size-only skip files that match in size\n");
rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n");
@@ -421,12 +428,12 @@ void usage(enum logcode F)
rprintf(F," --read-batch=FILE read a batched update from FILE\n");
rprintf(F," --protocol=NUM force an older protocol version to be used\n");
#ifdef ICONV_OPTION
rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filesnames\n");
rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filenames\n");
#endif
rprintf(F," -4, --ipv4 prefer IPv4\n");
rprintf(F," -6, --ipv6 prefer IPv6\n");
rprintf(F," --version print version number\n");
rprintf(F,"(-h) --help show this help (-h works with no other options)\n");
rprintf(F,"(-h) --help show this help (-h is --help only if used alone)\n");
rprintf(F,"\n");
rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
@@ -438,7 +445,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
OPT_NO_D, OPT_APPEND,
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
OPT_SERVER, OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
@@ -467,6 +474,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 },
@@ -477,7 +486,7 @@ static struct poptOption long_options[] = {
{"xattrs", 'X', POPT_ARG_NONE, 0, 'X', 0, 0 },
{"no-xattrs", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
{"no-X", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
{"times", 't', POPT_ARG_VAL, &preserve_times, 2, 0, 0 },
{"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
{"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
{"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
{"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 1, 0, 0 },
@@ -521,14 +530,19 @@ static struct poptOption long_options[] = {
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
{"no-one-file-system",0, POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"no-x", 0, POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
{"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
{"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
{"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 },
@@ -541,8 +555,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 },
@@ -561,11 +577,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 },
@@ -575,7 +593,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 },
@@ -603,15 +623,20 @@ static struct poptOption long_options[] = {
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
{"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 },
#ifdef ICONV_OPTION
{"iconv", 0, POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
{"no-iconv", 0, POPT_ARG_NONE, 0, OPT_NO_ICONV, 0, 0 },
#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 },
@@ -754,6 +779,8 @@ static void set_refuse_options(char *bp)
refused_progress = op->val;
else if (wildmatch("inplace", op->longName))
refused_inplace = op->val;
else if (wildmatch("no-iconv", op->longName))
refused_no_iconv = op->val;
break;
}
if (!is_wild)
@@ -864,7 +891,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);
@@ -874,8 +901,13 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
if (ref && *ref)
set_refuse_options(ref);
if (am_daemon)
if (am_daemon) {
set_refuse_options("log-file*");
#ifdef ICONV_OPTION
if (!*lp_charset(module_id))
set_refuse_options("iconv");
#endif
}
#ifdef ICONV_OPTION
if (!am_daemon && !protect_args && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
@@ -1001,16 +1033,17 @@ 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, NULL);
if (server_filter_list.head) {
arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
if (daemon_filter_list.head) {
int rej;
char *cp = strdup(arg);
char *dir, *cp = strdup(arg);
if (!cp)
out_of_memory("parse_arguments");
if (!*cp)
goto options_rejected;
clean_fname(cp, 1);
rej = check_filter(&server_filter_list, cp, 0) < 0;
dir = cp + (*cp == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0;
free(cp);
if (rej)
goto options_rejected;
@@ -1031,7 +1064,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
preserve_links = 1;
#endif
preserve_perms = 1;
preserve_times = 2;
preserve_times = 1;
preserve_gid = 1;
preserve_uid = 1;
preserve_devices = 1;
@@ -1063,8 +1096,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
break;
case 'q':
if (frommain)
quiet++;
quiet++;
break;
case 'x':
@@ -1122,6 +1154,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
read_batch = 1;
break;
case OPT_NO_ICONV:
#ifdef ICONV_OPTION
iconv_opt = NULL;
#endif
break;
case OPT_MAX_SIZE:
if ((max_size = parse_size_arg(&max_size_arg, 'b')) <= 0) {
snprintf(err_buf, sizeof err_buf,
@@ -1236,7 +1274,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);
@@ -1249,14 +1287,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
else
need_unsorted_flist = 1;
}
if (refused_no_iconv && !iconv_opt) {
create_refuse_error(refused_no_iconv);
return 0;
}
#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) {
@@ -1276,7 +1317,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");
@@ -1301,12 +1348,19 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
batch_name = NULL;
} else if (dry_run)
write_batch = 0;
}
} else if (write_batch < 0 && dry_run)
write_batch = 0;
if (read_batch && files_from) {
snprintf(err_buf, sizeof err_buf,
"--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",
@@ -1338,8 +1392,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;
@@ -1368,7 +1430,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;
}
@@ -1388,32 +1450,33 @@ 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, NULL);
argv[i] = sanitize_path(NULL, argv[i], "", 0, SP_KEEP_DOT_DIRS);
if (tmpdir)
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
if (backup_dir)
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
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;
clean_fname(tmpdir, 1);
if (check_filter(elp, tmpdir, 1) < 0)
dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
if (backup_dir) {
char *dir;
if (!*backup_dir)
goto options_rejected;
clean_fname(backup_dir, 1);
if (check_filter(elp, backup_dir, 1) < 0)
dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
}
@@ -1428,17 +1491,18 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
return 0;
}
if (backup_dir) {
backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
if (backup_dir_remainder < 32) {
size_t len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
if (len > sizeof backup_dir_buf - 128) {
snprintf(err_buf, sizeof err_buf,
"the --backup-dir path is WAY too long.\n");
return 0;
}
backup_dir_len = (int)len;
if (backup_dir_buf[backup_dir_len - 1] != '/') {
backup_dir_buf[backup_dir_len++] = '/';
backup_dir_buf[backup_dir_len] = '\0';
}
backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
if (verbose > 1 && !am_sender)
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
} else if (!backup_suffix_len && (!am_server || !am_sender)) {
@@ -1451,13 +1515,18 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
parse_rule(&filter_list, backup_dir_buf, 0, 0);
}
if (preserve_times) {
preserve_times = PRESERVE_FILE_TIMES;
if (!omit_dir_times)
preserve_times |= PRESERVE_DIR_TIMES;
#ifdef CAN_SET_SYMLINK_TIMES
preserve_times |= PRESERVE_LINK_TIMES;
#endif
}
if (make_backups && !backup_dir) {
omit_dir_times = 0; /* Implied, so avoid -O to sender. */
if (preserve_times > 1)
preserve_times = 1;
} else if (omit_dir_times) {
if (preserve_times > 1)
preserve_times = 1;
preserve_times &= ~PRESERVE_DIR_TIMES;
}
if (stdout_format) {
@@ -1565,7 +1634,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
if (partial_dir) {
if (*partial_dir)
clean_fname(partial_dir, 1);
clean_fname(partial_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (!*partial_dir || strcmp(partial_dir, ".") == 0)
partial_dir = NULL;
if (!partial_dir && refused_partial) {
@@ -1602,12 +1671,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, NULL);
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;
clean_fname(files_from, 1);
if (check_filter(&server_filter_list, files_from, 0) < 0)
dir = files_from + (*files_from == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&daemon_filter_list, FLOG, dir, 0) < 0)
goto options_rejected;
}
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
@@ -1677,8 +1748,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)
@@ -1748,24 +1819,40 @@ 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 && our allow_inc_recurse status. */
set_allow_inc_recurse();
#if SUBPROTOCOL_VERSION != 0
if (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"e%d.%d%s", PROTOCOL_VERSION, SUBPROTOCOL_VERSION,
allow_inc_recurse ? "i" : "");
} else
#endif
if (allow_inc_recurse) {
/* 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';
argstr[x++] = 'i';
#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';
#ifdef CAN_SET_SYMLINK_TIMES
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';
if (x != 1)
if (x > 1)
args[ac++] = argstr;
#ifdef ICONV_OPTION
@@ -1781,7 +1868,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)
@@ -1948,7 +2035,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];
@@ -1988,6 +2074,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;
@@ -1995,6 +2086,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
@@ -2004,68 +2151,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 = (
'daemon' => -1,
'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]"/) {
@@ -18,7 +24,7 @@ while (<IN>) {
undef $last_long_opt;
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
$last_long_opt = $1;
$long_opt{$1} = 0;
$long_opt{$1} = 0 unless exists $long_opt{$1};
} elsif (defined($last_long_opt)
&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
$long_opt{$last_long_opt} = 2;

48
packaging/git-status.pl Normal file
View File

@@ -0,0 +1,48 @@
# Do some git-status checking for the current dir and (optionally)
# the patches dir.
sub check_git_state
{
my($master_branch, $fatal_unless_clean, $check_patches_dir) = @_;
my($cur_branch) = check_git_status($fatal_unless_clean);
if ($cur_branch ne $master_branch) {
print "The checkout is not on the $master_branch branch.\n";
exit 1 if $master_branch ne 'master';
print "Do you want me to continue with --branch=$cur_branch? [n] ";
$_ = <STDIN>;
exit 1 unless /^y/i;
$_[0] = $master_branch = $cur_branch; # Updates caller's $master_branch too.
}
if ($check_patches_dir && -d 'patches/.git') {
($cur_branch) = check_git_status($fatal_unless_clean, 'patches');
if ($cur_branch ne $master_branch) {
print "The *patches* checkout is on branch $cur_branch, not branch $master_branch.\n";
print "Do you want to change it to branch $master_branch? [n] ";
$_ = <STDIN>;
exit 1 unless /^y/i;
system "cd patches && git checkout '$master_branch'";
}
}
}
sub check_git_status
{
my($fatal_unless_clean, $subdir) = @_;
$subdir = '.' unless defined $subdir;
my $status = `cd '$subdir' && git status`;
my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
my($cur_branch) = $status =~ /^# On branch (.+)\n/;
if ($fatal_unless_clean && !$is_clean) {
if ($subdir eq '.') {
$subdir = '';
} else {
$subdir = " *$subdir*";
}
die "The$subdir checkout is not clean:\n", $status;
}
($cur_branch, $is_clean, $status);
}
1;

View File

@@ -1,9 +1,12 @@
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.0pre4
Version: 3.0.9
%define fullversion %{version}
Release: 1
%define srcdir src
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/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
* Fri Oct 26 2007 Wayne Davison <wayned@samba.org>
Released 3.0.0pre4.
* Fri Sep 23 2011 Wayne Davison <wayned@samba.org>
Released 3.0.9.
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
Added installation of /etc/xinetd.d/rsync file and some commented-out
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

@@ -3,8 +3,8 @@ use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. It also requires a
# pristine CVS checkout of rsync (don't use your normal rsync build dir
# unless you're 100% sure that there are not unchecked-in changes).
# git checkout of rsync (feel free to use your normal rsync build dir as
# long as it doesn't have any uncommitted changes).
#
# If this is run with -ctu, it will make an updated "nightly" tar file in
# the nightly dir. It will also remove any old tar files, regenerate the
@@ -14,16 +14,13 @@ use strict;
use Getopt::Long;
use Date::Format;
# Choose any dir where a pristine rsync has been checked out of CVS.
our $unpacked = $ENV{HOME} . '/release/nightly';
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
# 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($cvs_update, $make_tar, $upload, $help_opt);
our($make_tar, $upload, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'cvs-update|c' => \$cvs_update,
'make-tar|t' => \$make_tar,
'upload|u' => \$upload,
'help|h' => \$help_opt,
@@ -32,70 +29,117 @@ our($cvs_update, $make_tar, $upload, $help_opt);
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
our $ztoday = time2str('%d %b %Y', time);
our $today = $ztoday;
our $gen_target = $upload ? 'gensend' : 'gen';
chdir($unpacked) or die $!;
if ($cvs_update) {
print "Updating from cvs...\n";
system 'cvs -q up' and die $!;
}
die "$dest does not exist\n" unless -d $dest;
die "There is no .git dir in the current directory.\n" unless -d '.git';
die "There is no rsync checkout in the current directory.\n" unless -f 'rsyncd.conf.yo';
if ($make_tar) {
print "Generating list of active CVS files...\n";
my($dir, @files);
open(CVS, '-|', 'cvs status 2>&1') or die $!;
while (<CVS>) {
if (/^cvs status: Examining (.*)/) {
if ($1 eq '.') {
$dir = '';
} else {
push(@files, $1);
$dir = $1 . '/';
}
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
push(@files, $dir . $1);
if ($2 ne 'Up-to-date') {
print "*** Not up-to-date: $dir$1\n";
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/;
system "make $gen_target" and die "make $gen_target failed!\n";
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extra_files = split(' ', $_);
last;
}
}
close CVS;
close IN;
print "Creating $unpacked/$name.tar.gz\n";
chdir('..') or die $!;
rename($unpacked, $name) or die $!;
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $nightly/$name.tar.gz $name") or die $!;
foreach (@files) {
print TAR "$name/$_\n";
my $confversion;
open(IN, '<', 'configure.ac') or die "Unable to open configure.ac: $!\n";
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$confversion = $1;
last;
}
}
close TAR;
rename($name, $unpacked) or die $!;
close IN;
die "Unable to find RSYNC_VERSION in configure.ac\n" unless defined $confversion;
open(IN, '<', 'OLDNEWS') or die "Unable to open OLDNEWS: $!\n";
$_ = <IN>;
my($lastversion) = /(\d+\.\d+\.\d+)/;
my $last_protocol_version;
while (<IN>) {
if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
$last_protocol_version = $pver if $ver eq $lastversion;
}
}
close IN;
die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
my($protocol_version,$subprotocol_version);
open(IN, '<', 'rsync.h') or die "Unable to open rsync.h: $!\n";
while (<IN>) {
if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
$protocol_version = $1;
} elsif (/^#define\s+SUBPROTOCOL_VERSION\s+(\d+)/) {
$subprotocol_version = $1;
}
}
close IN;
die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
die "Unable to determine the current SUBPROTOCOL_VERSION.\n" unless defined $subprotocol_version;
if ($confversion =~ /dev|pre/) {
if ($last_protocol_version ne $protocol_version) {
if ($subprotocol_version == 0) {
die "SUBPROTOCOL_VERSION must not be 0 for a non-final release with a changed PROTOCOL_VERSION.\n";
}
} else {
if ($subprotocol_version != 0) {
die "SUBPROTOCOL_VERSION must be 0 when the PROTOCOL_VERSION hasn't changed from the last release.\n";
}
}
} else {
if ($subprotocol_version != 0) {
die "SUBPROTOCOL_VERSION must be 0 for a final release.\n";
}
}
print "Creating $name.tar.gz\n";
system "rsync -a @extra_files $name/";
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
system "support/git-set-file-times --prefix=$name/";
system "fakeroot tar czf $dest/$name.tar.gz $name; rm -rf $name";
unlink($nightly_symlink);
symlink("$name.tar.gz", $nightly_symlink);
}
chdir($nightly) or die $!;
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
my $html_fn = $fn;
$html_fn =~ s/\.yo/.html/;
my $yo_tmp = "$dest/$fn";
(my $html_fn = "$dest/$fn") =~ s/\.yo/.html/;
open(IN, '<', "$unpacked/$fn") or die $!;
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
open(OUT, '>', $fn) or die $!;
open(OUT, '>', $yo_tmp) or die $!;
print OUT $_;
close OUT;
system "yodl2html -o $html_fn $fn";
system 'yodl2html', '-o', $html_fn, $yo_tmp;
unlink($fn);
unlink($yo_tmp);
}
chdir($dest) or die $!;
my $cnt = 0;
open(PIPE, '-|', 'ls -1t rsync-HEAD-*') or die $!;
while (<PIPE>) {
@@ -112,7 +156,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;
@@ -122,8 +166,7 @@ sub usage
die <<EOT;
Usage: nightly-rsync [OPTIONS]
-c, --cvs-update update $unpacked via CVS.
-t, --make-tar create a new tar file in $nightly
-t, --make-tar create a new tar file in $dest
-u, --upload upload the revised nightly dir to samba.org
-h, --help display this help
EOT

230
packaging/patch-update Executable file
View File

@@ -0,0 +1,230 @@
#!/usr/bin/perl
# This script is used to turn one or more of the "patch/BASE/*" branches
# into one or more diffs in the "patches" directory. Pass the option
# --gen if you want generated files in the diffs. Pass the name of
# one or more diffs if you want to just update a subset of all the
# diffs.
use strict;
use warnings;
use Getopt::Long;
my $patches_dir = 'patches';
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 ),
);
&usage if $help_opt;
if (defined $incl_generated_files) {
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
$incl_generated_files = 1;
}
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';
require 'packaging/git-status.pl';
check_git_state($master_branch, !$skip_branch_check, 1);
my $master_commit;
open PIPE, '-|', "git log -1 --no-color $master_branch" or die $!;
while (<PIPE>) {
if (/^commit (\S+)/) {
$master_commit = $1;
last;
}
}
close PIPE;
die "Unable to determine commit hash for master branch: $master_branch\n" unless defined $master_commit;
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extra_files = split(' ', $_);
last;
}
}
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 "$make_gen_cmd && rsync -a @extra_files $tmp_dir/master/" and exit 1;
}
our $last_touch = time;
my %patches;
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
while (<PIPE>) {
if (m# patch/\Q$master_branch\E/(.*)#o) {
$patches{$1} = 1;
}
}
close PIPE;
my @patches = sort keys %patches;
my(%parent, %description);
foreach my $patch (@patches) {
my $branch = "patch/$master_branch/$patch";
my $desc = '';
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) {
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;
}
if (@ARGV) {
# Limit the list of patches to actually process based on @ARGV.
@patches = ( );
foreach (@ARGV) {
s{^patch(es)?/} {};
s{\.diff$} {};
if (!$patches{$_}) {
die "Local branch not available for patch: $_\n";
}
push(@patches, $_);
}
}
my %completed;
foreach my $patch (@patches) {
next if $completed{$patch}++;
last unless update_patch($patch);
}
if ($incl_generated_files) {
system "rm -rf $tmp_dir";
}
sleep 1 while $last_touch >= time;
system "git checkout $master_branch" and exit 1;
exit;
sub update_patch
{
my($patch) = @_;
my $parent = $parent{$patch};
my $based_on;
if (defined $parent) {
unless ($completed{$parent}++) {
update_patch($parent);
}
$based_on = $parent = "patch/$master_branch/$parent";
} else {
$parent = $master_branch;
$based_on = $master_commit;
}
print "======== $patch ========\n";
sleep 1 while $incl_generated_files && $last_touch >= time;
system "git checkout patch/$master_branch/$patch" and return 0;
my $ok = system("git merge $based_on") == 0;
if (!$ok || $launch_shell) {
my($parent_dir) = $parent =~ m{([^/]+)$};
print qq|"git merge $based_on" incomplete -- please fix.\n| if !$ok;
$ENV{PS1} = "[$parent_dir] $patch: ";
while (1) {
if (system($ENV{SHELL}) != 0) {
print "Abort? [n/y] ";
$_ = <STDIN>;
next unless /^y/i;
return 0;
}
my($cur_branch, $is_clean, $status) = check_git_status(0);
last if $is_clean;
print $status;
}
}
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
print OUT $description{$patch}, "\nbased-on: $based_on\n";
if ($incl_generated_files) {
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
open(PIPE, '-|', 'git', 'diff', $based_on) or die $!;
DIFF: while (<PIPE>) {
while (m{^diff --git a/PATCH}) {
while (<PIPE>) {
last if m{^diff --git a/};
}
last DIFF if !defined $_;
}
next if /^index /;
print OUT $_;
}
close PIPE;
if ($incl_generated_files) {
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;
s#^\Q+++\E $tmp_dir/[^/]+/([^\t]+)\t.*#+++ b/$1#o;
print OUT $_;
}
close PIPE;
}
close OUT;
1;
}
exit;
sub usage
{
die <<EOT;
Usage: patch-update [OPTIONS] [patches/DIFF...]
Options:
-b, --branch=BRANCH The master branch to merge into the patch/BASE/* branches.
--gen[=DIR] Include generated files. Optional destination DIR
arg overrides the default of using the "patches" dir.
--skip-check Skip the check that ensures starting with a clean branch.
-s, --shell Launch a shell for every patch/BASE/* branch updated, not
just when a conflict occurs.
-h, --help Output this help message.
EOT
}

View File

@@ -1,184 +1,244 @@
#!/usr/bin/perl
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
# the git repository in the current directory will be updated, and the local
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to
# be a copy of the /home/ftp/pub/rsync dir on samba.org. If it is run
# in test mode, it instead expects a dir named ~/tmp/samba-rsync-ftp
# (e.g. copy ~/samba-rsync-ftp into ~/tmp and you can do a trial-run of
# a release without affecting the files in the ~/samba-rsync-ftp dir).
#
# Run this as "release-rsync live" to affect ~/samba-rsync-ftp instead
# of ~/tmp/samba-rsync-ftp.
use warnings;
use Cwd;
use Getopt::Long;
use Term::ReadKey;
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $releasedir = $ENV{HOME} . '/release';
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
my $passfile = $ENV{HOME} . '/.rsyncpass';
my $path = $ENV{PATH};
my $make_gen_cmd = 'make -f prepare-source.mak conf && ./config.status && make gen';
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 $break = <<EOT;
==========================================================================
EOT
my $note = <<EOT;
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
EOT
my $curdir = Cwd::cwd;
my $live = shift;
my $skipping = '';
print $break;
if ($live) {
print <<EOT;
== This will release a new version of rsync onto an unsuspecting world. ==
EOT
} else {
print <<EOT;
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
EOT
$dest =~ s#([^/]+$)#tmp/$1#;
$skipping = ' ** SKIPPING **';
}
die "$dest does not exist\n" unless -d $dest;
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
chdir($releasedir) or die $!;
system 'rm -rf rsync';
my(%dirs, @files);
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
while (<CVS>) {
print $_;
next if /\.(cvs)?ignore$/;
if (m#^[UP] rsync/(.*)#) {
my $fn = $1;
my($dir) = $fn =~ m#^(.+)/#;
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
push(@files, $fn);
}
END {
unlink($passfile);
}
chdir('rsync') or die $!;
my($version, $lastversion);
open(IN, '<', 'configure.in') or die $!;
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$version = $lastversion = $1;
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extra_files = split(' ', $_);
last;
}
}
close IN;
if ($lastversion =~ /cvs$/) {
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
($lastversion) = /(\d+\.\d+\.\d+)/;
my $break = <<EOT;
==========================================================================
EOT
print $break, <<EOT, $break, "\n";
== This will release a new version of rsync onto an unsuspecting world. ==
EOT
die "$dest does not exist\n" unless -d $dest;
die "There is no .git dir in the current directory.\n" unless -d '.git';
die "'a' must not exist in the current directory.\n" if -e 'a';
die "'b' must not exist in the current directory.\n" if -e 'b';
require 'packaging/git-status.pl';
check_git_state($master_branch, 1, 1);
my $confversion;
open(IN, '<', 'configure.ac') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$confversion = $1;
last;
}
}
close IN;
die "Unable to find RSYNC_VERSION in configure.ac\n" unless defined $confversion;
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
my($lastversion) = /(\d+\.\d+\.\d+)/;
my($last_protocol_version, %pdate);
while (<IN>) {
if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
$pdate{$ver} = $pdate if defined $pdate;
$last_protocol_version = $pver if $ver eq $lastversion;
}
}
close IN;
die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
print $break, "\nPlease enter the version number of this release: [$version] ";
my $protocol_version;
open(IN, '<', 'rsync.h') or die $!;
while (<IN>) {
if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
$protocol_version = $1;
last;
}
}
close IN;
die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
my $version = $confversion;
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
print "Please enter the version number of this release: [$version] ";
chomp($_ = <STDIN>);
if ($_ eq '.') {
$version =~ s/pre\d+//;
} elsif ($_ ne '') {
$version = $_;
}
$version =~ s/[-.]*pre[-.]*/pre/;
die "Invalid version: `$version'\n" unless $version =~ /^[\d.]+(pre\d+)?$/;
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
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";
}
my $cvstag = "release-$version";
$cvstag =~ s/[.]/-/g;
$cvstag =~ s/pre/-pre/;
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 $skipping2;
(my $finalversion = $version) =~ s/pre\d+//;
my($proto_changed,$proto_change_date);
if ($protocol_version eq $last_protocol_version) {
$proto_changed = 'unchanged';
$proto_change_date = "\t\t";
} else {
$proto_changed = 'changed';
if (!defined($proto_change_date = $pdate{$finalversion})) {
while (1) {
print "On what date did the protocol change to $protocol_version get checked in? (dd Mmm yyyy) ";
chomp($_ = <STDIN>);
last if /^\d\d \w\w\w \d\d\d\d$/;
}
$proto_change_date = "$_\t";
}
}
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
if ($lastversion =~ /pre/) {
if ($version !~ /pre/) {
if (!$pre) {
die "You should not diff a release version against a pre-release version.\n";
}
$diffdir = "$dest/old-previews";
$skipping2 = ' ** SKIPPING **';
} elsif ($version =~ /pre/) {
$diffdir = $dest;
$skipping2 = ' ** SKIPPING **';
$srcdir = $srcdiffdir = $lastsrcdir = 'src-previews';
$skipping = ' ** SKIPPING **';
} elsif ($pre) {
$srcdir = $srcdiffdir = 'src-previews';
$lastsrcdir = 'src';
$skipping = ' ** SKIPPING **';
} else {
$diffdir = "$dest/old-versions";
$skipping2 = '';
$srcdir = $lastsrcdir = 'src';
$srcdiffdir = 'src-diffs';
$skipping = '';
}
print "\n", $break, <<EOT;
\$version is "$version"
\$lastversion is "$lastversion"
\$cvstag is "$cvstag"
\$dest is "$dest"
\$releasedir is "$releasedir"
\$diffdir is "$diffdir"
\$curdir is "$curdir"
\$srcdir is "$srcdir"
\$srcdiffdir is "$srcdiffdir"
\$lastsrcdir is "$lastsrcdir"
\$release is "$release"
About to:
- make sure that SUBPROTOCOL_VERSION is 0$skipping2
- tweak the version in configure.in, configure, and the spec files
- make sure that configure, config.h.in, and proto.h are updated
- tweak NEWS and OLDNEWS to update the release date$skipping2
- tweak the date in the *.yo files and re-generate the man pages
- make sure that the patches dir has been updated
- page through the "cvs diff" output
- tweak SUBPROTOCOL_VERSION in rsync.h, if needed
- tweak the version in configure.ac and the spec files
- tweak NEWS and OLDNEWS to ensure header values are correct
- tweak the date in the *.yo files and generate the manpages
- generate configure.sh, config.h.in, and proto.h
- page through the differences
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
my $f_opt = /f/ ? ' -f' : '';
print $break;
system "./prepare-source && touch proto.h";
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.ac rsync.h NEWS OLDNEWS options.c ) );
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in configure ) );
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 . ' ' . get_subprotocol_version($2) }e
or die "Unable to find SUBPROTOCOL_VERSION define in $fn\n";
} elsif ($fn eq 'NEWS') {
s{^(NEWS for rsync \Q$finalversion\E )(\(UNRELEASED\))\s*(\nProtocol: )(\d+) (\([^)]+\))\n}
{ $1 . ($pre ? $2 : "($today)") . "$3$protocol_version ($proto_changed)\n" }ei
or die "The first 2 lines of $fn are not in the right format. They must be:\n"
. "NEWS for rsync $finalversion (UNRELEASED)\n"
. "Protocol: $protocol_version ($proto_changed)\n";
} elsif ($fn eq 'OLDNEWS') {
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$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).*}
{ ($pre ? $1 : "\t$ztoday") . $2 . $proto_change_date . $protocol_version }em
or die "Unable to find \"?? ??? $year\t$finalversion\" line in $fn\n";
} 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";
}
@@ -187,144 +247,175 @@ foreach my $fn (@tweak_files) {
close OUT;
}
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage rsync.1";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage rsyncd.conf.5";
mkdir('patches/tmp') or die $!;
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
print "\n", $break, $note, $break;
system "patches/verify-patches -n -an$f_opt";
print $break;
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
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/$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:
- "cvs commit" all changes$skipping
- "cvs tag" this release as $cvstag$skipping
- change the diffs in the patches dir to include generated files
- commit all version changes
- merge the $master_branch branch into the patch/$master_branch/* branches
- update the files in the "patches" dir and OPTIONALLY
(if you type 'y') to launch a shell for each patch
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
print "<Press Enter OR 'y' to continue> ";
my $ans = <STDIN>;
if ($live) {
system "cvs commit -m 'Preparing for release of $version'";
system "cvs tag -F $cvstag .";
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/$master_branch/*\" branches ...\n";
system "packaging/patch-update --branch=$master_branch --shell";
}
if (!/skip/i) {
print "\n", $break, $note, $break;
system "patches/verify-patches -pun -an";
if (-d 'patches/.git') {
system "cd patches && git commit -a -m 'The patches for $version.'" and exit 1;
}
my $tar_name = "rsync-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $tar_file = "$dest/$tar_name";
my $diff_file = "$dest/$diff_name";
print $break, <<EOT;
About to do the following in the samba-rsync-ftp dir:
- move the old tar/diff files into the appropriate old-* dirs
- hard-link the moved tar/diff files on samba.org$skipping
- create release tar, "$tar_name"
About to:
- create signed tag for this release: v$version
- create release diffs, "$diff_name"
- update README, *NEWS, TODO, and cvs.log
- update rsync*.html man pages
- gpg-sign the release files$skipping
- 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>;
chdir($releasedir) or die $!;
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
$ENV{PATH} = "$curdir/packaging/bin:$path";
print $break;
system "rm -rf rsync-$version";
rename('rsync', "rsync-$version") or die $!;
my $passphrase;
while (1) {
ReadMode('noecho');
print "\nEnter your GPG pass-phrase: ";
chomp($passphrase = <STDIN>);
ReadMode(0);
print "\n";
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
chdir($dest) or die $!;
# 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;
print "Shuffling old files ...\n";
$_ = `git tag -s -m 'Version $version.' v$version 2>&1`;
print $_;
next if /bad passphrase/;
exit 1 if /failed/;
# 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 (-d 'patches/.git') {
$_ = `cd patches && git tag -s -m 'Version $version.' v$version 2>&1`;
print $_;
exit 1 if /bad passphrase|failed/;
}
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.
if ($live) {
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
}
foreach (@moved_files) {
unlink($_);
}
chdir($releasedir) or die $!;
unlink($passfile);
last;
}
print "Creating $tar_file ...\n";
system "fakeroot tar czf $tar_file rsync-$version";
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
foreach (@files) {
print TAR "rsync-$version/$_\n";
}
close TAR;
$ENV{PATH} = $path;
# Extract the generated files from the old tar.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
print "Creating $diff_file ...\n";
system "rm -rf rsync-$version rsync-$lastversion";
system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
## TWEAK THE VERSIONS AS DESIRED HERE ##
#mkdir("rsync-$lastversion/support", 0755) or die $!;
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
#unlink("rsync-$lastversion/.ignore");
## END ##
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
system "$make_gen_cmd && rsync -a @extra_files b/" and exit 1;
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "rm -rf a";
rename('b', "rsync-$version");
print "Creating $srctar_file ...\n";
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 "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 rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
unlink("$dest/rsync-$version-NEWS");
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
system "rsync -a README NEWS OLDNEWS TODO $dest";
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-$version/rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
system "yodl2html -o $dest/rsync.html rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsyncd.conf.yo";
system "rm -rf rsync-*";
if ($live) {
chdir($dest) or die $!;
system "gpg -ba $tar_name; gpg -ba $diff_name";
print $break, <<EOT;
All done. Remember to announce the release on *BOTH*
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
EOT
} else {
print $break, "All done.\n";
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;
}
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 get_subprotocol_version
{
my($subver) = @_;
if ($pre && $proto_changed eq 'changed') {
return $subver == 0 ? 1 : $subver;
}
0;
}
sub usage
{
die <<EOT;
Usage: release-rsync [OPTIONS]
-b, --branch=BRANCH The branch to release (default: master)
-h, --help Display this help message
EOT
}

83
packaging/var-checker Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/perl
# This script checks the *.c files for extraneous "extern" variables,
# for vars that are defined but not used, and for inconsistent array
# sizes. Run it from inside the main rsync directory.
use strict;
use warnings;
my %add_syscall_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c tls.c trimslash.c );
my %add_compat_c = map { $_ => 1 } qw( t_stub.c tls.c trimslash.c wildtest.c );
my %add_util_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c );
my %sizes;
open(IN, '<', 'syscall.c') or die $!;
undef $/; my $syscall_c = <IN>; $/ = "\n";
close IN;
$syscall_c =~ s/^extern\s.*//mg;
open(IN, '<', 'lib/compat.c') or die $!;
undef $/; my $compat_c = <IN>; $/ = "\n";
close IN;
$compat_c =~ s/^extern\s.*//mg;
open(IN, '<', 'util.c') or die $!;
undef $/; my $util_c = <IN>; $/ = "\n";
close IN;
$util_c =~ s/^extern\s.*//mg;
my @files = glob('*.c');
foreach my $fn (@files) {
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
my @vars = /^(?!(?:extern|enum)\s)([a-zA-Z]\S*\s+.*);/mg;
my @externs = /^extern\s+(.*);/mg;
$_ .= $syscall_c if $add_syscall_c{$fn};
$_ .= $compat_c if $add_compat_c{$fn};
$_ .= $util_c if $add_util_c{$fn};
s/INFO_GTE/info_levels/g;
s/DEBUG_GTE/debug_levels/g;
check_vars($fn, 'var', @vars);
check_vars($fn, 'extern', @externs);
}
exit;
# The file's contents are in $_.
sub check_vars
{
my $fn = shift;
my $type = shift;
foreach my $line (@_) {
$line =~ s/\s*\{.*\}//;
$line =~ s/\s*\(.*\)//;
foreach my $item (split(/\s*,\s*/, $line)) {
$item =~ s/\s*=.*//;
my $sz = $item =~ s/(\[.*?\])// ? $1 : '';
my($var) = $item =~ /([^*\s]+)$/;
if (!defined $var) {
print "Bogus match? ($item)\n";
next;
}
if ($sz) {
if (defined $sizes{$var}) {
if ($sizes{$var} ne $sz) {
print $fn, ' has inconsistent size for "', $var,
"\": $sizes{$var} vs $sz\n";
}
} else {
$sizes{$var} = $sz;
}
}
my @matches = /(?<!\sstruct )\b(\Q$var\E)(?!\w)/g;
push(@matches, /(\QSIGACTION(\E)/g) if $var eq 'sigact';
print $fn, " has extraneous $type: \"", $var, "\"\n" if @matches == 1;
}
}
}

View File

@@ -211,7 +211,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
bufr = realloc_array( bufr, char, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func);
rprintf(FLOG, "%s Memory re-allocation failure.", func);
return( False );
}
}
@@ -223,7 +223,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
bufr[end] = '\0';
if( 0 == end ) /* Don't allow an empty name. */
{
rprintf(FERROR, "%s Empty section name in configuration file.\n", func );
rprintf(FLOG, "%s Empty section name in configuration file.\n", func );
return( False );
}
if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */
@@ -236,7 +236,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
if( i < 0 )
{
bufr[end] = '\0';
rprintf(FERROR, "%s Badly formed line in configuration file: %s\n",
rprintf(FLOG, "%s Badly formed line in configuration file: %s\n",
func, bufr );
return( False );
}
@@ -261,7 +261,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
}
/* We arrive here if we've met the EOF before the closing bracket. */
rprintf(FERROR, "%s Unexpected EOF in the configuration file: %s\n", func, bufr );
rprintf(FLOG, "%s Unexpected EOF in the configuration file: %s\n", func, bufr );
return( False );
} /* Section */
@@ -305,7 +305,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
bufr = realloc_array( bufr, char, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
return( False );
}
}
@@ -315,7 +315,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
case '=': /* Equal sign marks end of param name. */
if( 0 == end ) /* Don't allow an empty name. */
{
rprintf(FERROR, "%s Invalid parameter name in config. file.\n", func );
rprintf(FLOG, "%s Invalid parameter name in config. file.\n", func );
return( False );
}
bufr[end++] = '\0'; /* Mark end of string & advance. */
@@ -329,7 +329,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
if( i < 0 )
{
bufr[end] = '\0';
rprintf(FERROR, "%s Ignoring badly formed line in configuration file: %s\n",
rprintf(FLOG, "%s Ignoring badly formed line in configuration file: %s\n",
func, bufr );
return( True );
}
@@ -340,7 +340,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
case '\0': /* Shouldn't have EOF within param name. */
case EOF:
bufr[i] = '\0';
rprintf(FERROR, "%s Unexpected end-of-file at: %s\n", func, bufr );
rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr );
return( True );
default:
@@ -370,7 +370,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
bufr = realloc_array( bufr, char, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
return( False );
}
}
@@ -485,14 +485,14 @@ static FILE *OpenConfFile( char *FileName )
if( NULL == FileName || 0 == *FileName )
{
rprintf(FERROR,"%s No configuration filename specified.\n", func);
rprintf(FLOG, "%s No configuration filename specified.\n", func);
return( NULL );
}
OpenedFile = fopen( FileName, "r" );
if( NULL == OpenedFile )
{
rsyserr(FERROR, errno, "unable to open configuration file \"%s\"",
rsyserr(FLOG, errno, "unable to open configuration file \"%s\"",
FileName);
}
@@ -534,7 +534,7 @@ BOOL pm_process( char *FileName,
bufr = new_array( char, bSize );
if( NULL == bufr )
{
rprintf(FERROR,"%s memory allocation failure.\n", func);
rprintf(FLOG, "%s memory allocation failure.\n", func);
fclose(InFile);
return( False );
}
@@ -548,7 +548,7 @@ BOOL pm_process( char *FileName,
if( !result ) /* Generic failure. */
{
rprintf(FERROR,"%s Failed. Error returned from params.c:parse().\n", func);
rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func);
return( False );
}

14
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
@@ -133,6 +133,12 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
filesfrom_fd = -1;
chmod_modes = NULL; /* Let the sending side handle this. */
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
@@ -150,12 +156,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
child_main(argc, argv);
}
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rsyserr(FERROR, errno, "Failed to close");

View File

@@ -1,7 +0,0 @@
ID
Makefile
config.cache
config.h
config.log
config.status
dummy

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)
@@ -861,15 +865,16 @@ int poptGetNextOpt(poptContext con)
/*@=branchstate@*/
if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
return POPT_ERROR_BADOPERATION;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE
|| (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
if (longArg || (con->os->nextCharArg && con->os->nextCharArg[0] == '='))
return POPT_ERROR_UNWANTEDARG;
if (opt->arg) {
if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
long val = (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL ? opt->val : 1;
if (poptSaveInt((int *)opt->arg, opt->argInfo, val))
return POPT_ERROR_BADOPERATION;
}
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
} else {
con->os->nextArg = _free(con->os->nextArg);
/*@-usedef@*/ /* FIX: W2DO? */
if (longArg) {
@@ -877,7 +882,7 @@ int poptGetNextOpt(poptContext con)
longArg = expandNextArg(con, longArg);
con->os->nextArg = longArg;
} else if (con->os->nextCharArg) {
longArg = expandNextArg(con, con->os->nextCharArg);
longArg = expandNextArg(con, con->os->nextCharArg + (con->os->nextCharArg[0] == '='));
con->os->nextArg = longArg;
con->os->nextCharArg = NULL;
} else {
@@ -1198,6 +1203,8 @@ const char * poptStrerror(const int error)
switch (error) {
case POPT_ERROR_NOARG:
return POPT_("missing argument");
case POPT_ERROR_UNWANTEDARG:
return POPT_("option does not take an argument");
case POPT_ERROR_BADOPT:
return POPT_("unknown option");
case POPT_ERROR_BADOPERATION:

View File

@@ -82,6 +82,7 @@
/*@{*/
#define POPT_ERROR_NOARG -10 /*!< missing argument */
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
#define POPT_ERROR_UNWANTEDARG -12 /*!< option does not take an argument */
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */

View File

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

@@ -1,12 +1,51 @@
#!/bin/sh
# Use autoconf, autoheader, yodl, etc. to ready the generated files in the
# release. This is typically used after applying a diff from the "patches"
# directory in a CVS-checked-out version.
# Either use autoconf and autoheader to create configure.sh and config.h.in
# or (optionally) fetch the latest development versions of generated files.
#
# NOTE: if you use a diff from the "patches" directory of a *release tar*
# (as opposed to from CVS), this is not needed (but doesn't hurt anything).
# Specify one action or more than one to provide a fall-back:
#
# build build the config files [the default w/no arg]
# fetch fetch the latest dev config files
# fetchgen fetch all the latest dev generated files
# fetchSRC fetch the latest dev source files [NON-GENERATED FILES]
#
# The script stops after the first successful action.
dir=`dirname $0`
if test x"$dir" != x -a x"$dir" != x.; then
cd "$dir"
fi
make -f prepare-source.mak
if test $# = 0; then
set -- build
fi
for action in "${@}"; do
case "$action" in
build|make)
make -f prepare-source.mak
;;
fetch)
if perl --version >/dev/null 2>/dev/null; then
files='c*'
else
files='[cp]*'
fi
rsync -pvz rsync://rsync.samba.org/rsyncftp/generated-files/"$files" .
;;
fetchgen)
rsync -pvz rsync://rsync.samba.org/rsyncftp/generated-files/'*' .
;;
fetchSRC)
rsync -pvrz --exclude=/.git/ rsync://rsync.samba.org/ftp/pub/unpacked/rsync/ .
;;
*)
echo "Unknown action: $action"
exit 1
esac
if test $? = 0; then
exit
fi
done
exit 1

View File

@@ -1,25 +1,7 @@
gen: configure config.h.in proto.h man
conf: configure.sh config.h.in
configure: configure.in aclocal.m4
autoconf
configure.sh: configure.ac aclocal.m4
autoconf -o configure.sh
config.h.in: configure.in aclocal.m4
config.h.in: configure.ac aclocal.m4
autoheader && touch config.h.in
proto.h: *.c lib/compat.c
cat *.c lib/compat.c | awk -f mkproto.awk >proto.h.new
if diff proto.h proto.h.new >/dev/null; then \
rm proto.h.new; \
else \
mv proto.h.new proto.h; \
fi
man: rsync.1 rsyncd.conf.5
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
-./tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
-./tweak_manpage rsyncd.conf.5

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
@@ -22,8 +22,10 @@
#include "rsync.h"
extern struct stats stats;
extern int am_server;
extern int need_unsorted_flist;
extern struct stats stats;
extern struct file_list *cur_flist;
#define PROGRESS_HISTORY_SECS 5
@@ -38,9 +40,12 @@ 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;
static int current_file_index;
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
{
@@ -104,12 +109,24 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
if (is_last) {
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
stats.num_transferred_files,
stats.num_files - stats.current_file_index - 1,
stats.num_files - current_file_index - 1,
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)
{
if (need_unsorted_flist)
current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start;
else
current_file_index = ndx;
current_file_index -= cur_flist->flist_num;
}
void end_progress(OFF_T size)

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
@@ -24,6 +24,7 @@
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_root;
extern int am_server;
extern int do_progress;
extern int inc_recurse;
@@ -53,40 +54,39 @@ extern mode_t orig_umask;
extern struct stats stats;
extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
extern char *basis_dir[MAX_BASIS_DIRS+1];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct 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;
static int updating_basis_or_equiv;
/*
* get_tmpname() - create a tmp filename for a given filename
*
* If a tmpdir is defined, use that as the directory to
* put it in. Otherwise, the tmp filename is in the same
* directory as the given name. Note that there may be no
* directory at all in the given name!
*
* The tmp filename is basically the given filename with a
* dot prepended, and .XXXXXX appended (for mkstemp() to
* put its unique gunk in). Take care to not exceed
* either the MAXPATHLEN or NAME_MAX, esp. the last, as
* the basename basically becomes 8 chars longer. In that
* case, the original name is shortened sufficiently to
* make it all fit.
*
* Of course, there's no real reason for the tmp name to
* look like the original, except to satisfy us humans.
* As long as it's unique, rsync will work.
*/
#define TMPNAME_SUFFIX ".XXXXXX"
#define TMPNAME_SUFFIX_LEN ((int)sizeof TMPNAME_SUFFIX - 1)
int get_tmpname(char *fnametmp, char *fname)
/* get_tmpname() - create a tmp filename for a given filename
*
* If a tmpdir is defined, use that as the directory to put it in. Otherwise,
* the tmp filename is in the same directory as the given name. Note that
* there may be no directory at all in the given name!
*
* The tmp filename is basically the given filename with a dot prepended, and
* .XXXXXX appended (for mkstemp() to put its unique gunk in). We take care
* to not exceed either the MAXPATHLEN or NAME_MAX, especially the last, as
* the basename basically becomes 8 characters longer. In such a case, the
* original name is shortened sufficiently to make it all fit.
*
* Of course, the only reason the file is based on the original name is to
* make it easier to figure out what purpose a temp file is serving when a
* transfer is in progress. */
int get_tmpname(char *fnametmp, const char *fname)
{
int maxname, added, length = 0;
char *f;
const char *f;
char *suf;
if (tmpdir) {
/* Note: this can't overflow, so the return value is safe */
@@ -106,11 +106,12 @@ int get_tmpname(char *fnametmp, char *fname)
fnametmp[length++] = '.';
/* The maxname value is bufsize, and includes space for the '\0'.
* (Note that NAME_MAX get -8 for the leading '.' above.) */
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
* NAME_MAX needs an extra -1 for the name's leading dot. */
maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,
NAME_MAX - 1 - TMPNAME_SUFFIX_LEN);
if (maxname < 1) {
rprintf(FERROR, "temporary filename too long: %s\n", fname);
rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
fnametmp[0] = '\0';
return 0;
}
@@ -118,11 +119,68 @@ int get_tmpname(char *fnametmp, char *fname)
added = strlcpy(fnametmp + length, f, maxname);
if (added >= maxname)
added = maxname - 1;
memcpy(fnametmp + length + added, ".XXXXXX", 8);
suf = fnametmp + length + added;
/* Trim any dangling high-bit chars if the first-trimmed char (if any) is
* also a high-bit char, just in case we cut into a multi-byte sequence.
* We are guaranteed to stop because of the leading '.' we added. */
if ((int)f[added] & 0x80) {
while ((int)suf[-1] & 0x80)
suf--;
}
memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);
return 1;
}
/* Opens a temporary file for writing.
* Success: Writes name into fnametmp, returns fd.
* Failure: Clobbers fnametmp, returns -1.
* Calling cleanup_set() is the caller's job. */
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
{
int fd;
mode_t added_perms;
if (!get_tmpname(fnametmp, fname))
return -1;
if (am_root < 0) {
/* For --fake-super, the file must be useable by the copying
* user, just like it would be for root. */
added_perms = S_IRUSR|S_IWUSR;
} else {
/* For a normal copy, we need to be able to tweak things like xattrs. */
added_perms = S_IWUSR;
}
/* We initially set the perms without the setuid/setgid bits or group
* access to ensure that there is no race condition. They will be
* correctly updated after the right owner and group info is set.
* (Thanks to snabb@epipe.fi for pointing this out.) */
fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
#if 0
/* In most cases parent directories will already exist because their
* information should have been previously transferred, but that may
* not be the case with -R */
if (fd == -1 && relative_paths && errno == ENOENT
&& create_directory_path(fnametmp) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
}
#endif
if (fd == -1) {
rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
full_fname(fnametmp));
return -1;
}
return fd;
}
static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
const char *fname, int fd, OFF_T total_size)
@@ -174,7 +232,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
}
offset = sum.flength;
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
full_fname(fname), (double)j, (double)offset);
exit_cleanup(RERR_FILEIO);
}
@@ -211,8 +269,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
if (verbose > 3) {
rprintf(FINFO,
"chunk[%d] of size %ld at %.0f offset=%.0f\n",
i, (long)len, (double)offset2, (double)offset);
"chunk[%d] of size %ld at %.0f offset=%.0f%s\n",
i, (long)len, (double)offset2, (double)offset,
updating_basis_or_equiv && offset == offset2 ? " (seek)" : "");
}
if (mapbuf) {
@@ -222,14 +281,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_update(map, len);
}
if (updating_basis) {
if (updating_basis_or_equiv) {
if (offset == offset2 && fd != -1) {
OFF_T pos;
if (flush_write_file(fd) < 0)
goto report_write_error;
offset += len;
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"lseek of %s returned %.0f, not %.0f",
full_fname(fname),
(double)pos, (double)offset);
@@ -247,16 +306,18 @@ 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 && do_ftruncate(fd, offset) < 0) {
rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
full_fname(fname));
}
#endif
if (do_progress)
end_progress(total_size);
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {
report_write_error:
rsyserr(FERROR, errno, "write failed on %s",
rsyserr(FERROR_XFER, errno, "write failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
@@ -298,7 +359,7 @@ static void handle_delayed_updates(char *local_name)
/* We don't use robust_rename() here because the
* partial-dir must be on the same drive. */
if (do_rename(partialptr, fname) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"rename failed for %s (from %s)",
full_fname(fname), partialptr);
} else {
@@ -311,24 +372,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) {
rprintf(FINFO,
"(No batched update for%s \"%s\")\n",
redoing ? " resend of" : "",
f_name(cur_flist->files[next_gen_ndx], 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;
}
/**
@@ -337,7 +442,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;
@@ -364,8 +468,6 @@ int recv_files(int f_in, char *local_name)
if (delay_updates)
delayed_bits = bitbag_create(cur_flist->used + 1);
updating_basis = inplace;
while (1) {
cleanup_disable();
@@ -374,17 +476,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)
@@ -405,14 +503,15 @@ int recv_files(int f_in, char *local_name)
rprintf(FINFO, "recv_files(%s)\n", fname);
#ifdef SUPPORT_XATTRS
if (iflags & ITEM_REPORT_XATTR && !dry_run)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
recv_xattr_request(file, f_in);
#endif
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
&& !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))
set_file_attrs(fname, file, NULL, fname, 0);
#endif
continue;
@@ -446,17 +545,34 @@ int recv_files(int f_in, char *local_name)
}
}
stats.current_file_index = ndx;
if (!am_server && do_progress)
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.total_transferred_size += F_LENGTH(file);
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)
@@ -464,26 +580,12 @@ int recv_files(int f_in, char *local_name)
continue;
}
if (write_batch < 0) {
log_item(FINFO, file, &stats, iflags, NULL);
log_item(FCLIENT, file, &stats, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, F_LENGTH(file));
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) {
@@ -498,7 +600,6 @@ int recv_files(int f_in, char *local_name)
fnamecmp = get_backup_name(fname);
break;
case FNAMECMP_FUZZY:
updating_basis = 0;
if (file->dirname) {
pathjoin(fnamecmpbuf, MAXPATHLEN,
file->dirname, xname);
@@ -507,7 +608,6 @@ int recv_files(int f_in, char *local_name)
fnamecmp = xname;
break;
default:
updating_basis = 0;
if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
@@ -519,15 +619,19 @@ 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;
}
} else {
/* Reminder: --inplace && --partial-dir are never
* enabled at the same time. */
if (inplace && make_backups > 0) {
if (!(fnamecmp = get_backup_name(fname)))
fnamecmp = fname;
else
fnamecmp_type = FNAMECMP_BACKUP;
} else if (partial_dir && partialptr)
fnamecmp = partialptr;
else
@@ -554,11 +658,14 @@ int recv_files(int f_in, char *local_name)
}
}
updating_basis_or_equiv = inplace
&& (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);
if (fd1 == -1) {
st.st_mode = 0;
st.st_size = 0;
} else if (do_fstat(fd1,&st) != 0) {
rsyserr(FERROR, errno, "fstat %s failed",
rsyserr(FERROR_XFER, errno, "fstat %s failed",
full_fname(fnamecmp));
discard_receive_data(f_in, F_LENGTH(file));
close(fd1);
@@ -573,7 +680,7 @@ int recv_files(int f_in, char *local_name)
* and the underlying robust_unlink could cope
* with directories
*/
rprintf(FERROR,"recv_files: %s is a directory\n",
rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
full_fname(fnamecmp));
discard_receive_data(f_in, F_LENGTH(file));
close(fd1);
@@ -607,54 +714,22 @@ int recv_files(int f_in, char *local_name)
if (inplace) {
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
if (fd2 == -1) {
rsyserr(FERROR, errno, "open %s failed",
rsyserr(FERROR_XFER, errno, "open %s failed",
full_fname(fname));
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
} else {
if (!get_tmpname(fnametmp,fname)) {
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
fd2 = open_tmpfile(fnametmp, fname, file);
if (fd2 != -1)
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
}
/* we initially set the perms without the
* setuid/setgid bits to ensure that there is no race
* condition. They are then correctly updated after
* the lchown. Thanks to snabb@epipe.fi for pointing
* this out. We also set it initially without group
* access because of a similar race condition. */
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
/* in most cases parent directories will already exist
* because their information should have been previously
* transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT
&& create_directory_path(fnametmp) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rsyserr(FERROR, errno, "mkstemp %s failed",
full_fname(fnametmp));
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
if (fd2 == -1) {
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
/* log the transfer */
@@ -678,41 +753,50 @@ int recv_files(int f_in, char *local_name)
}
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
char *temp_copy_name;
if (partialptr == fname)
partialptr = temp_copy_name = NULL;
else if (*partial_dir == '/')
temp_copy_name = NULL;
else
temp_copy_name = partialptr;
finish_transfer(fname, fnametmp, fnamecmp,
temp_copy_name, file, recv_ok, 1);
if (fnamecmp == partialptr) {
partialptr = NULL;
if (!finish_transfer(fname, fnametmp, fnamecmp,
partialptr, file, recv_ok, 1))
recv_ok = -1;
else if (fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir);
if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
} 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 {
partialptr = NULL;
} 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
do_unlink(fnametmp);
}
cleanup_disable();
if (recv_ok > 0) {
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)))
send_msg_int(MSG_SUCCESS, ndx);
} else if (!recv_ok) {
enum logcode msgtype = redoing || read_batch ? FERROR : FINFO;
if (msgtype == FERROR || verbose) {
break;
case 0: {
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
if (msgtype == FERROR_XFER || verbose) {
char *errstr, *redostr, *keptstr;
if (!(keep_partial && partialptr) && !inplace)
keptstr = "discarded";
@@ -720,22 +804,32 @@ int recv_files(int f_in, char *local_name)
keptstr = "put into partial-dir";
else
keptstr = "retained";
if (msgtype == FERROR) {
if (msgtype == FERROR_XFER) {
errstr = "ERROR";
redostr = "";
} else {
errstr = "WARNING";
redostr = " (will try again)";
redostr = read_batch ? " (may try again)"
: " (will try again)";
}
rprintf(msgtype,
"%s: %s failed verification -- update %s%s.\n",
errstr, fname, keptstr, redostr);
errstr, local_name ? f_name(file, NULL) : fname,
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)
send_msg_int(MSG_NO_SEND, ndx);
break;
}
case -1:
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
break;
}
}
if (make_backups < 0)

38
rounding.c Normal file
View File

@@ -0,0 +1,38 @@
/*
* A pre-compilation helper program to aid in the creation of rounding.h.
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, visit the http://fsf.org website.
*/
#include "rsync.h"
#define ARRAY_LEN (EXTRA_ROUNDING+1)
#define SIZEOF(x) ((long int)sizeof (x))
struct test {
union file_extras extras[ARRAY_LEN];
struct file_struct file;
};
#define ACTUAL_SIZE SIZEOF(struct test)
#define EXPECTED_SIZE (SIZEOF(union file_extras) * ARRAY_LEN + SIZEOF(struct file_struct))
int main(UNUSED(int argc), UNUSED(char *argv[]))
{
static int test_array[1 - 2 * (ACTUAL_SIZE != EXPECTED_SIZE)];
test_array[0] = 0;
return 0;
}

239
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,12 +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 uid_ndx;
extern int gid_ndx;
extern int inc_recurse;
extern int inplace;
extern int flist_eof;
@@ -80,7 +79,6 @@ void setup_iconv(void)
# endif
if (!am_server && !allow_8bit_chars) {
/* It's OK if this fails... */
ic_chck = iconv_open(defset, defset);
@@ -205,13 +203,52 @@ 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)
{
int len, iflags = 0;
struct file_list *flist;
uchar fnamecmp_type = FNAMECMP_FNAME;
int ndx;
int ndx, save_verbose = verbose;
read_loop:
while (1) {
@@ -221,8 +258,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);
@@ -232,44 +278,38 @@ 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);
}
/* Send everything read from f_in to msg_fd_out. */
send_msg_int(MSG_FLIST, ndx);
start_flist_forward(f_in);
if (verbose > 3) {
rprintf(FINFO, "[%s] receiving flist for dir %d\n",
who_am_i(), ndx);
}
verbose = 0;
send_msg_int(MSG_FLIST, ndx);
start_flist_forward(f_in);
flist = recv_file_list(f_in);
flist->parent_ndx = ndx;
stop_flist_forward();
verbose = save_verbose;
}
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))) {
invalid_ndx:
rprintf(FERROR,
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
ndx, first_flist->ndx_start - 1, first_flist->prev->ndx_end,
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);
@@ -347,7 +387,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
if (dry_run)
return 1;
if (link_stat(fname, &sx2.st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return 0;
}
@@ -368,36 +408,43 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
new_mode |= S_ISGID;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
get_acl(fname, sxp);
#endif
#ifdef SUPPORT_XATTRS
if (am_root < 0)
set_stat_xattr(fname, file, new_mode);
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
if (am_root < 0)
set_stat_xattr(fname, file);
#endif
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
if (!preserve_times
|| (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
|| (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
if (ret < 0) {
rsyserr(FERROR, errno, "failed to set times on %s",
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
full_fname(fname));
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
else
file->flags |= FLAG_TIME_FAILED;
}
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
#ifndef CAN_CHOWN_SYMLINK
if (S_ISLNK(sxp->st.st_mode)) {
;
} else
@@ -415,31 +462,32 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
}
}
if (am_root < 0) {
;
} else if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
* unless have the privilege */
rsyserr(FERROR, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
} else
/* a lchown had been done - we have to re-stat if the
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
if (am_root >= 0) {
uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
if (do_lchown(fname, uid, gid) != 0) {
/* We shouldn't have attempted to change uid
* or gid unless have the privilege. */
rsyserr(FERROR_XFER, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
}
if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
/* A lchown had been done, so we need to re-stat if
* the destination had the setuid or setgid bits set
* (due to the side effect of the chown call). */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
}
}
updated = 1;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
/* It's OK to call set_acl() now, even for a dir, as the generator
* will enable owner-writability using chmod, if necessary.
@@ -447,15 +495,17 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
* If set_acl() changes permission bits in the process of setting
* an access ACL, it changes sxp->st.st_mode so we know whether we
* need to chmod(). */
if (preserve_acls && !S_ISLNK(new_mode) && set_acl(fname, file, sxp) == 0)
updated = 1;
if (preserve_acls && !S_ISLNK(new_mode)) {
if (set_acl(fname, file, sxp, new_mode) > 0)
updated = 1;
}
#endif
#ifdef HAVE_CHMOD
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"failed to set permissions on %s",
full_fname(fname));
goto cleanup;
@@ -500,15 +550,17 @@ RETSIGTYPE sig_int(UNUSED(int val))
}
/* Finish off a file transfer: renaming the file and setting the file's
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
* NULL and the robust_rename() call is forced to copy the temp file, we
* stage the file into the partial-dir and then rename it into place. */
void finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
* attributes (e.g. permissions, ownership, etc.). If the robust_rename()
* call is forced to copy the temp file and partialptr is both non-NULL and
* not an absolute path, we stage the file into the partial-dir and then
* rename it into place. This returns 1 on succcess or 0 on failure. */
int finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
{
int ret;
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
if (inplace) {
if (verbose > 2)
@@ -517,8 +569,12 @@ void finish_transfer(const char *fname, const char *fnametmp,
goto do_set_file_attrs;
}
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return;
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,
@@ -527,58 +583,83 @@ void finish_transfer(const char *fname, const char *fnametmp,
/* move tmp file over real file */
if (verbose > 2)
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
ret = robust_rename(fnametmp, fname, partialptr,
ret = robust_rename(fnametmp, fname, temp_copy_name,
file->mode & INITACCESSPERMS);
if (ret < 0) {
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname);
do_unlink(fnametmp);
return;
if (!partialptr || (ret == -2 && temp_copy_name)
|| robust_rename(fnametmp, partialptr, NULL,
file->mode & INITACCESSPERMS) < 0)
do_unlink(fnametmp);
return 0;
}
if (ret == 0) {
/* The file was moved into place (not copied), so it's done. */
return;
return 1;
}
/* The file was copied, so tweak the perms of the copied file. If it
* was copied to partialptr, move it into its final destination. */
fnametmp = partialptr ? partialptr : fname;
fnametmp = temp_copy_name ? temp_copy_name : fname;
do_set_file_attrs:
set_file_attrs(fnametmp, file, NULL, fnamecmp,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
if (partialptr) {
if (temp_copy_name) {
if (do_rename(fnametmp, fname) < 0) {
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
full_fname(fnametmp), fname);
} else
handle_partial_dir(partialptr, PDIR_DELETE);
return 0;
}
handle_partial_dir(temp_copy_name, PDIR_DELETE);
}
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_end) {
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 */
}

121
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,6 +32,9 @@
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
#define URL_PREFIX "rsync://"
#define SYMLINK_PREFIX "/rsyncd-munged/" /* This MUST have a trailing slash! */
#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
#define BACKUP_SUFFIX "~"
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
@@ -57,14 +60,17 @@
#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. */
#define FLAG_TOP_DIR (1<<0) /* sender/receiver/generator */
#define FLAG_OWNED_BY_US (1<<0) /* generator: set by make_file() for aux flists only */
#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
#define FLAG_DIR_CREATED (1<<1) /* generator */
#define FLAG_CONTENT_DIR (1<<2) /* sender/receiver/generator */
#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) */
@@ -74,11 +80,16 @@
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator (checked on all types) */
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
#define FLAG_TIME_FAILED (1<<11)/* generator */
/* These flags are passed to functions but not stored. */
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
#define FLAG_DIVERT_DIRS (1<<16) /* sender, but must be unique */
/* These flags are for get_dirlist(). */
#define GDL_IGNORE_FILTER_RULES (1<<0)
/* Some helper macros for matching bits. */
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
#define BITS_EQUAL(b1,b2,mask) (((unsigned)(b1) & (unsigned)(mask)) \
@@ -89,8 +100,8 @@
/* 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 12
* It must ALWAYS be 0 when the protocol goes final (and NEVER before)! */
#define SUBPROTOCOL_VERSION 0
/* We refuse to interoperate with versions that are not in this range.
* Note that we assume we'll work with later versions: the onus is on
@@ -124,6 +135,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)
@@ -140,8 +154,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)
@@ -162,8 +177,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)
@@ -183,18 +199,37 @@
#define SIGNIFICANT_ITEM_FLAGS (~(\
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
#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)
/* Log-message categories. Only FERROR and FINFO get sent over the socket,
* but FLOG and FSOCKERR can be sent over the receiver -> generator pipe.
* FLOG only goes to the log file, not the client; FCLIENT is the opposite. */
enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
#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 {
FNONE=0, /* never sent */
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) */
};
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, MSG_SOCKERR=FSOCKERR, /* sibling logging */
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 */
MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
@@ -305,6 +340,18 @@ enum msgcode {
#include <utime.h>
#endif
#if defined HAVE_LUTIMES || defined HAVE_UTIMENSAT
#define CAN_SET_SYMLINK_TIMES 1
#endif
#if defined HAVE_LCHOWN || defined CHOWN_MODIFIES_SYMLINK
#define CAN_CHOWN_SYMLINK 1
#endif
#if defined HAVE_LCHMOD || defined HAVE_SETATTRLIST
#define CAN_CHMOD_SYMLINK 1
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -316,10 +363,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>
@@ -327,7 +370,9 @@ enum msgcode {
#include <stdarg.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <syslog.h>
#include <sys/file.h>
@@ -369,7 +414,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
@@ -392,16 +437,18 @@ 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;
#undef SIZEOF_OFF_T
#define SIZEOF_OFF_T SIZEOF_LONG
#endif
#ifndef HAVE_SIZE_T
typedef unsigned int size_t;
@@ -475,10 +522,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
@@ -524,6 +573,7 @@ struct hashtable {
void *nodes;
int32 size, entries;
uint32 node_size;
int key64;
};
struct ht_int32_node {
@@ -641,7 +691,7 @@ extern int xattrs_ndx;
#define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
#define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
#define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
#define F_NDX(f) REQ_EXTRA(f, ic_ndx)->num
#define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
/* These items are per-entry optional: */
#define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num /* non-dirs */
@@ -656,7 +706,7 @@ extern int xattrs_ndx;
/* This optional item might follow an F_HL_*() item.
* (Note: a device doesn't need to check LEN64_BUMP(f).) */
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + 2 - 1)->unum)
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + DEV_EXTRA_CNT - 1)->unum)
/* The sum is only present on regular files. */
#define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
@@ -707,7 +757,7 @@ struct file_list {
int used, malloced;
int low, high; /* 0-relative index values excluding empties */
int ndx_start; /* the start offset for inc_recurse mode */
int ndx_end; /* the end offset for inc_recurse mode */
int flist_num; /* 1-relative file_list number or 0 */
int parent_ndx; /* dir_flist index of parent directory */
int in_progress, to_redo;
};
@@ -798,11 +848,19 @@ struct stats {
int64 flist_size;
int num_files;
int num_transferred_files;
int current_file_index;
};
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 {
@@ -837,7 +895,7 @@ typedef struct {
#define RL_CONVERT (1<<2)
typedef struct {
char is_dot_dir;
char name_type;
char fname[1]; /* has variable size */
} relnamecache;
@@ -1028,6 +1086,10 @@ extern int errno;
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
#define PRESERVE_FILE_TIMES (1<<0)
#define PRESERVE_DIR_TIMES (1<<1)
#define PRESERVE_LINK_TIMES (1<<2)
/* Initial mask on permissions given to temporary files. Mask off setuid
bits and group access because of potential race-condition security
holes, and mask other access because mode 707 is bizarre */
@@ -1088,6 +1150,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

597
rsync.yo
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
-*- indented-text -*-
Notes towards a new version of rsync
Notes towards a new version of rsync
Martin Pool <mbp@samba.org>, September 2001.
@@ -13,7 +13,7 @@ Good things about the current implementation:
- Fairly reliable.
- The choice of runnning over a plain TCP socket or tunneling over
- The choice of running over a plain TCP socket or tunneling over
ssh.
- rsync operations are idempotent: you can always run the same
@@ -51,7 +51,7 @@ Bad things about the current implementation:
hard to modify/extend
- Both the program and the protocol assume a single non-interactive
one-way transfer
one-way transfer
- A list of all files are held in memory for the entire transfer,
which cripples scalability to large file trees
@@ -88,7 +88,7 @@ Protocol philosophy:
Questionable features:
These are neat, but not necessarily clean or worth preserving.
These are neat, but not necessarily clean or worth preserving.
- The remote rsync can be wrapped by some other program, such as in
tridge's rsync-mail scripts. The general feature of sending and
@@ -100,7 +100,7 @@ Desirable features:
These don't really require architectural changes; they're just
something to keep in mind.
- Synchronize ACLs and extended attributes
- Anonymous servers should be efficient
@@ -122,7 +122,7 @@ Desirable features:
Alternatively, as long as transfers are idempotent, we can just
restart the whole thing. [NFSv4]
- Scripting support.
- Scripting support.
- Propagate atimes and do not modify them. This is very ugly on
Unix. It might be better to try to add O_NOATIME to kernels, and
@@ -224,7 +224,7 @@ Scripting hooks:
- What basis file to use
- Logging
- Whether to allow transfers (for public servers)
- Authentication
@@ -275,7 +275,7 @@ Pie-in-the-sky features:
These might have a severe impact on the protocol, and are not
clearly in our core requirements. It looks like in many of them
having scripting hooks will allow us
having scripting hooks will allow us
- Transport over UDP multicast. The hard part is handling multiple
destinations which have different basis files. We can look at
@@ -344,7 +344,7 @@ In favour of using a new protocol:
- If we start from scratch, it can be documented as we go, and we
can avoid design decisions that make the protocol complex or
implementation-bound.
implementation-bound.
Error handling:
@@ -365,7 +365,7 @@ Concurrency:
- We can do nonblocking network IO, but not so for disk.
- It makes sense to on the destination be generating signatures and
applying patches at the same time.
applying patches at the same time.
- Can structure this with nonblocking, threads, separate processes,
etc.
@@ -381,7 +381,7 @@ Uses:
http://www.ietf.org/proceedings/00jul/00july-133.htm#P24510_1276764
- Sync with PDA
- Network backup systems
- CVS filemover
@@ -419,7 +419,7 @@ Filesystem migration:
Atomic updates:
The NFSv4 working group wants atomic migration. Most of the
responsibility for this lies on the NFS server or OS.
responsibility for this lies on the NFS server or OS.
If migrating a whole tree, then we could do a nearly-atomic rename
at the end. This ties in to having separate basis and destination
@@ -427,11 +427,11 @@ Atomic updates:
There's no way in Unix to replace a whole set of files atomically.
However, if we get them all onto the destination machine and then do
the updates quickly it would greatly reduce the window.
the updates quickly it would greatly reduce the window.
Scalability:
We should aim to work well on machines in use in a year or two.
That probably means transfers of many millions of files in one
batch, and gigabytes or terabytes of data.
@@ -466,4 +466,4 @@ Related work:
- http://freshmeat.net/search/?site=Freshmeat&q=mirror&section=projects
- BitTorrent -- p2p mirroring
http://bitconjurer.org/BitTorrent/
http://bitconjurer.org/BitTorrent/

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(26 Oct 2007)()()
manpage(rsyncd.conf)(5)(23 Sep 2011)()()
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,77 +96,164 @@ 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
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).
It is fine if the path includes internal spaces -- they will be retained
verbatim (which means that you shouldn't try to escape them). If your final
directory has a trailing space (and this is somehow not something you wish to
fix), append a trailing slash to the path to avoid losing the trailing
whitespace.
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges,
of not being able to follow symbolic links that are either absolute or outside
of the new root path, and of complicating the preservation of usernames and groups
(see below). When "use chroot" is false, for security reasons,
symlinks may only be relative paths pointing to other files within the root
path, and leading slashes are removed from most absolute paths (options
such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
rooted in the module's "path" dir, just as if chroot was specified).
The default for "use chroot" is true.
of the new root path, and of complicating the preservation of users and groups
by name (see below).
In order to preserve usernames and groupnames, rsync needs to be able to
As an additional safety feature, you can specify a dot-dir in the module's
"path" to indicate the point where the chroot should occur. This allows rsync
to run in a chroot with a non-"/" path for the top of the transfer hierarchy.
Doing this guards against unintended library loading (since those absolute
paths will not be inside the transfer hierarchy unless you have used an unwise
pathname), and lets you setup libraries for the chroot that are outside of the
transfer. For example, specifying "/var/rsync/./module1" will chroot to the
"/var/rsync" directory and set the inside-chroot path to "/module1". If you
had omitted the dot-dir, the chroot would have used the whole path, and the
inside-chroot path would have been "/".
When "use chroot" is false or the inside-chroot path is not "/", rsync will:
(1) munge symlinks by
default for security reasons (see "munge symlinks" for a way to turn this
off, but only if you trust your users), (2) substitute leading slashes in
absolute paths with the module's path (so that options such as
bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
rooted in the module's "path" dir), and (3) trim ".." path elements from
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 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.
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
process in the chroot namespace will need to have access to the resources
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())).
This means the rsync
process in the chroot hierarchy will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
able to copy the IDs, just as if the bf(--numeric-ids) option had been
specified.
/etc/group, but perhaps additional dynamic libraries as well).
Note that you are free to setup user/group information in the chroot area
differently from your normal system. For example, you could abbreviate
the list of users and groups. Also, you can protect this information from
being downloaded/uploaded by adding an exclude rule to the rsyncd.conf file
(e.g. "bf(exclude = /etc/**)"). Note that having the exclusion affect uploads
is a relatively new feature in rsync, so make sure your daemon is
at least 2.6.3 to effect this. Also note that it is safest to exclude a
directory and all its contents combining the rule "/some/dir/" with the
rule "/some/dir/**" just to be sure that rsync will not allow deeper
access to some of the excluded files inside the directory (rsync tries to
do this automatically, but you might as well specify both to be extra
sure).
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 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).
dit(bf(max connections)) The "max connections" option allows you to
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 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.
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 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)) 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 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
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 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" 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 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 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 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,
the daemon will use the value of the "charset" parameter regardless of the
character set the client actually passed. This allows the daemon to
support charset conversion in a chroot module without extra files in the
chroot area, and also ensures that name-translation is done in a consistent
manner. If the "charset" parameter is not set, the bf(--iconv) option is
refused, just as if "iconv" had been specified via "refuse options".
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)) 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
@@ -175,11 +262,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,
@@ -189,95 +276,100 @@ 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
daemon side to behave as if the bf(--fake-user) command-line option had
daemon side to behave as if the bf(--fake-super) command-line option had
been specified. This allows the full attributes of a file to be stored
without having to have the daemon actually running as root.
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.
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(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(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(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 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(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(incoming chmod)) This option allows you to specify a set of
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 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
@@ -286,7 +378,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
@@ -296,7 +388,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
@@ -304,36 +396,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.
@@ -368,28 +460,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
@@ -397,14 +489,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
@@ -412,7 +504,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.)
@@ -423,7 +515,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
@@ -448,14 +540,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
@@ -468,9 +560,9 @@ quote(tt( refuse options = c delete))
The reason the above refuses all delete options is that the options imply
bf(--delete), and implied options are refused just like explicit options.
As an additional safety feature, the refusal of "delete" also refuses
bf(remove-sent-files) when the daemon is the sender; if you want the latter
bf(remove-source-files) when the daemon is the sender; if you want the latter
without the former, instead refuse "delete-*" -- that refuses all the
delete modes without affecting bf(--remove-sent-files).
delete modes without affecting bf(--remove-source-files).
When an option is refused, the daemon prints an error message and exits.
To prevent all compression when serving files,
@@ -478,21 +570,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 bf(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
@@ -562,21 +654,21 @@ A more sophisticated example would be:
verb(
uid = nobody
gid = nobody
use chroot = no
use chroot = yes
max connections = 4
syslog facility = local5
pid file = /var/run/rsyncd.pid
[ftp]
path = /var/ftp/pub
path = /var/ftp/./pub
comment = whole ftp area (approx 6.1 GB)
[sambaftp]
path = /var/ftp/pub/samba
path = /var/ftp/./pub/samba
comment = Samba ftp area (approx 300 MB)
[rsyncftp]
path = /var/ftp/pub/rsync
path = /var/ftp/./pub/rsync
comment = rsync ftp area (approx 6 MB)
[sambawww]
@@ -614,7 +706,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre4 of rsync.
This man page is current for version 3.0.9 of rsync.
manpagesection(CREDITS)

View File

@@ -129,7 +129,10 @@ RUNSHFLAGS='-e'
export RUNSHFLAGS
# for Solaris
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
if [ -d /usr/xpg4/bin ]; then
PATH="/usr/xpg4/bin/:$PATH"
export PATH
fi
if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
if set -x; then
@@ -154,12 +157,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 +241,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)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
recv_xattr_request(file, f_in);
#endif
@@ -265,7 +259,8 @@ void send_files(int f_in, int f_out)
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
stats.current_file_index = ndx;
if (!am_server && do_progress)
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.total_transferred_size += F_LENGTH(file);
@@ -280,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);
}
@@ -289,13 +284,13 @@ void send_files(int f_in, int f_out)
if (errno == ENOENT) {
enum logcode c = am_daemon
&& protocol_version < 28 ? FERROR
: FINFO;
: FWARNING;
io_error |= IOERR_VANISHED;
rprintf(c, "file has vanished: %s\n",
full_fname(fname));
} else {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"send_files failed to open %s",
full_fname(fname));
}
@@ -308,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);
@@ -349,7 +344,7 @@ void send_files(int f_in, int f_out)
j = unmap_file(mbuf);
if (j) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, j,
rsyserr(FERROR_XFER, j,
"read errors mapping %s",
full_fname(fname));
}
@@ -367,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");

207
socket.c
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
@@ -26,23 +26,28 @@
#include "rsync.h"
#include "ifuncs.h"
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
#include <netinet/tcp.h>
extern char *bind_address;
extern char *sockopts;
extern int default_af_hint;
extern int connect_timeout;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Establish a proxy connection on an open socket to a web proxy by
* using the CONNECT method. If proxy_user and proxy_pass are not NULL,
* they are used to authenticate to the proxy using the "Basic"
* proxy-authorization protocol
**/
static int sock_exec(const char *prog);
/* Establish a proxy connection on an open socket to a web proxy by using the
* CONNECT method. If proxy_user and proxy_pass are not NULL, they are used to
* authenticate to the proxy using the "Basic" proxy-authorization protocol. */
static int establish_proxy_connection(int fd, char *host, int port,
char *proxy_user, char *proxy_pass)
{
@@ -123,10 +128,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
}
/**
* Try to set the local address for a newly-created socket. Return -1
* if this fails.
**/
/* Try to set the local address for a newly-created socket.
* Return -1 if this fails. */
int try_bind_local(int s, int ai_family, int ai_socktype,
const char *bind_addr)
{
@@ -157,32 +160,33 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
return -1;
}
/* connect() timeout handler based on alarm() */
static RETSIGTYPE contimeout_handler(UNUSED(int val))
{
connect_timeout = -1;
}
/**
* Open a socket to a tcp remote host with the specified port .
/* Open a socket to a tcp remote host with the specified port.
*
* Based on code from Warren. Proxy support by Stephen Rothwell.
* getaddrinfo() rewrite contributed by KAME.net.
*
* Now that we support IPv6 we need to look up the remote machine's
* address first, using @p af_hint to set a preference for the type
* of address. Then depending on whether it has v4 or v6 addresses we
* try to open a connection.
* Now that we support IPv6 we need to look up the remote machine's address
* first, using af_hint to set a preference for the type of address. Then
* depending on whether it has v4 or v6 addresses we try to open a connection.
*
* The loop allows for machines with some addresses which may not be
* reachable, perhaps because we can't e.g. route ipv6 to that network
* but we can get ip4 packets through.
* The loop allows for machines with some addresses which may not be reachable,
* perhaps because we can't e.g. route ipv6 to that network but we can get ip4
* packets through.
*
* @param bind_addr Local address to use. Normally NULL to bind
* the wildcard address.
* bind_addr: local address to use. Normally NULL to bind the wildcard address.
*
* @param af_hint Address family, e.g. AF_INET or AF_INET6.
**/
* af_hint: address family, e.g. AF_INET or AF_INET6. */
int open_socket_out(char *host, int port, const char *bind_addr,
int af_hint)
{
int type = SOCK_STREAM;
int error, s;
int error, s, j, addr_cnt, *errnos;
struct addrinfo hints, *res0, *res;
char portbuf[10];
char *h, *cp;
@@ -244,12 +248,17 @@ int open_socket_out(char *host, int port, const char *bind_addr,
return -1;
}
for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}
errnos = new_array0(int, addr_cnt);
if (!errnos)
out_of_memory("open_socket_out");
s = -1;
/* Try to connect to all addresses for this machine until we get
* through. It might e.g. be multi-homed, or have both IPv4 and IPv6
* addresses. We need to create a socket for each record, since the
* address record tells us what protocol to use to try to connect. */
for (res = res0; res; res = res->ai_next) {
for (res = res0, j = 0; res; res = res->ai_next, j++) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0)
continue;
@@ -261,11 +270,30 @@ int open_socket_out(char *host, int port, const char *bind_addr,
s = -1;
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
if (connect_timeout > 0) {
SIGACTION(SIGALRM, contimeout_handler);
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);
if (errno == EINTR)
continue;
close(s);
s = -1;
break;
}
if (connect_timeout > 0)
alarm(0);
if (s < 0) {
errnos[j] = errno;
continue;
}
if (proxied
&& establish_proxy_connection(s, host, port,
proxy_user, proxy_pass) != 0) {
@@ -273,19 +301,36 @@ int open_socket_out(char *host, int port, const char *bind_addr,
s = -1;
continue;
}
if (verbose >= 3) {
char buf[2048];
if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0)
snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error));
rprintf(FINFO, "Connected to %s (%s)\n", h, buf);
}
break;
}
freeaddrinfo(res0);
if (s < 0) {
rsyserr(FERROR, errno, "failed to connect to %s", h);
return -1;
if (s < 0 || verbose >= 3) {
char buf[2048];
for (res = res0, j = 0; res; res = res->ai_next, j++) {
if (errnos[j] == 0)
continue;
if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0)
snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error));
rsyserr(FERROR, errnos[j], "failed to connect to %s (%s)", h, buf);
}
if (s < 0)
s = -1;
}
freeaddrinfo(res0);
free(errnos);
return s;
}
/**
* Open an outgoing socket, but allow for it to be intercepted by
/* Open an outgoing socket, but allow for it to be intercepted by
* $RSYNC_CONNECT_PROG, which will execute a program across a TCP
* socketpair rather than really opening a socket.
*
@@ -294,8 +339,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
*
* This is based on the Samba LIBSMB_PROG feature.
*
* @param bind_addr Local address to use. Normally NULL to get the stack default.
**/
* bind_addr: local address to use. Normally NULL to get the stack default. */
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
int af_hint)
{
@@ -348,9 +392,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
}
/**
* Open one or more sockets for incoming data using the specified type,
/* Open one or more sockets for incoming data using the specified type,
* port, and address.
*
* The getaddrinfo() call may return several address results, e.g. for
@@ -359,9 +401,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
* We return an array of file-descriptors to the sockets, with a trailing
* -1 value to indicate the end of the list.
*
* @param bind_addr Local address to bind, or NULL to allow it to
* default.
**/
* bind_addr: local address to bind, or NULL to allow it to default. */
static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
@@ -411,6 +451,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) {
@@ -462,9 +506,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
}
/*
* Determine if a file descriptor is in fact a socket
*/
/* Determine if a file descriptor is in fact a socket. */
int is_a_socket(int fd)
{
int v;
@@ -550,7 +592,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++) {
@@ -604,7 +646,9 @@ struct
} socket_options[] = {
{"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
{"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
#ifdef SO_BROADCAST
{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
#endif
#ifdef TCP_NODELAY
{"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
#endif
@@ -632,13 +676,11 @@ struct
#ifdef SO_RCVTIMEO
{"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
#endif
{NULL,0,0,0,0}};
{NULL,0,0,0,0}
};
/**
* Set user socket options
**/
/* Set user socket options. */
void set_socket_options(int fd, char *options)
{
char *tok;
@@ -704,15 +746,10 @@ void set_socket_options(int fd, char *options)
}
/**
* This is like socketpair but uses tcp. It is used by the Samba
* regression test code.
*
* The function guarantees that nobody else can attach to the socket,
* or if they do that this function fails and the socket gets closed
* returns 0 on success, -1 on failure the resulting file descriptors
* are symmetrical.
**/
/* This is like socketpair but uses tcp. The function guarantees that nobody
* else can attach to the socket, or if they do that this function fails and
* the socket gets closed. Returns 0 on success, -1 on failure. The resulting
* file descriptors are symmetrical. Currently only for RSYNC_CONNECT_PROG. */
static int socketpair_tcp(int fd[2])
{
int listener;
@@ -733,16 +770,12 @@ static int socketpair_tcp(int fd[2])
sock2.sin_len = sizeof sock2;
#endif
sock2.sin_family = PF_INET;
sock2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
if (listen(listener, 1) != 0)
goto failed;
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
goto failed;
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
if (bind(listener, (struct sockaddr *)&sock2, sizeof sock2) != 0
|| listen(listener, 1) != 0
|| getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0
|| (fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
goto failed;
set_nonblocking(fd[1]);
@@ -755,7 +788,7 @@ static int socketpair_tcp(int fd[2])
} else
connect_done = 1;
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
if ((fd[0] = accept(listener, (struct sockaddr *)&sock2, &socklen)) == -1)
goto failed;
close(listener);
@@ -783,18 +816,15 @@ static int socketpair_tcp(int fd[2])
}
/**
* Run a program on a local tcp socket, so that we can talk to it's
* stdin and stdout. This is used to fake a connection to a daemon
* for testing -- not for the normal case of running SSH.
/* Run a program on a local tcp socket, so that we can talk to it's stdin and
* stdout. This is used to fake a connection to a daemon for testing -- not
* for the normal case of running SSH.
*
* @return a socket which is attached to a subprocess running
* "prog". stdin and stdout are attached. stderr is left attached to
* the original stderr
**/
int sock_exec(const char *prog)
* Retruns a socket which is attached to a subprocess running "prog". stdin and
* stdout are attached. stderr is left attached to the original stderr. */
static int sock_exec(const char *prog)
{
pid_t pid;
int fd[2];
if (socketpair_tcp(fd) != 0) {
@@ -803,14 +833,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

36
support/git-set-file-times Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/perl -w
use strict;
# Sets mtime and atime of files to the latest commit time in git.
#
# This is useful after the first clone of the rsync repository BEFORE you
# do any building. It is also safe if you have done a "make distclean".
my %ls;
my $commit_time;
my $prefix = @ARGV && $ARGV[0] =~ s/^--prefix=// ? shift : '';
$/ = "\0";
open FH, 'git ls-files -z|' or die $!;
while (<FH>) {
chomp;
$ls{$_} = $_;
}
close FH;
$/ = "\n";
open FH, "git log -r --name-only --no-color --pretty=raw -z @ARGV |" or die $!;
while (<FH>) {
chomp;
if (/^committer .*? (\d+) (?:[\-\+]\d+)$/) {
$commit_time = $1;
} elsif (s/\0\0commit [a-f0-9]{40}$// or s/\0$//) {
my @files = delete @ls{split(/\0/, $_)};
@files = grep { defined $_ } @files;
next unless @files;
map { s/^/$prefix/ } @files;
utime $commit_time, $commit_time, @files;
}
last unless %ls;
}
close FH;

View File

@@ -6,18 +6,28 @@
# we get a -l USER option, we try to use "sudo -u USER" to run the
# command.
prefix=''
cd # Default path is home dir, just like ssh.
user=''
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
eval $prefix "${@}"
if [ "$user" ]; then
prefix=''
if [ $do_cd = y ]; then
home=`perl -e "print((getpwnam('$user'))[7])"`
prefix="cd '$home' ;"
fi
sudo -H -u "$user" sh -c "$prefix $*"
else
[ $do_cd = y ] && cd
eval "${@}"
fi

View File

@@ -1,4 +1,4 @@
#!/usr/bin/perl -w
#!/usr/bin/perl
# This script takes a command-line arg of a source directory
# that will be passed to rsync, and generates a set of excludes
# that will exclude all mount points from the list. This is
@@ -18,19 +18,24 @@
# easily adapted to read /etc/mtab or similar.
#
# ADDENDUM: The addition of the --filter option (which has support for
# absolute-anchored excludes) has made this script less useful than it
# was. Beginning with 2.6.4, you can achieve the effect of this script
# through this command:
# absolute-anchored excludes) can make this script unneeded in some
# scenarios. If you don't need delete protection on the receiving side
# (or if the destination path is identical to the source path), then you
# can exclude some absolute paths from the transfer based on the mount
# dirs. For instance:
#
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/
# awk '{print $2}' /proc/mounts | grep -v '^/$' | \
# rsync -avf 'merge,/- -' /dir host:/dest/
use strict;
use warnings;
use Cwd 'abs_path';
my $file = '/proc/mounts';
my $dir = shift || '/';
$dir = abs_path($dir);
$dir =~ s#([^/]*)$##;
my $trailing_slash = $dir =~ m{./$} ? '/' : '';
$dir = abs_path($dir) . $trailing_slash;
$dir =~ s{([^/]*)$}{};
my $trailing = $1;
$trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
$trailing .= '/' if $trailing ne '';
@@ -38,7 +43,7 @@ $trailing .= '/' if $trailing ne '';
open(IN, $file) or die "Unable to open $file: $!\n";
while (<IN>) {
$_ = (split)[1];
next unless s#^\Q$dir$trailing\E##o && $_ ne '';
next unless s{^\Q$dir$trailing\E}{}o && $_ ne '';
print "- /$trailing$_\n";
}
close IN;

60
support/munge-symlinks Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/perl
# This script will either prefix all symlink values with the string
# "/rsyncd-munged/" or remove that prefix.
use strict;
use Getopt::Long;
my $SYMLINK_PREFIX = '/rsyncd-munged/';
my $munge_opt;
&GetOptions(
'munge' => sub { $munge_opt = 1 },
'unmunge' => sub { $munge_opt = 0 },
'all' => \( my $all_opt ),
'help|h' => \( my $help_opt ),
) or &usage;
&usage if $help_opt || !defined $munge_opt;
my $munged_re = $all_opt ? qr/^($SYMLINK_PREFIX)+(?=.)/ : qr/^$SYMLINK_PREFIX(?=.)/;
push(@ARGV, '.') unless @ARGV;
open(PIPE, '-|', 'find', @ARGV, '-type', 'l') or die $!;
while (<PIPE>) {
chomp;
my $lnk = readlink($_) or next;
if ($munge_opt) {
next if !$all_opt && $lnk =~ /$munged_re/;
$lnk =~ s/^/$SYMLINK_PREFIX/;
} else {
next unless $lnk =~ s/$munged_re//;
}
if (!unlink($_)) {
warn "Unable to unlink symlink: $_ ($!)\n";
} elsif (!symlink($lnk, $_)) {
warn "Unable to recreate symlink: $_ -> $lnk ($!)\n";
} else {
print "$_ -> $lnk\n";
}
}
close PIPE;
exit;
sub usage
{
die <<EOT;
Usage: munge-symlinks --munge|--unmunge [--all] [DIR|SYMLINK...]
--munge Add the $SYMLINK_PREFIX prefix to symlinks if not already
present, or always when combined with --all.
--unmunge Remove one $SYMLINK_PREFIX prefix from symlinks or all
such prefixes with --all.
See the "munge symlinks" option in the rsyncd.conf manpage for more details.
EOT
}

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,12 +86,12 @@ our %long_opt = (
'inplace' => 0,
'link-dest' => 2,
'list-only' => 0,
'log-file' => 3,
'log-format' => 1,
'max-delete' => 1,
'max-size' => 1,
'min-size' => 1,
'modify-window' => 1,
'no-i-r' => 0,
'no-implied-dirs' => 0,
'no-r' => 0,
'no-relative' => 0,
@@ -106,10 +108,12 @@ our %long_opt = (
'size-only' => 0,
'skip-compress' => 1,
'specials' => 0,
'stats' => 0,
'suffix' => 1,
'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;
@@ -170,10 +175,10 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
} else {
if ($subdir ne '/') {
# Validate args to ensure they don't try to leave our restricted dir.
s#//+#/#g;
s#^/##;
s#^$#.#;
die "Do not use .. in any path!\n" if m#(^|/)\\?\.\\?\.(\\?/|$)#;
s{//+}{/}g;
s{^/}{};
s{^$}{.};
die "$0: do not use .. in any path!\n" if m{(^|/)\\?\.\\?\.(\\?/|$)};
}
push(@args, bsd_glob($_, GLOB_LIMIT|GLOB_NOCHECK|GLOB_BRACE|GLOB_QUOTE));
}
@@ -200,10 +205,10 @@ sub check_arg
my($opt, $arg, $type) = @_;
$arg =~ s/\\(.)/$1/g;
if ($subdir ne '/' && ($type == 3 || ($type == 2 && !$am_sender))) {
$arg =~ s#//#/#g;
$arg =~ s{//}{/}g;
die "Do not use .. in --$opt; anchor the path at the root of your restricted dir.\n"
if $arg =~ m#(^|/)\.\.(/|$)#;
$arg =~ s#^/#$subdir/#;
if $arg =~ m{(^|/)\.\.(/|$)};
$arg =~ s{^/}{$subdir/};
}
$arg;
}

115
syscall.c
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
@@ -34,6 +34,7 @@ extern int am_root;
extern int read_only;
extern int list_only;
extern int preserve_perms;
extern int preserve_executability;
#define RETURN_ERROR_IF(x,e) \
do { \
@@ -151,10 +152,11 @@ int do_chmod(const char *path, mode_t mode)
int code;
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
if (S_ISLNK(mode)) {
#ifdef HAVE_LCHMOD
code = lchmod(path, mode & CHMOD_BITS);
#elif defined HAVE_SETATTRLIST
code = lchmod(path, mode & CHMOD_BITS);
#else
if (S_ISLNK(mode)) {
# if defined HAVE_SETATTRLIST
struct attrlist attrList;
uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
@@ -162,13 +164,14 @@ int do_chmod(const char *path, mode_t mode)
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.commonattr = ATTR_CMN_ACCESSMASK;
code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
#else
# else
code = 1;
#endif
# endif
} else
code = chmod(path, mode & CHMOD_BITS);
if (code != 0 && preserve_perms)
return code;
code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
#endif /* !HAVE_LCHMOD */
if (code != 0 && (preserve_perms || preserve_executability))
return code;
return 0;
}
#endif
@@ -180,6 +183,22 @@ int do_rename(const char *fname1, const char *fname2)
return rename(fname1, fname2);
}
#ifdef HAVE_FTRUNCATE
int do_ftruncate(int fd, OFF_T size)
{
int ret;
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
do {
ret = ftruncate(fd, size);
} while (ret < 0 && errno == EINTR);
return ret;
}
#endif
void trim_trailing_slashes(char *name)
{
int l;
@@ -211,6 +230,7 @@ int do_mkstemp(char *template, mode_t perms)
{
RETURN_ERROR_IF(dry_run, 0);
RETURN_ERROR_IF(read_only, EROFS);
perms |= S_IWUSR;
#if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
{
@@ -281,11 +301,76 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
#endif
}
char *d_name(struct dirent *di)
#ifdef HAVE_UTIMENSAT
int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
{
#ifdef HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;
#endif
struct timespec t[2];
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
t[0].tv_sec = 0;
t[0].tv_nsec = UTIME_NOW;
t[1].tv_sec = modtime;
t[1].tv_nsec = mod_nsec;
return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
}
#endif
#ifdef HAVE_LUTIMES
int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
{
struct timeval t[2];
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
t[0].tv_sec = time(NULL);
t[0].tv_usec = 0;
t[1].tv_sec = modtime;
t[1].tv_usec = mod_nsec / 1000;
return lutimes(fname, t);
}
#endif
#ifdef HAVE_UTIMES
int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
{
struct timeval t[2];
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
t[0].tv_sec = time(NULL);
t[0].tv_usec = 0;
t[1].tv_sec = modtime;
t[1].tv_usec = mod_nsec / 1000;
return utimes(fname, t);
}
#elif defined HAVE_UTIME
int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
{
#ifdef HAVE_STRUCT_UTIMBUF
struct utimbuf tbuf;
#else
time_t t[2];
#endif
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
# ifdef HAVE_STRUCT_UTIMBUF
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
return utime(fname, &tbuf);
# else
t[0] = time(NULL);
t[1] = modtime;
return utime(fname, t);
# endif
}
#else
#error Need utimes or utime function.
#endif

View File

@@ -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,12 @@ int module_id = -1;
int relative_paths = 0;
int human_readable = 0;
int module_dirlen = 0;
int preserve_times = 0;
int preserve_xattrs = 0;
mode_t orig_umask = 002;
char *partial_dir;
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 +58,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 +71,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
@@ -29,6 +29,7 @@ int read_only = 0;
int list_only = 0;
int verbose = 0;
int preserve_perms = 0;
int preserve_executability = 0;
int
main(int argc, char **argv)

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,9 +41,11 @@ 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 "$RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
runtest "daemon recv --write-batch" 'checkit "\"$ignore23\" $RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
# The script would have aborted on error, so getting here means we pass.
exit 0

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

@@ -25,7 +25,7 @@ hands_setup
# Build chkdir with a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
checkit "$RSYNC -avvvvz '$fromdir/' localhost::test-to/" "$chkdir" "$todir"
checkit "'$ignore23' $RSYNC -avvvvz '$fromdir/' localhost::test-to/" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

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,18 +106,18 @@ $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"
grep -v block2.5 <"$chkfile" >"$chkfile.new"
mv "$chkfile.new" "$chkfile"
fi
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
@@ -127,22 +128,22 @@ echo ""
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
if test -b "$fromdir/block2.5"; then
if test -r "$fromdir/block2.5"; then
set -x
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
| tee "$outfile"
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"
diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
fi
# The script would have aborted on error, so getting here means we've won.

Some files were not shown because too many files have changed in this diff Show More