Compare commits

...

680 Commits

Author SHA1 Message Date
Wayne Davison
f8d2ecd223 Preparing for release of 3.1.2pre1 2015-08-08 12:47:35 -07:00
Wayne Davison
453914e35b Update the copyright year. 2015-08-08 12:47:03 -07:00
Wayne Davison
3f26e38f86 Mention latest fixes. 2015-08-08 12:42:13 -07:00
Wayne Davison
81d1ca0683 Don't create so many empty backup dirs.
Fixes bug 10724.
2015-08-08 12:19:42 -07:00
Wayne Davison
289ccbd02f Allow samba.org hostname to be overridden. 2015-08-02 11:15:17 -07:00
Wayne Davison
85d3877be9 Improve mergedir filter handling internals.
Fixes bug 10995.
2015-07-13 10:56:13 -07:00
Wayne Davison
e203245d76 Make sure chk subdir can't diverge in time from its src subdir. 2015-07-12 14:00:45 -07:00
Wayne Davison
dfbcc4f7ec Avoid --remove-sent-file issue for non-regular files. 2015-07-12 13:26:01 -07:00
Wayne Davison
0bcb8b639a Mention local-only effect of --msgs2stderr. 2015-07-12 13:10:05 -07:00
Wayne Davison
77f750f167 Mention how we handle a module named "global". 2015-07-12 10:38:32 -07:00
Wayne Davison
23afe20780 Brant Gurganus's autoconf updates.
This improves some obsolete autoconf macros and increases the minimum
autoconf version from 2.60 to 2.69.  Fixes bug 11369.
2015-07-07 10:37:12 -07:00
Wayne Davison
e12a6c087c Add parent-dir validation for --no-inc-recurse too. 2015-07-04 16:25:23 -07:00
Wayne Davison
6feb7d37df Change "fail" to "test_fail".
Fixes bug 11322.
2015-06-10 15:20:01 -07:00
Wayne Davison
81ff413bb0 Make the checksum_seed a bit harder to predict. 2015-05-11 14:32:45 -07:00
Wayne Davison
eac858085e Add compat flag to allow proper seed checksum order.
Fixes the equivalent of librsync's CVE-2014-8242 issue.
2015-05-11 12:36:20 -07:00
Wayne Davison
2ac35b4507 Pass -I option to aclocal. 2015-05-01 15:17:41 -07:00
Tiziano Müller
3bc319766d Use AS_IF instead of plain if/then/fi 2015-05-01 14:26:21 -07:00
Tiziano Müller
a689fb1f5f Ignore .deps directories. 2015-05-01 14:26:21 -07:00
Tiziano Müller
b560a96b2c Check for perl and assign it to a var since it is needed for generating the protocol header. 2015-05-01 14:26:21 -07:00
Tiziano Müller
51e3c3da85 Remove dead targets from build system 2015-05-01 14:26:21 -07:00
Wayne Davison
461086bbe7 Handle configure's new version style. 2015-05-01 14:26:21 -07:00
Tiziano Müller
00694610a6 Specify package name and version in call to AC_INIT 2015-05-01 14:26:21 -07:00
Tiziano Müller
8e3a6db842 Properly quote arguments for AC_LIBOBJ. 2015-05-01 14:26:21 -07:00
Wayne Davison
8354cad53e Must define LIBOBJDIR in the Makefile. 2015-05-01 14:26:05 -07:00
Tiziano Müller
317a0e8ca5 Use AC_CONFIG_LIBOBJ_DIR and AC_REPLACE_FUNCS to adhere to autoconf standards 2015-04-26 17:54:08 -07:00
Tiziano Müller
066ad8c719 Modularize m4 macros
Split acinclude.m4 into one file per function in m4/
2015-04-26 17:54:06 -07:00
Tiziano Müller
ec4f644d2f Properly quote m4 macro 2015-04-26 16:50:41 -07:00
Wayne Davison
4bf342c60f Update generated-files logic. 2015-04-26 16:50:41 -07:00
Tiziano Müller
a2f733c664 Rename aclocal.m4 to acinclude.m4 and add make target
It is common practice to split up m4 files for easier maintenance and
generate the required aclocal.m4 using `aclocal` instead.
2015-04-26 16:50:16 -07:00
Stefan Behrens
3ea74eb388 rsync: fix of-by-one in check of snprintf() result.
Fixes bug 11229.
2015-04-22 10:31:04 -07:00
Wayne Davison
962f8b9004 Complain if an inc-recursive path is not right for its dir.
This ensures that a malicious sender can't use a just-sent
symlink as a trasnfer path.
2014-12-31 13:48:42 -08:00
Wayne Davison
ae189e18de Mention that --append can be dangerous. 2014-12-31 13:10:46 -08:00
Wayne Davison
5b34561cf7 Call set_modtime even if only NSEC is different. 2014-12-31 13:10:37 -08:00
Wayne Davison
5546dab329 Use usleep() for msleep() if it is available. 2014-11-27 12:02:56 -08:00
Wayne Davison
6128f56694 Add a missing closing paren. 2014-10-10 14:15:11 -07:00
Wayne Davison
743f5a30d5 Prepare the repository for more development. 2014-09-06 11:00:52 -07:00
Wayne Davison
a955e93316 Mention DRY RUN in --debug=exit output. 2014-09-06 10:47:13 -07:00
Wayne Davison
aca7dd3bff Adding the long options that BackupPC likes to use. 2014-09-04 13:44:50 -07:00
Wayne Davison
bc55aa04df Set GIT_MERGE_AUTOEDIT=no in the environment. 2014-07-31 15:59:32 -07:00
Wayne Davison
f438d5abe0 Match latest git's repo branch message. 2014-07-31 14:52:30 -07:00
Wayne Davison
6fe798392b Match latest git's repo status messages. 2014-07-31 14:47:09 -07:00
Wayne Davison
6ceb9ea012 Remove superfluous ${INSTALL_STRIP} uses. 2014-07-31 14:39:09 -07:00
Wayne Davison
6900d35cce Fix a typo. 2014-07-31 14:38:16 -07:00
Wayne Davison
7cb0de6326 Preparing for release of 3.1.1 2014-06-22 09:50:03 -07:00
Wayne Davison
61e74afc42 Add a clarification about shell wildcard expansion. 2014-06-22 09:41:17 -07:00
Wayne Davison
0466e46b9f Make sure the link() destination file doesn't exist. 2014-06-22 09:04:24 -07:00
Wayne Davison
aa4c6db043 Make sure cmp_time() doesn't mess up due to a time_t overflow.
Fixes bug 10643.
2014-06-15 17:53:34 -07:00
Wayne Davison
edb0d9c792 Updated NEWS & tweaked a comment. 2014-06-14 09:55:37 -07:00
Wayne Davison
6ffd8f2169 Put zlib and popt -I options early in the CFLAGS. 2014-06-14 09:48:56 -07:00
Wayne Davison
ba43e88527 Fix hard-link bugs when receiver isn't capable.
If the receiving side cannot hard-link symlinks and/or special files
(including devices) then we now properly handle incoming hard-linked
items (creating separate identical items).
2014-06-13 16:05:08 -07:00
Wayne Davison
ff08acd4f2 Added a flag to disable xattr hlink optimization.
I added a compatibility flag for protocol 31 that will let both sides
know if they should be using the xattr optimization that attempted to
avoid sending xattr info for hardlinked files.  Since this optimization
was causing some issues, this compatibility flag will ensure that both
sides know if they should be trying to use the optimization or not.
2014-06-08 10:42:14 -07:00
Wayne Davison
03bb593f81 I missed this tweak in the undo of a prior xattr optimization. 2014-06-08 10:21:27 -07:00
Wayne Davison
4c8eb5f951 Preparing for release of 3.1.1pre2 2014-05-26 15:42:03 -07:00
Wayne Davison
f491d17352 Mention all the latest changes in the NEWS. 2014-05-26 14:08:31 -07:00
Wayne Davison
288e64a79f Avoid an xattr-finding glitch on the receiver.
Fixes bug 9594.
2014-05-26 14:08:31 -07:00
Wayne Davison
0872dff60c Add new-compress option to rrsync. 2014-05-26 12:13:01 -07:00
Wayne Davison
3ce7a65c11 Make --omit-dir-times avoid early-create directories. 2014-05-25 16:43:14 -07:00
Wayne Davison
de8ec0b309 Exit with a partial-transfer error for a sender-remove failure. 2014-05-25 16:00:13 -07:00
Wayne Davison
677c6e14cc Check for attr lib. 2014-05-05 09:25:13 -07:00
Wayne Davison
7665ba5b36 Fix usermap/groupmap parsing of MIN-MAX IDs. 2014-04-30 12:34:15 -07:00
Wayne Davison
adc600cbe2 Check F_IS_ACTIVE() in a few more spots.
The code needs to ignore flist entries that were marked inactive (by
either duplicate removal or empty-dir pruning) in a few more spots.
2014-04-20 14:41:54 -07:00
Wayne Davison
43d6d0c5ba Change args to file_checksum() to prepare for future changes. 2014-04-19 16:26:35 -07:00
Wayne Davison
22a3ac0b55 Add new-style compression that skips matching data.
Adding new-style compression that only compresses the literal data that
is sent over the wire and not also matching file data that was not sent.
This new-style compression is compatible with external zlib instances,
and will eventually become the default (once enough time has passed that
all servers support the --new-compress and --old-compress options).

NOTE: if you build rsync with an external zlib (i.e. if you specified
configure --with-included-zlib=no) you will ONLY get support for the
--new-compress option!  A client will treat -z as uncompressed (with a
warning) and a server will exit with an error (unless -zz was used).
2014-04-19 12:18:19 -07:00
Wayne Davison
1524c2e5c7 Expand the backslash description a bit more in excludes. 2014-04-19 10:16:00 -07:00
Wayne Davison
0dedfbce2c Avoid infinite wait reading secrets file. 2014-04-13 13:51:36 -07:00
Wayne Davison
4cad402ea8 Receiver now rejects invalid filenames in filelist.
If the receiver gets a filename with a leading slash (w/o --relative)
and/or a filename with an embedded ".." dir in the path, it dies with
an error (rather than continuing). Those invalid paths should never
happen in reality, so just reject someone trying to pull a fast one.
2014-04-13 10:36:59 -07:00
Wayne Davison
306d112730 Mention how "max verbosity" affects info & debug opts. 2014-03-07 23:47:40 -08:00
Wayne Davison
371242e4e8 Have receiver strip bogus leading slashes on filenames.
If the receiver is running without --relative, it shouldn't be receiving
any filenames with a leading slash.  To ensure that the sender doesn't
try to pull a fast one on us, we now make flist_sort_and_clean() strip a
leading slash even if --relative isn't specified.
2014-03-02 16:47:01 -08:00
Wayne Davison
e1bfdf67f3 Avoid the use of an extra leading dot when using --temp-dir. 2014-02-26 14:00:10 -08:00
Wayne Davison
3fe686b577 Explicitly mention that dirs aren't affected by --update. 2014-02-24 11:30:07 -08:00
Wayne Davison
783611707b Include a systemd file that some distros might want. 2014-02-24 10:19:14 -08:00
Wayne Davison
cd909fde87 Fix --info=progress2 info as a file is transferred.
Applying Anish Shankar's patch to fix speed and stats of files as they
are transferred.  Fixes bug 10450.
2014-02-24 10:07:18 -08:00
Wayne Davison
4dfe7c9f3e Improve the *.spec file a bit. 2014-01-27 09:57:28 -08:00
Wayne Davison
7fb4c08c24 Use the patch's list of generated files for each patch. 2014-01-27 09:18:03 -08:00
Wayne Davison
8946cfc6f8 Preparing for release of 3.1.1pre1 2014-01-26 09:32:43 -08:00
Wayne Davison
dfa5b49110 Bump the year to 2014. 2014-01-26 09:29:15 -08:00
Wayne Davison
1bf6203616 More NEWS improvements. 2014-01-26 09:21:47 -08:00
Wayne Davison
a3f852bd78 Fix "unchanged" protocol designation. 2014-01-19 19:44:30 -08:00
Wayne Davison
72e7fb5b92 Mention the latest NEWS items. 2014-01-19 15:24:07 -08:00
Wayne Davison
740551d657 Undo the hard-link xattr optimization in 78286a03.
I'm backing out the xattr optimization that was put in to try
to make xattr data sending more optimal on hard-linked files.
The code was causing hard-to-reproduce bugs, and it's better to
get things done fully & correctly over fully optimally.
2014-01-19 14:59:43 -08:00
Wayne Davison
a106ed78d5 Fix the leaving of a temp file w/o partial-file saving.
Fixed bug 10350.
2014-01-19 14:35:05 -08:00
Wayne Davison
bba31ddf12 Avoid ACL and/or xattr lookups on IS_MISSING_FILE() entries.
Fixes bug 10381.
2014-01-19 12:24:01 -08:00
Wayne Davison
31825a94b3 Add IS_MISSING_FILE(statbuf) macro. 2014-01-19 12:23:39 -08:00
Wayne Davison
5dcef7c6dd Adding IVAL64() and SIVAL64(). 2014-01-19 12:02:38 -08:00
Wayne Davison
72e0c45078 Handle more x86 hosts w/o resorting to CAREFUL_ALIGNMENT. 2014-01-19 11:48:14 -08:00
Wayne Davison
0593471e99 We really depend on autoconf 2.60 these days. 2014-01-02 10:56:03 -08:00
Wayne Davison
1b29458ea4 Adding rsync-no-vanished script for bug 10356. 2014-01-01 10:35:08 -08:00
Wayne Davison
d3414a7d23 Warn about lack of yodl2man at end of configure run. 2014-01-01 10:03:45 -08:00
Wayne Davison
9e2e7a1b2d Restoring use of socketpair on cygwin.
Use of socketpair is much faster on cygwin, and some folks report fewer
hangs using the modern socketpair implementation vs pipes.
2013-12-25 14:20:53 -08:00
Wayne Davison
d34eaa8183 Use 0 (not NULL) for a non-pointer arg. 2013-12-25 14:19:30 -08:00
Wayne Davison
b4ea93c676 Try to fix bug 7865 for some acl() EINVAL results. 2013-12-25 10:18:41 -08:00
Wayne Davison
6df5d81ce2 Fix a few issues with make_path().
The make_path() utility function was not returning the right status
when --dry-run was used, so I added some stat() checking that only
happens for -n.  I also noticed that the function was not handling
the case where the whole path needed to be created, so I fixed that.
Fixes bug 10209.
2013-12-23 10:30:28 -08:00
Wayne Davison
0e3152febd Change owner+group before setting xattrs to avoid xattr loss.
Fixes bug 10163.
2013-12-23 09:49:17 -08:00
Wayne Davison
e9398b1dc5 Fix a typo that Stefan Beller pointed out. 2013-12-14 16:25:18 -08:00
Wayne Davison
83792c1cbf A delete_item() error should use FERROR_XFER.
Fixes bug 10024.
2013-12-01 15:58:17 -08:00
Wayne Davison
32540aa091 Tweak log_delete() to send MSG_DELETED more.
If the client is the sender and it is wanting to log deletes, the
current generator code neglects to send MSG_DELETED to the client side
unless some delete verbosity is enabled.  With this new version on the
generator side, the logfile will now mention deletes, even if the
sending (client) side is an older rsync.  Fixes bug 10182.
2013-11-28 11:13:05 -08:00
Wayne Davison
836e0c5df4 Create and use write_bigbuf() function for extra-large buffer sizes. 2013-11-25 13:12:35 -08:00
Wayne Davison
2cd87086f0 Use chunked xattr reading in OS X sys_lgetxattr(). 2013-11-25 13:12:09 -08:00
Wayne Davison
eaa4e2d1ee Fix itemize bug with --link-dest, -X, and -n.
When running with --*-dest & -X, some alt-dest-found files would not
use the right name when looking up old attrs in itemize(), causing a
weird error for a --dry-run copy.  Fixes bug 10238.
2013-11-25 09:18:18 -08:00
Wayne Davison
e461cefbab Avoid useless keepalive msgs that would kill an older rsync.
This fix avoids the sending of keep-alive messages from the receiver
to the sender when we are still sending the file list (at which time
an older rsync would die if it received such a keep-alive message).
The messages aren't actually needed, since we haven't forked yet, and
the single flow of data keeps the procs alive.
2013-11-10 16:15:39 -08:00
Wayne Davison
18217a94c4 Fix timeout checking in safe_read(). 2013-11-09 10:49:59 -08:00
Wayne Davison
090ef59b29 Change safe_read() to select() before reading. 2013-11-09 10:32:44 -08:00
Wayne Davison
708db6f772 Git rid of uneeded extern. 2013-10-27 11:26:29 -07:00
Wayne Davison
63f9197611 Return an error if a buffer overflows in do_mknod(). 2013-10-27 10:12:53 -07:00
Wayne Davison
f643330eb1 Restore sending of "-ef" marker to the server. 2013-10-27 09:49:16 -07:00
Wayne Davison
bc0d094d2a Don't use comma_num() in FLOG output. 2013-10-27 09:48:57 -07:00
Wayne Davison
64dff88db9 Don't forget about --debug and --info for rrsync. 2013-10-04 14:10:44 -07:00
Wayne Davison
637ebad048 A few more new options that rsync 3.1.0 can pass. 2013-10-04 13:59:04 -07:00
Wayne Davison
487bf9290c Prepare repository for more development. 2013-10-03 10:45:49 -07:00
Wayne Davison
bc58313bf7 Preparing for release of 3.1.0 2013-09-28 13:55:54 -07:00
Wayne Davison
de78297b61 Remove unused var. 2013-09-28 13:53:23 -07:00
Wayne Davison
9c7d755dfe Flush write buffer on an aborted in-place transfer. 2013-09-28 10:40:27 -07:00
Wayne Davison
60cc5d4b78 Mention latest news. 2013-09-16 09:23:35 -07:00
Wayne Davison
1220c93a99 Fix the visit-all-patches path. 2013-09-16 09:16:30 -07:00
Wayne Davison
7d7538d43c Fix error in write_sparse() on incomplete write.
Fix a problem where sparse_seek could get left non-zero when we
did not finish writing all the data that would take us to that
sparse gap.  Issue pointed out by David Taylor.
2013-09-16 09:02:46 -07:00
Wayne Davison
de94193353 Remove bypassed checksums in --inplace to improve speed.
When checking a checksum that refers to a part of an --inplace file that
has been overwritten w/o getting SUMFLG_SAME_OFFSET set, we remove the
checksum from the list.  This will speed up files that have a lot of
identical checksum blocks (e.g. sequences of zeros) that we can't use
due to them not getting marked as being the same.  Patch provided by
Michael Chapman.
2013-08-03 09:59:38 -07:00
Wayne Davison
05fce6582a Preparing for release of 3.1.0pre1 2013-07-28 10:36:43 -07:00
Wayne Davison
62327b1281 We need a trailing dot when using --server --daemon. 2013-07-12 15:28:54 -07:00
Wayne Davison
99c9520ea7 Look for REMOTE_HOST before SSH_* environment options. 2013-07-12 15:24:58 -07:00
Wayne Davison
01959d6387 Set DESTDIR for make install. 2013-06-23 15:47:09 -07:00
Wayne Davison
807f3a44ba Mention latest changes. 2013-06-16 16:59:24 -07:00
Wayne Davison
2791e0b542 Be a little clearer about full-line comments. 2013-06-16 16:43:14 -07:00
Wayne Davison
d6a7ed99c1 Get GPL name right. 2013-06-16 16:36:27 -07:00
Wayne Davison
4066d61a9d Mention right option when using --delete-delay. 2013-06-16 16:33:32 -07:00
Wayne Davison
70d4a945f7 Support rsync daemon over SSL via stunnel.
Added the client rsync-ssl script and various client/daemon support
files needed for talking to an rsync daemon over SSL on port 874 (no
tls support).  This uses an elegant stunnel setup that was detailed
by dozzie (see the resources page) now that stunnel4 has improved
command-spawning support.  Also incorporates some tweaks by devzero
(e.g. the nice no-tmpfile-config client-side code) and a few by me
(including logging of the actual remote IP that came in to the
stunnel process).  This probably still needs a little work.
2013-06-15 16:40:10 -07:00
Wayne Davison
0488a14b99 Fix "make check". 2013-06-11 18:06:53 -07:00
Wayne Davison
a213d1cd6e Move some code from util.c to util2.c and add sum_as_hex(). 2013-06-11 13:36:44 -07:00
Wayne Davison
fc2d6fabe7 Set number_separator the first time it gets used. 2013-06-11 13:28:45 -07:00
Wayne Davison
a508e88fcf More NEWS changes. 2013-06-09 22:28:24 -07:00
Wayne Davison
f0da824237 Upgrading zlib to 1.2.8. 2013-06-09 22:27:33 -07:00
Wayne Davison
b74250037c Rename lsh.pl -> lsh. 2013-06-09 19:40:56 -07:00
Wayne Davison
f93094fa9f Rename lsh -> lsh.sh. 2013-06-09 19:40:56 -07:00
Wayne Davison
baf382d62e Updating NEWS with the latest changes. 2013-06-09 16:02:19 -07:00
Wayne Davison
12505e02b1 Allow --password-file=- for a stdin-supplied password. 2013-06-09 12:11:53 -07:00
Wayne Davison
d6df07392e Fix module-name splitting with --protect-args.
Fixes bug 8838.
2013-06-02 15:54:48 -07:00
Wayne Davison
d9ca1e4990 Tweak --checksum-seed docs. 2013-06-02 13:14:27 -07:00
Wayne Davison
0ab8e166f4 Avoid preallocation on inplace file that is already long enough. 2013-06-02 12:37:48 -07:00
Wayne Davison
1e9ee19a71 Look for got_kill_signal in a couple more spots. 2013-05-28 12:59:47 -07:00
Wayne Davison
9bf065860f Improve logic of code vs exit_code (etc.) in cleanup. 2013-05-26 16:23:37 -07:00
Wayne Davison
5b46454364 Forward a MSG_ERROR_EXIT value to generator too.
Fixes bug 9882.
2013-05-26 16:23:37 -07:00
Wayne Davison
d4070db631 Avoid I/O via signal-handler thread.
The cleanup code will try to flush the output buffer in some
circumstances, which is not valid if we're handling an async signal
(since it might have interrupted some partial I/O in the main thread).
These signals now set a flag and try to let the main I/O handler take
care of the exit strategy.  Fixes a protocol error that could happen
when trying to exit after a kill signal.
2013-05-26 16:22:56 -07:00
Wayne Davison
cb784f18ec Improve iconvbufs() to do more buffer size checks.
- If iconv() returns EINVAL or EILSEQ and the error is being ignored, make
  sure that there is room in the output buffer to store the erroneous char.
- When accepting an erroneous char, be sure to break if there are no more
  input characters (without calling iconv() with a zero input length).
2013-05-19 23:56:34 +00:00
Wayne Davison
2dc2070992 Fix msleep() if time goes backwards. Fixes bug 9789. 2013-05-19 22:55:08 +00:00
Wayne Davison
4442f8037b Fixed unused variable warnings in free_stat_x. 2013-05-19 22:01:29 +00:00
Wayne Davison
333e3a9ff0 Add an implementation of getpass for systems that lack one. 2013-05-19 22:01:29 +00:00
Wayne Davison
94073d20e4 Use S_IXUSR instead of the now-obsolete S_IEXEC. 2013-05-19 22:01:29 +00:00
Wayne Davison
750ec9bcdc Updated to the version dated 2013-04-24. 2013-05-19 22:01:07 +00:00
Wayne Davison
7fdba7aaf8 Updated to the version dated 2013-05-16. 2013-05-19 22:00:44 +00:00
Wayne Davison
eec26089b1 Improve description of --max-delete. 2013-01-20 11:30:08 -08:00
Wayne Davison
76340ea44c Fix weird error in test programs on SunOS. 2013-01-19 12:07:38 -08:00
Wayne Davison
7e1a9c4d79 Update copyright year. 2013-01-19 11:05:53 -08:00
Wayne Davison
16a9883649 Update OLDNEWS with 3.0.9 info. 2013-01-19 11:05:15 -08:00
Wayne Davison
bd7d36cc6c Free ACL/xattr info in try_dests_reg() loop. 2013-01-19 10:25:18 -08:00
Wayne Davison
d42e7181d5 Add free_stat_x() inline function. 2013-01-19 10:25:18 -08:00
Wayne Davison
c03bb3d181 Further improve non-empty-destination --link-dest behavior:
- Avoid relinking a file that is already linked correctly.
- Avoid trashing the stat buffer of an existing file in try_dests_reg().
2013-01-19 10:24:46 -08:00
Wayne Davison
cee326436c Remove -3 return from try_dests_reg() again -- let it do a local copy
when the dest file is unlinked and the hard link fails.
2013-01-19 09:08:39 -08:00
Wayne Davison
0ae92567ed Align fileio's map_ptr() reads. Fixes bug 8177. 2013-01-18 15:30:08 -08:00
Wayne Davison
42f759ad9a Reformat a few things for wider lines. 2013-01-18 15:20:43 -08:00
Wayne Davison
e1ded58983 Improve handling of existing files for alt-dest opts.
Fixes bug #5644.
2013-01-18 11:57:49 -08:00
Wayne Davison
0bacaccee6 Perl version of lsh that can change user w/o sudo. 2012-10-07 16:33:30 -07:00
Wayne Davison
d46f8314b6 Fix bogus "vanished file" with "./" prefixes.
Fixes bug 9212.
2012-10-07 10:47:58 -07:00
Wayne Davison
7cefbf106f Fix indentation that used expanded tabs. 2012-10-03 15:20:43 -07:00
Wayne Davison
f143b55ef1 Avoid an unused variable warning if no setvbuf. 2012-09-23 12:03:19 -07:00
Wayne Davison
ee51a745c1 Make read_args() return the full request.
When a daemon is sent multiple request args, they are now joined into a
single return value (separated by spaces) so that the RSYNC_REQUEST
environment variable is accurate for any "pre-xfer exec".  The values
in RSYNC_ARG# vars are no longer truncated at the "." arg, so that all
the request values are also listed (separately) in RSYNC_ARG#.
2012-09-23 11:15:36 -07:00
Wayne Davison
0d34fbdf5a Make daemon listener exit w/code 0 on SIGTERM. 2012-06-16 10:31:14 -07:00
Wayne Davison
d51a3adb4f Set the modtime to 0 on a partial file.
Fixes debian bug 624826.
2012-05-05 08:01:09 -07:00
Wayne Davison
b55115ec6f Fix --only-write-batch hang with --hard-links.
Fixes bug 8565.
2012-01-28 12:04:26 -08:00
Wayne Davison
f5e2b8f803 Add a slash-stripping version of rsync in support dir. 2012-01-28 10:42:01 -08:00
Wayne Davison
41c5ba641f flist->in_progress is only needed w/inc_recurese. 2012-01-28 10:42:01 -08:00
Wayne Davison
0dfd2a64ec Make stderr line-buffered w/--msgs2stderr. 2012-01-28 10:42:01 -08:00
Wayne Davison
6686b93a7a Add new --outbuf=N|L|B option. 2012-01-28 10:41:58 -08:00
Wayne Davison
9510fa9ab8 Allow --max-size=0 and --min-size=0.
Fixes bug 7965.
2011-12-24 12:35:37 -08:00
Wayne Davison
d74512eb05 Complain if the --block-size=N value is too large.
Fixes bug 8036.
2011-12-24 12:35:37 -08:00
Wayne Davison
1a2704512a Improve the handling of verbose/debug messages
The sender no longer allows a filelist to be sent in the middle of
parsing an incoming message, so that the directory sending doesn't block
all further input reading.  The generator no longer allows recursive
reading of info/error messages when it is waiting for the message buffer
to flush.  This avoids a stack overflow when lots of messages are coming
from the receiver and the sender is not reading things quickly enough.
The I/O code now avoids sending debug messages that could mess up the
I/O buffer it was in the middle of tweaking.  This fixes an infinite
loop in reduce_iobuf_size() with high levels of debug enabled.  Several
I/O-related messages were changed to output only when --msgs2stderr is
enabled.
2011-12-21 12:14:49 -08:00
Wayne Davison
a3b62ff4cf Avoid double-free of xattr/acl data in real_sx.
Fixes bug 8665.
2011-12-16 09:07:19 -08:00
Wayne Davison
60ef397057 Mention that %a and %h are daemon-only escapes. 2011-11-24 07:55:11 -08:00
Wayne Davison
89e049ad7f Another asprintf() return-value-check tweak. 2011-11-23 13:14:35 -08:00
Wayne Davison
036094d30e Committing missed manpage tweak. 2011-11-23 12:36:50 -08:00
Wayne Davison
48b51d0004 make repeated --fuzzy option look into alt-dest dirs. 2011-11-23 12:29:25 -08:00
Wayne Davison
7da17144fd Add compatibility with an unmodified zlib. 2011-11-21 09:22:14 -08:00
Wayne Davison
cbdff74b44 Fix --compress data-duplication bug. 2011-11-21 09:17:17 -08:00
Wayne Davison
37a729768b Fix version expansion. 2011-11-21 09:10:49 -08:00
Wayne Davison
8dd6ea1f1e Fix --delete-missing-args when --relative is active. 2011-10-22 10:24:54 -07:00
Wayne Davison
7c8f180900 Test asprintf() failure with < 0, not <= 0. 2011-10-08 09:16:43 -07:00
Wayne Davison
3527677043 Let's cast getpid() to an int instead of a long for snprintf(). 2011-10-08 09:15:36 -07:00
Wayne Davison
fd91c3b666 Fix two unused-variable compiler warnings. 2011-09-22 23:37:07 -07:00
Wayne Davison
15df927ae2 Fix xattr memory leak. Fixes bug 8475. 2011-09-22 09:13:31 -07:00
Ben Walton
8adceeb2b3 Testsuite/dir-sgid: use symbolic mode to set sgid bit
The chmod on Solaris (9 and 10) cannot set the sgid bit on a directory
using absolute mode, so use symbolic mode.  Avoids a skipped test.
2011-09-22 08:28:07 -07:00
Wayne Davison
0c7fdf705e Add solaris xattr support to the tests.
Change the xattr case statements to use $HOST_OS.
(Slightly tweaked version of a Ben Walton patch.)
2011-09-20 13:24:42 -07:00
Wayne Davison
439d5d8929 Better fakeroot support helps Solaris. 2011-09-20 13:17:42 -07:00
Wayne Davison
de219101ed Change stat order for better ELOOP determination. 2011-09-20 13:02:12 -07:00
Wayne Davison
79853c30c0 Be sure to use STRUCT_STAT. 2011-09-20 12:54:06 -07:00
Wayne Davison
953feeadd2 Make do_readlink() support fake-super w/o O_NOFOLLOW. 2011-09-19 09:29:00 -07:00
Wayne Davison
3417881d5c Make --delete-excluded work better with --filter=merge. 2011-09-15 07:52:38 -07:00
Wayne Davison
397fb1acd2 When modifying PATH, export it (for Solaris). 2011-09-15 07:32:07 -07:00
Wayne Davison
db0443cf90 Added "SORTED TRANSFER ORDER" manpage section. 2011-09-13 16:04:21 -07:00
Wayne Davison
d5bff8ffe2 Cleanup some manpage & --help info. 2011-09-13 15:30:40 -07:00
Wayne Davison
a7d7f52ae0 Use "|| true" in our xattr test runs. 2011-09-13 08:07:31 -07:00
Wayne Davison
847ddaf071 Make sure other early exit calls can't hang in noop_io_until_death(). 2011-09-12 17:56:23 -07:00
Wayne Davison
c4c5dc68b9 Improve the usage for --help. 2011-09-11 22:46:57 -07:00
Ben Walton
c4170cbaac Better configure support for Solaris xattrs
If we have the attropen() function, allow OS conditional enabling of
extended attribute support.  This removes the need to pass
--enable-extended-attributes to force the feature activation on Solaris.
2011-09-11 18:48:52 -07:00
Wayne Davison
de407c03d2 Fix a potential hang on an empty file list.
Fixes bug 8423.
2011-09-11 11:08:14 -07:00
Wayne Davison
c1005fb256 Document --msgs2stderr. 2011-09-11 11:01:04 -07:00
Wayne Davison
70c4bfb770 Error out if --password-file specifed and it fails.
Fixes bug 8440.
2011-09-06 21:22:22 -07:00
Wayne Davison
a470b675af Dirs need +rx as well as +w for non-super xfers.
Fixes bug 8242.
2011-09-03 12:41:22 -07:00
Wayne Davison
5561c14978 Move implied_dot_dir=1, just to be safe. 2011-08-27 14:58:20 -07:00
Wayne Davison
865efe9456 Fix sending of "." attributes for implied-dot-dir. 2011-08-27 12:05:07 -07:00
Wayne Davison
18749579b5 Fix bwlimit multiplication overflow. Fixes bug 8375. 2011-08-27 12:05:07 -07:00
Wayne Davison
a05758fde6 Some option-parsing clarifiation in the intro. 2011-08-27 12:04:45 -07:00
Wayne Davison
fb0d4403f0 Fix misplaced parens on getnameinfo() call. 2011-08-06 11:21:40 -07:00
Wayne Davison
3fd0357f9f Ignore socketpair() on cygwin. Fixes bug 8356. 2011-08-06 11:19:00 -07:00
Wayne Davison
64fa23add9 Tweak includes to fix non-defined NULL on some systems. 2011-07-31 23:31:24 -07:00
Wayne Davison
0a77adee0b Fix Minix build errors. Fixes bug 8313. 2011-07-22 11:17:57 -07:00
Wayne Davison
0a04a80d9f Replace another inet_ntop() call with getnameinfo(). 2011-07-16 16:16:04 -07:00
Wayne Davison
7ae666d2a7 Add more connect debug info, as Carlos suggested. 2011-07-12 16:02:31 -07:00
Wayne Davison
fbf4c261f4 Move freeaddrinfo() call after failure-reporting loop. 2011-07-11 18:15:51 -07:00
Wayne Davison
425747c2f3 Fix a comment. 2011-07-04 16:32:06 -07:00
Wayne Davison
03cd1ae4fa Handle FES_NO_SEND properly on a hard-linked file.
Fixes bug 8246.
2011-07-04 16:13:45 -07:00
Wayne Davison
01580c794a Fix #ifdef in unchanged_attrs(). Fixes bug 8268. 2011-06-26 09:52:47 -07:00
Wayne Davison
a59a7b2423 Fix reading side of fake-symlink bug 7109. 2011-06-18 13:42:30 -07:00
Wayne Davison
5bfe006882 Make daemon-exclude errors more error-like.
Fixes bug 7765.
2011-06-18 12:44:26 -07:00
Wayne Davison
852585b1fc Check if sender file changed before allowing a remove.
Fixes bug 7691.
2011-06-18 12:29:21 -07:00
Wayne Davison
e2c1e482e0 Set NO_SYMLINK_USER_XATTRS on linux. Fixes bug 7109. 2011-06-18 10:12:47 -07:00
Wayne Davison
4591bb2f66 Only skip deletions on IOERR_GENERAL. Fixes bug 7809. 2011-06-04 13:04:46 -07:00
Wayne Davison
810dc9fc2a Don't force \(em in the manpages. Fixes bug 7941. 2011-06-04 12:53:10 -07:00
Wayne Davison
d80f7d6cc3 Add a colon if a non-empty pre-xfer exec message follows. 2011-06-04 12:12:49 -07:00
Wayne Davison
e3bc529de9 Handle EINTR when reading the pre-xfer exec message. 2011-06-04 12:08:18 -07:00
Wayne Davison
820f7a7b57 Send error messages from pre-xfer exec script to the user. 2011-06-04 10:46:22 -07:00
Wayne Davison
a131954b7b Linux needs symlink xattrs. Fixes bug 8201. 2011-06-04 09:47:24 -07:00
Wayne Davison
f187ce36cc We need VA_COPY() defined more. Fix dangling #endif. 2011-05-30 12:48:04 -07:00
Wayne Davison
2fff0a4f28 Merge latest samba version to get va_end() fixes, etc. 2011-05-30 10:24:57 -07:00
Wayne Davison
cb0db58fb3 Fix unwritable directory issue due to misordered chmod call. 2011-05-30 08:24:27 -07:00
Wayne Davison
582aead623 Expand NO_ENTRY items from fake-super ACLs in get_rsync_acl(). 2011-05-25 08:59:47 -07:00
Wayne Davison
d518e02243 Use a union for idlist's name/max_id value. Fixes bug 8137. 2011-05-16 18:24:34 -07:00
Wayne Davison
b9cc2d4c86 Explicitly mention spaces in the "path" setting. 2011-05-16 11:34:15 -07:00
Wayne Davison
ac30d22ae5 Check for linux/falloc.h header file. 2011-05-16 08:26:40 -07:00
Wayne Davison
8bcd6a4aff Abort if the cd fails. 2011-05-07 13:01:21 -07:00
Wayne Davison
58663df432 Turn empty remote args into dot dirs. 2011-05-07 12:42:16 -07:00
Wayne Davison
da7acc5e42 Make --files-from allow a missing trailing arg w/--server. 2011-05-07 12:16:50 -07:00
Wayne Davison
54d13604fa Mention the number of child args. 2011-05-07 12:11:56 -07:00
Wayne Davison
3ed84dbc98 Don't die if man-copy fails. 2011-04-28 18:50:21 -07:00
Wayne Davison
0308092914 Handle non-srcdir man copying when yodl isn't installed. 2011-04-28 16:41:03 -07:00
Wayne Davison
a13d3b3d77 Avoid adding a slash to path '/'. 2011-04-22 16:06:15 -07:00
Wayne Davison
813d5a25e3 Fix a potential crash when trying to find a better block match. 2011-04-22 16:06:06 -07:00
Wayne Davison
591c224584 Improve lsh's handling of -l user option w/cd. 2011-04-09 08:51:26 -07:00
Wayne Davison
b223d96bf0 Add some temp-name dot heuristics for OS X's sake.
- Drop one leading '.' from the filename (before adding our own).
 - Drop one trailing '.' from a (possibly truncated) name prior to
   the .XXXXXX suffix being added.
 - Allow the temp-name to collapse to just the .XXXXXX suffix
   if the path is long enough to require that.

Note that we don't try to remove multiple dots from a filename
that actually has multiple consecutive dots, since we might as
well learn early if the final name is going to fail or not.
2011-04-05 13:35:13 -07:00
Wayne Davison
28b519c93b Applying the preallocate patch. 2011-04-04 21:57:57 -07:00
Wayne Davison
8686d3abba Move var declaration for older C compilers. 2011-04-03 18:02:45 -07:00
Wayne Davison
73b9b90a0b Adding release info for 3.0.8 to the trunk. 2011-03-26 14:50:52 -07:00
Wayne Davison
98ec67d786 Verify the module list output of the daemon-via-ssh check. 2011-03-26 11:07:27 -07:00
Wayne Davison
0de5157564 Tweak dir xattrs after the writability fudging. 2011-03-26 10:19:04 -07:00
Wayne Davison
78286a03d1 Avoid re-setting (and sending) xattrs on a hard-linked file w/the same xattrs.
Improved the xattrs testing to include hard-linking.
2011-03-26 10:09:20 -07:00
Wayne Davison
d699d815d6 Enhance the -liconv check for OS X. Fixes bug 8018. 2011-03-20 19:33:28 -07:00
Wayne Davison
e5e6d3c410 Get the branch set right before listing names and handling --delete. 2011-03-19 16:34:37 -07:00
Wayne Davison
016ce71568 Make it possible to create a new patch file while on a patch branch. 2011-03-19 16:29:47 -07:00
Wayne Davison
2792a83d58 Don't send user/group names for ACLs with --numeric-ids.
Fixes bug 8020.
2011-03-18 14:59:03 -07:00
Wayne Davison
0b67d5e396 Fix xattrs test on OS X. 2011-03-13 20:48:18 -07:00
Wayne Davison
d52aeae4e9 Improve the &merge/&include example explanation. 2011-03-11 17:39:33 -08:00
Wayne Davison
f7c3a25052 Change rsyncd.conf &merge directive to match *.inc.
This allows the same rsyncd.d directory to be used for a set
of merge files (*.inc) and a set of include files (*.conf).
2011-03-11 16:13:33 -08:00
Wayne Davison
6da6b02bb7 Suggest a better solution for a make without wildcard support. 2011-02-26 08:12:28 -08:00
Wayne Davison
da9b72b36c Clarify what extraneous hard link are. 2011-02-23 07:19:52 -08:00
Wayne Davison
75a1a04847 Get rid of obsolete tempfs warning. 2011-02-22 15:37:26 -08:00
Wayne Davison
eee2c77a93 Some uid/gid fixes for (id_t)-1 and other large ID values.
The code now avoids any special internal meaning for uid/gid -1, which
allows it to be mapped to a better value (use 4294967295 instead of -1
as the ID to map).  Replaced atol() with something than can return a
value > 0x7FFFFFFF and that will error-out if the value overflows.  If
chown() is called with a uid or gid of -1, complain that the ID is not
settable and signal a transfer error.  Fixes bug 6936.
2011-02-22 10:27:35 -08:00
Wayne Davison
7766e67321 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:52:48 -08:00
Wayne Davison
4403b1332f Fix --force with --one-file-system w/o --delete. 2011-02-22 08:26:13 -08:00
Wayne Davison
c82711b34e Fix issue with devices-fake test. 2011-02-22 08:25:11 -08:00
Wayne Davison
b2e446d0cb Fix devices test on OS w/o hard-linked devices. 2011-02-22 07:39:10 -08:00
Wayne Davison
3bd9f51917 Improve some hard-link caveats in the manpage. 2011-02-20 23:30:53 -08:00
Wayne Davison
86e90c58f4 Add .hg dir exclude to default_cvsignore list.
Fixes bug 7957.
2011-02-17 22:09:08 -08:00
Wayne Davison
e1fe1d55c4 Updated a comment to match a 3.0.x change. 2011-01-29 22:24:49 -08:00
Matt McCutchen
57edc4808f Avoid changing file_extra_cnt during deletion.
The I/O code can receive incremental file-list chunks during deletion,
and their OPT_EXTRA fields would get corrupted when file_extra_cnt is
incremented.

Instead of temporarily enabling uid_ndx to find out whether the user
owns a file, have make_file() set a flag for that purpose.

Applied with a few minor tweaks by Wayne.  Fixes bug 7936.
2011-01-29 22:05:16 -08:00
Wayne Davison
69be312b5e Some minor variable and flag cleanup. 2011-01-29 22:01:37 -08:00
Wayne Davison
4b4bcbe674 Optimize finding the sum that matches our --inplace position. 2011-01-16 17:35:50 -08:00
Wayne Davison
3f26945cb1 Include backup in map_ptr() to avoid backing up when reading. 2011-01-15 11:16:49 -08:00
Wayne Davison
580cffdec9 Sender realigns chunks with generator during an --inplace copy
when sending a sequence of zeros.
2011-01-14 21:32:15 -08:00
Wayne Davison
58a1c1a218 Make sure an alternate --inplace sum has the right length
and add missing break in --inplace same-offset loop.
2011-01-14 15:37:48 -08:00
Wayne Davison
53e6507e14 Fix a bug in the trailing-slash handling. 2011-01-13 23:00:30 -08:00
Wayne Davison
3feece5938 Improve the discussion of the absolute-filter alternative. 2011-01-13 17:16:32 -08:00
Wayne Davison
4ab6125214 Have build farm always use included popt. 2011-01-04 08:00:31 -08:00
Wayne Davison
49eb0c4a35 Mention that sorting the --files-from input is helpful. 2011-01-03 19:49:05 -08:00
Wayne Davison
050e5334d8 Added "listen backlog" daemon config paramater. 2011-01-03 19:42:27 -08:00
Wayne Davison
bf4170ade8 Daemon supports forward-DNS lookups for simple hostnames
in hosts deny/allow config settings.
2011-01-03 19:04:06 -08:00
Wayne Davison
6500e0769a Avoid reading ACL/xattr info on filetypes not being copied.
Make OS X avoid xattr access on device/special files.
Fixes bug 5458.
2011-01-03 11:20:04 -08:00
Wayne Davison
aa3faf5f8c Separate the dirs from the files in xattrs.text. 2011-01-01 21:23:19 -08:00
Wayne Davison
8030518dd0 Clarify incremental recursion's effect on --hard-link. 2011-01-01 18:21:40 -08:00
Wayne Davison
e630fd1186 Some --inplace manpage enhancements. 2011-01-01 18:16:49 -08:00
Wayne Davison
d3f5c628d7 Avoid directory permission issues with --fake-super.
Fixes bug 7070.
2011-01-01 18:09:57 -08:00
Wayne Davison
8b6ebde1f3 Be clear on which part(s) of testsuite's checkit() failed. 2011-01-01 18:09:16 -08:00
Wayne Davison
1c99b1d956 Report all socket connection errors if we fail.
Fixes bug 6588.
2011-01-01 14:00:40 -08:00
Wayne Davison
575933e9d0 Itemize xattrs of a missing dir from an alt-dest dir.
Fixes bug 6576.
2011-01-01 13:10:28 -08:00
Wayne Davison
14013906ca Use full_fname() for system error messages. 2011-01-01 13:09:58 -08:00
Wayne Davison
d1b3118c16 Tweak the year. 2011-01-01 11:52:03 -08:00
Wayne Davison
8f30d21584 Protect a remote filename that starts with a dash. 2010-12-23 22:09:45 -08:00
Wayne Davison
3f770ab0a5 Set NO_SYMLINK_XATTRS on linux the easy way.
Fixes bug 7109.
2010-12-19 08:54:11 -08:00
Wayne Davison
743348e848 Fix issues with unchanged_attrs() for symlinks. 2010-12-18 08:48:07 -08:00
Wayne Davison
14ebc5b618 Fix crash when --backup-dir is excessively long. 2010-12-16 22:15:04 -08:00
Wayne Davison
aef2b8ce41 Enhance --chmod to allow octal values. 2010-12-16 21:53:07 -08:00
Wayne Davison
9f5c16e51d Avoid splitting a multi-byte character when trimming a name.
Fixes bug 7816.
2010-11-26 09:35:43 -08:00
Wayne Davison
8484ddd3d1 A couple comment tweaks. 2010-11-20 09:30:35 -08:00
Wayne Davison
51b2ff03b3 Optimize --inplace chunck search to avoid a non-aligned search. 2010-11-12 09:07:58 -08:00
Wayne Davison
96e051c86a Use ftruncate() at the end of a --sparse file.
Fixes bug 7337.
2010-11-06 10:13:16 -07:00
Wayne Davison
55f767c5ca Mention seek effect of an unmoved --inplace chunk. 2010-11-06 08:14:21 -07:00
Wayne Davison
5ebe9a46d7 Add @group auth and overrides to "auth user" daemon config. 2010-10-12 10:34:38 -07:00
Wayne Davison
d64bda1c1e Some quoting fixes/improvements. 2010-09-06 08:41:46 -07:00
Wayne Davison
c6679e04f8 If we create an off_t type, define SIZEOF_OFF_T. 2010-09-06 08:26:41 -07:00
Wayne Davison
9cb20c605f Fix rsync_xal_set reference in an error. 2010-09-06 08:09:46 -07:00
Wayne Davison
ba342e22e7 Undo unintended mode-reference tweak. 2010-08-28 18:02:22 -07:00
Wayne Davison
29358819ca Fix description of how to force new prototype generation. 2010-08-27 07:44:17 -07:00
Wayne Davison
2a189350f2 Move time setting to syscall.c and add syscall fallback.
See bug 5506 and bug 7621.
2010-08-26 15:31:07 -07:00
Wayne Davison
020df16def Make case_N.h more generic. 2010-08-26 11:13:02 -07:00
Wayne Davison
2624e005e2 Add --omit-link-times and use CAN_SET_SYMLINK_TIMES less. 2010-08-26 11:12:58 -07:00
Wayne Davison
c9bf436e5b Mention need of wildcard support in make.
See bug 7625.
2010-08-26 08:50:34 -07:00
Wayne Davison
8b48c68285 Remove duplication for -x option. 2010-08-26 07:58:22 -07:00
Wayne Davison
aff4850053 Add some new dont-compress suffixes.
As suggested in bug 6839.
2010-08-21 14:41:53 -07:00
Wayne Davison
b32fd63459 Avoid a crash with --append-verify when discarding the received data.
Fixes bug 6293.
2010-08-21 14:25:48 -07:00
Wayne Davison
3b22184d4c Avoid a non-writable-by-the-user file when copying xattrs.
Fixes part of the problem in bug 5147.
2010-08-21 14:14:31 -07:00
Wayne Davison
929002a2d5 Avoid infinite loop if the file's length is negative.
Fixes bug 4664.
2010-08-21 13:48:01 -07:00
Wayne Davison
a64840a29d Don't mention bug fixes that are queued up for 3.0.8. 2010-07-03 08:57:28 -07:00
Wayne Davison
0f6b683c8e Refer to the right lsetxattr() caller in a error message. 2010-07-03 08:14:02 -07:00
Wayne Davison
18070203c2 Replace another assert with a descriptive error. 2010-06-26 16:06:09 -07:00
Wayne Davison
b3e41255a6 I like braces when multiple lines are indented. 2010-06-26 11:43:09 -07:00
Wayne Davison
9dbb94a7e6 Older protocols should send 1-incremented dev numbers. 2010-06-26 11:42:55 -07:00
Wayne Davison
1c9eafdda0 Mention more changes. 2010-06-26 10:59:30 -07:00
Wayne Davison
cf0f454b8a More manpage improvements. 2010-06-26 10:52:04 -07:00
Wayne Davison
d8c55a6e04 Mention more output changes. 2010-06-26 10:01:24 -07:00
Wayne Davison
b320b7d6e5 Manpage improvements for --stats, --human-readable, and --list-only. 2010-06-26 10:01:13 -07:00
Wayne Davison
54504b8e4f Output list-only sizes using any human-readable setting. 2010-06-26 10:00:29 -07:00
Wayne Davison
de32838ea2 Fix accessors F_LENGTH() and F_MOD_NSEC(). 2010-06-26 08:54:57 -07:00
Wayne Davison
ce571e64b6 Close the socket fds in the "post-xfer exec" process. 2010-06-19 10:50:28 -07:00
Wayne Davison
9541770faf Get rid of some trailing whitespace. 2010-06-19 10:49:09 -07:00
Wayne Davison
3be1d9beb2 Fix compression-ignoring of upper-case suffixes.
Fixes bug 7512.
2010-06-19 09:47:00 -07:00
Wayne Davison
292a5c2b72 Fix a couple socketpair_tcp() issues (see bug 7514). 2010-06-19 09:39:55 -07:00
Wayne Davison
e60c8b59fe Fix daemon-filter crash issue (bug 7489). 2010-06-04 23:09:20 -07:00
Wayne Davison
130cdd0d90 Avoid a double-increment of a file's st_dev value
while supporting older rsyncs that send dev == 0.
2010-05-29 10:57:09 -07:00
Wayne Davison
db22e586da Make sure our idev_find() hashtable use is right. 2010-05-29 09:21:30 -07:00
Wayne Davison
60c25caa64 Make sure we never try to store a 0 key and tweak key64 init. 2010-05-29 09:20:26 -07:00
Wayne Davison
c3541d30b6 Turn an assert into two more descriptive errors. 2010-05-29 08:52:59 -07:00
Wayne Davison
86be7a0e64 Mention --debug=hlink's level limits. 2010-05-29 08:52:26 -07:00
Wayne Davison
47573508f4 Update rrsync with the latest options. 2010-05-26 11:24:00 -07:00
Wayne Davison
d1fe65fc5e Make an empty-string dest-dir the same as "." again. 2010-05-02 17:05:07 -07:00
Wayne Davison
9fbec6e44c May as well use do_mkdir() directly these days. 2010-04-30 12:58:17 -07:00
Wayne Davison
25082d1ef6 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.

Ultimately this should be upstreamed, but for now lets get this
functionality into rsync.
2010-04-24 10:00:38 -07:00
Matt McCutchen
5deb19e4ea Man page description of --xattrs should not assume a push. 2010-04-24 09:58:09 -07:00
Matt McCutchen
0b8a9bd69d Minor restructuring/clarification to get_backup_name.
(Tweaked by Wayne to follow his preferred style.)
2010-04-24 09:56:34 -07:00
Matt McCutchen
7a3ce973c3 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-04-24 09:51:54 -07:00
Matt McCutchen
be8234cd59 Point out that the file_struct in log_delete is zero-initialized
because it is static.

It took me long enough to realize this that I think it is worth
documenting.
2010-04-24 09:51:05 -07:00
Matt McCutchen
d0f2bbb83e Rename configure.in to configure.ac, the current autoconf standard. 2010-04-24 09:34:43 -07:00
Matt McCutchen
ef7441669b Fix erroneous "--fake-user" in the rsyncd.conf(5) man page. 2010-04-24 09:30:04 -07:00
Matt McCutchen
9a54a640f7 Don't set the umask to 0 any more: it's ugly and pointless. 2010-04-24 09:28:58 -07:00
Matt McCutchen
58a79f4b44 Amplify the man page description of --hard-links (see bug 3693), and
improve that of --inplace while I'm at it.
2010-04-24 08:11:54 -07:00
Matt McCutchen
ae03e0e008 Document the "copy-some-dirlinks" trick in the man page.
Originally explained at:

http://lists.samba.org/archive/rsync/2006-February/014838.html
2010-04-24 08:07:56 -07:00
Wayne Davison
554dc122f2 Removing now-redundant path-size check from send_if_directory(). 2010-03-31 14:57:01 -07:00
Wayne Davison
8c934eba05 Fix a typo that Andrea Gelmini pointed out. 2010-03-27 12:06:45 -07:00
Wayne Davison
41ae04e09c Get rid of trailing whitespace. 2010-03-27 12:05:01 -07:00
Wayne Davison
9a7532e516 Fix directory-length overflow bug (7057). 2010-03-26 16:58:39 -07:00
Wayne Davison
9b594a530f Handle files that spring up while doing backup path checking. 2010-03-09 11:58:07 -08:00
Wayne Davison
5d8dcd1edb Write out the right compat_flags value into the batch file. 2010-02-17 14:55:34 -08:00
Wayne Davison
afccb3d326 If a module has no path setting, return an error. 2010-02-06 13:40:12 -08:00
Wayne Davison
0d78a27893 Mention what -XX (repeated --xattrs) does. 2010-02-06 13:32:47 -08:00
Wayne Davison
05c36015f7 More --timeout improvements, especially for the receiving side:
- The receiver now sends keep-alive messages to the generator
  when it is actively doing work and hasn't sent anything
  recently.  This ensures that the generator won't timeout
  if the receiver is working hard.
- The perform_io() code has improved keep-alive participation.
- Allow the sender to send some keep-alive messages, which
  ensures that if it is in a lull, it can probe the socket.
2010-01-02 10:58:39 -08:00
Wayne Davison
e34f43495c Don't try to send MSG_ERROR_EXIT after a timeout. 2010-01-02 09:14:19 -08:00
Wayne Davison
4256264991 Always use lchmod() if it is available. 2009-12-31 14:10:38 -08:00
Wayne Davison
fa5a06ad0c Mention 2010 in the main copyright. 2009-12-31 13:43:10 -08:00
Wayne Davison
794f2cbab3 Adding release info for 3.0.7 to the trunk. 2009-12-31 13:41:23 -08:00
Wayne Davison
12e59929e2 Allow any gcc to make use of __builtin_alloca for alloca. 2009-12-30 20:04:20 -08:00
Wayne Davison
fc4bb1230e Configure check for -Wno-unused-parameter now tries to link too. 2009-12-30 19:59:49 -08:00
Wayne Davison
a01e3b490e Change naming of local patch-related branches and unify
the git-status checking into a library.
2009-12-30 13:57:39 -08:00
Wayne Davison
2b2a473831 Add understanding of RSYNC_PROTECT_ARGS environment var. 2009-12-30 12:29:47 -08:00
Wayne Davison
4c4a296209 Allow "./configure --with-protect-args" to make -s the default. 2009-12-29 12:08:41 -08:00
Wayne Davison
e89a0fc094 Handle check-in and tagging of patches dir. 2009-12-26 14:29:51 -08:00
Wayne Davison
164faae84f Improve handling of MSG_IO_ERROR message. 2009-12-23 14:14:54 -08:00
Wayne Davison
de6ab501b6 Pass the 'f' compatibility flag to the server (via -e)
so that 3.0.7 knows we support the safer flist-xfer method.
2009-12-21 14:37:47 -08:00
Wayne Davison
4286ea6036 Don't die if inflate() returns Z_BUF_ERROR in see_deflate_token(). 2009-12-21 10:15:13 -08:00
Wayne Davison
626b5ae839 Don't set last_io_out in check_timeout. 2009-12-19 13:42:35 -08:00
Wayne Davison
92d021488e Improve --timeout method to take into account all I/O that is going on.
The receiving side also switches timeout handling from the receiver to
the generator, which obviates the need for the sender to send any
keep-alive messages at all (for protocol 31 and beyond).  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 11:00:36 -08:00
Wayne Davison
82b2a31a46 Added an am_receiver variable. 2009-12-19 10:14:49 -08:00
Wayne Davison
eeea1bbd72 Improved some I/O comments. 2009-12-17 09:00:52 -08:00
Wayne Davison
aa3999d66c Fix the val reading for MSG_ERROR_EXIT. Use 0-length MSG_DATA when
MSG_NOOP is not available (is both safer and supports older rsyncs).
2009-12-16 12:38:54 -08:00
Wayne Davison
6e9ad2bb03 Allow per-test timeout overrides. Give hardlinks more time. 2009-12-15 08:44:46 -08:00
Wayne Davison
c5130bc123 Improve the timeout messages. 2009-12-15 08:32:18 -08:00
Wayne Davison
f8e1fa6272 Free a strdup() in do_cmd() that checker was complaining about. 2009-12-13 19:28:01 -08:00
Wayne Davison
8e7f3107a4 Avoid -u option to id since solaris doesn't support it. 2009-12-13 18:15:09 -08:00
Wayne Davison
c2dd3ec32c Avoid a compiler warnings about a signed/unsigned mismatch. 2009-12-13 17:52:05 -08:00
Wayne Davison
e9ad7bb1f8 Increase the testrun timeout for slow compilefarm systems. 2009-12-13 17:49:09 -08:00
Wayne Davison
b9107ee61e Fix a compiler warning about a %d mismatch. 2009-12-13 17:47:35 -08:00
Wayne Davison
45426a7604 Run each testsuite test with a timeout. 2009-12-13 14:14:38 -08:00
Wayne Davison
dc2a0923a2 Avoid another checker warning. 2009-12-13 13:21:30 -08:00
Wayne Davison
ac32cdd7d4 Prevent the reading of another message before the end of the current one. 2009-12-12 21:54:52 -08:00
Wayne Davison
6d952fdbe7 Change a variable name in read_a_msg(). 2009-12-12 21:40:02 -08:00
Wayne Davison
870cf55287 This should fix another checker warning. 2009-12-12 15:58:53 -08:00
Wayne Davison
7d0fe4da70 Fix checker compile warning. 2009-12-12 15:51:03 -08:00
Wayne Davison
763880ba81 Turn iobuf.in into a circular input buffer. 2009-12-12 15:16:46 -08:00
Wayne Davison
2885270b52 Fix a hang that can happen when the sender is sending an extra file-list
and no one is reading (i.e. do advantageous reading in perform_io()).
2009-12-12 09:46:02 -08:00
Wayne Davison
0c2e8f9364 Don't send MSG_ERROR_EXIT messages at the end of the transfer.
Added some debug output for MSG_ERROR_EXIT messages.
2009-12-12 08:54:36 -08:00
Wayne Davison
24079e988f Don't (wrongly) retouch dir permissions with --fake-super.
(Patch from Matt.)
2009-11-28 21:46:42 -08:00
Wayne Davison
8a68cad1f7 Add IPv6 detection on cygwin. 2009-11-26 15:17:49 -08:00
Wayne Davison
d03c0b1ed3 Fix a comment. 2009-11-23 22:45:29 -08:00
Wayne Davison
907e6a32a0 Change the handling of circular buffers to not waste 4 bytes
all the time (we only waste from 1-3 bytes some of the time).
2009-11-23 08:16:18 -08:00
Wayne Davison
e4c598c830 Make some RERR_* choices better, and another noop_io_until_death() tweak. 2009-11-16 12:35:17 -08:00
Wayne Davison
ae598f3847 Don't complain about a socket EOF unless it affects a read.
Make sure a write error drains any messages in the input buffer.
2009-11-15 12:54:55 -08:00
Wayne Davison
d85d029b92 Tweak the noop_io_until_death() timeout and comment it. 2009-11-14 23:05:52 -08:00
Wayne Davison
d620b907e4 Improved a couple comments and added some "else" optimizations. 2009-11-14 10:01:13 -08:00
Wayne Davison
5692657757 No need to check MIN_FILECNT_LOOKAHEAD w/extra_flist_sending_enabled. 2009-11-14 09:58:25 -08:00
Wayne Davison
c493b6b81d Make the two "wrap-bytes" sections simpler and more similar. 2009-11-14 09:56:42 -08:00
Wayne Davison
4e2a7e59e5 Prefer send_msg_int() over send_msg() for better debug output. 2009-11-14 09:52:40 -08:00
Wayne Davison
b82d8c9d1a Tweaked sizing checks in perform_io(). 2009-11-14 09:51:26 -08:00
Wayne Davison
75ea845904 Fixed the buffer-has-space check in write_buf(). 2009-11-14 09:43:02 -08:00
Wayne Davison
ce795fcd75 Make --bwlimit take the same size suffixes as the --max-size option
(while keeping it backward compatible). Improve --bwlimit docs.
2009-11-12 23:55:21 -08:00
Wayne Davison
aa381148a3 Fix the daemon test when running it as root. 2009-11-12 22:05:45 -08:00
Wayne Davison
cece2e3f5e Make use of seteuid() determined by configure. 2009-11-08 20:17:02 -08:00
Wayne Davison
f397616e00 Change an RERR_* to RERR_FILEIO. 2009-11-08 11:51:02 -08:00
Wayne Davison
4351c039ad Mention who got the unknown logcode. 2009-11-08 11:50:43 -08:00
Wayne Davison
304d7b5817 More improvements for abnormal exits. 2009-11-08 11:45:55 -08:00
Wayne Davison
9270e88d76 Save first filename and linenum in case exit_cleanup() recurses. 2009-11-08 00:12:33 -08:00
Wayne Davison
2907af472d Try to silence some warnings from "checker". 2009-11-07 09:46:20 -08:00
Wayne Davison
8346c62a95 Mention the error improvements. 2009-11-07 09:46:01 -08:00
Wayne Davison
4655dcf218 Give noop_io_until_death() a time limit. 2009-11-07 09:45:43 -08:00
Wayne Davison
f9185203ee Added notifications about error-exit values:
- The receiver notifies the generator if it is exiting with an error,
  and then, if it is a server, waits around for the generator to die.
  This ensures that the client side has time to read the error.
- The generator or sender will notifiy the other side of the transfer of
  an error-exit value if protocol 31 is in effect.  This will get rid of
  some "connection unexpectedly closed" errors that are really expected
  events due to a fatal exit on the other side.
2009-11-07 01:22:11 -08:00
Wayne Davison
84c11e85a4 Fix MSG_IO_TIMEOUT when the daemon is the receiver. 2009-11-01 13:57:17 -08:00
Wayne Davison
6be8a8b14d A daemon treats --msgs2stderr as "output only to the log, not the user". 2009-11-01 13:43:29 -08:00
Wayne Davison
ef9d3a152b Make sure rwrite() can handle any logcode value in --msgs2stderr mode. 2009-11-01 13:26:15 -08:00
Wayne Davison
fe16d9a67d Fix a hang when dealing with really large numbers of files
in an incremental recursion scan.
2009-10-29 17:35:54 -07:00
Wayne Davison
23a0d1e200 Get rid of some unneeded externs. 2009-10-27 12:38:30 -07:00
Wayne Davison
a0f1ed55cd Change the daemon-timeout conveyance into a protocol-31 message. 2009-10-27 12:38:04 -07:00
Wayne Davison
4dde3347fb Fix %b and %c so that they count per-transfer bytes again. 2009-10-25 22:27:01 -07:00
Wayne Davison
44a97a34b1 Enhance log_format_has() to understand the "'" modifier. 2009-10-25 21:24:48 -07:00
Wayne Davison
281a141ea7 Updated NEWS with some of the recent changes. 2009-10-25 13:51:09 -07:00
Wayne Davison
8e6b4ddbe8 A few more --files-from fixes, and an enhanced testsuite for it. 2009-10-24 12:39:58 -07:00
Wayne Davison
9ccc8f8bbb Add a check30 target. 2009-10-24 12:37:26 -07:00
Wayne Davison
2170667802 Make use of $suitedir. 2009-10-24 11:42:29 -07:00
Wayne Davison
705132bcee Fixed some backward-compatibility issues with --files-from. 2009-10-24 11:12:37 -07:00
Wayne Davison
0dd2310cac Moved some --iconv text that was supposed to be in --files-from. 2009-10-24 00:23:21 -07:00
Wayne Davison
cbc63a09e8 Fixed a couple iconv loops to properly handle incomplete chars
that span two reads.
2009-10-24 00:19:40 -07:00
Wayne Davison
a0a88e0ef3 Move free_xbuf() into ifuncs.h. 2009-10-23 22:55:06 -07:00
Wayne Davison
d8a7290f86 Give iconvbufs() an ICB_INIT flag. 2009-10-23 22:51:29 -07:00
Wayne Davison
3b8f819222 A protocol 31 daemon will inform the client about its timeout setting
so that the client will be able to cooperate with keep-alive.
2009-10-20 15:07:51 -07:00
Wayne Davison
8b3e6fb985 Make sure daemon's io_timeout is used as a maximum value. 2009-10-20 15:05:15 -07:00
Wayne Davison
d720569422 Moved a few group-related functions with some minor tweaks; 2009-10-20 07:54:21 -07:00
Wayne Davison
0a56ef128c Silence some rprintf() size_t warnings. 2009-10-19 08:06:21 -07:00
Wayne Davison
0a9fbe17de Allow %VAR% environment references in daemon-config parameter values. 2009-10-17 16:30:23 -07:00
Wayne Davison
d23cc156aa Call seteuid() when calling setuid(). 2009-10-17 15:03:11 -07:00
Wayne Davison
6f098b0f8c Fix some man page problems Scott Kostyshak pointed out. 2009-10-17 11:06:49 -07:00
Wayne Davison
1ec57e4ddc Fix check for an empty output buffer and limit to flist_eof. 2009-10-17 11:06:20 -07:00
Wayne Davison
20caffd2b3 A major overhaul of I/O routines, creating perform_io().
Files-from data is now sent as multiplexed I/O so that it can mingle
with any messages (such as debug output).  Requires protocol 31.

Protocol 31 no longer disables output verbosity in a couple instances
that used to cause protocol issues.

Got rid of MSG_* messages that have implied raw data that follows after
them.  We instead send a negative index value as a part of the raw data
stream, which is guaranteed to be output together with the following
data.  This only affects the (in-progress) protocol 31 and the (self-
contained) communication stream from the receiver to the generator.

Added --debug=IO and improved --debug=FLIST.  Some --debug=IO output
requires --msgs2stderr to be used to see it (i.e. sending a message
about sending a message would send another message, ad infinitum).
2009-10-17 00:03:32 -07:00
Wayne Davison
df6350a8b8 Avoid type-punned compiler warnings for the byteorder.h macros
by using inline functions for the 4-char <-> uint32 conversions.
2009-10-13 21:10:57 -07:00
Wayne Davison
7a7810aa2f Avoid calling send_extra_file_list() when we shouldn't. 2009-10-13 10:45:23 -07:00
Wayne Davison
41000dffc1 Avoid stopping multiplexed out over the message fd.
Use simpler multiplexed-out stopping method.
Make sure we can't false-match a socket fd.
2009-10-12 09:10:50 -07:00
Wayne Davison
d8587b4690 Change the msg pipe to use a real multiplexed IO mode
for the data that goes from the receiver to the generator.
2009-10-02 14:18:51 -07:00
Wayne Davison
e8bb37f567 Better mask handling, including some changes to help solaris. 2009-09-12 09:40:31 -07:00
Wayne Davison
ee1c00fea8 Pass "new_mode" to set_acl() and change its return values. 2009-09-12 09:27:07 -07:00
Wayne Davison
1b502f3ec2 Put file descriptor arg at the start of the arg list for consistency. 2009-09-12 09:13:38 -07:00
Wayne Davison
44d7d045c7 Improve the "--delete does not work without -r or -d" message. 2009-09-07 14:22:59 -07:00
Wayne Davison
1a2e41af94 Add support for transferring & setting nsec time values. 2009-09-07 14:11:58 -07:00
Wayne Davison
accc091fe9 Always use lutimes() if it is available. 2009-09-07 13:45:33 -07:00
Wayne Davison
4b660bae92 Add a few new "dont compress" suffixes and improve the docs. 2009-09-05 10:29:29 -07:00
Wayne Davison
2f1fb732d4 Improve error handling and get rid of a lingering fprintf(). 2009-09-05 10:25:42 -07:00
Wayne Davison
59924aa8cf Fix daemon's conveyance of io_error value from sender. 2009-09-05 09:40:53 -07:00
Wayne Davison
b15fa9bd7b Avoid an dry-run error trying to stat a prior hard-link
file that hasn't really been created.
2009-09-05 08:18:35 -07:00
Wayne Davison
2c1aa2efac Need to use O_RDONLY in solaris sys_lremovexattr(). 2009-09-03 15:25:55 -07:00
Wayne Davison
6e310d38fc Have --fake-super turn a symlink into a file when
NO_SYMLINK_XATTRS is defined.
2009-09-02 09:06:29 -07:00
Wayne Davison
3b83a22057 Define and use "our_gid" variable. 2009-09-02 08:56:34 -07:00
Wayne Davison
8e15bd87dd Better compiling if SUPPORT_LINKS is not defined. 2009-09-02 08:53:40 -07:00
Wayne Davison
4a440e4be8 Rebuild proto.h if config.h changes. 2009-09-02 08:52:41 -07:00
Wayne Davison
486ecd3d9c Fix attropen() flags for writing an xattr on solaris. 2009-09-02 07:37:55 -07:00
Wayne Davison
17cc4c383b Fix read_xattr() for solaris. 2009-09-01 12:11:32 -07:00
Wayne Davison
c55fb5e1d6 Create non-transferred files in a more atomic manner:
If a symlink, device, special-file, or hard-linked file is replacing
an existing non-directory, the new file is created using a temporary
filename and then renamed into place.  Also changed the handling of
a cluster of hard-linked symlinks/devices/special-files to always
ensure the first item in the cluster is correct, since it doesn't
really save any significant work to try to find an existing correct
item later in the cluster to link with.
2009-08-29 16:18:57 -07:00
Wayne Davison
8a21be11f0 Fix the chmod-temp-dir test if /var/tmp doesn't exist.
Fixes bug 6569.
2009-08-22 09:34:01 -07:00
Wayne Davison
ce827c3e50 Have the sender use dead time to pad out the file list. 2009-08-22 08:15:26 -07:00
Wayne Davison
2523d0cc14 Allow Solaris sys_llistxattr() to return the list length when size == 0. 2009-08-15 06:43:06 -07:00
Wayne Davison
18bd04018d Fix some variable references. 2009-08-15 06:27:19 -07:00
Wayne Davison
4c3e9c09eb Fix a bogus free in uncache_tmp_xattrs(). 2009-08-14 07:05:48 -07:00
Wayne Davison
05a652d0b7 Some improvements to the solaris xattr routines.
Inspired by the patch to bug 6633.
2009-08-13 08:02:53 -07:00
Wayne Davison
845ed84d70 Fix a warning about a %d not getting an int (on some platforms). 2009-08-10 09:24:53 -07:00
Wayne Davison
049f8cbc8a Initial version of xattr routines for Solaris. 2009-08-08 13:27:58 -07:00
Wayne Davison
0d5ebab1d6 Add conditional support for excluding types of files from xattr ops. 2009-08-08 13:21:26 -07:00
Wayne Davison
dab0fb7cf0 Get section reference right. Fixes bug #6573. 2009-08-01 11:29:55 -07:00
Wayne Davison
62342430bf Added solaris IPv6 checking to configure. Fixes #6438.
Patch from Tim Spriggs.
2009-06-05 13:02:55 -07:00
Wayne Davison
63070274f2 Mention that --whole-file is not the default for a local transfer when
writing a batch file.
2009-06-01 09:09:09 -07:00
Wayne Davison
06886d36cf Adding a new script that creates a local patch/* branch
for each file given on the command-line.
2009-05-23 13:40:34 -07:00
Wayne Davison
9ba4d44fa8 Improved the usage output. 2009-05-23 13:40:23 -07:00
Wayne Davison
350242c5c1 Determine the master's commit hash and note it in each patch
that is based on the master in the new "based-on:" line.
2009-05-23 13:12:01 -07:00
Wayne Davison
181c9faf92 Mention some recent changes. 2009-05-23 11:45:17 -07:00
Matt McCutchen
c8fa85b23b Refactorings to the filter code, most notably:
- Improve function name: parse_rule -> parse_filter_str (to make the
  similarity with parse_filter_file clearer, and better indicate that
  it can parse multiple rules when FILTRULE_WORD_SPLIT is specified).

- In preparation for rule prefixes containing information beyond the
  rflags, change the code to pass around a full "template" filter_rule
  instead of just rflags.  Callers of parse_filter_{str,file} that want
  to specify only rflags can use rule_template(rflags) .

- Remove the MODIFIERS_* strings and instead hand-code the condition
  under which each modifier is valid.  This should make it easier to
  see that the conditions are correct.

- Tighten up default modifiers on merge rules:
  - Disallow "!" because it isn't useful.
  - If the merge rule specifies a side via "s" or "r", the rules in the
    file cannot also specify a side via "s", "r", "hide", etc.

[Patch was changed by Wayne a bit prior to application.]
2009-05-23 11:20:40 -07:00
Wayne Davison
a61ec6b168 Improved a couple variable names. 2009-05-23 10:41:16 -07:00
Wayne Davison
7b6c5c7794 Use typedefs for the filter structures. 2009-05-23 09:07:43 -07:00
Wayne Davison
b32d425451 Change filter MATCHFLGs to FILTRULEs. 2009-05-23 09:07:35 -07:00
Wayne Davison
134f97c9cc Support an older AIX system that doesn't have ENOTSUP. 2009-05-14 11:23:38 -07:00
Wayne Davison
87755c6cea Switch from inet_aton() to inet_pton() (since we supply a compatibility
function for the latter, it will always exist).
2009-05-14 11:22:37 -07:00
Wayne Davison
8f73c8a498 Adding release info for 3.0.6 to the trunk. 2009-05-08 11:13:37 -07:00
Wayne Davison
0cdb547f5c Fix typo pointed out by Chris Pepper. 2009-05-07 08:02:17 -07:00
Wayne Davison
56017d3150 Enhance name_to_{u,g}id() to optionally parse numbers and rename
to {user,group}_to_*().  Based on a patch by Matt McCutchen.
2009-05-07 07:34:42 -07:00
Matt McCutchen
d960af72b2 Move the description of include/exclude modifiers to a better place
in the man page.
2009-05-05 07:46:54 -07:00
Wayne Davison
fd2b6046cb Clarify which options are transfer rules, and what that means. 2009-04-27 07:26:23 -07:00
Wayne Davison
a8e6e14869 Change sending/receiving/storing of the rdev value for special files.
Since the value is not needed, protocol 31 no longer sends it, while
older protocols are optimized so the sender just sends a valid rdev
value 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:43:32 -07:00
Wayne Davison
307555eba3 Use upper-case HLINK in a --debug setting to avoid a really weird bug
in the strncasecmp() of OpenSUSE 10.2 (x86_64).
2009-04-13 21:07:12 -07:00
Wayne Davison
261808dac1 Switch to upper-case in the {debug,info}_verbosity arrays. 2009-04-13 07:37:49 -07:00
Wayne Davison
5250c3bc20 Changed the commands used to "make gen" without any stoppage. 2009-04-12 15:44:52 -07:00
Wayne Davison
9eaba7266c Don't allow --remove-s*-files with --read-batch. 2009-04-12 12:57:31 -07:00
Wayne Davison
d510e82fc6 Fixed the use of --xattrs with --only-write-batch. 2009-04-12 12:51:20 -07:00
Wayne Davison
4e9c7fae8f The suffix must be non-empty if the backup-dir is the same as the dest
dir.
2009-04-11 17:31:13 -07:00
Wayne Davison
3696674bc6 More backup improvements:
- Changed get_backup_name() to verify the backup path, and make any
  missing directories.  This avoids accidental use of a symlink as a dir
  in a backup path, and gets rid of any other non-dirs that are in the
  way.  It also avoids the need for various operations to retry after
  calling make_bak_dir(), simplifying several pices of code.
- Changed create_directory_path() to make_path(), giving it flags that
  lets the caller decide if it should skip a leading slash or drop the
  trailing filename.
- Mention when we create the backup directory, so the user is not caught
  unaware when rsync uses a directory they didn't expect.
- Got rid of some dir-moving backup code that is not used.
- Added a little more backup-debug output.
2009-04-11 11:51:07 -07:00
Wayne Davison
5e2d51ee06 Fix "just in case" unlink. Prefer renaming of normal files
if hard-linking fails.
2009-04-11 06:37:49 -07:00
Wayne Davison
d735fe2014 Improved link_or_rename() to handle prefer_rename better. 2009-04-10 23:33:08 -07:00
Wayne Davison
7e6c8ad653 Don't try to backup a file being removed from the backup area. 2009-04-10 23:14:06 -07:00
Wayne Davison
407ea78a62 Allow a "make reconfigure" to continue, even if the Makefile changes. 2009-04-10 16:24:12 -07:00
Wayne Davison
cb197514d9 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:22:44 -07:00
Wayne Davison
a055dbdd88 Allow $RSYNC_TEST_TMP to indicate a good tmp dir for our tests. 2009-04-10 08:19:16 -07:00
Wayne Davison
5eb8bd4962 Don't try to simplify an ACL that has a mask w/o any named values. 2009-04-09 22:49:24 -07:00
Wayne Davison
e129500c85 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:39:34 -07:00
Wayne Davison
7fc2ca2551 Make sure that config.h.in is up-to-date before allowing the
Makefile-updating rule to run ./config.status.
2009-04-04 07:52:26 -07:00
Wayne Davison
83c32ca572 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:25:25 -07:00
Wayne Davison
1a85a969a7 Fixed improper deletion of mount-point hierarchies.
Fixes bug #6240.
2009-03-31 20:15:44 -07:00
Wayne Davison
7f2591eaea Fixed a word ending that Jesse Weinstein and revamp some of the text
to make it clearer.
2009-03-31 14:34:31 -07:00
Wayne Davison
eecc969e9b Make symlink iconv work for a local copy.
Fixes issue mention in bug #5615.
2009-03-29 13:24:15 -07:00
Matt McCutchen
f8605c5b89 Give a meaningful error message when we fail to write to a batch file. 2009-03-13 09:45:35 -07:00
Wayne Davison
42d8ec616d My version of Matt's improvements related to missing source args:
- Implement --ignore-missing-args.
- In the absence of --*-missing-args, a missing source arg is an
  FERROR_XFER, but doesn't need to be an IOERR_GENERAL.
- Revise the man page.
2009-03-13 09:37:31 -07:00
Wayne Davison
7781241889 Make missing args governed by protect filters, not hide. 2009-03-13 08:49:53 -07:00
Wayne Davison
b5473dd4a9 Made --list-only output missing args as a "*missing" line. 2009-03-06 22:42:13 -08:00
Wayne Davison
4e0fa131fe Don't let --chmod tweak a 0 mode value (which marks a missing arg). 2009-03-06 22:41:23 -08:00
Wayne Davison
17a1676976 Simplify an "if" in ssh-basic.test. Fixes bug #6169; 2009-03-06 07:07:43 -08:00
Wayne Davison
b4d30300b9 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:46:57 -08:00
Wayne Davison
e6f3a33c5e Make the backup code call unsafe_symlink() correctly. 2009-03-03 08:42:56 -08:00
Wayne Davison
ce66f41791 Added the --delete-missing-args option to delete specified
files on the receiver that don't exist on the sender.
2009-02-28 09:25:26 -08:00
Wayne Davison
8d10cbfcb1 Made --progress use ir-chk instead of to-chk when the incremental
recursion scan is still active.  Mention the output change more
prominently in the NEWS file.  Updated the --progress output in
the manpage, with mention of the new "ir-chk" string's meaning.
2009-02-28 08:07:01 -08:00
Wayne Davison
e8d6fe6261 Properly indent some lines. 2009-02-19 23:09:20 -08:00
Wayne Davison
7f367bb1b4 Added a way for supplementary groups to be specified in the rsyncd.conf
file.  Also made explicitly-set uid/gid values no longer ignored by a
daemon that was not run by a super-user.
2009-02-19 23:08:48 -08:00
Wayne Davison
df7ec1cf42 Adding a way for log-format numbers to become more human readable. 2009-02-18 07:26:48 -08:00
Wayne Davison
6437b817c0 Mention that only the first line of a password-file is used. 2009-02-16 10:31:58 -08:00
Wayne Davison
d39d60a129 Handle a link_stat() failure with errno ENOENT as a vanished file. 2009-02-14 08:35:57 -08:00
Wayne Davison
49c2407141 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:50:09 -08:00
Wayne Davison
44ae54114a 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:48:40 -08:00
Wayne Davison
43eb865f9a Made copy_section() and string_set() simpler, getting rid of a
"FIXME" comment that we don't need to fix.
2009-02-06 07:27:18 -08:00
Wayne Davison
789213909d Combine Globals and Locals into a Vars struct that parallels Defaults,
shortening some code.  Improve comments and make other minor cleanups.
Based on a patch that Matt McCutchen posted to the mailing list.
2009-02-05 07:35:33 -08:00
Wayne Davison
46cd1ef6bc 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:23:59 -08:00
Wayne Davison
6e80613717 Do not try to send a symlink with a 0-length value.
This avoids a transfer error in the receiver.
2009-02-04 18:13:09 -08:00
Wayne Davison
dc6fb11b41 We only need to send --stats to a remote receiver now. 2009-01-30 08:45:54 -08:00
Wayne Davison
4d13a2fe55 A few more improvements to the hostspec-parsing code. 2009-01-28 23:17:46 -08:00
Wayne Davison
58cf354711 Fixed the parsing of IPv6 literal addresses with a username
prefixed.  Fixes bug #6067.
2009-01-28 15:59:06 -08:00
Wayne Davison
7a498f5b6c Check the right flist_num in gen_wants_ndx(). 2009-01-18 23:02:36 -08:00
Wayne Davison
243e9a366d Added a "Defaults" structure with both globals and locals in it.
Initialize both the Globals and Locals back to their default values
when reading the config.  This fixes a bug where locals set in the
global section were not getting reset to their default value if the
config item was removed from the file.
2009-01-18 22:42:41 -08:00
Wayne Davison
b53c202e45 A couple minor function-call tweaks. 2009-01-18 22:40:17 -08:00
Wayne Davison
aef68d7892 Renamed some typedefs:
- global -> global_vars
- section -> local_vars
- global_and_section -> all_vars
2009-01-18 22:39:57 -08:00
Wayne Davison
077e543b7d Renamed sDefault to Locals. 2009-01-18 22:39:20 -08:00
Wayne Davison
9784f01cbc Use a varint when sending the error_code. 2009-01-17 14:52:13 -08:00
Wayne Davison
bc40a30503 Fixed the delete statistics with --delete-delay and --delete-after. 2009-01-17 14:46:42 -08:00
Wayne Davison
4079d6a684 Fixed a hang in the inc_recurse batch-reading code. 2009-01-17 13:59:08 -08:00
Wayne Davison
df694f72ed Change some args from "char *" to "const char *" in order to get rid of
a compiler warning that was just introduced.  Also avoids changing the
host string to lower-case in access.c (by using iwildmatch()).
2009-01-15 00:23:07 -08:00
Matt McCutchen
11ef77b76a Added the "reverse lookup" daemon-config parameter. 2009-01-15 00:22:36 -08:00
Wayne Davison
abd32c9585 Send the --stats option for proper del-stats operation. 2009-01-14 07:38:37 -08:00
Wayne Davison
01e293f1b5 Use "use warnings" rather than -w on the #! line. 2009-01-13 14:52:03 -08:00
Wayne Davison
8051aa5a34 Adding recent release info from the 3.0.x branch. 2009-01-13 13:53:01 -08:00
Matt McCutchen
46d68be3da Fixed recv_add_uid() to properly differentiate users and groups. 2009-01-13 11:21:06 -08:00
Matt McCutchen
bb499bd7a0 Handle simultaneous arrival of multiple connections. 2009-01-13 09:42:54 -08:00
Wayne Davison
416cef36e9 Tweaked the --delete-* option summaries. 2009-01-08 17:01:38 -08:00
Wayne Davison
1fb6a4018d Avoid a server-side problem with -e is at the start of the short options.
(Bug #6020)
2009-01-07 16:39:22 -08:00
Wayne Davison
fc4a695cdd Tweaked s### and m## to avoid vim highlighting issues. 2009-01-07 16:38:06 -08:00
Wayne Davison
83238ed0bb Fixed bug #6011: use of target in configure. 2009-01-03 20:50:54 -08:00
Wayne Davison
21cddef2b4 Improved the backup code:
- Backups do not interfere with an atomic update (when possible).
- Backing up a file will remove a directory that is in the way
  and visa versa.
- Unify the backup-dir and non-backup-dir code in backup.c.
- Improved the backup tests a little bit.
2009-01-03 12:02:47 -08:00
Wayne Davison
b3bf9b9df9 Update the copyright year. 2009-01-03 10:57:14 -08:00
Wayne Davison
974e18191c Make delete_item() public, moving it into delete.c. 2009-01-03 10:52:50 -08:00
Wayne Davison
09ca0d15d3 Added init_stat_x() to avoid duplication of acl/xattr init code. 2009-01-03 08:53:59 -08:00
Wayne Davison
c43c66125e Allow opendir() in send_directory() to fail with ENOENT. 2008-12-27 11:09:53 -08:00
Wayne Davison
8b7a752024 Mention the mapfrom/mapto scripts and how they work. 2008-11-15 18:32:21 -08:00
Wayne Davison
2df20057e3 Adding the --usermap/--groupmap/--chown options. 2008-11-15 18:13:00 -08:00
Wayne Davison
9556f156a9 Make it clearer which configure files changed. 2008-11-15 15:31:38 -08:00
Wayne Davison
aade88bfc2 An ftruncate() failure should result in FERROR_XFER. 2008-11-15 14:50:40 -08:00
Wayne Davison
3795dafd97 Change clean_fname() to keep "//" at the start for cygwin. 2008-11-15 14:18:36 -08:00
Wayne Davison
e4ed195bb7 Change some size_t vars to ints. 2008-11-11 18:06:11 -08:00
Wayne Davison
faf980ffb5 Make sparse_seek an OFF_T (pointed out by Pedro Valasco). 2008-11-11 18:05:27 -08:00
Wayne Davison
b3ad9649bc A "make reconfigure" doesn't stop if configure changes. 2008-11-11 15:55:14 -08:00
Matt McCutchen
d4d56eed8a 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:05:21 -08:00
Wayne Davison
3ce3cabe34 Fixed the use of a dot-dir path (foo/./bar) inside of a files-from file. 2008-11-09 21:37:04 -08:00
Wayne Davison
9411292489 Fixed a bunch of "warn_unused_result" compiler warnings. 2008-11-09 18:56:21 -08:00
Wayne Davison
b4de848d75 Avoid a potential hang when --remove-*-files is active. 2008-11-09 17:59:11 -08:00
Matt McCutchen
89cb47212e 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:52:27 -08:00
Wayne Davison
1049378d9c Mention rsync's definition of client and server. 2008-10-25 09:43:50 -07:00
Wayne Davison
9ddc2b64da Fixed our supplied getnameinfo()'s ability to do a reverse lookup,
as reported in bug 5851.
2008-10-25 09:21:13 -07:00
Wayne Davison
b3347e2a03 Adding hashtable debugging output (--debug=hash). 2008-10-15 07:51:45 -07:00
Wayne Davison
d8e8ef323a Fixed a glitch when using -s with a remote-shell daemon. 2008-10-11 11:11:10 -07:00
Wayne Davison
ea0f037930 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:00:51 -07:00
Wayne Davison
08b7c3ed83 Fixed send_protected_args() to send "." in place of an empty arg. 2008-10-11 10:27:16 -07:00
Wayne Davison
76181461f5 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:30:26 -07:00
Wayne Davison
2c11e80e2e Fix the error message on one of the rename operations. 2008-09-29 21:54:49 -07:00
Wayne Davison
e366e5303f Enhanced the --stats output:
- Mention how many files were created (protocol >= 29).
- Mention how many files were deleted (new in protocol 31).
- Follow the file-count, created-count, and deleted-count
  with a break-out list of each count by type.
2008-09-26 22:14:01 -07:00
Wayne Davison
0a23e33630 Properly ignore source args on a --read-batch command. 2008-09-26 20:45:49 -07:00
Wayne Davison
8ab02ccd52 More batch-mode fixes to handle redos properly (and without hanging). 2008-09-26 20:32:04 -07:00
Wayne Davison
e0c572c5c6 Moved the flist_ndx_{push,pop}() routines from io.c into util.c. 2008-09-26 19:45:08 -07:00
Wayne Davison
315c2152d0 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-24 08:00:50 -07:00
Wayne Davison
6d301fa3de Don't send a bogus "-" option to an older server if there were
no short options specified.
2008-09-23 19:35:36 -07:00
Wayne Davison
af2dea6033 Fixed skipping of unneeded updates in a batch file when
incremental recursion is active.  Added test.
2008-09-23 19:31:14 -07:00
Wayne Davison
7fdb3bdab9 Remove bogus "non-empty" qualifier in '*' discussion. 2008-09-14 19:58:15 -07:00
Wayne Davison
794d033981 A couple instant-rsyncd improvements:
- Prompt the user for the parameters when missing.
- Allow the creation of a module without a user+password.
2008-09-11 08:50:14 -07:00
Matt McCutchen
45574a73c1 Add instant-rsyncd to support/ . 2008-09-11 08:05:06 -07:00
Wayne Davison
26e21efc5a Convey the cleaned-up module-path to the user in all cases.
Fixed a just-introduced problem with a relative module-path.
2008-09-11 07:35:40 -07:00
Wayne Davison
433c6753a8 Fix the %P logfile escape inside a chroot. 2008-09-10 16:45:06 -07:00
Wayne Davison
46b1361b41 Adding 3.0.4 release line to OLDNEWS. 2008-09-06 09:50:49 -07:00
Wayne Davison
9e7acc86c3 Adding human_readable var. 2008-09-03 16:10:45 -07:00
Wayne Davison
56c7ed9983 Changed some "rsync" commands into proper "$RSYNC" commands. 2008-09-03 12:15:36 -07:00
Wayne Davison
5dd14f0c33 Split up the ifuncs.h file into 3 .h files. 2008-09-01 19:11:36 -07:00
Wayne Davison
2a147e9fcb Don't define an array with no size. 2008-09-01 19:01:48 -07:00
Wayne Davison
7634fc8eb6 A little tidying up to follow my preferred style. 2008-09-01 17:08:26 -07:00
Matt McCutchen
daa8d92094 Several fixes for merge file handling:
- Free a mergelist's parent_dirscanned filters the last time it is
  popped or as soon as the filters are discarded due to the "n"
  modifier.  Aside from not leaking memory, this is needed to clean up
  any mergelists defined during the parent_dirscan to avoid crashing by
  trying to restore nonexistent state for them in pop_local_filters.
- Make push_local_filters save the current mergelist_cnt, and make
  pop_local_filters assert that it has the correct number of mergelists
  before restoring their state.
- Assert that mergelists get deactivated in strict LIFO order to catch
  any glitches as soon as they happen.  Free linked lists of filters in
  reverse order to make that the case.
- Add a bunch of mergelist-related debug output (--debug=filter2).
2008-09-01 17:01:19 -07:00
Wayne Davison
adc2476fa2 Output numbers in 3-digit groups by default (e.g. 1,234,567).
Also improved the human-readable output functions, including
adding the ability to output negative numbers.
2008-09-01 13:27:11 -07:00
Wayne Davison
34c3ca8f35 Verify that SUBPROTOCOL_VERSION is set correctly when making a
nightly tar file release.  Fixed the opening comments.
2008-08-31 11:55:09 -07:00
Wayne Davison
4f282b0b92 Added extra file-changing logic to ensure that the various files that
mention the protocol number have the right value, that the check-in date
for a protocol-change release is specified, and that a pre-release with
a protocol change doesn't have SUBPROTOCOL_VERSION set to 0.  Prompt for
releasing a branch if -b option was not used and we're on a branch.
2008-08-31 10:13:38 -07:00
Wayne Davison
8b3e60523a Improved the fix that ensures that the generator gets notified about an
I/O error for the incremental directory that generated the error.  The
PROTOCOL_VERSION was bumped to 31 to implement this.
2008-08-31 09:43:39 -07:00
Wayne Davison
1d891835e7 Improved rwrite() to handle a stderr exception without playing games
with the msgs2stderr value.
2008-08-24 14:07:10 -07:00
Wayne Davison
0b78944600 Some minor improvements to the flushing code to try to make it
even more solid.
2008-08-24 13:40:36 -07:00
Wayne Davison
79daa59618 Make the !flist_eof assumption explicit before the check_for_io_err
code calls wait_for_receiver().
2008-08-24 12:54:49 -07:00
Wayne Davison
72de4140d5 Added /support/savetransfer to .gitignore. 2008-08-17 09:28:50 -07:00
Wayne Davison
94a4a125bc An improved RERR_PARTIAL message. 2008-08-17 09:23:28 -07:00
Wayne Davison
e982d59146 Changed flist_for_ndx() to optionally die with an error
if the index isn't found.
2008-08-14 07:40:56 -07:00
Wayne Davison
c78e4ea905 Made an error of readlink_stat() use the right function name. 2008-08-10 07:32:54 -07:00
Wayne Davison
0b7bce2c7b Make sure that the hlink node->data allocation doesn't fail. 2008-08-08 07:48:41 -07:00
Wayne Davison
87678cefd1 Tweaked the symlink iconv buffer size and fixed a comment. 2008-08-02 13:45:50 -07:00
Wayne Davison
7c7462cd30 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:26:17 -07:00
Wayne Davison
e34ad4e925 Refer to the symlink's contents as "symlink data", not "symlink name". 2008-08-02 10:20:51 -07:00
Wayne Davison
f303b749f2 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:14:36 -07:00
Wayne Davison
91fd15b8b6 Skip new symlink conversion step if the remote rsync is not
new enough to do symlink content conversions.
2008-08-02 07:06:15 -07:00
Wayne Davison
6e5b682273 The --iconv option now converts the content of a symlink too. 2008-08-01 19:21:02 -07:00
Wayne Davison
902ee53ea4 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:03:59 -07:00
Wayne Davison
c9f540f37d Changed the iconv-related message that was being output as the
lone --info=misc2 message into a --debug=iconv message so that
all iconv info will be output when requesting iconv debugging.
2008-08-01 18:15:28 -07:00
Wayne Davison
0479eb7601 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:04:24 -07:00
Wayne Davison
459abd75f5 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:03:57 -07:00
Wayne Davison
342bfb5e23 Output an FERROR* for a general io_error, and an FWARNING for other
io_error flags.
2008-07-31 07:59:45 -07:00
Wayne Davison
1fe0d14263 Mention a missing sender-side hash improvment that went out in 3.0.0. 2008-07-30 08:33:05 -07:00
Wayne Davison
c8b823f9d8 Make hard-linking work when a device has an st_dev of 0. 2008-07-29 18:06:26 -07:00
Wayne Davison
45c37e737f Mention some mount options that can interfere with --link-dest. 2008-07-28 18:25:18 -07:00
Wayne Davison
41adbcec9f Added a client --munge-links option that works like the daemon
"munge symlinks" parameter.
2008-07-28 16:35:03 -07:00
Wayne Davison
582831a447 - Don't require a daemon config &directive to use an equal sign.
- Improved some daemon-config error messages.
2008-07-27 16:25:11 -07:00
Wayne Davison
312b68417f Made include_config() more efficient, and fixed a memory leak. 2008-07-27 15:14:20 -07:00
Wayne Davison
2206abf884 Added a command-line override for daemon config parameters:
--dparam=PARAMETER=VALUE (-M PARAMETER=VALUE).
2008-07-27 12:13:35 -07:00
Wayne Davison
fcd613d6c7 - Got rid of unused pstring/P_GSTRING/P_SEP/P_SEPARATOR code.
- Made pointer-adding code a little better.
2008-07-27 12:06:26 -07:00
Wayne Davison
8a3ddcfc81 Added &include and &merge config-file directives that allow the
daemon's config file incorporate the contents of other files.
2008-07-26 20:03:45 -07:00
Wayne Davison
c9604e2115 Changed the module array to use an item_list structure. 2008-07-26 19:57:02 -07:00
Wayne Davison
b583594ac7 Change the references to "service" to be either "section" or "module". 2008-07-26 19:11:32 -07:00
Wayne Davison
36828daef1 Reorder the static functions to avoid the need for forward declarations. 2008-07-26 17:47:02 -07:00
Wayne Davison
8880d8ec5e Since the loadparm.c file is changing, I'm reformatting it to use the
rsync style.
2008-07-26 17:42:09 -07:00
Wayne Davison
56fc9f70d3 Enhanced the release scripts to be able to handle a branch release. 2008-07-23 23:40:06 -07:00
Wayne Davison
aacd188034 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 08:31:17 -07:00
Wayne Davison
bb640d3221 Explicitly cast a -1 that is being assigned to a size_t. 2008-07-21 23:22:40 -07:00
Wayne Davison
0566dc54b1 Use PTR_ADD for the new instances of void-pointer arithmetic. 2008-07-21 23:12:02 -07:00
Wayne Davison
aad635f766 Explicitly cast an int64 to an int32. 2008-07-21 23:11:23 -07:00
Wayne Davison
a72f37bb67 Got rid of a variable that was set but not used. 2008-07-21 23:11:04 -07:00
Wayne Davison
93465f51bc Improved var-checker and tweaked all the issues it found. 2008-07-21 00:10:22 -07:00
Wayne Davison
26a7af26aa Renamed extern-squish -> var-checker. 2008-07-21 00:09:16 -07:00
Wayne Davison
b791d6802b Include the array-size in array externs so that IBM's code-checker
can do more checking for us.
2008-07-20 22:41:29 -07:00
Wayne Davison
741597c2df Turn off extra debugging now that the problem is fixed. 2008-07-20 22:28:19 -07:00
Wayne Davison
37077bd339 Improved the handling of --msgs2stderr a little more. 2008-07-20 22:27:23 -07:00
Wayne Davison
ced4fd8993 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-20 20:34:06 -07:00
Wayne Davison
eabc85ef5e Added a debug-helping option, --msgs2stderr, than should help all
messages to be seen in a situation where rsync is dying (as long
as stderr is a viable output method for the remote rsync).
2008-07-20 20:08:08 -07:00
Wayne Davison
5a18b34de3 Changed the chksum debug flag to deltasum. 2008-07-20 20:02:09 -07:00
Wayne Davison
56ac812359 A few more HLINK debug messages. 2008-07-20 13:54:53 -07:00
Wayne Davison
e42fc158c9 Output even more debug messages. 2008-07-20 13:06:54 -07:00
Wayne Davison
886df221c1 Added a '%C' (MD5 checksum) flag for the output/logfile formatting. 2008-07-19 22:50:28 -07:00
Wayne Davison
fb01d1fb07 Changed the POOL_QALIGN flag to POOL_NO_QALIGN, reversing the setting
(making pools aligned by default).  Added the missing code to make the
documented behavior of pool_free() with a NULL addr work.  Updated the
pool_alloc.3 manpage.
2008-07-19 09:20:56 -07:00
Wayne Davison
51ce67d599 Improved the alignment code and changed POOL_APPEND to POOL_PREPEND. 2008-07-18 20:57:52 -07:00
Wayne Davison
a02348b5df We now pass the POOL_QALIGN flag to pool_create(). Also optimized
the verbose-message check at the start of recv_file_list().
2008-07-18 20:46:58 -07:00
Wayne Davison
28a5b78c6f Improved the hard-link logging. 2008-07-18 17:35:22 -07:00
Wayne Davison
7bbd60101e Turn on flist5 debugging. 2008-07-18 17:34:59 -07:00
Wayne Davison
d239efa3ff Some minor tweaking for the info+debug option parsing. 2008-07-18 08:17:05 -07:00
Wayne Davison
269a8fb604 Make the hands.test use a higher hlink debug level. 2008-07-18 08:12:06 -07:00
Wayne Davison
b1617a0825 Add --debug=hlink to hands.test. 2008-07-18 07:19:21 -07:00
Wayne Davison
806f530bcb Don't interrupt the make for a generated file didn't really change. 2008-07-17 20:02:56 -07:00
Wayne Davison
7f0db4fd8e Use big_num() in a few more places. 2008-07-17 17:01:10 -07:00
Wayne Davison
3a8fad7805 Moving big_num() into lib/compat.c so tls.c can use it. 2008-07-17 16:59:59 -07:00
Wayne Davison
0c096e29aa Added some HLINK debugging output and enabled it for hardlink tests. 2008-07-17 07:43:11 -07:00
Wayne Davison
6d56efa6ea Changed human_num() to big_num() with an extra arg so that it can
be used in place of all %.0f output idioms.
2008-07-17 07:37:31 -07:00
Wayne Davison
97dde6b620 A couple xattr fixes for --fake-super. 2008-07-14 23:48:33 -07:00
Wayne Davison
75d9697869 A few more minor improvements in the --info/--debug code. 2008-07-14 23:36:21 -07:00
Wayne Davison
f35798a57e Added a "test_fail" function to 00-hello.test. 2008-07-14 22:47:03 -07:00
Wayne Davison
b8993a1ee9 Made the info_verbosity array 1 element larger. 2008-07-14 07:40:10 -07:00
Wayne Davison
951e826b75 Added the --info=FLAGS an --debug=FLAGS options, which allows
fine-grained output control (in addition to the coarse -v).
2008-07-13 20:51:08 -07:00
Wayne Davison
d8d1389348 Fixed the timeout/flush loop-check logic to work properly with
incremental recursion.
2008-07-13 17:29:47 -07:00
Wayne Davison
2970362338 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-11 09:48:33 -07:00
Wayne Davison
7a2eca415b Added the --remote-option=OPT (-M OPT) option. 2008-07-05 08:31:16 -07:00
Wayne Davison
854411909b Got rid of some trailing whitespace. 2008-07-05 01:41:19 -07:00
Wayne Davison
bb4e4d889f The --progress output now leaves the cursor at the end of the line
(instead of the start) in order to be extra sure that an error won't
overwrite it.  We also ensure that the progress option can't be enabled
on the server side.
2008-07-05 00:31:46 -07:00
Wayne Davison
93f3fbf73e Prepare repository for more development. 2008-07-04 23:45:57 -07:00
Wayne Davison
d252e47d09 Improved the docs for various delete options. 2008-07-04 13:14:16 -07:00
161 changed files with 18159 additions and 8050 deletions

11
.gitignore vendored
View File

@@ -3,12 +3,16 @@
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
aclocal.m4
/proto.h
/proto.h-tstamp
/rsync.1
@@ -20,11 +24,15 @@ config.status
/getgroups
/gmon.out
/rsync
/rsync-ssl
/stunnel-rsync
/stunnel-rsyncd.conf
/shconfig
/testdir
/tests-dont-exist
/testtmp
/tls
/testrun
/trimslash
/t_unsafe
/wildtest
@@ -32,6 +40,9 @@ config.status
/rounding.h
/doc/rsync.pdf
/doc/rsync.ps
/support/savetransfer
/testsuite/chown-fake.test
/testsuite/devices-fake.test
/testsuite/xattrs-hlink.test
/patches
.deps

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

@@ -4,6 +4,7 @@
prefix=@prefix@
datarootdir=@datarootdir@
exec_prefix=@exec_prefix@
stunnel4=@STUNNEL4@
bindir=@bindir@
mandir=@mandir@
@@ -13,45 +14,48 @@ CFLAGS=@CFLAGS@
CPPFLAGS=@CPPFLAGS@
EXEEXT=@EXEEXT@
LDFLAGS=@LDFLAGS@
LIBOBJDIR=lib/
INSTALLCMD=@INSTALL@
INSTALLMAN=@INSTALL@
srcdir=@srcdir@
MKDIR_P=@MKDIR_P@
VPATH=$(srcdir)
SHELL=/bin/sh
VERSION=@VERSION@
VERSION=@RSYNC_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
GENFILES=configure.sh aclocal.m4 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 itypes.h inums.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@
ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
zlib_OBJS=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
util.o main.o checksum.o match.o syscall.o log.o backup.o
util.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.o
OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
OBJS3=progress.o pipe.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
# Programs we must have to run the test cases
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
testrun$(EXEEXT) trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test testsuite/xattrs-hlink.test
# Objects for CHECK_PROGS to clean
CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
CHECK_OBJS=tls.o testrun.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:
@@ -59,16 +63,30 @@ CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: conf_stop make_stop rsync$(EXEEXT) @MAKE_MAN@
all: Makefile rsync$(EXEEXT) rsync-ssl stunnel-rsync stunnel-rsyncd.conf @MAKE_MAN@
install: all
-mkdir -p ${DESTDIR}${bindir}
-${MKDIR_P} ${DESTDIR}${bindir}
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
-mkdir -p ${DESTDIR}${mandir}/man1
-mkdir -p ${DESTDIR}${mandir}/man5
-${MKDIR_P} ${DESTDIR}${mandir}/man1
-${MKDIR_P} ${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-ssl-client: rsync-ssl stunnel-rsync
-${MKDIR_P} ${DESTDIR}${bindir}
${INSTALLCMD} -m 755 rsync-ssl ${DESTDIR}${bindir}
${INSTALLCMD} -m 755 stunnel-rsync ${DESTDIR}${bindir}
install-ssl-daemon: stunnel-rsyncd.conf
-${MKDIR_P} ${DESTDIR}/etc/stunnel
${INSTALLCMD} -m 644 stunnel-rsyncd.conf ${DESTDIR}/etc/stunnel/rsyncd.conf
@if ! ls /etc/rsync-ssl/certs/server.* >/dev/null 2>/dev/null; then \
echo "Note that you'll need to install the certificate used by /etc/stunnel/rsyncd.conf"; \
fi
install-all: install install-ssl-client install-ssl-daemon
install-strip:
$(MAKE) INSTALL_STRIP='-s' install
@@ -101,6 +119,9 @@ rounding.h: rounding.c rsync.h
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
testrun$(EXEEXT): testrun.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ testrun.o
getgroups$(EXEEXT): getgroups.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getgroups.o $(LIBS)
@@ -111,49 +132,91 @@ 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 lib/wildmatch.o
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o util2.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: conf proto.h man
gensend: gen
rsync -aivzc $(GENFILES) samba.org:/home/ftp/pub/rsync/generated-files/
rsync -aivzc $(GENFILES) $${SAMBA_HOST-samba.org}:/home/ftp/pub/rsync/generated-files/
conf:
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
conf_stop: configure.sh config.h.in
aclocal.m4: m4/*.m4
aclocal -I $(srcdir)/m4
configure.sh config.h.in: configure.in aclocal.m4
configure.sh config.h.in: configure.ac aclocal.m4
@if test -f configure.sh; then cp -p configure.sh configure.sh.old; else touch configure.sh.old; fi
@if test -f config.h.in; then cp -p config.h.in config.h.in.old; else touch config.h.in.old; fi
autoconf -o configure.sh
autoheader && touch config.h.in
@echo 'Configure files changed -- perhaps run:'
@echo ' make reconfigure'
@exit 1
@if diff configure.sh configure.sh.old >/dev/null 2>&1; then \
echo "configure.sh is unchanged."; \
rm configure.sh.old; \
else \
echo "configure.sh has CHANGED."; \
fi
@if diff config.h.in config.h.in.old >/dev/null 2>&1; then \
echo "config.h.in is unchanged."; \
rm config.h.in.old; \
else \
echo "config.h.in has CHANGED."; \
fi
@if test -f configure.sh.old -o -f config.h.in.old; then \
if test "$(MAKECMDGOALS)" = reconfigure; then \
echo 'Continuing with "make reconfigure".'; \
else \
echo 'You may need to run:'; \
echo ' make reconfigure'; \
exit 1; \
fi \
fi
reconfigure: configure.sh
./config.status --recheck
./config.status
make_stop: Makefile
Makefile: Makefile.in config.status
Makefile: Makefile.in config.status configure.sh config.h.in
@if test -f Makefile; then cp -p Makefile Makefile.old; else touch Makefile.old; fi
@./config.status
@echo "Makefile updated -- rerun your make command."
@exit 1
@if diff Makefile Makefile.old >/dev/null 2>&1; then \
echo "Makefile is unchanged."; \
rm Makefile.old; \
else \
if test "$(MAKECMDGOALS)" = reconfigure; then \
echo 'Continuing with "make reconfigure".'; \
else \
echo "Makefile updated -- rerun your make command."; \
exit 1; \
fi \
fi
rsync-ssl: $(srcdir)/rsync-ssl.in Makefile
sed 's;\@bindir\@;$(bindir);g' <$(srcdir)/rsync-ssl.in >rsync-ssl
@chmod +x rsync-ssl
stunnel-rsync: $(srcdir)/stunnel-rsync.in Makefile
sed 's;\@stunnel4\@;$(stunnel4);g' <$(srcdir)/stunnel-rsync.in >stunnel-rsync
@chmod +x stunnel-rsync
stunnel-rsyncd.conf: $(srcdir)/stunnel-rsyncd.conf.in Makefile
sed 's;\@bindir\@;$(bindir);g' <$(srcdir)/stunnel-rsyncd.conf.in >stunnel-rsyncd.conf
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
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
man: rsync.1 rsyncd.conf.5 man-copy
man-copy:
@-if test -f rsync.1; then :; else echo 'Copying srcdir rsync.1'; cp -p $(srcdir)/rsync.1 .; fi
@-if test -f rsyncd.conf.5; then :; else echo 'Copying srcdir rsyncd.conf.5'; cp -p $(srcdir)/rsyncd.conf.5 .; fi
rsync.1: rsync.yo
yodl2man -o rsync.1 $(srcdir)/rsync.yo
@@ -165,7 +228,7 @@ rsyncd.conf.5: rsyncd.conf.yo
clean: cleantests
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h
rounding rounding.h *.old
cleantests:
rm -rf ./testtmp*
@@ -175,6 +238,7 @@ cleantests:
# the source directory.
distclean: clean
rm -f Makefile config.h config.status
rm -f rsync-ssl stunnel-rsync stunnel-rsyncd.conf
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
@@ -213,6 +277,9 @@ check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
check30: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=30
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)
@@ -223,6 +290,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.
@@ -237,21 +307,10 @@ installcheck: $(CHECK_PROGS) $(CHECK_SYMLINKS)
splint:
splint +unixlib +gnuextensions -weak rsync.c
rsync.dvi: doc/rsync.texinfo
texi2dvi -o $@ $<
rsync.ps: rsync.dvi
dvips -ta4 -o $@ $<
rsync.pdf: doc/rsync.texinfo
texi2dvi -o $@ --pdf $<
doxygen:
cd $(srcdir) && rm dox/html/* && doxygen
# for maintainers only
doxygen-upload:
rsync -avzv $(srcdir)/dox/html/ --delete \
samba.org:/home/httpd/html/rsync/doxygen/head/
$${SAMBA_HOST-samba.org}:/home/httpd/html/rsync/doxygen/head/

108
NEWS
View File

@@ -1,89 +1,37 @@
NEWS for rsync 3.0.3 (29 Jun 2008)
Protocol: 30 (unchanged)
Changes since 3.0.2:
NEWS for rsync 3.1.2 (UNRELEASED)
Protocol: 31 (unchanged)
Changes since 3.1.1:
SECURITY FIXES:
- Make sure that all transferred files use only path names from inside the
transfer. This makes it impossible for a malicious sender to try to make
the receiver use an unsafe destination path for a transferred file, such
as a just-sent symlink.
BUG FIXES:
- Fixed a wildcard matching problem in the daemon when a module has
"use chroot" enabled.
- Fixed a crash bug in the hard-link code.
- Fixed the sending of xattr directory information when the code finds a
--link-dest or --copy-dest directory with unchanged xattrs -- the
destination directory now gets these unchanged xattrs properly applied.
- Fixed an xattr-sending glitch that could cause an "Internal abbrev"
error.
- Fixed the combination of --xattrs and --backup.
- The generator no longer allows a '.' dir to be excluded by a daemon-
exclude rule.
- Fixed deletion handling when copying a single, empty directory (with no
files) to a differently named, non-existent directory.
- Fixed the conversion of spaces into dashes in the %M log escape.
- Fixed several places in the code that were not returning the right
errno when a function failed.
- Fixed the backing up of a device or special file into a backup dir.
- Moved the setting of the socket options prior to the connect().
- If rsync exits in the middle of a --progress output, it now outputs a
newline to help prevent the progress line from being overwritten.
- Fixed a problem with how a destination path with a trailing slash or
a trailing dot-dir was compared against the daemon excludes.
- Fixed the sending of large (size > 16GB) files when talking to an older
rsync (protocols < 30): we now use a compatible block size limit.
- If a file's length is so huge that we overflow a checksum buffer count
(i.e. several hundred TB), warn the user and avoid sending an invalid
checksum struct over the wire.
- If a source arg is excluded, --relative no longer adds the excluded
arg's implied dirs to the transfer. This fix also made the exclude
check happen in the better place in the sending code.
- Use the overflow_exit() function for overflows, not out_of_memory().
- Improved the code to better handle a system that has only 32-bit file
offsets.
- Change the checksum seed order in the per-block checksums. This prevents
someone from trying to create checksum blocks that match in sum but not
content.
- Fixed a with the per-dir filter files (using -FF) that could trigger an
assert failure.
- Only skip set_modtime() on a transferred file if the time is exactly
right.
- Don't create an empty backup dir for a transferred file that doesn't
exist yet.
ENHANCEMENTS:
- The rsyncd.conf manpage now consistently refers to the parameters in
the daemon config file as "parameters".
- The description of the --inplace option was improved.
EXTRAS:
- Added a new script in the support directory, deny-rsync, which allows
an admin to (temporarily) replace the rsync command with a script that
sends an error message to the remote client via the rsync protocol.
- Added "(DRY RUN)" info to the --debug=exit output line.
- Use usleep() for our msleep() function if it is available.
- Added a few extra long-option names to rrsync script, which will make
BackupPC happier.
- Misc. manpage tweaks.
DEVELOPER RELATED:
- Fixed a testcase failure if the tests are run as root and made some
compatibility improvements.
- Improved the daemon tests, including checking module comments, the
listing of files, and the ensuring that daemon excludes can't affect
a dot-dir arg.
- Improved some build rules for those that build in a separate directory
from the source, including better install rules for the man pages, and
the fixing of a proto.h-tstamp rule that could make the binaries get
rebuild without cause.
- Improved the testsuite to work around a problem with some utilities
(e.g. cp -p & touch -r) rounding sub-second timestamps.
- Ensure that the early patches don't cause any generated-file hunks to
bleed-over into patches that follow.
- Fixed a bug with the Makefile's use of INSTALL_STRIP.
- Improve a test in the suite that could get an erroneous timestamp error.
- Tweaks for newer versions of git in the packaging tools.
- Improved the m4 generation rules and some autoconf idioms.

914
OLDNEWS
View File

@@ -1,3 +1,903 @@
NEWS for rsync 3.1.1 (22 Jun 2014)
Protocol: 31 (unchanged)
Changes since 3.1.0:
BUG FIXES:
- If the receiver gets bogus filenames from the sender (an unexpected
leading slash or a ".." infix dir), exit with an error. This prevents a
malicious sender from trying to inject filenames that would affect an
area outside the destination directories.
- Fixed a failure to remove the partial-transfer temp file when interrupted
(and rsync is not saving the partial files).
- Changed the chown/group/xattr-set order to avoid losing some security-
related xattr info (that would get cleared by a chown).
- Fixed a bug in the xattr-finding code that could make a non-root-run
receiver not able to find some xattr numbers.
- Fixed a bug in the early daemon protocol where a timeout failed to be
honored (e.g. if the remote side fails to send us the initial protocol
greeting).
- Fixed unintended inclusion of commas in file numbers in the daemon log.
- We once again send the 'f' sub-flag (of -e) to the server side so it
knows that we can handle incremental-recursion directory errors properly
in older protocols.
- Fixed an issue with too-aggressive keep-alive messages causing a problem
for older rsync versions early in the transfer.
- Fixed an incorrect message about backup-directory-creation when using
--dry-run and the backup dir is not an absolute path.
- Fixed a bug where a failed deletion and/or a failed sender-side removal
would not affect the exit code.
- Fixed a bug that caused a failure when combining --delete-missing-args
with --xattrs and/or --acls.
- Fixed a strange dir_depth assertion error that was caused by empty-dir
removals and/or duplicate files in the transfer.
- Fixed a problem with --info=progress2's output stats where rsync would
only update the stats at the end of each file's transfer. It now uses
the data that is flowing for the current file, making the stats more
accurate and less jumpy.
- Fixed an itemize bug that affected the combo of --link-dest, -X, and -n.
- Fixed a problem with delete messages not appearing in the log file when
the user didn't use --verbose.
- Improve chunked xattr reading for OS X.
- Removed an attempted hard-link xattr optimization that was causing a
transfer failure. This removal is flagged in the compatibility code, so
if a better fix can be discovered, we have a way to flip it on again.
- Fixed a bug when the receiver is not configured to be able to hard link
symlimks/devices/special-file items but the sender sent some of these
items flagged as hard-linked.
- We now generate a better error if the buffer overflows in do_mknod().
- Fixed a problem reading more than 16 ACLs on some OSes.
- Fixed the reading of the secrets file to avoid an infinite wait when
the username is missing.
- Fixed a parsing problem in the --usermap/--groupmap options when using
MIN-MAX numbers.
- Switched Cygwin back to using socketpair "pipes" to try to speed it up.
- Added knowledge of a few new options to rrsync.
ENHANCEMENTS:
- Tweaked the temp-file naming when --temp-dir=DIR is used: the temp-file
names will not get a '.' prepended.
- Added support for a new-compression idiom that does not compress all the
matching data in a transfer. This can help rsync to use less cpu when a
transfer has a lot of matching data, and also makes rsync compatible with
a non-bundled zlib. See the --new-compress and --old-compress options in
the manpage.
- Added the support/rsync-no-vanished wrapper script.
- Made configure more prominently mention when we failed to find yodl (in
case the user wants to be able to generate manpages from *.yo files).
- Have manpage mention how a daemon's max-verbosity setting affects info
and debug options. Also added more clarification on backslash removals
for excludes that contain wildcards.
- Have configure check if for the attr lib (for getxattr) for those systems
that need to link against it explicitly.
- Change the early dir-creation logic to only use that idiom in an
inc-recursive copy that is preserving directory times. e.g. using
--omit-dir-times will avoid these early directories being created.
- Fix a bug in cmp_time() that would return a wrong result if the 2 times
differed by an amount greater than what a time_t can hold.
DEVELOPER RELATED:
- We now include an example systemd file (in packaging/systemd).
- Tweaked configure to make sure that any intended use of the included popt
and/or zlib code is put early in the CFLAGS.
NEWS for rsync 3.1.0 (28 Sep 2013)
Protocol: 31 (changed)
Changes since 3.0.9:
OUTPUT CHANGES:
- Output numbers in 3-digit groups by default (e.g. 1,234,567). See the
--human-readable option for a way to turn it off. See also the daemon's
"log format" parameter and related command-line options (including
--out-format) for a modifier that can be used to request digit-grouping
or human-readable output in log escapes. (Note that log output is
unchanged by default.)
- The --list-only option is now affected by the --human-readable setting.
It will display digit groupings by default, and unit suffixes if higher
levels of readability are requested. Also, the column width for the size
output has increased from 11 to 14 characters when human readability is
enabled. Use --no-h to get the old-style output and column size.
- The output of the --progress option has changed: the string "xfer" was
shortened to "xfr", and the string "to-check" was shortened to "to-chk",
both designed to make room for the (by default) wider display of file
size numbers without making the total line-length longer. Also, when
incremental recursion is enabled, the string "ir-chk" will be used
instead of "to-chk" up until the incremental-recursion scan is done,
letting you know that the value to check and the total value will still
be increasing as new files are found.
- Enhanced the --stats output: 1) to mention how many files were created
(protocol >= 28), 2) to mention how many files were deleted (a new line
for protocol 31, but only output when --delete is in effect), and 3) to
follow the file-count, created-count, and deleted-count with a subcount
list that shows the counts by type. The wording of the transferred count
has also changed so that it is clearer that it is only a count of regular
files.
BUG FIXES:
- Fixed a bug in the iconv code when EINVAL or EILSEQ is returned with a
full output buffer.
- Fixed some rare bugs in --iconv processing that might cause a multibyte
character to get translated incorrectly.
- Fixed a bogus "vanished file" error if some files were specified with
"./" prefixes and others were not.
- Fixed a bug in --sparse where an extra gap could get inserted after a
partial write.
- Changed the way --progress overwrites its prior output in order to make
it nearly impossible for the progress to get overwritten by an error.
- Improved the propagation of abnormal-exit error messages. This should
help the client side to receive errors from the server when it is exiting
abnormally, and should also avoid dying with an "connection unexpectedly
closed" exit when the closed connection is really expected.
- The sender now checks each file it plans to remove to ensure that it
hasn't changed from the first stat's info. This helps to avoid losing
file data when the user is not using the option in a safe manner.
- Fixed a data-duplication bug in the compress option that made compression
less efficient. This improves protocol 31 onward, while behaving in a
compatible (buggy) manner with older rsync protocols.
- When creating a temp-file, rsync is now a bit smarter about it dot-char
choices, which can fix a problem on OS X with names that start with "..".
- Rsync now sets a cleanup flag for --inplace and --append transfers that
will flush the write buffer if the transfer aborts. This ensures that
more received data gets written out to the disk on an aborted transfer
(which is quite helpful on a slow, flaky connection).
- The reads that map_ptr() now does are aligned on 1K boundaries. This
helps some filesystems and/or files that don't like unaligned reads.
- Fix an issue in the msleep() function if time jumps backwards.
- Fix daemon-server module-name splitting bug where an arg would get split
even if --protect-args was used.
ENHANCEMENTS:
- Added the --remote-option=OPT (-M OPT) command-line option that is useful
for things like sending a remote --log-file=FILE or --fake-super option.
- Added the --info=FLAGS and --debug=FLAGS options to allow finer-grained
control over what is output. Added an extra type of --progress output
using --info=progress2.
- The --msgs2stderr option can help with debugging rsync by allowing the
debug messages to get output to stderr rather than travel via the socket
protocol.
- Added the --delete-missing-args and --ignore-missing-args options to
either delete or ignore user-specified files on the receiver that are
missing on the sender (normally the absence of user-specified files
generates an error).
- Added a "T" (terabyte) category to the --human-readable size suffixes.
- Added the --usermap/--groupmap/--chown options for manipulating file
ownership during the copy.
- Added the "%C" escape to the log-output handling, which will output the
MD5 checksum of any transferred file, or all files if --checksum was
specified (when protocol 30 or above is in effect).
- Added the "reverse lookup" parameter to the rsync daemon config file to
allow reverse-DNS lookups to be disabled.
- Added a forward-DNS lookup for the daemon's hosts allow/deny config. Can
be disabled via "forward lookup" parameter (defaults to enabled).
- Added a way for more than one group to be specified in the daemon's
config file, including a way to specify that you want all of the
specified user's groups without having to name them. Also changed the
daemon to complain about an inability to set explicitly-specified uid/gid
values, even when not run by a super-user.
- The daemon now tries to send the user the error messages from the
pre-xfer exec script when it fails.
- Improved the use of alt-dest options into an existing hierarchy of files:
If a match is found in an alt-dir, it takes precedence over an existing
file. (We'll need to wait for a future version before attribute-changes
on otherwise unchanged files are safe when using an existing hierarchy.)
- Added per-user authorization options and group-authorization support to
the daemon's "auth users" parameter.
- Added a way to reference environment variables in a daemon's config file
(using %VAR% references).
- When replacing a non-dir with a symlink/hard-link/device/special-file,
the update should now be done in an atomic manner.
- Avoid re-sending xattr info for hard-linked files w/the same xattrs
(protocol 31).
- The backup code was improved to use better logic maintaining the backup
directory hierarchy. Also, when a file is being backed up, rsync tries
to hard-link it into place so that the upcoming replacement of the
destination file will be atomic (for the normal, non-inplace logic).
- Added the ability to synchronize nano-second modified times.
- Added a few more default suffixes for the "dont compress" settings.
- Added the checking of the RSYNC_PROTECT_ARGS environment variable to allow
the default for the --protect-args command-line option to be overridden.
- Added the --preallocate command-line option.
- Allow --password-file=- to read the password from stdin (filename "-").
- Rsync now comes packaged with an rsync-ssl helper script that can be
used to contact a remote rsync daemon using a piped-stunnel command.
It also includes an stunnel config file to run the server side to
support ssl daemon connections. See the packaging/lsb/rsync.spec
file for one way to package the resulting files. (Suggestions for
how to make this even easier to install & use are welcomed.)
- Improved the speed of some --inplace updates when there are lots of
identical checksum blocks that end up being unusable.
- Added the --outbuf=N|L|B option for choosing the output buffering.
- Repeating the --fuzzy option now causes the code to look for fuzzy
matches inside alt-dest directories too.
- The --chmod option now supports numeric modes, e.g. --chmod=644,D755
- Added some Solaris xattr code.
- Made an rsync daemon (the listening process) exit with a 0 status when
it was signaled to die. This helps launchd.
- Improved the RSYNC_* environment variables for the pre-xfer exec script:
when a daemon is sent multiple request args, they are now joined into a
single return value (separated by spaces) so that the RSYNC_REQUEST
environment variable is accurate for any "pre-xfer exec". The values in
RSYNC_ARG# vars are no longer truncated at the "." arg (prior to the
request dirs/files), so that all the requested values are also listed
(separately) in RSYNC_ARG# variables.
EXTRAS:
- Added an "instant-rsyncd" script to the support directory, which makes
it easy to configure a simple rsync daemon in the current directory.
- Added the "mapfrom" and "mapto" scripts to the support directory, which
makes it easier to do user/group mapping in a local transfer based on
passwd/group files from another machine.
- There's a new, improved version of the lsh script in the support dir:
it's written in perl and supports -u without resorting to using sudo
(when run as root). The old shell version is now named lsh.sh.
- There is a helper script named rsync-slash-strip in the support directory
for anyone that wants to change the way rsync handles args with trailing
slashes. (e.g. arg/ would get stripped to arg while arg/. would turn into
arg/).
INTERNAL:
- The I/O code was rewritten to be simpler and do bigger buffered reads
over the socket. The I/O between the receiver and the generator was
changed to be standard multiplexed-I/O (like that over the socket).
- The sender tries to use any dead time while the generator is looking for
files to transfer in order to do sender-side directory scanning in a more
parallel manner.
- A daemon can now inform a client about a daemon-configured timeout value
so that the client can assist in the keep-alive activity (protocol 31).
- The filter code received some refactoring to make it more extendible, to
read better, and do better sanity checking.
- Really big numbers are now output using our own big-num routine rather
than casting them to a double and using a %.0f conversion.
- The pool_alloc library has received some minor improvements in alignment
handling.
- Added init_stat_x() function to avoid duplication of acl/xattr init code.
- The included zlib was upgraded from 1.2.3 to 1.2.8.
- Rsync can now be compiled to use an unmodified zlib library instead of
the tweaked one that is included with rsync. This will eventually
become the default, at which point we'll start the countdown to removing
the included zlib. Until then, feel free to configure using:
./configure --with-included-zlib=no
DEVELOPER RELATED:
- Added more conditional debug output.
- Fixed some build issues for android and minix.
NEWS for rsync 3.0.9 (23 Sep 2011)
Protocol: 30 (unchanged)
Changes since 3.0.8:
BUG FIXES:
- Fix a crash bug in checksum scanning when --inplace is used.
- Fix a hang if a hard-linked file cannot be opened by the sender (e.g.
if it has no read permission).
- Fix preservation of a symlink's system xattrs (e.g. selinux) on Linux.
- Fix a memory leak in the xattr code.
- Fixed a bug with --delete-excluded when a filter merge file has a rule
that specifies a receiver-only side restriction.
- Fix a bug with the modifying of unwritable directories.
- Fix --fake-super's interaction with --link-dest same-file comparisons.
- Fix the updating of the curr_dir buffer to avoid a duplicate slash.
- Fix the directory permissions on an implied dot-dir when using --relative
(e.g. /outside/path/././send/path).
- Fixed some too-long sleeping instances when using --bwlimit.
- Fixed when symlink ownership difference-checking gets compiled into
unchanged_attrs().
- Improved the socket-error reporting when multiple protocols fail.
- Fixed a case where a socket error could reference just-freed memory.
- Failing to use a password file that was specified on the command-line is
now a fatal error.
- Fix the non-root updating of directories that don't have the read and/or
execute permission.
- Make daemon-excluded file errors more error-like.
- Fix a compilation issue on older C compilers (due to a misplaced var
declaration).
- Make configure avoid finding socketpair on cygwin.
- Avoid trying to reference SO_BROADCAST if the OS doesn't support it.
- Fix some issues with the post-processing of the man pages.
- Fixed the user home-dir handling in the support/lsh script.
- Some minor manpage improvements.
NEWS for rsync 3.0.8 (26 Mar 2011)
Protocol: 30 (unchanged)
Changes since 3.0.7:
BUG FIXES:
- Fixed two buffer-overflow issues: one where a directory path that is
exactly MAXPATHLEN was not handled correctly, and one handling a
--backup-dir that is extra extra large.
- Fixed a data-corruption issue when preserving hard-links without
preserving file ownership, and doing deletions either before or during
the transfer (CVE-2011-1097). This fixes some assert errors in the
hard-linking code, and some potential failed checksums (via -c) that
should have matched.
- Fixed a potential crash when an rsync daemon has a filter/exclude list
and the transfer is using ACLs or xattrs.
- Fixed a hang if a really large file is being processed by an rsync that
can't handle 64-bit numbers. Rsync will now complain about the file
being too big and skip it.
- For devices and special files, we now avoid gathering useless ACL and/or
xattr information for files that aren't being copied. (The un-copied
files are still put into the file list, but there's no need to gather
data that is not going to be used.) This ensures that if the user uses
--no-D, that rsync can't possibly complain about being unable to gather
extended information from special files that are in the file list (but
not in the transfer).
- Properly handle requesting remote filenames that start with a dash. This
avoids a potential error where a filename could be interpreted as a
(usually invalid) option.
- Fixed a bug in the comparing of upper-case letters in file suffixes for
--skip-compress.
- If an rsync daemon has a module configured without a path setting, rsync
will now disallow access to that module.
- If the destination arg is an empty string, it will be treated as a
reference to the current directory (as 2.x used to do).
- If rsync was compiled with a newer time-setting function (such as
lutimes), rsync will fall-back to an older function (such as utimes) on a
system where the newer function is not around. This helps to make the
rsync binary more portable in mixed-OS-release situations.
- Fixed a batch-file writing bug that would not write out the full set of
compatibility flags that the transfer was using. This fixes a potential
protocol problem for a batch file that contains a sender-side I/O error:
it would have been sent in a way that the batch-reader wasn't expecting.
- Some improvements to the hard-linking code to ensure that device-number
hashing is working right, and to supply more information if the hard-link
code fails.
- The --inplace code was improved to not search for an impossible checksum
position. The quadruple-verbose chunk[N] message will now mention when
an inplace chunk was handled by a seek rather than a read+write.
- Improved ACL mask handling, e.g. for Solaris.
- Fixed a bug that prevented --numeric-ids from disabling the translation
of user/group IDs for ACLs.
- Fixed an issue where an xattr and/or ACL transfer that used an alt-dest
option (e.g. --link-dest) could output an error trying to itemize the
changes against the alt-dest directory's xattr/ACL info but was instead
trying to access the not-yet-existing new destination directory.
- Improved xattr system-error messages to mention the full path to the
file.
- The --link-dest checking for identical symlinks now avoids considering
attribute differences that cannot be changed on the receiver.
- Avoid trying to read/write xattrs on certain file types for certain OSes.
Improved configure to set NO_SYMLINK_XATTRS, NO_DEVICE_XATTRS, and/or
NO_SPECIAL_XATTRS defines in config.h.
- Improved the unsafe-symlink errors messages.
- Fixed a bug setting xattrs on new files that aren't user writable.
- Avoid re-setting xattrs on a hard-linked file w/the same xattrs.
- Fixed a bug with --fake-super when copying files and dirs that aren't
user writable.
- Fixed a bug where a sparse file could have its last sparse block turned
into a real block when rsync sets the file size (requires ftruncate).
- If a temp-file name is too long, rsync now avoids truncating the name in
the middle of adjacent high-bit characters. This prevents a potential
filename error if the filesystem doesn't allow a name to contain an
invalid multi-byte sequence.
- If a muli-protocol socket connection fails (i.e., when contacting a
daemon), we now report all the failures, not just the last one. This
avoids losing a relevant error (e.g. an IPv4 connection-refused error)
that happened before the final error (e.g. an IPv6 protocol-not-supported
error).
- Generate a transfer error if we try to call chown with a -1 for a uid or
a gid (which is not settable).
- Fixed the working of --force when used with --one-file-system.
- Fix the popt arg parsing so that an option that doesn't take an arg will
reject an attempt to supply one (can configure --with-included-popt if
your system's popt library doesn't yet have this fix).
- A couple minor option tweaks to the support/rrsync script, and also some
regex changes that make vim highlighting happier.
- Fixed some issues in the support/mnt-excl script.
- Various manpage improvements.
ENHANCEMENTS:
- Added ".hg/" to the default cvs excludes (see -C & --cvs-exclude).
DEVELOPER RELATED:
- Use lchmod() whenever it is available (not just on symlinks).
- A couple fixes to the socketpair_tcp() routine.
- Updated the helper scripts in the packaging subdirectory.
- Renamed configure.in to configure.ac.
- Fixed configure's checking for iconv routines for newer OS X versions.
- Fixed the testsuite/xattrs.test script on OS X.
NEWS for rsync 3.0.7 (31 Dec 2009)
Protocol: 30 (unchanged)
Changes since 3.0.6:
BUG FIXES:
- Fixed a bogus free when using --xattrs with --backup.
- Avoid an error when --dry-run was trying to stat a prior hard-link file
that hasn't really been created.
- Fixed a problem with --compress (-z) where the receiving side could
return the error "inflate (token) returned -5".
- Fixed a bug where --delete-during could delete in a directory before it
noticed that the sending side sent an I/O error for that directory (both
sides of the transfer must be at least 3.0.7).
- Improved --skip-compress's error handling of bad character-sets and got
rid of a lingering debug fprintf().
- Fixed the daemon's conveyance of io_error value from the sender.
- An rsync daemon use seteuid() (when available) if it used setuid().
- Get the permissions right on a --fake-super transferred directory that
needs more owner permissions to emulate root behavior.
- An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
its modifier when sending the filter rules to the remote rsync.
- Improved the "--delete does not work without -r or -d" message.
- Improved rsync's handling of --timeout to avoid a weird timeout case
where the sender could timeout even though it has recently written data
to the socket (but hasn't read data recently, due to the writing).
- Some misc manpage improvements.
- Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
- Make sure that a timeout specified in the daemon's config is used as a
maximum timeout value when the user also specifies a timeout.
- Improved the error-exit reporting when rsync gets an error trying to
cleanup after an error: the initial error is reported.
- Improved configure's detection of IPv6 for solaris and cygwin.
- The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
- Made our (only used if missing) getaddrinfo() routine use inet_pton()
(which we also provide) instead of inet_aton().
- The exit-related debug messages now mention the program's role so it is
clear who output what message.
DEVELOPER RELATED:
- Got rid of type-punned compiler warnings output by newer gcc versions.
- The Makefile now ensures that proto.h will be rebuilt if config.h changes.
- The testsuite no longer uses "id -u", so it works better on solaris.
NEWS for rsync 3.0.6 (8 May 2009)
Protocol: 30 (unchanged)
Changes since 3.0.5:
BUG FIXES:
- Fixed a --read-batch hang when rsync is reading a batch file that was
created from an incremental-recursion transfer.
- Fixed the daemon's socket code to handle the simultaneous arrival of
multiple connections.
- Fix --safe-links/--copy-unsafe-links to properly handle symlinks that
have consecutive slashes in the value.
- Fixed the parsing of an [IPv6_LITERAL_ADDR] when a USER@ is prefixed.
- The sender now skips a (bogus) symlink that has a 0-length value, which
avoids a transfer error in the receiver.
- Fixed a case where the sender could die with a tag-0 error if there was
an I/O during the sending of the file list.
- Fixed the rrsync script to avoid a server-side problem when -e is at the
start of the short options.
- Fixed a problem where a vanished directory could turn into an exit code
23 instead of the proper exit code 24.
- Fixed the --iconv conversion of symlinks when doing a local copy.
- Fixed a problem where --one-file-system was not stopping deletions on the
receiving side when a mount-point directory did not match a directory in
the transfer.
- Fixed the dropping of an ACL mask when no named ACL values were present.
- Fixed an ACL/xattr corruption issue where the --backup option could cause
rsync to associate the wrong ACL/xattr information with received files.
- Fixed the use of --xattrs with --only-write-batch.
- Fixed the use of --dry-run with --read-batch.
- Fixed configure's erroneous use of target.
- Fixed configure's --disable-debug option.
- Fixed a run-time issue for systems that can't find iconv_open() by adding
the --disable-iconv-open configure option.
- Complain and die if the user tries to combine --remove-source-files (or
the deprecated --remove-sent-files) with --read-batch.
- Fixed an failure transferring special files from Solaris to Linux.
NEWS for rsync 3.0.5 (28 Dec 2008)
Protocol: 30 (unchanged)
Changes since 3.0.4:
BUG FIXES:
- Initialize xattr data in a couple spots in the hlink code, which avoids a
crash when the xattr pointer's memory happens to start out non-zero.
Also fixed the itemizing of an alt-dest file's xattrs when hard-linking.
- Don't send a bogus "-" option to an older server if there were no short
options specified.
- Fixed skipping of unneeded updates in a batch file when incremental
recursion is active. Added a test for this. Made batch-mode handle
"redo" files properly (and without hanging).
- Fix the %P logfile escape when the daemon logs from inside a chroot.
- Fixed the use of -s (--protect-args) when used with a remote source or
destination that had an empty path (e.g. "host:"). Also fixed a problem
when -s was used when accessing a daemon via a remote-shell.
- Fixed the use of a dot-dir path (e.g. foo/./bar) inside a --files-from
file when the root of the transfer isn't the current directory.
- Fixed a bug with "-K --delete" removing symlinks to directories when
incremental recursion is active.
- Fixed a hard to trigger hang when using --remove-source-files.
- Got rid of an annoying delay when accessing a daemon via a remote-shell.
- Properly ignore (superfluous) source args on a --read-batch command.
- Improved the manpage's description of the '*' wildcard to remove the
confusing "non-empty" qualifier.
- Fixed reverse lookups in the compatibility-library version of
getnameinfo().
- Fixed a bug when using --sparse on a sparse file that has over 2GB of
consecutive sparse data.
- Avoid a hang when using at least 3 --verbose options on a transfer with a
client sender (which includes local copying).
- Fixed a problem with --delete-delay reporting an error when it was ready
to remove a directory that was now gone.
- Got rid of a bunch of "warn_unused_result" compiler warnings.
- If an ftruncate() on a received file fails, it now causes a partial-
transfer warning.
- Allow a path with a leading "//" to be preserved (CYGWIN only).
ENHANCEMENTS:
- Made the support/atomic-rsync script able to perform a fully atomic
update of the copied hierarchy when the destination is setup using a
particular symlink idiom.
NEWS for rsync 3.0.4 (6 Sep 2008)
Protocol: 30 (unchanged)
Changes since 3.0.3:
BUG FIXES:
- Fixed a bug in the hard-linking code where it would sometimes try to
allocate 0 bytes of memory (which fails on some OSes, such as AIX).
- Fixed the hard-linking of files from a device that has a device number
of 0 (which seems to be a common device number on NetBSD).
- Fixed the handling of a --partial-dir that cannot be created. This
particularly impacts the --delay-updates option (since the files cannot
be delayed without a partial-dir), and was potentially destructive if
the --remove-source-files was also specified.
- Fixed a couple issues in the --fake-super handling of xattrs when the
destination files have root-level attributes (e.g. selinux values) that
a non-root copy can't affect.
- Improved the keep-alive check in the generator to fire consistently in
incremental-recursion mode when --timeout is enabled.
- The --iconv option now converts the content of a symlink too, instead
of leaving it in the wrong character-set (requires 3.0.4 on both sides
of the transfer).
- When using --iconv, if a filename fails to convert on the receiving side,
this no longer makes deletions in the root-dir of the transfer fail
silently (the user now gets a warning about deletions being disabled
due to IO error as long as --ignore-errors was not specified).
- When using --iconv, if a server-side receiver can't convert a filename,
the error message sent back to the client no longer mangles the name
with the wrong charset conversion.
- Fixed a potential alignment issue in the IRIX ACL code when allocating
the initial "struct acl" object. Also, cast mallocs to avoid warnings.
- Changed some errors that were going to stdout to go to stderr.
- Made human_num() and human_dnum() able to output a negative number
(rather than outputting a cryptic string of punctuation).
ENHANCEMENTS:
- Rsync will avoid sending an -e option to the server if an older protocol
is requested (and thus the option would not be useful). This lets the
user specify the --protocol=29 option to access an overly-restrictive
server that is rejecting the protocol-30 use of -e to the server.
- Improved the message output for an RERR_PARTIAL exit.
DEVELOPER RELATED:
- The Makefile will not halt for just a timestamp change on the Makefile
or the configure files, only for actual changes in content.
- Changed some commands in the testsuite's xattrs.test that called "rsync"
instead of "$RSYNC".
- Enhanced the release scripts to be able to handle a branch release and
to do even more consistency checks on the files.
NEWS for rsync 3.0.3 (29 Jun 2008)
Protocol: 30 (unchanged)
Changes since 3.0.2:
BUG FIXES:
- Fixed a wildcard matching problem in the daemon when a module has
"use chroot" enabled.
- Fixed a crash bug in the hard-link code.
- Fixed the sending of xattr directory information when the code finds a
--link-dest or --copy-dest directory with unchanged xattrs -- the
destination directory now gets these unchanged xattrs properly applied.
- Fixed an xattr-sending glitch that could cause an "Internal abbrev"
error.
- Fixed the combination of --xattrs and --backup.
- The generator no longer allows a '.' dir to be excluded by a daemon-
exclude rule.
- Fixed deletion handling when copying a single, empty directory (with no
files) to a differently named, non-existent directory.
- Fixed the conversion of spaces into dashes in the %M log escape.
- Fixed several places in the code that were not returning the right
errno when a function failed.
- Fixed the backing up of a device or special file into a backup dir.
- Moved the setting of the socket options prior to the connect().
- If rsync exits in the middle of a --progress output, it now outputs a
newline to help prevent the progress line from being overwritten.
- Fixed a problem with how a destination path with a trailing slash or
a trailing dot-dir was compared against the daemon excludes.
- Fixed the sending of large (size > 16GB) files when talking to an older
rsync (protocols < 30): we now use a compatible block size limit.
- If a file's length is so huge that we overflow a checksum buffer count
(i.e. several hundred TB), warn the user and avoid sending an invalid
checksum struct over the wire.
- If a source arg is excluded, --relative no longer adds the excluded
arg's implied dirs to the transfer. This fix also made the exclude
check happen in the better place in the sending code.
- Use the overflow_exit() function for overflows, not out_of_memory().
- Improved the code to better handle a system that has only 32-bit file
offsets.
ENHANCEMENTS:
- The rsyncd.conf manpage now consistently refers to the parameters in
the daemon config file as "parameters".
- The description of the --inplace option was improved.
EXTRAS:
- Added a new script in the support directory, deny-rsync, which allows
an admin to (temporarily) replace the rsync command with a script that
sends an error message to the remote client via the rsync protocol.
DEVELOPER RELATED:
- Fixed a testcase failure if the tests are run as root and made some
compatibility improvements.
- Improved the daemon tests, including checking module comments, the
listing of files, and the ensuring that daemon excludes can't affect
a dot-dir arg.
- Improved some build rules for those that build in a separate directory
from the source, including better install rules for the man pages, and
the fixing of a proto.h-tstamp rule that could make the binaries get
rebuild without cause.
- Improved the testsuite to work around a problem with some utilities
(e.g. cp -p & touch -r) rounding sub-second timestamps.
- Ensure that the early patches don't cause any generated-file hunks to
bleed-over into patches that follow.
NEWS for rsync 3.0.2 (8 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.1:
@@ -290,6 +1190,11 @@ Changes since 2.6.9:
- Fixed rsync's ability to remove files that are not writable by the file's
owner when rsync is running as the same user.
- When transferring large files, the sender's hashtable of checksums is
kept at a more reasonable state of fullness (no more than 80% full) so
that the scanning of the hashtable will not bog down as the number of
blocks increases.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
@@ -2745,6 +3650,15 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? Aug 2015 3.1.2 31
22 Jun 2014 3.1.1 31
28 Sep 2013 3.1.0 31 Aug 2008 31
23 Sep 2011 3.0.9 30
26 Mar 2011 3.0.8 30
31 Dec 2009 3.0.7 30
08 May 2009 3.0.6 30
28 Dec 2008 3.0.5 30
06 Sep 2008 3.0.4 30
29 Jun 2008 3.0.3 30
08 Apr 2008 3.0.2 30
03 Apr 2008 3.0.1 30

View File

@@ -2,7 +2,7 @@
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2004-2008 Wayne Davison
* Copyright (C) 2004-2015 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
@@ -20,14 +20,50 @@
#include "rsync.h"
static int match_hostname(char *host, char *tok)
static int allow_forward_dns;
extern const char undetermined_hostname[];
static int match_hostname(const char **host_ptr, const char *addr, const char *tok)
{
struct hostent *hp;
unsigned int i;
const char *host = *host_ptr;
if (!host || !*host)
return 0;
return wildmatch(tok, host);
/* First check if the reverse-DNS-determined hostname matches. */
if (iwildmatch(tok, host))
return 1;
if (!allow_forward_dns)
return 0;
/* Fail quietly if tok is an address or wildcarded entry, not a simple hostname. */
if (!tok[strspn(tok, ".0123456789")] || tok[strcspn(tok, ":/*?[")])
return 0;
/* Now try forward-DNS on the token (config-specified hostname) and see if the IP matches. */
if (!(hp = gethostbyname(tok)))
return 0;
for (i = 0; hp->h_addr_list[i] != NULL; i++) {
if (strcmp(addr, inet_ntoa(*(struct in_addr*)(hp->h_addr_list[i]))) == 0) {
/* If reverse lookups are off, we'll use the conf-specified
* hostname in preference to UNDETERMINED. */
if (host == undetermined_hostname) {
if (!(*host_ptr = strdup(tok)))
*host_ptr = undetermined_hostname;
}
return 1;
}
}
return 0;
}
static int match_binary(char *b1, char *b2, char *mask, int addrlen)
static int match_binary(const char *b1, const char *b2, const char *mask, int addrlen)
{
int i;
@@ -56,7 +92,7 @@ static void make_mask(char *mask, int plen, int addrlen)
return;
}
static int match_address(char *addr, char *tok)
static int match_address(const char *addr, const char *tok)
{
char *p;
struct addrinfo hints, *resa, *rest;
@@ -70,24 +106,16 @@ static int match_address(char *addr, char *tok)
#endif
char mask[16];
char *a = NULL, *t = NULL;
unsigned int len;
if (!addr || !*addr)
return 0;
p = strchr(tok,'/');
if (p) {
if (p)
*p = '\0';
len = p - tok;
} else
len = strlen(tok);
/* Fail quietly if tok is a hostname (not an address) */
if (strspn(tok, ".0123456789") != len
#ifdef INET6
&& strchr(tok, ':') == NULL
#endif
) {
/* Fail quietly if tok is a hostname, not an address. */
if (tok[strspn(tok, ".0123456789")] && strchr(tok, ':') == NULL) {
if (p)
*p = '/';
return 0;
@@ -210,7 +238,7 @@ static int match_address(char *addr, char *tok)
return ret;
}
static int access_match(char *list, char *addr, char *host)
static int access_match(const char *list, const char *addr, const char **host_ptr)
{
char *tok;
char *list2 = strdup(list);
@@ -219,11 +247,9 @@ static int access_match(char *list, char *addr, char *host)
out_of_memory("access_match");
strlower(list2);
if (host)
strlower(host);
for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
if (match_hostname(host, tok) || match_address(addr, tok)) {
if (match_hostname(host_ptr, addr, tok) || match_address(addr, tok)) {
free(list2);
return 1;
}
@@ -233,16 +259,21 @@ static int access_match(char *list, char *addr, char *host)
return 0;
}
int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
int allow_access(const char *addr, const char **host_ptr, int i)
{
const char *allow_list = lp_hosts_allow(i);
const char *deny_list = lp_hosts_deny(i);
if (allow_list && !*allow_list)
allow_list = NULL;
if (deny_list && !*deny_list)
deny_list = NULL;
allow_forward_dns = lp_forward_lookup(i);
/* If we match an allow-list item, we always allow access. */
if (allow_list) {
if (access_match(allow_list, addr, host))
if (access_match(allow_list, addr, host_ptr))
return 1;
/* For an allow-list w/o a deny-list, disallow non-matches. */
if (!deny_list)
@@ -251,7 +282,7 @@ int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
/* If we match a deny-list item (and got past any allow-list
* items), we always disallow access. */
if (deny_list && access_match(deny_list, addr, host))
if (deny_list && access_match(deny_list, addr, host_ptr))
return 0;
/* Allow all other access. */

205
acls.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2006-2008 Wayne Davison
* Copyright (C) 2006-2015 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,6 +90,9 @@ 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)
@@ -112,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
@@ -129,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;
}
@@ -336,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;
}
@@ -420,7 +423,7 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
#ifdef ACLS_NEED_MASK
mask_bits = racl->mask_obj == NO_ENTRY ? racl->group_obj & ~NO_ENTRY : racl->mask_obj;
COE( sys_acl_create_entry,(smb_acl, &entry) );
COE( sys_acl_set_info,(entry, SMB_ACL_MASK, mask_bits, NULL) );
COE( sys_acl_set_info,(entry, SMB_ACL_MASK, mask_bits, 0) );
#else
if (racl->mask_obj != NO_ENTRY) {
COE( sys_acl_create_entry,(smb_acl, &entry) );
@@ -492,9 +495,15 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
}
racl->user_obj = IVAL(buf, 0);
if (racl->user_obj == NO_ENTRY)
racl->user_obj = (mode >> 6) & 7;
racl->group_obj = IVAL(buf, 4);
if (racl->group_obj == NO_ENTRY)
racl->group_obj = (mode >> 3) & 7;
racl->mask_obj = IVAL(buf, 8);
racl->other_obj = IVAL(buf, 12);
if (racl->other_obj == NO_ENTRY)
racl->other_obj = mode & 7;
if (cnt) {
char *bp = buf + 4*4;
@@ -536,6 +545,24 @@ 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;
} else if (IS_MISSING_FILE(sxp->st))
return 0;
if (get_rsync_acl(fname, sxp->acc_acl, SMB_ACL_TYPE_ACCESS,
sxp->st.st_mode) < 0) {
free_acl(sxp);
@@ -557,7 +584,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;
@@ -569,9 +596,9 @@ static void send_ida_entries(const ida_entries *idal, int f)
const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
name = add_uid(ida->id);
name = numeric_ids ? NULL : add_uid(ida->id);
} else
name = add_gid(ida->id);
name = numeric_ids ? NULL : add_gid(ida->id);
write_varint(f, ida->id);
if (inc_recurse && name) {
int len = strlen(name);
@@ -583,8 +610,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);
@@ -617,7 +644,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;
@@ -627,28 +654,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);
@@ -673,7 +700,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);
@@ -689,7 +716,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)
@@ -712,7 +739,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;
@@ -727,7 +754,7 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
if (ndx != 0)
return ndx - 1;
ndx = racl_list->count;
duo_item = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
duo_item->racl = empty_rsync_acl;
@@ -735,29 +762,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;
@@ -766,12 +792,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)
@@ -794,17 +820,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)
{
@@ -850,12 +909,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) );
@@ -868,7 +929,7 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
errfun);
}
return (mode_t)~0;
return (mode_t)-1;
}
#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
@@ -937,7 +998,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
if (type == SMB_ACL_TYPE_ACCESS) {
cur_mode = change_sacl_perms(duo_item->sacl, &duo_item->racl,
cur_mode, mode);
if (cur_mode == (mode_t)~0)
if (cur_mode == (mode_t)-1)
return 0;
}
#endif
@@ -953,17 +1014,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;
@@ -977,18 +1038,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) {
@@ -996,16 +1057,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.
@@ -1048,6 +1108,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
@@ -1081,7 +1144,7 @@ int default_perms_for_dir(const char *dir)
/* Apply the permission-bit entries of the default ACL, if any. */
if (racl.user_obj != NO_ENTRY) {
perms = rsync_acl_get_perms(&racl);
if (verbose > 2)
if (DEBUG_GTE(ACL, 1))
rprintf(FINFO, "got ACL-based default perms %o for directory %s\n", perms, dir);
}

View File

@@ -2,7 +2,7 @@
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2002-2008 Wayne Davison
* Copyright (C) 2002-2015 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,7 +19,9 @@
*/
#include "rsync.h"
#include "itypes.h"
extern int read_only;
extern char *password_file;
/***************************************************************************
@@ -76,129 +78,6 @@ static void gen_challenge(const char *addr, char *challenge)
base64_encode(digest, len, challenge, 0);
}
/* Return the secret for a user from the secret file, null terminated.
* Maximum length is len (not counting the null). */
static int get_secret(int module, const char *user, char *secret, int len)
{
const char *fname = lp_secrets_file(module);
STRUCT_STAT st;
int fd, ok = 1;
const char *p;
char ch, *s;
if (!fname || !*fname)
return 0;
if ((fd = open(fname, O_RDONLY)) < 0)
return 0;
if (do_stat(fname, &st) == -1) {
rsyserr(FLOG, errno, "stat(%s)", fname);
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
ok = 0;
}
}
if (!ok) {
rprintf(FLOG, "continuing without secrets file\n");
close(fd);
return 0;
}
if (*user == '#') {
/* Reject attempt to match a comment. */
close(fd);
return 0;
}
/* Try to find a line that starts with the user name and a ':'. */
p = user;
while (1) {
if (read(fd, &ch, 1) != 1) {
close(fd);
return 0;
}
if (ch == '\n')
p = user;
else if (p) {
if (*p == ch)
p++;
else if (!*p && ch == ':')
break;
else
p = NULL;
}
}
/* Slurp the secret into the "secret" buffer. */
s = secret;
while (len > 0) {
if (read(fd, s, 1) != 1 || *s == '\n')
break;
if (*s == '\r')
continue;
s++;
len--;
}
*s = '\0';
close(fd);
return 1;
}
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");
if (!filename)
return NULL;
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FWARNING, errno, "could not open password file \"%s\"",
filename);
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
if (do_stat(filename, &st) == -1) {
rsyserr(FWARNING, errno, "stat(%s)", filename);
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FWARNING, "password file must not be other-accessible\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FWARNING, "password file must be owned by root when running as root\n");
ok = 0;
}
if (!ok) {
close(fd);
rprintf(FWARNING, "continuing without password file\n");
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
n = read(fd, buffer, sizeof buffer - 1);
close(fd);
if (n > 0) {
buffer[n] = '\0';
if ((p = strtok(buffer, "\n\r")) != NULL)
return strdup(p);
}
return NULL;
}
/* Generate an MD4 hash created from the combination of the password
* and the challenge string and return it base64-encoded. */
static void generate_hash(const char *in, const char *challenge, char *out)
@@ -214,6 +93,127 @@ static void generate_hash(const char *in, const char *challenge, char *out)
base64_encode(buf, len, out, 0);
}
/* Return the secret for a user from the secret file, null terminated.
* Maximum length is len (not counting the null). */
static const char *check_secret(int module, const char *user, const char *group,
const char *challenge, const char *pass)
{
char line[1024];
char pass2[MAX_DIGEST_LEN*2];
const char *fname = lp_secrets_file(module);
STRUCT_STAT st;
int ok = 1;
int user_len = strlen(user);
int group_len = group ? strlen(group) : 0;
char *err;
FILE *fh;
if (!fname || !*fname || (fh = fopen(fname, "r")) == NULL)
return "no secrets file";
if (do_fstat(fileno(fh), &st) == -1) {
rsyserr(FLOG, errno, "fstat(%s)", fname);
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
ok = 0;
}
}
if (!ok) {
fclose(fh);
return "ignoring secrets file";
}
if (*user == '#') {
/* Reject attempt to match a comment. */
fclose(fh);
return "invalid username";
}
/* Try to find a line that starts with the user (or @group) name and a ':'. */
err = "secret not found";
while ((user || group) && fgets(line, sizeof line, fh) != NULL) {
const char **ptr, *s = strtok(line, "\n\r");
int len;
if (!s)
continue;
if (*s == '@') {
ptr = &group;
len = group_len;
s++;
} else {
ptr = &user;
len = user_len;
}
if (!*ptr || strncmp(s, *ptr, len) != 0 || s[len] != ':')
continue;
generate_hash(s+len+1, challenge, pass2);
if (strcmp(pass, pass2) == 0) {
err = NULL;
break;
}
err = "password mismatch";
*ptr = NULL; /* Don't look for name again. */
}
fclose(fh);
memset(line, 0, sizeof line);
memset(pass2, 0, sizeof pass2);
return err;
}
static const char *getpassf(const char *filename)
{
STRUCT_STAT st;
char buffer[512], *p;
int n;
if (!filename)
return NULL;
if (strcmp(filename, "-") == 0) {
n = fgets(buffer, sizeof buffer, stdin) == NULL ? -1 : (int)strlen(buffer);
} else {
int fd;
if ((fd = open(filename,O_RDONLY)) < 0) {
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);
exit_cleanup(RERR_SYNTAX);
}
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);
close(fd);
}
if (n > 0) {
buffer[n] = '\0';
if ((p = strtok(buffer, "\n\r")) != NULL)
return strdup(p);
}
rprintf(FERROR, "ERROR: failed to read a password from %s\n", filename);
exit_cleanup(RERR_SYNTAX);
}
/* Possibly negotiate authentication with the client. Use "leader" to
* start off the auth if necessary.
*
@@ -226,9 +226,12 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
char *users = lp_auth_users(module);
char challenge[MAX_DIGEST_LEN*2];
char line[BIGPATHBUFLEN];
char secret[512];
char pass2[MAX_DIGEST_LEN*2];
char **auth_uid_groups = NULL;
int auth_uid_groups_cnt = -1;
const char *err = NULL;
int group_match = -1;
char *tok, *pass;
char opt_ch = '\0';
/* if no auth list then allow anyone in! */
if (!users || !*users)
@@ -238,7 +241,7 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
io_printf(f_out, "%s%s\n", leader, challenge);
if (!read_line_old(f_in, line, sizeof line)
if (!read_line_old(f_in, line, sizeof line, 0)
|| (pass = strchr(line, ' ')) == NULL) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"invalid challenge response\n",
@@ -251,36 +254,91 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
out_of_memory("auth_server");
for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
if (wildmatch(tok, line))
break;
char *opts;
/* See if the user appended :deny, :ro, or :rw. */
if ((opts = strchr(tok, ':')) != NULL) {
*opts++ = '\0';
opt_ch = isUpper(opts) ? toLower(opts) : *opts;
if (opt_ch == 'r') { /* handle ro and rw */
opt_ch = isUpper(opts+1) ? toLower(opts+1) : opts[1];
if (opt_ch == 'o')
opt_ch = 'r';
else if (opt_ch != 'w')
opt_ch = '\0';
} else if (opt_ch != 'd') /* if it's not deny, ignore it */
opt_ch = '\0';
} else
opt_ch = '\0';
if (*tok != '@') {
/* Match the username */
if (wildmatch(tok, line))
break;
} else {
#ifdef HAVE_GETGROUPLIST
int j;
/* See if authorizing user is a real user, and if so, see
* if it is in a group that matches tok+1 wildmat. */
if (auth_uid_groups_cnt < 0) {
gid_t gid_list[64];
uid_t auth_uid;
auth_uid_groups_cnt = sizeof gid_list / sizeof (gid_t);
if (!user_to_uid(line, &auth_uid, False)
|| getallgroups(auth_uid, gid_list, &auth_uid_groups_cnt) != NULL)
auth_uid_groups_cnt = 0;
else {
if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)
out_of_memory("auth_server");
for (j = 0; j < auth_uid_groups_cnt; j++)
auth_uid_groups[j] = gid_to_group(gid_list[j]);
}
}
for (j = 0; j < auth_uid_groups_cnt; j++) {
if (auth_uid_groups[j] && wildmatch(tok+1, auth_uid_groups[j])) {
group_match = j;
break;
}
}
if (group_match >= 0)
break;
#else
rprintf(FLOG, "your computer doesn't support getgrouplist(), so no @group authorization is possible.\n");
#endif
}
}
free(users);
if (!tok) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"unauthorized user\n",
lp_name(module), host, addr);
if (!tok)
err = "no matching rule";
else if (opt_ch == 'd')
err = "denied by rule";
else {
char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;
err = check_secret(module, line, group, challenge, pass);
}
memset(challenge, 0, sizeof challenge);
memset(pass, 0, strlen(pass));
if (auth_uid_groups) {
int j;
for (j = 0; j < auth_uid_groups_cnt; j++) {
if (auth_uid_groups[j])
free(auth_uid_groups[j]);
}
free(auth_uid_groups);
}
if (err) {
rprintf(FLOG, "auth failed on module %s from %s (%s) for %s: %s\n",
lp_name(module), host, addr, line, err);
return NULL;
}
memset(secret, 0, sizeof secret);
if (!get_secret(module, line, secret, sizeof secret - 1)) {
memset(secret, 0, sizeof secret);
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"missing secret for user \"%s\"\n",
lp_name(module), host, addr, line);
return NULL;
}
generate_hash(secret, challenge, pass2);
memset(secret, 0, sizeof secret);
if (strcmp(pass, pass2) != 0) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"password mismatch\n",
lp_name(module), host, addr);
return NULL;
}
if (opt_ch == 'r')
read_only = 1;
else if (opt_ch == 'w')
read_only = 0;
return strdup(line);
}

520
backup.c
View File

@@ -2,7 +2,7 @@
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* Copyright (C) 2003-2008 Wayne Davison
* Copyright (C) 2003-2015 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,8 +19,8 @@
*/
#include "rsync.h"
#include "ifuncs.h"
extern int verbose;
extern int am_root;
extern int preserve_acls;
extern int preserve_xattrs;
@@ -34,209 +34,230 @@ extern char backup_dir_buf[MAXPATHLEN];
extern char *backup_suffix;
extern char *backup_dir;
/* make a complete pathname for backup file */
/* Returns -1 on error, 0 on missing dir, and 1 on present dir. */
static int validate_backup_dir(void)
{
STRUCT_STAT st;
if (do_lstat(backup_dir_buf, &st) < 0) {
if (errno == ENOENT)
return 0;
rsyserr(FERROR, errno, "backup lstat %s failed", backup_dir_buf);
return -1;
}
if (!S_ISDIR(st.st_mode)) {
int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
if (delete_item(backup_dir_buf, st.st_mode, flags) == 0)
return 0;
return -1;
}
return 1;
}
/* Create a backup path from the given fname, putting the result into
* backup_dir_buf. Any new directories (compared to the prior backup
* path) are ensured to exist as directories, replacing anything else
* that may be in the way (e.g. a symlink). */
static BOOL copy_valid_path(const char *fname)
{
const char *f;
int val;
BOOL ret = True;
stat_x sx;
char *b, *rel = backup_dir_buf + backup_dir_len, *name = rel;
for (f = fname, b = rel; *f && *f == *b; f++, b++) {
if (*b == '/')
name = b + 1;
}
if (stringjoin(rel, backup_dir_remainder, fname, backup_suffix, NULL) >= backup_dir_remainder) {
rprintf(FERROR, "backup filename too long\n");
*name = '\0';
return False;
}
for ( ; ; name = b + 1) {
if ((b = strchr(name, '/')) == NULL)
return True;
*b = '\0';
val = validate_backup_dir();
if (val == 0)
break;
if (val < 0) {
*name = '\0';
return False;
}
*b = '/';
}
init_stat_x(&sx);
for ( ; b; name = b + 1, b = strchr(name, '/')) {
*b = '\0';
while (do_mkdir(backup_dir_buf, ACCESSPERMS) < 0) {
if (errno == EEXIST) {
val = validate_backup_dir();
if (val > 0)
break;
if (val == 0)
continue;
} else
rsyserr(FERROR, errno, "backup mkdir %s failed", backup_dir_buf);
*name = '\0';
ret = False;
goto cleanup;
}
/* Try to transfer the directory settings of the actual dir
* that the files are coming from. */
if (x_stat(rel, &sx.st, NULL) < 0)
rsyserr(FERROR, errno, "backup stat %s failed", full_fname(rel));
else {
struct file_struct *file;
if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
continue;
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(rel, &sx);
cache_tmp_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(rel, &sx);
cache_tmp_xattr(file, &sx);
free_xattr(&sx);
}
#endif
set_file_attrs(backup_dir_buf, file, NULL, NULL, 0);
unmake_file(file);
}
*b = '/';
}
cleanup:
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return ret;
}
/* Make a complete pathname for backup file and verify any new path elements. */
char *get_backup_name(const char *fname)
{
if (backup_dir) {
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
fname, backup_suffix, NULL) < backup_dir_remainder)
return backup_dir_buf;
} else {
if (stringjoin(backup_dir_buf, MAXPATHLEN,
fname, backup_suffix, NULL) < MAXPATHLEN)
/* copy fname into backup_dir_buf while validating the dirs. */
if (copy_valid_path(fname))
return backup_dir_buf;
/* copy_valid_path() has printed an error message. */
return NULL;
}
if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, backup_suffix, NULL) < MAXPATHLEN)
return backup_dir_buf;
rprintf(FERROR, "backup filename too long\n");
return NULL;
}
/* simple backup creates a backup with a suffix in the same directory */
static int make_simple_backup(const char *fname)
/* Has same return codes as make_backup(). */
static inline int link_or_rename(const char *from, const char *to,
BOOL prefer_rename, STRUCT_STAT *stp)
{
int rename_errno;
const char *fnamebak = get_backup_name(fname);
if (!fnamebak)
return 0;
while (1) {
if (do_rename(fname, fnamebak) == 0) {
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
fname, fnamebak);
}
break;
}
/* cygwin (at least version b19) reports EINVAL */
if (errno == ENOENT || errno == EINVAL)
break;
rename_errno = errno;
if (errno == EISDIR && do_rmdir(fnamebak) == 0)
continue;
if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
continue;
rsyserr(FERROR, rename_errno, "rename %s to backup %s",
fname, fnamebak);
errno = rename_errno;
return 0;
}
return 1;
}
/****************************************************************************
Create a directory given an absolute path, perms based upon another directory
path
****************************************************************************/
int make_bak_dir(const char *fullpath)
{
char fbuf[MAXPATHLEN], *rel, *end, *p;
struct file_struct *file;
int len = backup_dir_len;
stat_x sx;
while (*fullpath == '.' && fullpath[1] == '/') {
fullpath += 2;
len -= 2;
}
if (strlcpy(fbuf, fullpath, sizeof fbuf) >= sizeof fbuf)
return -1;
rel = fbuf + len;
end = p = rel + strlen(rel);
/* Try to find an existing dir, starting from the deepest dir. */
while (1) {
if (--p == fbuf)
return -1;
if (*p == '/') {
*p = '\0';
if (mkdir_defmode(fbuf) == 0)
break;
if (errno != ENOENT) {
rsyserr(FERROR, errno,
"make_bak_dir mkdir %s failed",
full_fname(fbuf));
return -1;
}
}
}
/* Make all the dirs that we didn't find on the way here. */
while (1) {
if (p >= rel) {
/* Try to transfer the directory settings of the
* actual dir that the files are coming from. */
if (x_stat(rel, &sx.st, NULL) < 0) {
rsyserr(FERROR, errno,
"make_bak_dir stat %s failed",
full_fname(rel));
} else {
#ifdef SUPPORT_ACLS
sx.acc_acl = sx.def_acl = NULL;
#ifdef SUPPORT_HARD_LINKS
if (!prefer_rename) {
#ifndef CAN_HARDLINK_SYMLINK
if (S_ISLNK(stp->st_mode))
return 0; /* Use copy code. */
#endif
#ifdef SUPPORT_XATTRS
sx.xattr = NULL;
#ifndef CAN_HARDLINK_SPECIAL
if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
return 0; /* Use copy code. */
#endif
if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
continue;
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
get_acl(rel, &sx);
cache_acl(file, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
get_xattr(rel, &sx);
cache_xattr(file, &sx);
free_xattr(&sx);
}
#endif
set_file_attrs(fbuf, file, NULL, NULL, 0);
unmake_file(file);
}
}
*p = '/';
p += strlen(p);
if (p == end)
break;
if (mkdir_defmode(fbuf) < 0) {
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
full_fname(fbuf));
return -1;
if (do_link(from, to) == 0) {
if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: HLINK %s successful.\n", from);
return 2;
}
/* We prefer to rename a regular file rather than copy it. */
if (!S_ISREG(stp->st_mode) || errno == EEXIST || errno == EISDIR)
return 0;
}
return 0;
}
/* 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) {
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;
#endif
if (do_rename(from, to) == 0) {
if (stp->st_nlink > 1 && !S_ISDIR(stp->st_mode)) {
/* If someone has hard-linked the file into the backup
* dir, rename() might return success but do nothing! */
robust_unlink(from); /* Just in case... */
}
if (save_errno) {
errno = save_errno;
return -1;
}
}
return 0;
}
/* If we have a --backup-dir, then we get here from make_backup().
* We will move the file to be deleted into a parallel directory tree. */
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;
/* return if no file to keep */
if (x_lstat(fname, &sx.st, NULL) < 0)
if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: RENAME %s successful.\n", from);
return 1;
#ifdef SUPPORT_ACLS
sx.acc_acl = sx.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
sx.xattr = NULL;
#endif
if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
return 1; /* the file could have disappeared */
if (!(buf = get_backup_name(fname))) {
unmake_file(file);
return 0;
}
return 0;
}
/* Hard-link, rename, or copy an item to the backup name. Returns 0 for
* failure, 1 if item was moved, 2 if item was duplicated or hard linked
* into backup area, or 3 if item doesn't exist or isn't a regular file. */
int make_backup(const char *fname, BOOL prefer_rename)
{
stat_x sx;
struct file_struct *file;
int save_preserve_xattrs;
char *buf;
int ret = 0;
init_stat_x(&sx);
/* Return success if no file to keep. */
if (x_lstat(fname, &sx.st, NULL) < 0)
return 3;
if (!(buf = get_backup_name(fname)))
return 0;
/* Try a hard-link or a rename first. Using rename is not atomic, but
* is more efficient than forcing a copy for larger files when no hard-
* linking is possible. */
if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
goto success;
if (errno == EEXIST || errno == EISDIR) {
STRUCT_STAT bakst;
if (do_lstat(buf, &bakst) == 0) {
int flags = get_del_for_flag(bakst.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
if (delete_item(buf, bakst.st_mode, flags) != 0)
return 0;
}
if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
goto success;
}
/* Fall back to making a copy. */
if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
return 3; /* the file could have disappeared */
#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
@@ -244,119 +265,78 @@ 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))) {
int save_errno;
do_unlink(buf);
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);
}
kept = 1;
do_unlink(fname);
}
if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */
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);
if (verbose > 2) {
rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
full_fname(fname), ret_code);
}
kept = 1;
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
rsyserr(FERROR, errno, "mknod %s failed", full_fname(buf));
else if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
ret = 2;
}
#ifdef SUPPORT_LINKS
if (!kept && preserve_links && S_ISLNK(file->mode)) {
if (!ret && preserve_links && S_ISLNK(file->mode)) {
const char *sl = F_SYMLINK(file);
if (safe_symlinks && unsafe_symlink(sl, buf)) {
if (verbose) {
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
full_fname(buf), sl);
if (safe_symlinks && unsafe_symlink(sl, fname)) {
if (INFO_GTE(SYMSAFE, 1)) {
rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
fname, sl);
}
kept = 1;
ret = 2;
} else {
do_unlink(buf);
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;
if (do_symlink(sl, buf) < 0)
rsyserr(FERROR, errno, "link %s -> \"%s\"", full_fname(buf), sl);
else if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: SYMLINK %s successful.\n", fname);
ret = 2;
}
}
#endif
if (!kept && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
fname);
if (!ret && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
unmake_file(file);
return 1;
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return 3;
}
/* move to keep tree if a file */
if (!kept) {
if (robust_move(fname, buf) != 0) {
/* Copy to backup tree if a file. */
if (!ret) {
if (copy_file(fname, buf, -1, file->mode) < 0) {
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
full_fname(fname), buf);
} else if (sx.st.st_nlink > 1) {
/* If someone has hard-linked the file into the backup
* dir, rename() might return success but do nothing! */
robust_unlink(fname); /* Just in case... */
unmake_file(file);
#ifdef SUPPORT_ACLS
uncache_tmp_acls();
#endif
#ifdef SUPPORT_XATTRS
uncache_tmp_xattrs();
#endif
return 0;
}
if (DEBUG_GTE(BACKUP, 1))
rprintf(FINFO, "make_backup: COPY %s successful.\n", fname);
ret = 2;
}
save_preserve_xattrs = preserve_xattrs;
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",
fname, buf);
}
return 1;
}
/* main backup switch routine */
int make_backup(const char *fname)
{
if (backup_dir)
return keep_backup(fname);
return make_simple_backup(fname);
success:
if (INFO_GTE(BACKUP, 1))
rprintf(FINFO, "backed up %s to %s\n", fname, buf);
return ret;
}

73
batch.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* Copyright (C) 2004-2008 Wayne Davison
* Copyright (C) 2004-2015 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
@@ -20,7 +20,7 @@
*/
#include "rsync.h"
#include "zlib/zlib.h"
#include <zlib.h>
#include <time.h>
extern int eol_nulls;
@@ -43,7 +43,7 @@ extern char *batch_name;
extern char *iconv_opt;
#endif
extern struct filter_list_struct filter_list;
extern filter_rule_list filter_list;
int batch_stream_flags;
@@ -135,7 +135,7 @@ void check_batch_flags(void)
set ? "Please" : "Do not");
exit_cleanup(RERR_SYNTAX);
}
if (verbose) {
if (INFO_GTE(MISC, 1)) {
rprintf(FINFO,
"%sing the %s option to match the batchfile.\n",
set ? "Sett" : "Clear", flag_name[i]);
@@ -156,40 +156,50 @@ void check_batch_flags(void)
append_mode = 2;
}
static void write_arg(int fd, char *arg)
static int write_arg(int fd, char *arg)
{
char *x, *s;
int len, ret = 0;
if (*arg == '-' && (x = strchr(arg, '=')) != NULL) {
write(fd, arg, x - arg + 1);
if (write(fd, arg, x - arg + 1) != x - arg + 1)
ret = -1;
arg += x - arg + 1;
}
if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) {
write(fd, "'", 1);
if (write(fd, "'", 1) != 1)
ret = -1;
for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) {
write(fd, s, x - s + 1);
write(fd, "'", 1);
if (write(fd, s, x - s + 1) != x - s + 1
|| write(fd, "'", 1) != 1)
ret = -1;
}
write(fd, s, strlen(s));
write(fd, "'", 1);
return;
len = strlen(s);
if (write(fd, s, len) != len
|| write(fd, "'", 1) != 1)
ret = -1;
return ret;
}
write(fd, arg, strlen(arg));
len = strlen(arg);
if (write(fd, arg, len) != len)
ret = -1;
return ret;
}
static void write_filter_rules(int fd)
{
struct filter_struct *ent;
filter_rule *ent;
write_sbuf(fd, " <<'#E#'\n");
for (ent = filter_list.head; ent; ent = ent->next) {
unsigned int plen;
char *p = get_rule_prefix(ent->match_flags, "- ", 0, &plen);
char *p = get_rule_prefix(ent, "- ", 0, &plen);
write_buf(fd, p, plen);
write_sbuf(fd, ent->pattern);
if (ent->match_flags & MATCHFLG_DIRECTORY)
if (ent->rflags & FILTRULE_DIRECTORY)
write_byte(fd, '/');
write_byte(fd, eol_nulls ? 0 : '\n');
}
@@ -205,13 +215,13 @@ 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,
batch_name, ".sh", NULL);
fd = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IEXEC);
S_IRUSR | S_IWUSR | S_IXUSR);
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
filename);
@@ -219,7 +229,8 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
}
/* Write argvs info to BATCH.sh file */
write_arg(fd, argv[0]);
if (write_arg(fd, argv[0]) < 0)
err = 1;
if (filter_list.head) {
if (protocol_version >= 29)
write_sbuf(fd, " --filter=._-");
@@ -240,25 +251,31 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
i++;
continue;
}
write(fd, " ", 1);
if (write(fd, " ", 1) != 1)
err = 1;
if (strncmp(p, "--write-batch", len = 13) == 0
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
write(fd, "--read-batch", 12);
if (write(fd, "--read-batch", 12) != 12)
err = 1;
if (p[len] == '=') {
write(fd, "=", 1);
write_arg(fd, p + len + 1);
if (write(fd, "=", 1) != 1
|| write_arg(fd, p + len + 1) < 0)
err = 1;
}
} else
write_arg(fd, p);
} else {
if (write_arg(fd, p) < 0)
err = 1;
}
}
if (!(p = check_for_hostspec(argv[argc - 1], &p, &i)))
p = argv[argc - 1];
write(fd, " ${1:-", 6);
write_arg(fd, p);
if (write(fd, " ${1:-", 6) != 6
|| write_arg(fd, p) < 0)
err = 1;
write_byte(fd, '}');
if (filter_list.head)
write_filter_rules(fd);
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
if (write(fd, "\n", 1) != 1 || close(fd) < 0 || err) {
rsyserr(FERROR, errno, "Batch file %s write error",
filename);
exit_cleanup(RERR_FILEIO);

View File

@@ -2,7 +2,7 @@
* Simple byteorder handling.
*
* Copyright (C) 1992-1995 Andrew Tridgell
* Copyright (C) 2007-2008 Wayne Davison
* Copyright (C) 2007-2015 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,10 +19,11 @@
*/
#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. */
#ifdef __i386__
#if defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || __amd64
#define CAREFUL_ALIGNMENT 0
#endif
@@ -32,21 +33,92 @@
#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 IVAL64(buf,pos) (IVAL(buf,pos)|(int64)IVAL(buf,(pos)+4)<<32)
#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 SIVAL(buf,pos,val) SIVALX(buf,pos,(uint32)(val))
#define SIVAL64(buf,pos,val) (SIVAL(buf,pos,val),SIVAL(buf,(pos)+4,(val)>>32))
#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);
}
static inline int64
IVAL64(const char *buf, int pos)
{
union {
const char *b;
const int64 *num;
} u;
u.b = buf + pos;
return *u.num;
}
static inline void
SIVAL64(char *buf, int pos, int64 val)
{
union {
char *b;
int64 *num;
} u;
u.b = buf + pos;
*u.num = 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-2008 Wayne Davison
* Copyright (C) 2006-2015 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-2008 Wayne Davison
* Copyright (C) 2004-2015 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,8 +23,7 @@
extern int checksum_seed;
extern int protocol_version;
int csum_length = SHORT_SUM_LENGTH; /* initial value */
extern int proper_seed_order;
/*
a simple 32 bit checksum that can be upadted from either end
@@ -56,10 +55,18 @@ void get_checksum2(char *buf, int32 len, char *sum)
if (protocol_version >= 30) {
uchar seedbuf[4];
md5_begin(&m);
md5_update(&m, (uchar *)buf, len);
if (checksum_seed) {
SIVAL(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
if (proper_seed_order) {
if (checksum_seed) {
SIVALu(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
}
md5_update(&m, (uchar *)buf, len);
} else {
md5_update(&m, (uchar *)buf, len);
if (checksum_seed) {
SIVALu(seedbuf, 0, checksum_seed);
md5_update(&m, seedbuf, 4);
}
}
md5_result(&m, (uchar *)sum);
} else {
@@ -100,10 +107,10 @@ void get_checksum2(char *buf, int32 len, char *sum)
}
}
void file_checksum(char *fname, char *sum, OFF_T size)
void file_checksum(const char *fname, const STRUCT_STAT *st_p, char *sum)
{
struct map_struct *buf;
OFF_T i, len = size;
OFF_T i, len = st_p->st_size;
md_context m;
int32 remainder;
int fd;
@@ -114,7 +121,7 @@ void file_checksum(char *fname, char *sum, OFF_T size)
if (fd == -1)
return;
buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
buf = map_file(fd, len, MAX_MAP_SIZE, CSUM_CHUNK);
if (protocol_version >= 30) {
md5_begin(&m);

32
chmod.c
View File

@@ -2,7 +2,7 @@
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* Copyright (C) 2005-2008 Wayne Davison
* Copyright (C) 2005-2015 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 @@
*/
#include "rsync.h"
#include "itypes.h"
extern mode_t orig_umask;
@@ -35,10 +36,12 @@ struct chmod_mode_struct {
#define CHMOD_ADD 1
#define CHMOD_SUB 2
#define CHMOD_EQ 3
#define CHMOD_SET 4
#define STATE_ERROR 0
#define STATE_1ST_HALF 1
#define STATE_2ND_HALF 2
#define STATE_OCTAL_NUM 3
/* Parse a chmod-style argument, and break it down into one or more AND/OR
* pairs in a linked list. We return a pointer to new items on succcess
@@ -87,6 +90,10 @@ struct chmod_mode_struct *parse_chmod(const char *modestr,
curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0);
curr_mode->ModeOR = bits + topoct;
break;
case CHMOD_SET:
curr_mode->ModeAND = 0;
curr_mode->ModeOR = bits;
break;
}
curr_mode->flags = flags;
@@ -99,7 +106,8 @@ struct chmod_mode_struct *parse_chmod(const char *modestr,
where = what = op = topoct = topbits = flags = 0;
}
if (state != STATE_2ND_HALF) {
switch (state) {
case STATE_1ST_HALF:
switch (*modestr) {
case 'D':
if (flags & FLAG_FILES_ONLY)
@@ -138,10 +146,17 @@ struct chmod_mode_struct *parse_chmod(const char *modestr,
state = STATE_2ND_HALF;
break;
default:
state = STATE_ERROR;
if (isDigit(modestr) && *modestr < '8' && !where) {
op = CHMOD_SET;
state = STATE_OCTAL_NUM;
where = 1;
what = *modestr - '0';
} else
state = STATE_ERROR;
break;
}
} else {
break;
case STATE_2ND_HALF:
switch (*modestr) {
case 'r':
what |= 4;
@@ -168,6 +183,15 @@ struct chmod_mode_struct *parse_chmod(const char *modestr,
state = STATE_ERROR;
break;
}
break;
case STATE_OCTAL_NUM:
if (isDigit(modestr) && *modestr < '8') {
what = what*8 + *modestr - '0';
if (what > CHMOD_BITS)
state = STATE_ERROR;
} else
state = STATE_ERROR;
break;
}
modestr++;
}

139
cleanup.c
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-2008 Wayne Davison
* Copyright (C) 2003-2015 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,14 +22,21 @@
#include "rsync.h"
extern int dry_run;
extern int am_server;
extern int am_daemon;
extern int am_receiver;
extern int io_error;
extern int keep_partial;
extern int got_xfer_error;
extern int protocol_version;
extern int output_needs_newline;
extern char *partial_dir;
extern char *logfile_name;
BOOL shutting_down = False;
BOOL flush_ok_after_signal = False;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
@@ -81,7 +88,7 @@ int cleanup_got_literal = 0;
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 int cleanup_fd_r = -1, cleanup_fd_w = -1;
static pid_t cleanup_pid = 0;
pid_t cleanup_child_pid = -1;
@@ -93,75 +100,108 @@ 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 unmodified_code = 0;
static int switch_step = 0;
static int exit_code = 0, exit_line = 0;
static const char *exit_file = NULL;
static int first_code = 0;
SIGACTION(SIGUSR1, SIG_IGN);
SIGACTION(SIGUSR2, SIG_IGN);
if (exit_code) /* Preserve first error code when recursing. */
code = exit_code;
if (!exit_code) { /* Preserve first error exit info when recursing. */
exit_code = code;
exit_file = file;
exit_line = line < 0 ? -line : 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;
first_code = code;
if (verbose > 3) {
if (output_needs_newline) {
fputc('\n', stdout);
output_needs_newline = 0;
}
if (DEBUG_GTE(EXIT, 2)) {
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;
int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
if (pid == cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code)
code = exit_code = status;
if (status > exit_code)
exit_code = status;
}
}
/* 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)) {
const char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
if (cleanup_got_literal && (cleanup_fname || cleanup_fd_w != -1)) {
if (cleanup_fd_r != -1) {
close(cleanup_fd_r);
cleanup_fd_r = -1;
}
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
cleanup_fd_w = -1;
}
if (cleanup_fname && cleanup_new_fname && keep_partial
&& handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
int tweak_modtime = 0;
const char *fname = cleanup_fname;
cleanup_fname = NULL;
if (!partial_dir) {
/* We don't want to leave a partial file with a modern time or it
* could be skipped via --update. Setting the time to something
* really old also helps it to stand out as unfinished in an ls. */
tweak_modtime = 1;
cleanup_file->modtime = 0;
}
finish_transfer(cleanup_new_fname, fname, NULL, NULL,
cleanup_file, tweak_modtime, !partial_dir);
}
finish_transfer(cleanup_new_fname, fname, NULL, NULL,
cleanup_file, 0, !partial_dir);
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
io_flush(FULL_FLUSH);
if (flush_ok_after_signal) {
flush_ok_after_signal = False;
if (code == RERR_SIGNAL)
io_flush(FULL_FLUSH);
}
if (!exit_code && !code)
io_flush(FULL_FLUSH);
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code)
if (exit_code)
kill_all(SIGUSR1);
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
@@ -169,32 +209,56 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
unlink(lp_pid_file());
}
if (code == 0) {
if (exit_code == 0) {
if (code)
exit_code = code;
if (io_error & IOERR_DEL_LIMIT)
code = exit_code = RERR_DEL_LIMIT;
exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = exit_code = RERR_VANISHED;
exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || got_xfer_error)
code = exit_code = RERR_PARTIAL;
exit_code = RERR_PARTIAL;
}
if (code || am_daemon || (logfile_name && (am_server || !verbose)))
log_exit(code, file, line);
/* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
* we don't want to output a duplicate error. */
if ((exit_code && line > 0)
|| am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
log_exit(exit_code, exit_file, exit_line);
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (verbose > 2) {
if (DEBUG_GTE(EXIT, 1)) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): "
"about to call exit(%d)\n",
unmodified_code, file, line, code);
"[%s] _exit_cleanup(code=%d, file=%s, line=%d): "
"about to call exit(%d)%s\n",
who_am_i(), first_code, exit_file, exit_line, exit_code,
dry_run ? " (DRY RUN)" : "");
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (am_server && code)
if (exit_code && exit_code != RERR_SOCKETIO && exit_code != RERR_STREAMIO && exit_code != RERR_SIGNAL1
&& exit_code != RERR_TIMEOUT && !shutting_down && (protocol_version >= 31 || am_receiver)) {
if (line > 0) {
if (DEBUG_GTE(EXIT, 3)) {
rprintf(FINFO, "[%s] sending MSG_ERROR_EXIT with exit_code %d\n",
who_am_i(), exit_code);
}
send_msg_int(MSG_ERROR_EXIT, exit_code);
}
noop_io_until_death();
}
/* FALLTHROUGH */
#include "case_N.h"
switch_step++;
if (am_server && exit_code)
msleep(100);
close_all();
@@ -203,12 +267,13 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
break;
}
exit(code);
exit(exit_code);
}
void cleanup_disable(void)
{
cleanup_fname = cleanup_new_fname = NULL;
cleanup_fd_r = cleanup_fd_w = -1;
cleanup_got_literal = 0;
}

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-2008 Wayne Davison
* Copyright (C) 2002-2015 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
@@ -41,7 +41,6 @@ char *client_addr(int fd)
static int initialised;
struct sockaddr_storage ss;
socklen_t length = sizeof ss;
char *ssh_info, *p;
if (initialised)
return addr_buf;
@@ -49,11 +48,14 @@ char *client_addr(int fd)
initialised = 1;
if (am_server) { /* daemon over --rsh mode */
char *env_str;
strlcpy(addr_buf, "0.0.0.0", sizeof addr_buf);
if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
|| (ssh_info = getenv("SSH_CLIENT")) != NULL
|| (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
strlcpy(addr_buf, ssh_info, sizeof addr_buf);
if ((env_str = getenv("REMOTE_HOST")) != NULL
|| (env_str = getenv("SSH_CONNECTION")) != NULL
|| (env_str = getenv("SSH_CLIENT")) != NULL
|| (env_str = getenv("SSH2_CLIENT")) != NULL) {
char *p;
strlcpy(addr_buf, env_str, sizeof addr_buf);
/* Truncate the value to just the IP address. */
if ((p = strchr(addr_buf, ' ')) != NULL)
*p = '\0';
@@ -108,6 +110,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

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-2008 Wayne Davison
* Copyright (C) 2002-2015 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
@@ -20,10 +20,9 @@
*/
#include "rsync.h"
#include "ifuncs.h"
#include "itypes.h"
extern int quiet;
extern int verbose;
extern int dry_run;
extern int output_motd;
extern int list_only;
@@ -37,6 +36,7 @@ extern int ignore_errors;
extern int preserve_xattrs;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int munge_symlinks;
extern int sanitize_paths;
extern int numeric_ids;
extern int filesfrom_fd;
@@ -48,25 +48,23 @@ 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 daemon_filter_list;
extern char curr_dir[];
extern filter_rule_list daemon_filter_list;
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
#define MAX_GID_LIST 32
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
@@ -75,12 +73,20 @@ struct chmod_mode_struct *daemon_chmod_modes;
char *module_dir = NULL;
unsigned int module_dirlen = 0;
char *full_module_path;
static int rl_nulls = 0;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
static gid_t gid_list[MAX_GID_LIST];
static int gid_count = 0;
/* Used when "reverse lookup" is off. */
const char undetermined_hostname[] = "UNDETERMINED";
/**
* Run a client connected to an rsyncd. The alternative to this
* function for remote-shell connections is do_cmd().
@@ -158,7 +164,7 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int
}
/* This strips the \n. */
if (!read_line_old(f_in, buf, bufsiz)) {
if (!read_line_old(f_in, buf, bufsiz, 0)) {
if (am_client)
rprintf(FERROR, "rsync: did not see server greeting\n");
return -1;
@@ -259,7 +265,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
else
else if (**argv == '-') {
if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
out_of_memory("start_inband_exchange");
} else
sargs[sargc++] = *argv;
argv++;
argc--;
@@ -267,7 +276,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
sargs[sargc] = NULL;
if (verbose > 1)
if (DEBUG_GTE(CMD, 1))
print_child_argv("sending daemon args:", sargs);
io_printf(f_out, "%.*s\n", modlen, modname);
@@ -277,7 +286,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
kluge_around_eof = list_only && protocol_version < 25 ? 1 : 0;
while (1) {
if (!read_line_old(f_in, line, sizeof line)) {
if (!read_line_old(f_in, line, sizeof line, 0)) {
rprintf(FERROR, "rsync: didn't get server startup line\n");
return -1;
}
@@ -331,7 +340,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
if (protocol_version < 23) {
if (protocol_version == 22 || !am_sender)
io_start_multiplex_in();
io_start_multiplex_in(f_in);
}
free(modname);
@@ -339,76 +348,179 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
return 0;
}
static char *finish_pre_exec(pid_t pid, int fd, char *request,
static char *finish_pre_exec(pid_t pid, int write_fd, int read_fd, char *request,
char **early_argv, char **argv)
{
int j = 0, status = -1;
char buf[BIGPATHBUFLEN], *bp;
int j = 0, status = -1, msglen = sizeof buf - 1;
if (!request)
request = "(NONE)";
write_buf(fd, request, strlen(request)+1);
write_buf(write_fd, request, strlen(request)+1);
if (early_argv) {
for ( ; *early_argv; early_argv++)
write_buf(fd, *early_argv, strlen(*early_argv)+1);
write_buf(write_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);
for ( ; argv[j]; j++)
write_buf(write_fd, argv[j], strlen(argv[j])+1);
write_byte(write_fd, 0);
close(fd);
close(write_fd);
/* Read the stdout from the pre-xfer exec program. This it is only
* displayed to the user if the script also returns an error status. */
for (bp = buf; msglen > 0; msglen -= j) {
if ((j = read(read_fd, bp, msglen)) <= 0) {
if (j == 0)
break;
if (errno == EINTR)
continue;
break; /* Just ignore the read error for now... */
}
bp += j;
if (j > 1 && bp[-1] == '\n' && bp[-2] == '\r') {
bp--;
j--;
bp[-1] = '\n';
}
}
*bp = '\0';
close(read_fd);
if (wait_process(pid, &status, 0) < 0
|| !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
char *e;
if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s\n",
if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s%s\n%s",
status, status < 0 ? ": " : "",
status < 0 ? strerror(errno) : "") < 0)
out_of_memory("finish_pre_exec");
status < 0 ? strerror(errno) : "",
*buf ? ":" : "", buf) < 0)
return "out_of_memory in finish_pre_exec\n";
return e;
}
return NULL;
}
#ifdef HAVE_PUTENV
static int read_arg_from_pipe(int fd, char *buf, int limit)
{
char *bp = buf, *eob = buf + limit - 1;
while (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)
bp++;
int got = read(fd, bp, 1);
if (got != 1) {
if (got < 0 && errno == EINTR)
continue;
return -1;
}
if (*bp == '\0')
break;
if (bp < eob)
bp++;
}
*bp = '\0';
return bp - buf;
}
#endif
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
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 add_a_group(int f_out, const char *gname)
{
gid_t gid;
if (!group_to_gid(gname, &gid, True)) {
rprintf(FLOG, "Invalid gid %s\n", gname);
io_printf(f_out, "@ERROR: invalid gid %s\n", gname);
return -1;
}
if (gid_count == MAX_GID_LIST) {
rprintf(FLOG, "Too many groups specified via gid parameter.\n");
io_printf(f_out, "@ERROR: too many groups\n");
return -1;
}
gid_list[gid_count++] = gid;
return 0;
}
#ifdef HAVE_GETGROUPLIST
static int want_all_groups(int f_out, uid_t uid)
{
const char *err;
gid_count = MAX_GID_LIST;
if ((err = getallgroups(uid, gid_list, &gid_count)) != NULL) {
rsyserr(FLOG, errno, "%s", err);
io_printf(f_out, "@ERROR: %s\n", err);
return -1;
}
return 0;
}
#elif defined HAVE_INITGROUPS
static struct passwd *want_all_groups(int f_out, uid_t uid)
{
struct passwd *pw;
if ((pw = getpwuid(uid)) == NULL) {
rsyserr(FLOG, errno, "getpwuid failed");
io_printf(f_out, "@ERROR: getpwuid failed\n");
return NULL;
}
/* Start with the default group and initgroups() will add the reset. */
gid_count = 1;
gid_list[0] = pw->pw_gid;
return pw;
}
#endif
static void set_env_str(const char *var, const char *str)
{
#ifdef HAVE_PUTENV
char *mem;
if (asprintf(&mem, "%s=%s", var, str) < 0)
out_of_memory("set_env_str");
putenv(mem);
#endif
}
#ifdef HAVE_PUTENV
static void set_env_num(const char *var, long num)
{
char *mem;
if (asprintf(&mem, "%s=%ld", var, num) < 0)
out_of_memory("set_env_num");
putenv(mem);
}
#endif
static int rsync_module(int f_in, int f_out, int i, const char *addr, const char *host)
{
int argc;
char **argv, **orig_argv, **orig_early_argv, *chroot_path = NULL;
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;
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
struct passwd *pw = NULL;
#endif
uid_t uid;
int set_uid;
char *p, *err_msg = NULL;
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int ret, pre_exec_fd = -1;
int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
int save_munge_symlinks;
pid_t pre_exec_pid = 0;
char *request = NULL;
set_env_str("RSYNC_MODULE_NAME", name);
#ifdef ICONV_OPTION
iconv_opt = lp_charset(i);
if (*iconv_opt)
@@ -416,7 +528,14 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
iconv_opt = NULL;
#endif
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
/* If reverse lookup is disabled globally but enabled for this module,
* we need to do it now before the access check. */
if (host == undetermined_hostname && lp_reverse_lookup(i))
host = client_name(f_in);
set_env_str("RSYNC_HOST_NAME", host);
set_env_str("RSYNC_HOST_ADDR", addr);
if (!allow_access(addr, &host, i)) {
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
if (!lp_list(i))
@@ -448,18 +567,17 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
return -1;
}
read_only = lp_read_only(i); /* may also be overridden by auth_server() */
auth_user = auth_server(f_in, f_out, i, host, addr, "@RSYNCD: AUTHREQD ");
if (!auth_user) {
io_printf(f_out, "@ERROR: auth failed on module %s\n", name);
return -1;
}
set_env_str("RSYNC_USER_NAME", auth_user);
module_id = i;
if (lp_read_only(i))
read_only = 1;
if (lp_transfer_logging(i) && !logfile_format)
logfile_format = lp_log_format(i);
if (log_format_has(logfile_format, 'i'))
@@ -467,61 +585,83 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
logfile_format_has_o_or_i = 1;
am_root = (MY_UID() == 0);
uid = MY_UID();
am_root = (uid == 0);
if (am_root) {
p = lp_uid(i);
if (!name_to_uid(p, &uid)) {
if (!isDigit(p)) {
rprintf(FLOG, "Invalid uid %s\n", p);
io_printf(f_out, "@ERROR: invalid uid %s\n", p);
p = *lp_uid(i) ? lp_uid(i) : am_root ? NOBODY_USER : NULL;
if (p) {
if (!user_to_uid(p, &uid, True)) {
rprintf(FLOG, "Invalid uid %s\n", p);
io_printf(f_out, "@ERROR: invalid uid %s\n", p);
return -1;
}
set_uid = 1;
} else
set_uid = 0;
p = *lp_gid(i) ? strtok(lp_gid(i), ", ") : NULL;
if (p) {
/* The "*" gid must be the first item in the list. */
if (strcmp(p, "*") == 0) {
#ifdef HAVE_GETGROUPLIST
if (want_all_groups(f_out, uid) < 0)
return -1;
#elif defined HAVE_INITGROUPS
if ((pw = want_all_groups(f_out, uid)) == NULL)
return -1;
#else
rprintf(FLOG, "This rsync does not support a gid of \"*\"\n");
io_printf(f_out, "@ERROR: invalid gid setting.\n");
return -1;
#endif
} else if (add_a_group(f_out, p) < 0)
return -1;
while ((p = strtok(NULL, ", ")) != NULL) {
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
if (pw) {
rprintf(FLOG, "This rsync cannot add groups after \"*\".\n");
io_printf(f_out, "@ERROR: invalid gid setting.\n");
return -1;
}
uid = atoi(p);
}
p = lp_gid(i);
if (!name_to_gid(p, &gid)) {
if (!isDigit(p)) {
rprintf(FLOG, "Invalid gid %s\n", p);
io_printf(f_out, "@ERROR: invalid gid %s\n", p);
#endif
if (add_a_group(f_out, p) < 0)
return -1;
}
gid = atoi(p);
}
} else if (am_root) {
if (add_a_group(f_out, NOBODY_GROUP) < 0)
return -1;
}
/* TODO: If we're not root, but the configuration requests
* that we change to some uid other than the current one, then
* log a warning. */
/* TODO: Perhaps take a list of gids, and make them into the
* supplementary groups. */
module_dir = lp_path(i);
if (*module_dir == '\0') {
rprintf(FLOG, "No path specified for module %s\n", name);
io_printf(f_out, "@ERROR: no path setting.\n");
return -1;
}
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0';
p += 2;
} else if ((p = strdup("/")) == NULL) /* MEMORY LEAK */
out_of_memory("rsync_module");
*p = '\0'; /* Temporary... */
if (!(module_chdir = normalize_path(module_dir, True, NULL)))
return path_failure(f_out, module_dir, False);
*p = '/';
if (!(p = normalize_path(p + 2, True, &module_dirlen)))
return path_failure(f_out, strstr(module_dir, "/./"), False);
if (!(full_module_path = normalize_path(module_dir, False, NULL)))
full_module_path = module_dir;
module_dir = p;
} else {
if (!(module_chdir = normalize_path(module_dir, False, NULL)))
return path_failure(f_out, module_dir, False);
full_module_path = module_chdir;
module_dir = "/";
module_dirlen = 1;
}
} else {
if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
return path_failure(f_out, module_dir, False);
full_module_path = module_dir = module_chdir;
}
/* We do a change_dir() that doesn't actually call chdir()
* just to make a relative path absolute. */
strlcpy(line, curr_dir, sizeof line);
if (!change_dir(module_dir, CD_SKIP_CHDIR))
goto chdir_failed;
if (strcmp(curr_dir, module_dir) != 0
&& (module_dir = strdup(curr_dir)) == NULL)
out_of_memory("rsync_module");
change_dir(line, CD_SKIP_CHDIR); /* Restore curr_dir. */
if (use_chroot) {
chroot_path = module_dir;
module_dir = p; /* p is "/" or our inside-chroot path */
}
module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
set_env_str("RSYNC_MODULE_PATH", full_module_path);
if (module_dirlen == 1) {
module_dirlen = 0;
@@ -530,53 +670,32 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
set_filter_dir(module_dir, module_dirlen);
p = lp_filter(i);
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
p = lp_include_from(i);
parse_filter_file(&daemon_filter_list, p, MATCHFLG_INCLUDE,
parse_filter_file(&daemon_filter_list, p, rule_template(FILTRULE_INCLUDE),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
parse_rule(&daemon_filter_list, p,
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
parse_filter_str(&daemon_filter_list, p,
rule_template(FILTRULE_INCLUDE | FILTRULE_WORD_SPLIT),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
parse_filter_file(&daemon_filter_list, p, 0,
parse_filter_file(&daemon_filter_list, p, rule_template(0),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
log_init(1);
#ifdef HAVE_PUTENV
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (!use_chroot)
p = module_dir;
else if (module_dirlen) {
pathjoin(line, sizeof line, chroot_path, module_dir+1);
p = line;
} else
p = chroot_path;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", p) < 0
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
out_of_memory("rsync_module");
putenv(modname);
putenv(modpath);
putenv(hostaddr);
putenv(hostname);
putenv(username);
umask(orig_umask);
/* For post-xfer exec, fork a new process to run the rsync
* daemon while this process waits for the exit status and
* runs the indicated command at that point. */
@@ -588,19 +707,20 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
return -1;
}
if (pid) {
if (asprintf(&p, "RSYNC_PID=%ld", (long)pid) > 0)
putenv(p);
close(f_in);
if (f_out != f_in)
close(f_out);
set_env_num("RSYNC_PID", (long)pid);
if (wait_process(pid, &status, 0) < 0)
status = -1;
if (asprintf(&p, "RSYNC_RAW_STATUS=%d", status) > 0)
putenv(p);
set_env_num("RSYNC_RAW_STATUS", status);
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else
status = -1;
if (asprintf(&p, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(p);
system(lp_postxfer_exec(i));
set_env_num("RSYNC_EXIT_STATUS", status);
if (system(lp_postxfer_exec(i)) < 0)
status = -1;
_exit(status);
}
}
@@ -608,10 +728,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* command, though it first waits for the parent process to
* send us the user's request via a pipe. */
if (*lp_prexfer_exec(i)) {
int fds[2];
if (asprintf(&p, "RSYNC_PID=%ld", (long)getpid()) > 0)
putenv(p);
if (pipe(fds) < 0 || (pre_exec_pid = fork()) < 0) {
int arg_fds[2], error_fds[2];
set_env_num("RSYNC_PID", (long)getpid());
if (pipe(arg_fds) < 0 || pipe(error_fds) < 0 || (pre_exec_pid = fork()) < 0) {
rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
return -1;
@@ -619,37 +738,43 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (pre_exec_pid == 0) {
char buf[BIGPATHBUFLEN];
int j, len;
close(fds[1]);
set_blocking(fds[0]);
len = read_arg_from_pipe(fds[0], buf, BIGPATHBUFLEN);
close(arg_fds[1]);
close(error_fds[0]);
pre_exec_arg_fd = arg_fds[0];
pre_exec_error_fd = error_fds[1];
set_blocking(pre_exec_arg_fd);
set_blocking(pre_exec_error_fd);
len = read_arg_from_pipe(pre_exec_arg_fd, buf, BIGPATHBUFLEN);
if (len <= 0)
_exit(1);
if (asprintf(&p, "RSYNC_REQUEST=%s", buf) > 0)
putenv(p);
set_env_str("RSYNC_REQUEST", buf);
for (j = 0; ; j++) {
len = read_arg_from_pipe(fds[0], buf,
len = read_arg_from_pipe(pre_exec_arg_fd, buf,
BIGPATHBUFLEN);
if (len <= 0) {
if (!len)
break;
_exit(1);
}
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) > 0)
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0)
putenv(p);
}
close(fds[0]);
close(pre_exec_arg_fd);
close(STDIN_FILENO);
close(STDOUT_FILENO);
dup2(pre_exec_error_fd, STDOUT_FILENO);
close(pre_exec_error_fd);
status = system(lp_prexfer_exec(i));
if (!WIFEXITED(status))
_exit(1);
_exit(WEXITSTATUS(status));
}
close(fds[0]);
set_blocking(fds[1]);
pre_exec_fd = fds[1];
close(arg_fds[0]);
close(error_fds[1]);
pre_exec_arg_fd = arg_fds[1];
pre_exec_error_fd = error_fds[0];
set_blocking(pre_exec_arg_fd);
set_blocking(pre_exec_error_fd);
}
umask(0);
}
#endif
@@ -666,65 +791,64 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(chroot_path)) {
rsyserr(FLOG, errno, "chroot %s failed", chroot_path);
if (chroot(module_chdir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!change_dir(module_dir, CD_NORMAL))
goto chdir_failed;
if (module_dirlen)
sanitize_paths = 1;
} else {
if (!change_dir(module_dir, CD_NORMAL)) {
chdir_failed:
rsyserr(FLOG, errno, "chdir %s failed\n", module_dir);
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
sanitize_paths = 1;
module_chdir = module_dir;
}
if (!change_dir(module_chdir, CD_NORMAL))
return path_failure(f_out, module_chdir, True);
if (module_dirlen || !use_chroot)
sanitize_paths = 1;
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
munge_symlinks = !use_chroot || module_dirlen;
if (munge_symlinks) {
STRUCT_STAT st;
if (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);
char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
rprintf(FLOG, "Symlink munging is unsafe when a %s directory exists.\n",
prefix);
io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
exit_cleanup(RERR_UNSUPPORTED);
}
}
if (am_root) {
/* XXXX: You could argue that if the daemon is started
* by a non-root user and they explicitly specify a
* gid, then we should try to change to that gid --
* this could be possible if it's already in their
* supplementary groups. */
/* TODO: Perhaps we need to document that if rsyncd is
* started by somebody other than root it will inherit
* all their supplementary groups. */
if (setgid(gid)) {
rsyserr(FLOG, errno, "setgid %d failed", (int)gid);
if (gid_count) {
if (setgid(gid_list[0])) {
rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_list[0]);
io_printf(f_out, "@ERROR: setgid failed\n");
return -1;
}
#ifdef HAVE_SETGROUPS
/* Get rid of any supplementary groups this process
* might have inheristed. */
if (setgroups(1, &gid)) {
/* Set the group(s) we want to be active. */
if (setgroups(gid_count, gid_list)) {
rsyserr(FLOG, errno, "setgroups failed");
io_printf(f_out, "@ERROR: setgroups failed\n");
return -1;
}
#endif
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
/* pw is set if the user wants all the user's groups. */
if (pw && initgroups(pw->pw_name, pw->pw_gid) < 0) {
rsyserr(FLOG, errno, "initgroups failed");
io_printf(f_out, "@ERROR: initgroups failed\n");
return -1;
}
#endif
}
if (setuid(uid)) {
rsyserr(FLOG, errno, "setuid %d failed", (int)uid);
if (set_uid) {
if (setuid(uid) < 0
#ifdef HAVE_SETEUID
|| seteuid(uid) < 0
#endif
) {
rsyserr(FLOG, errno, "setuid %ld failed", (long)uid);
io_printf(f_out, "@ERROR: setuid failed\n");
return -1;
}
@@ -747,7 +871,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
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 */
save_munge_symlinks = munge_symlinks;
reset_output_levels(); /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv);
if (protect_args && ret) {
orig_early_argv = orig_argv;
@@ -758,9 +884,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
} else
orig_early_argv = NULL;
munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
orig_early_argv, orig_argv);
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_arg_fd, pre_exec_error_fd,
request, orig_early_argv, orig_argv);
}
if (orig_early_argv)
@@ -798,13 +926,12 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
#ifndef DEBUG
/* don't allow the logs to be flooded too fast */
if (verbose > lp_max_verbosity(i))
verbose = lp_max_verbosity(i);
limit_output_verbosity(lp_max_verbosity(i));
#endif
if (protocol_version < 23
&& (protocol_version == 22 || am_sender))
io_start_multiplex_out();
io_start_multiplex_out(f_out);
else if (!ret || err_msg) {
/* We have to get I/O multiplexing started so that we can
* get the error back to the client. This means getting
@@ -828,13 +955,19 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (files_from)
write_byte(f_out, 0);
}
io_start_multiplex_out();
io_start_multiplex_out(f_out);
}
if (!ret || err_msg) {
if (err_msg)
rwrite(FERROR, err_msg, strlen(err_msg), 0);
else
if (err_msg) {
while ((p = strchr(err_msg, '\n')) != NULL) {
int len = p - err_msg + 1;
rwrite(FERROR, err_msg, len, 0);
err_msg += len;
}
if (*err_msg)
rprintf(FERROR, "%s\n", err_msg);
} else
option_error();
msleep(400);
exit_cleanup(RERR_UNSUPPORTED);
@@ -857,7 +990,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
if (lp_timeout(i) && (!io_timeout || lp_timeout(i) < io_timeout))
set_io_timeout(lp_timeout(i));
/* If we have some incoming/outgoing chmod changes, append them to
@@ -882,7 +1015,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
with "list = False". */
static void send_listing(int fd)
{
int n = lp_numservices();
int n = lp_num_modules();
int i;
for (i = 0; i < n; i++) {
@@ -911,7 +1044,7 @@ static int load_config(int globals_only)
int start_daemon(int f_in, int f_out)
{
char line[1024];
char *addr, *host;
const char *addr, *host;
int i;
io_set_sock_fds(f_in, f_out);
@@ -924,7 +1057,7 @@ int start_daemon(int f_in, int f_out)
exit_cleanup(RERR_SYNTAX);
addr = client_addr(f_in);
host = client_name(f_in);
host = lp_reverse_lookup(-1) ? client_name(f_in) : undetermined_hostname;
rprintf(FLOG, "connect from %s (%s)\n", host, addr);
if (!am_server) {
@@ -936,7 +1069,7 @@ int start_daemon(int f_in, int f_out)
return -1;
line[0] = 0;
if (!read_line_old(f_in, line, sizeof line))
if (!read_line_old(f_in, line, sizeof line, 0))
return -1;
if (!*line || strcmp(line, "#list") == 0) {
@@ -972,20 +1105,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) {
if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666)) == -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));
snprintf(pidbuf, sizeof pidbuf, "%d\n", (int)pid);
len = strlen(pidbuf);
if (write(fd, pidbuf, len) != len)
goto failure;
close(fd);
}
@@ -1043,6 +1179,7 @@ int daemon_main(void)
fprintf(stderr, "Failed to parse config file: %s\n", config_file);
exit_cleanup(RERR_SYNTAX);
}
set_dparams(0);
if (no_detach)
create_pid_file();
@@ -1059,7 +1196,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-2008 Wayne Davison
* Copyright (C) 2004-2015 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,11 @@
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;
int want_xattr_optim = 0;
int proper_seed_order = 0;
extern int verbose;
extern int am_server;
extern int am_sender;
extern int local_server;
@@ -33,6 +36,7 @@ extern int inplace;
extern int recurse;
extern int use_qsort;
extern int allow_inc_recurse;
extern int preallocate_files;
extern int append_mode;
extern int fuzzy_basis;
extern int read_batch;
@@ -53,16 +57,18 @@ extern char *partial_dir;
extern char *dest_option;
extern char *files_from;
extern char *filesfrom_host;
extern struct filter_list_struct filter_list;
extern filter_rule_list filter_list;
extern int need_unsorted_flist;
#ifdef ICONV_OPTION
extern iconv_t ic_send, ic_recv;
extern char *iconv_opt;
#endif
/* These index values are for the file-list's extra-attribute array. */
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
int sender_symlink_iconv = 0; /* sender should convert symlink content */
#ifdef ICONV_OPTION
int filesfrom_convert = 0;
@@ -70,6 +76,10 @@ int filesfrom_convert = 0;
#define CF_INC_RECURSE (1<<0)
#define CF_SYMLINK_TIMES (1<<1)
#define CF_SYMLINK_ICONV (1<<2)
#define CF_SAFE_FLIST (1<<3)
#define CF_AVOID_XATTR_OPTIM (1<<4)
#define CF_CHKSUM_SEED_FIX (1<<5)
static const char *client_info;
@@ -157,7 +167,7 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
if (verbose > 3) {
if (DEBUG_GTE(PROTO, 1)) {
rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
am_server? "Server" : "Client", remote_protocol, protocol_version);
}
@@ -184,6 +194,14 @@ void setup_protocol(int f_out,int f_in)
if (read_batch)
check_batch_flags();
#ifndef SUPPORT_PREALLOCATION
if (preallocate_files && !am_sender) {
rprintf(FERROR, "preallocation is not supported on this %s\n",
am_server ? "Server" : "Client");
exit_cleanup(RERR_SYNTAX);
}
#endif
if (protocol_version < 30) {
if (append_mode == 1)
append_mode = 2;
@@ -243,25 +261,40 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
} else if (protocol_version >= 30) {
int compat_flags;
if (am_server) {
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
#ifdef CAN_SET_SYMLINK_TIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
#ifdef ICONV_OPTION
compat_flags |= CF_SYMLINK_ICONV;
#endif
if (local_server || strchr(client_info, 'f') != NULL)
compat_flags |= CF_SAFE_FLIST;
if (local_server || strchr(client_info, 'x') != NULL)
compat_flags |= CF_AVOID_XATTR_OPTIM;
if (local_server || strchr(client_info, 'C') != NULL)
compat_flags |= CF_CHKSUM_SEED_FIX;
write_byte(f_out, compat_flags);
} else
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;
want_xattr_optim = protocol_version >= 31 && !(compat_flags & CF_AVOID_XATTR_OPTIM);
proper_seed_order = compat_flags & CF_CHKSUM_SEED_FIX ? 1 : 0;
if (am_sender) {
receiver_symlink_times = am_server
? strchr(client_info, 'L') != NULL
: !!(compat_flags & CF_SYMLINK_TIMES);
}
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
#ifdef CAN_SET_SYMLINK_TIMES
else
receiver_symlink_times = 1;
#endif
#ifdef ICONV_OPTION
sender_symlink_iconv = iconv_opt && (am_server
? local_server || strchr(client_info, 's') != NULL
: !!(compat_flags & CF_SYMLINK_ICONV));
#endif
if (inc_recurse && !allow_inc_recurse) {
/* This should only be able to happen in a batch. */
@@ -270,8 +303,9 @@ 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) || protocol_version >= 31;
need_messages_from_generator = 1;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
#ifdef CAN_SET_SYMLINK_TIMES
} else if (!am_sender) {
receiver_symlink_times = 1;
#endif
@@ -281,10 +315,10 @@ void setup_protocol(int f_out,int f_in)
unsort_ndx = ++file_extra_cnt;
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
int rflags = FILTRULE_NO_PREFIXES | FILTRULE_DIRECTORY;
if (!am_sender || protocol_version >= 30)
flags |= MATCHFLG_PERISHABLE;
parse_rule(&filter_list, partial_dir, flags, 0);
rflags |= FILTRULE_PERISHABLE;
parse_filter_str(&filter_list, partial_dir, rule_template(rflags), 0);
}
@@ -299,7 +333,7 @@ void setup_protocol(int f_out,int f_in)
if (am_server) {
if (!checksum_seed)
checksum_seed = time(NULL);
checksum_seed = time(NULL) ^ (getpid() << 6);
write_int(f_out, checksum_seed);
} else {
checksum_seed = read_int(f_in);

650
config.guess vendored Executable file → Normal file
View File

@@ -1,14 +1,12 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
# Copyright 1992-2013 Free Software Foundation, Inc.
timestamp='2006-07-02'
timestamp='2013-05-16'
# This file 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 2 of the License, or
# 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
@@ -17,26 +15,22 @@ timestamp='2006-07-02'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Per Bothner <per@bothner.com>.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
# Originally written by Per Bothner.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit build system type.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
#
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -56,8 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -139,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
eval $set_cc_for_build
cat <<-EOF > $dummy.c
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
;;
esac
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -161,6 +175,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
@@ -169,7 +184,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep __ELF__ >/dev/null
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
@@ -179,7 +194,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
os=netbsd
os=netbsd
;;
esac
# The OS release
@@ -200,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
@@ -222,7 +241,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -268,7 +287,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
exit ;;
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
@@ -294,12 +316,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
arm:riscos:*:*|arm:RISCOS:*:*)
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -323,14 +345,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
SUN_ARCH="i386"
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH="x86_64"
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
@@ -374,23 +415,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
@@ -460,8 +501,8 @@ EOF
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -474,7 +515,7 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
@@ -531,7 +572,7 @@ EOF
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[45])
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
@@ -574,52 +615,52 @@ EOF
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -639,7 +680,7 @@ EOF
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep __LP64__ >/dev/null
grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
@@ -710,22 +751,22 @@ EOF
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
@@ -749,14 +790,14 @@ EOF
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -768,37 +809,51 @@ EOF
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
case ${UNAME_MACHINE} in
pc98)
echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
i*:MINGW*:*)
*:MINGW64*:*)
echo ${UNAME_MACHINE}-pc-mingw64
exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
x86:Interix*:[3456]*)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T:Interix*:[3456]*)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
@@ -819,93 +874,21 @@ EOF
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
echo crisv32-axis-linux-gnu
exit ;;
frv:Linux:*:*)
echo frv-unknown-linux-gnu
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
mips:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef mips
#undef mipsel
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=mipsel
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=mips
#else
CPU=
#endif
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^CPU/{
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef mips64
#undef mips64el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=mips64el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=mips64
#else
CPU=
#endif
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^CPU/{
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
echo or32-unknown-linux-gnu
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -916,103 +899,126 @@ EOF
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
or1k:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-gnu ;;
PA8*) echo hppa2.0-unknown-linux-gnu ;;
*) echo hppa-unknown-linux-gnu ;;
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us. cd to the root directory to prevent
# problems with other programs or directories called `ld' in the path.
# Set LC_ALL=C to ensure ld outputs messages in English.
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
| sed -ne '/supported targets:/!d
s/[ ][ ]*/ /g
s/.*supported targets: *//
s/ .*//
p'`
case "$ld_supported_targets" in
elf32-i386)
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
;;
a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
exit ;;
"")
# Either a pre-BFD a.out linker (linux-gnuoldld) or
# one that does not give us useful --help.
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
exit ;;
esac
# Determine whether the default compiler is a.out or elf
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include <features.h>
#ifdef __ELF__
# ifdef __GLIBC__
# if __GLIBC__ >= 2
LIBC=gnu
# else
LIBC=gnulibc1
# endif
# else
LIBC=gnulibc1
# endif
#else
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
LIBC=gnu
#else
LIBC=gnuaout
#endif
#endif
#ifdef __dietlibc__
LIBC=dietlibc
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^LIBC/{
s: ::g
p
}'`"
test x"${LIBC}" != x && {
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit
}
test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
@@ -1020,11 +1026,11 @@ EOF
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
@@ -1041,7 +1047,7 @@ EOF
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
@@ -1056,7 +1062,7 @@ EOF
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
@@ -1084,10 +1090,13 @@ EOF
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i386.
echo i386-pc-msdosdjgpp
exit ;;
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configury will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
@@ -1122,8 +1131,18 @@ EOF
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
@@ -1136,7 +1155,7 @@ EOF
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
@@ -1156,10 +1175,10 @@ EOF
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
@@ -1185,11 +1204,11 @@ EOF
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
@@ -1199,6 +1218,12 @@ EOF
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
@@ -1208,6 +1233,15 @@ EOF
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
@@ -1216,9 +1250,21 @@ EOF
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
eval $set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1232,7 +1278,10 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NSE-?:NONSTOP_KERNEL:*:*)
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
@@ -1277,13 +1326,13 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
@@ -1298,11 +1347,14 @@ EOF
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
eval $set_cc_for_build
cat >$dummy.c <<EOF
#ifdef _SEQUENT_
@@ -1320,11 +1372,11 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
"4"
#else
""
""
#endif
); exit (0);
); exit (0);
#endif
#endif
@@ -1458,9 +1510,9 @@ This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
and
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
If the version you run ($0) is already up to date, please
send the following data and any information you think might be

382
config.sub vendored Executable file → Normal file
View File

@@ -1,44 +1,40 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
# Copyright 1992-2013 Free Software Foundation, Inc.
timestamp='2006-07-02'
timestamp='2013-04-24'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
#
# This file 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 2 of the License, or
# This file 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.
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -72,8 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -120,12 +115,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -148,10 +149,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray)
-apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -166,10 +170,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
;;
-hiux*)
os=-hiuxwe2
;;
@@ -214,6 +218,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
@@ -238,24 +248,34 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64vr | mips64vrel \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
@@ -266,30 +286,45 @@ case $basic_machine in
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nios | nios2 \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| or32 \
| open8 \
| or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -299,6 +334,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -313,29 +363,37 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64vr-* | mips64vrel-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
@@ -346,31 +404,41 @@ case $basic_machine in
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-*)
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -388,7 +456,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -434,6 +502,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -442,10 +514,35 @@ case $basic_machine in
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@@ -474,8 +571,8 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
@@ -513,6 +610,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
@@ -628,7 +729,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -667,6 +767,14 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
@@ -678,10 +786,21 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
mingw64)
basic_machine=x86_64-pc
os=-mingw64
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
@@ -710,10 +829,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i386-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -778,6 +905,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -808,6 +941,14 @@ case $basic_machine in
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
@@ -852,9 +993,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -879,7 +1021,11 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
rdos | rdos64)
basic_machine=x86_64-pc
os=-rdos
;;
rdos32)
basic_machine=i386-pc
os=-rdos
;;
@@ -909,6 +1055,10 @@ case $basic_machine in
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
@@ -920,6 +1070,9 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
@@ -941,6 +1094,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
@@ -997,17 +1153,9 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tic55x | c55x*)
basic_machine=tic55x-unknown
os=-coff
;;
tic6x | c6x*)
basic_machine=tic6x-unknown
os=-coff
tile*)
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
@@ -1076,6 +1224,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1084,6 +1235,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@@ -1122,7 +1277,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1169,9 +1324,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1192,21 +1350,23 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1214,7 +1374,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1253,7 +1413,7 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
-os400*)
os=-os400
;;
-wince*)
@@ -1302,7 +1462,7 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
-tpf*)
os=-tpf
;;
-triton*)
@@ -1338,12 +1498,14 @@ case $os in
-aros*)
os=-aros
;;
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
@@ -1366,7 +1528,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
spu-*)
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
@@ -1378,8 +1543,20 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
c4x-* | tic4x-*)
os=-coff
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1399,19 +1576,22 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
or1k-*)
os=-elf
;;
or32-*)
os=-coff
;;
@@ -1430,7 +1610,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-knuth)
*-knuth)
os=-mmixware
;;
*-wec)
@@ -1535,7 +1715,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
-aix*)
-cnk*|-aix*)
vendor=ibm
;;
-beos*)

2
configure vendored
View File

@@ -8,6 +8,8 @@ realconfigure="$dir/configure.sh"
if test ! -f "$realconfigure"; then
if test -f "$HOME/build_farm/build_test.fns"; then
# Test the included popt
set -- --with-included-popt "${@}"
# Allow the build farm to grab latest files via rsync.
actions='build fetch'
else

View File

@@ -1,34 +1,24 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT()
AC_INIT([rsync],[3.1.2pre1],[http://rsync.samba.org/bugzilla.html])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
AC_PREREQ([2.69])
RSYNC_VERSION=3.0.3
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
AC_SUBST(RSYNC_VERSION, $PACKAGE_VERSION)
AC_MSG_NOTICE([Configuring rsync $PACKAGE_VERSION])
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$PACKAGE_VERSION"], [rsync release version])
LDFLAGS=${LDFLAGS-""}
AC_CANONICAL_TARGET([])
AC_CANONICAL_HOST
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
dnl define the directory for replacement function since AC_LIBOBJ does not
dnl officially support subdirs and fails with automake
AC_CONFIG_LIBOBJ_DIR([lib])
# We must decide this before testing the compiler.
@@ -37,23 +27,36 @@ fi
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--disable-debug],
[disable debugging symbols and features]))
AS_HELP_STRING([--disable-debug],[disable debugging symbols and features]))
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_MKDIR_P
AC_PROG_CC_STDC
AC_SUBST(SHELL)
AC_PATH_PROG([PERL], [perl])
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],
[turn on CPU profiling]))
AS_HELP_STRING([--enable-profile],[turn on CPU profiling]))
if test x"$enable_profile" = x"yes"; then
CFLAGS="$CFLAGS -pg"
fi
@@ -61,8 +64,7 @@ fi
# Specifically, this turns on panic_action handling.
AC_ARG_ENABLE(maintainer-mode,
AC_HELP_STRING([--enable-maintainer-mode],
[turn on extra debug features]))
AS_HELP_STRING([--enable-maintainer-mode],[turn on extra debug features]))
if test x"$enable_maintainer_mode" = x"yes"; then
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
fi
@@ -78,17 +80,26 @@ if test x"$GCC" = x"yes"; then
fi
AC_ARG_WITH(included-popt,
AC_HELP_STRING([--with-included-popt], [use bundled popt library, not from system]))
AS_HELP_STRING([--with-included-popt],[use bundled popt library, not from system]))
AC_ARG_WITH(included-zlib,
AS_HELP_STRING([--with-included-zlib],[use bundled zlib library, not from system]))
AC_ARG_WITH(protected-args,
AS_HELP_STRING([--with-protected-args],[make --protected-args option the default]))
if test x"$with_protected_args" = x"yes"; then
AC_DEFINE_UNQUOTED(RSYNC_USE_PROTECTED_ARGS, 1, [Define to 1 if --protected-args should be the default])
fi
AC_ARG_WITH(rsync-path,
AC_HELP_STRING([--with-rsync-path=PATH], [set default --rsync-path to PATH (default: rsync)]),
AS_HELP_STRING([--with-rsync-path=PATH],[set default --rsync-path to PATH (default: rsync)]),
[ RSYNC_PATH="$with_rsync_path" ],
[ RSYNC_PATH="rsync" ])
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
AC_ARG_WITH(rsyncd-conf,
AC_HELP_STRING([--with-rsyncd-conf=PATH], [set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
AS_HELP_STRING([--with-rsyncd-conf=PATH],[set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
[ if test ! -z "$with_rsyncd_conf" ; then
case $with_rsyncd_conf in
yes|no)
@@ -109,7 +120,7 @@ AC_ARG_WITH(rsyncd-conf,
AC_DEFINE_UNQUOTED(RSYNCD_SYSCONF, "$RSYNCD_SYSCONF", [location of configuration file for rsync server])
AC_ARG_WITH(rsh,
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
AS_HELP_STRING([--with-rsh=CMD],[set remote shell command to CMD (default: ssh)]))
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
if test x$HAVE_REMSH = x1; then
@@ -126,11 +137,16 @@ 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
else
MAKE_MAN=man-copy
fi
# Some programs on solaris are only found in /usr/xpg4/bin (or work better than others versions).
AC_PATH_PROG(SHELL_PATH, sh, /bin/sh, [/usr/xpg4/bin$PATH_SEPARATOR$PATH])
AC_PATH_PROG(FAKEROOT_PATH, fakeroot, /usr/bin/fakeroot, [/usr/xpg4/bin$PATH_SEPARATOR$PATH])
AC_ARG_WITH(nobody-group,
AC_HELP_STRING([--with-nobody-group=GROUP],
[set the default unprivileged group (default nobody or nogroup)]),
AS_HELP_STRING([--with-nobody-group=GROUP],[set the default unprivileged group (default nobody or nogroup)]),
[ NOBODY_GROUP="$with_nobody_group" ])
if test x"$with_nobody_group" = x; then
@@ -151,7 +167,7 @@ AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unpriv
# arrgh. libc in some old debian version screwed up the largefile
# stuff, getting byte range locking wrong
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <fcntl.h>
@@ -183,8 +199,7 @@ int main(void)
unlink(tpl);
exit(WEXITSTATUS(status));
}
],
rsync_cv_HAVE_BROKEN_LARGEFILE=yes,rsync_cv_HAVE_BROKEN_LARGEFILE=no,rsync_cv_HAVE_BROKEN_LARGEFILE=cross)])
]])],[rsync_cv_HAVE_BROKEN_LARGEFILE=yes],[rsync_cv_HAVE_BROKEN_LARGEFILE=no],[rsync_cv_HAVE_BROKEN_LARGEFILE=cross])])
if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
AC_SYS_LARGEFILE
fi
@@ -194,11 +209,10 @@ ipv6lib=none
ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6],
[don't even try to use IPv6]))
AS_HELP_STRING([--disable-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/
@@ -242,6 +256,16 @@ AC_DEFINE(INET6, 1, [true if you have IPv6])])
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
solaris)
# http://www.sun.com
AC_EGREP_CPP(yes, [
#include <netinet/ip6.h>
#ifdef __sun
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
toshiba)
AC_EGREP_CPP(yes, [
#include <sys/param.h>
@@ -275,6 +299,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
@@ -287,10 +320,9 @@ fi
dnl Do you want to disable use of locale functions
AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale],
[disable locale features]))
AS_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
@@ -314,11 +346,12 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
sys/un.h sys/attr.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h \
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
popt.h popt/popt.h)
popt.h popt/popt.h linux/falloc.h netinet/in_systm.h netinet/ip.h \
zlib.h)
AC_HEADER_MAJOR
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sys/types.h>
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
@@ -336,8 +369,7 @@ int main(void)
exit(1);
return 0;
}
],
rsync_cv_MAKEDEV_TAKES_3_ARGS=yes,rsync_cv_MAKEDEV_TAKES_3_ARGS=no,rsync_cv_MAKEDEV_TAKES_3_ARGS=no)])
]])],[rsync_cv_MAKEDEV_TAKES_3_ARGS=yes],[rsync_cv_MAKEDEV_TAKES_3_ARGS=no],[rsync_cv_MAKEDEV_TAKES_3_ARGS=no])])
if test x"$rsync_cv_MAKEDEV_TAKES_3_ARGS" = x"yes"; then
AC_DEFINE(MAKEDEV_TAKES_3_ARGS, 1, [Define to 1 if makedev() takes 3 args])
fi
@@ -356,19 +388,33 @@ AC_CHECK_SIZEOF(off64_t)
AC_CHECK_SIZEOF(time_t)
AC_C_INLINE
AC_C_LONG_DOUBLE
AC_TYPE_SIGNAL
AC_TYPE_LONG_DOUBLE_WIDER
ac_cv_c_long_double=$ac_cv_type_long_double_wider
if test $ac_cv_c_long_double = yes; then
AC_DEFINE([HAVE_LONG_DOUBLE],[1],[Define to 1 if the type `long double' works and has more range or precision than `double'.])
fi
AC_TYPE_UID_T
AC_CHECK_TYPES([mode_t,off_t,size_t,pid_t,id_t])
AC_TYPE_GETGROUPS
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_MEMBERS([struct stat.st_rdev,
struct stat.st_mtimensec,
struct stat.st_mtim.tv_nsec],,,[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif])
TYPE_SOCKLEN_T
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
rsync_cv_errno=yes,rsync_cv_have_errno_decl=no)])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <errno.h>]], [[int i = errno]])],[rsync_cv_errno=yes],[rsync_cv_have_errno_decl=no])])
if test x"$rsync_cv_errno" = x"yes"; then
AC_DEFINE(HAVE_ERRNO_DECL, 1, [Define to 1 if errno is declared in errno.h])
fi
@@ -411,13 +457,15 @@ 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])
AC_CACHE_VAL(am_cv_proto_iconv, [
AC_TRY_COMPILE([
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <iconv.h>
extern
@@ -429,7 +477,7 @@ size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, si
#else
size_t iconv();
#endif
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
]], [[]])],[am_cv_proto_iconv_arg1=""],[am_cv_proto_iconv_arg1="const"])
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
AC_MSG_RESULT([$]{ac_t:-
@@ -439,8 +487,7 @@ AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
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_REPLACE_FUNCS([inet_ntop inet_pton])
AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>])
AC_HAVE_TYPE([struct sockaddr_storage], [#include <sys/types.h>
@@ -459,23 +506,19 @@ 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" -a x"$ac_cv_type_struct_addrinfo" = x"yes"; then
AS_IF([test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" -a x"$ac_cv_type_struct_addrinfo" = x"yes"],[
# Tru64 UNIX has getaddrinfo() but has it renamed in libc as
# something else so we must include <netdb.h> to get the
# redefinition.
AC_CHECK_FUNCS(getaddrinfo, ,
[AC_MSG_CHECKING([for getaddrinfo by including <netdb.h>])
AC_TRY_LINK([#include <sys/types.h>
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
[AC_MSG_RESULT([yes])
#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 and required types.])],
[AC_MSG_RESULT([no])
AC_LIBOBJ(lib/getaddrinfo)])])
else
AC_LIBOBJ(lib/getaddrinfo)
fi
[Define to 1 if you have the "getaddrinfo" function and required types.])],[AC_MSG_RESULT([no])
AC_LIBOBJ([getaddrinfo])])])
],[AC_LIBOBJ([getaddrinfo])])
AC_CHECK_MEMBER([struct sockaddr.sa_len],
[ AC_DEFINE(HAVE_SOCKADDR_LEN, 1, [Do we have sockaddr.sa_len?]) ],
@@ -553,23 +596,63 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
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 getgrouplist \
initgroups utimensat posix_fallocate attropen setvbuf usleep)
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
dnl Preallocation stuff (also fallocate, posix_fallocate function tests above):
AC_CACHE_CHECK([for useable fallocate],rsync_cv_have_fallocate,[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h>
#include <sys/types.h>]], [[fallocate(0, 0, 0, 0);]])],[rsync_cv_have_fallocate=yes],[rsync_cv_have_fallocate=no])])
if test x"$rsync_cv_have_fallocate" = x"yes"; then
AC_DEFINE(HAVE_FALLOCATE, 1, [Define to 1 if you have the fallocate function and it compiles and links without error])
fi
AC_CACHE_CHECK([for SYS_fallocate],rsync_cv_have_sys_fallocate,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/syscall.h>
#include <sys/types.h>]], [[syscall(SYS_fallocate, 0, 0, (loff_t)0, (loff_t)0);]])],[rsync_cv_have_sys_fallocate=yes],[rsync_cv_have_sys_fallocate=no])])
if test x"$rsync_cv_have_sys_fallocate" = x"yes"; then
AC_DEFINE(HAVE_SYS_FALLOCATE, 1, [Define to 1 if you have the SYS_fallocate syscall number])
fi
if test x"$ac_cv_func_posix_fallocate" = x"yes"; then
AC_MSG_CHECKING([whether posix_fallocate is efficient])
case $host_os in
*cygwin*)
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EFFICIENT_POSIX_FALLOCATE, 1,
[Define if posix_fallocate is efficient (Cygwin)])
;;
*)
AC_MSG_RESULT(no)
;;
esac
fi
dnl End of preallocation stuff
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
fi
AC_ARG_ENABLE(iconv-open,
AS_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])
AS_HELP_STRING([--disable-iconv],[disable rsync's --iconv option]),
[], [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).])
@@ -583,7 +666,7 @@ if test x"$enable_iconv" != x"no"; then
fi
AC_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symlink,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -595,14 +678,13 @@ AC_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symli
if (symlink("conftest.no-such", dangling_symlink) < 0) abort();
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(1);
exit(0);
}],
rsync_cv_chown_modifies_symlink=yes,rsync_cv_chown_modifies_symlink=no,rsync_cv_chown_modifies_symlink=no)])
}]])],[rsync_cv_chown_modifies_symlink=yes],[rsync_cv_chown_modifies_symlink=no],[rsync_cv_chown_modifies_symlink=no])])
if test $rsync_cv_chown_modifies_symlink = yes; then
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -612,16 +694,16 @@ AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_sym
main() {
unlink(FILENAME);
if (symlink("conftest.no-such", FILENAME) < 0) abort();
unlink(FILENAME "2");
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_symlink=yes,rsync_cv_can_hardlink_symlink=no,rsync_cv_can_hardlink_symlink=no)])
}]])],[rsync_cv_can_hardlink_symlink=yes],[rsync_cv_can_hardlink_symlink=no],[rsync_cv_can_hardlink_symlink=no])])
if test $rsync_cv_can_hardlink_symlink = yes; then
AC_DEFINE(CAN_HARDLINK_SYMLINK, 1, [Define to 1 if link() can hard-link symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link special files],rsync_cv_can_hardlink_special,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -631,28 +713,29 @@ AC_CACHE_CHECK([whether link() can hard-link special files],rsync_cv_can_hardlin
main() {
unlink(FILENAME);
if (mkfifo(FILENAME, 0777) < 0) abort();
unlink(FILENAME "2");
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_special=yes,rsync_cv_can_hardlink_special=no,rsync_cv_can_hardlink_special=no)])
}]])],[rsync_cv_can_hardlink_special=yes],[rsync_cv_can_hardlink_special=no],[rsync_cv_can_hardlink_special=no])])
if test $rsync_cv_can_hardlink_special = yes; then
AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
fi
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sys/types.h>
#include <sys/socket.h>
main() {
int fd[2];
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
}],
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
}]])],[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
AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function])
fi
AC_REPLACE_FUNCS([getpass])
if test x"$with_included_popt" != x"yes"; then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
fi
@@ -670,7 +753,7 @@ AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"; then
AC_MSG_RESULT($srcdir/popt)
BUILD_POPT='$(popt_OBJS)'
CFLAGS="$CFLAGS -I$srcdir/popt"
CFLAGS="-I$srcdir/popt $CFLAGS"
if test x"$ALLOCA" != x
then
# this can be removed when/if we add an included alloca.c;
@@ -681,44 +764,58 @@ else
AC_MSG_RESULT(no)
fi
# We default to using our zlib unless --with-included-zlib=no is given.
if test x"$with_included_zlib" != x"no"; then
with_included_zlib=yes
elif test x"$ac_cv_header_zlib_h" != x"yes"; then
with_included_zlib=yes
fi
if test x"$with_included_zlib" != x"yes"; then
AC_CHECK_LIB(z, deflateParams, , [with_included_zlib=yes])
fi
AC_MSG_CHECKING([whether to use included zlib])
if test x"$with_included_zlib" = x"yes"; then
AC_MSG_RESULT($srcdir/zlib)
BUILD_ZLIB='$(zlib_OBJS)'
CFLAGS="-I$srcdir/zlib $CFLAGS"
else
AC_DEFINE(EXTERNAL_ZLIB, 1, [Define to 1 if using external zlib])
AC_MSG_RESULT(no)
fi
AC_CACHE_CHECK([for unsigned char],rsync_cv_SIGNED_CHAR_OK,[
AC_TRY_COMPILE([],[signed char *s = ""],
rsync_cv_SIGNED_CHAR_OK=yes,rsync_cv_SIGNED_CHAR_OK=no)])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[signed char *s = ""]])],[rsync_cv_SIGNED_CHAR_OK=yes],[rsync_cv_SIGNED_CHAR_OK=no])])
if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
AC_DEFINE(SIGNED_CHAR_OK, 1, [Define to 1 if "signed char" is a valid type])
fi
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
AC_TRY_RUN([#include <sys/types.h>
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <sys/types.h>
#include <dirent.h>
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) exit(0); exit(1);} ],
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
di->d_name[0] == 0) exit(0); exit(1);} ]])],[rsync_cv_HAVE_BROKEN_READDIR=yes],[rsync_cv_HAVE_BROKEN_READDIR=no],[rsync_cv_HAVE_BROKEN_READDIR=cross])])
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_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_STRUCT_UTIMBUF=yes,rsync_cv_HAVE_STRUCT_UTIMBUF=no)])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <utime.h>]], [[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));]])],[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,[
AC_TRY_COMPILE([#include <sys/time.h>
#include <unistd.h>],
[struct timeval tv; exit(gettimeofday(&tv, NULL));],
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no)])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/time.h>
#include <unistd.h>]], [[struct timeval tv; exit(gettimeofday(&tv, NULL));]])],[rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes],[rsync_cv_HAVE_GETTIMEOFDAY_TZ=no])])
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" != x"no"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [Define to 1 if gettimeofday() takes a time-zone arg])
fi
AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sys/types.h>
#include <stdarg.h>
void foo(const char *format, ...) {
@@ -736,15 +833,14 @@ void foo(const char *format, ...) {
exit(0);
}
main() { foo("hello"); }
],
rsync_cv_HAVE_C99_VSNPRINTF=yes,rsync_cv_HAVE_C99_VSNPRINTF=no,rsync_cv_HAVE_C99_VSNPRINTF=cross)])
]])],[rsync_cv_HAVE_C99_VSNPRINTF=yes],[rsync_cv_HAVE_C99_VSNPRINTF=no],[rsync_cv_HAVE_C99_VSNPRINTF=cross])])
if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [Define to 1 if vsprintf has a C99-compatible return value])
fi
AC_CACHE_CHECK([for secure mkstemp],rsync_cv_HAVE_SECURE_MKSTEMP,[
AC_TRY_RUN([#include <stdlib.h>
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -757,12 +853,9 @@ main() {
if (fstat(fd, &st) != 0) exit(1);
if ((st.st_mode & 0777) != 0600) exit(1);
exit(0);
}],
rsync_cv_HAVE_SECURE_MKSTEMP=yes,
rsync_cv_HAVE_SECURE_MKSTEMP=no,
rsync_cv_HAVE_SECURE_MKSTEMP=cross)])
}]])],[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
@@ -777,29 +870,27 @@ fi
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
main() { int rc, ec; char *fn = "fifo-test";
unlink(fn); rc = mknod(fn,S_IFIFO,0600); ec = errno; unlink(fn);
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_FIFOS=yes,rsync_cv_MKNOD_CREATES_FIFOS=no,rsync_cv_MKNOD_CREATES_FIFOS=cross)])
return 0;}]])],[rsync_cv_MKNOD_CREATES_FIFOS=yes],[rsync_cv_MKNOD_CREATES_FIFOS=no],[rsync_cv_MKNOD_CREATES_FIFOS=cross])])
if test x"$rsync_cv_MKNOD_CREATES_FIFOS" = x"yes"; then
AC_DEFINE(MKNOD_CREATES_FIFOS, 1, [Define to 1 if mknod() can create FIFOs.])
fi
AC_CACHE_CHECK([if mknod creates sockets],rsync_cv_MKNOD_CREATES_SOCKETS,[
AC_TRY_RUN([
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
main() { int rc, ec; char *fn = "sock-test";
unlink(fn); rc = mknod(fn,S_IFSOCK,0600); ec = errno; unlink(fn);
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_SOCKETS=yes,rsync_cv_MKNOD_CREATES_SOCKETS=no,rsync_cv_MKNOD_CREATES_SOCKETS=cross)])
return 0;}]])],[rsync_cv_MKNOD_CREATES_SOCKETS=yes],[rsync_cv_MKNOD_CREATES_SOCKETS=no],[rsync_cv_MKNOD_CREATES_SOCKETS=cross])])
if test x"$rsync_cv_MKNOD_CREATES_SOCKETS" = x"yes"; then
AC_DEFINE(MKNOD_CREATES_SOCKETS, 1, [Define to 1 if mknod() can create sockets.])
fi
@@ -834,16 +925,19 @@ AC_SUBST(OBJ_SAVE)
AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_SUBST(BUILD_POPT)
AC_SUBST(BUILD_ZLIB)
AC_SUBST(MAKE_MAN)
AC_PATH_PROG([STUNNEL], [stunnel], [stunnel], [$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
AC_PATH_PROG([STUNNEL4], [stunnel4], [$STUNNEL], [$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
AC_CHECK_FUNCS(_acl __acl _facl __facl)
#################################################
# check for ACL support
AC_MSG_CHECKING([whether to support ACLs])
AC_ARG_ENABLE(acl-support,
AC_HELP_STRING([--disable-acl-support],
[disable ACL support]))
AS_HELP_STRING([--disable-acl-support],[disable ACL support]))
if test x"$enable_acl_support" = x"no"; then
AC_MSG_RESULT(no)
@@ -854,7 +948,7 @@ else
AC_DEFINE(HAVE_UNIXWARE_ACLS, 1, [true if you have UnixWare ACLs])
AC_DEFINE(SUPPORT_ACLS, 1, [Define to 1 to add support for ACLs])
;;
*solaris*|*cygwin*)
solaris*|*cygwin*)
AC_MSG_RESULT(Using solaris ACLs)
AC_DEFINE(HAVE_SOLARIS_ACLS, 1, [true if you have solaris ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
@@ -888,21 +982,17 @@ else
*)
AC_MSG_RESULT(running tests:)
AC_CHECK_LIB(acl,acl_get_file)
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
AC_TRY_LINK([#include <sys/types.h>
#include <sys/acl.h>],
[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);],
samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no)])
AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/acl.h>]], [[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);]])],[samba_cv_HAVE_POSIX_ACLS=yes],[samba_cv_HAVE_POSIX_ACLS=no])])
AC_MSG_CHECKING(ACL test results)
if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then
AC_MSG_RESULT(Using posix ACLs)
AC_DEFINE(HAVE_POSIX_ACLS, 1, [true if you have posix ACLs])
AC_DEFINE(SUPPORT_ACLS, 1)
AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[
AC_TRY_LINK([#include <sys/types.h>
#include <sys/acl.h>],
[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);],
samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
#include <sys/acl.h>]], [[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);]])],[samba_cv_HAVE_ACL_GET_PERM_NP=yes],[samba_cv_HAVE_ACL_GET_PERM_NP=no])])
if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
AC_DEFINE(HAVE_ACL_GET_PERM_NP, 1, [true if you have acl_get_perm_np])
fi
@@ -921,9 +1011,8 @@ fi
# check for extended attribute support
AC_MSG_CHECKING(whether to support extended attributes)
AC_ARG_ENABLE(xattr-support,
AC_HELP_STRING([--disable-xattr-support],
[disable extended attributes]),
[], [case "$ac_cv_func_getxattr$ac_cv_func_extattr_get_link" in
AS_HELP_STRING([--disable-xattr-support],[disable extended attributes]),
[], [case "$ac_cv_func_getxattr$ac_cv_func_extattr_get_link$ac_cv_func_attropen" in
*yes*) enable_xattr_support=maybe ;;
*) enable_xattr_support=no ;;
esac])
@@ -937,17 +1026,27 @@ else
AC_MSG_RESULT(Using Linux xattrs)
AC_DEFINE(HAVE_LINUX_XATTRS, 1, [True if you have Linux xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
AC_DEFINE(NO_SYMLINK_USER_XATTRS, 1, [True if symlinks do not support user xattrs])
AC_CHECK_LIB(attr,getxattr)
;;
darwin*)
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*)
AC_MSG_RESULT(Using Solaris xattrs)
AC_DEFINE(HAVE_SOLARIS_XATTRS, 1, [True if you have Solaris xattrs])
AC_DEFINE(SUPPORT_XATTRS, 1)
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)
@@ -962,7 +1061,7 @@ if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wno-unused-parameter"
AC_COMPILE_IFELSE([ ], [rsync_warn_flag=yes], [rsync_warn_flag=no])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#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"
@@ -981,3 +1080,8 @@ AC_OUTPUT
AC_MSG_RESULT()
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
AC_MSG_RESULT()
if test x$HAVE_YODL2MAN != x1; then
AC_MSG_RESULT([ Note that yodl2man was not found, so pre-existing manpage files will be])
AC_MSG_RESULT([ used w/o change (if available) -- no .yo file changes will be used.])
AC_MSG_RESULT()
fi

240
delete.c Normal file
View File

@@ -0,0 +1,240 @@
/*
* Deletion routines used in rsync.
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2015 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"
extern int am_root;
extern int make_backups;
extern int max_delete;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
extern struct stats stats;
int ignore_perishable = 0;
int non_perishable_cnt = 0;
int skipped_deletes = 0;
static inline int is_backup_file(char *fn)
{
int k = strlen(fn) - backup_suffix_len;
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
}
/* The directory is about to be deleted: if DEL_RECURSE is given, delete all
* its contents, otherwise just checks for content. Returns DR_SUCCESS or
* DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The
* buffer is used for recursion, but returned unchanged.)
*/
static enum delret delete_dir_contents(char *fname, uint16 flags)
{
struct file_list *dirlist;
enum delret ret;
unsigned remainder;
void *save_filters;
int j, dlen;
char *p;
if (DEBUG_GTE(DEL, 3)) {
rprintf(FINFO, "delete_dir_contents(%s) flags=%d\n",
fname, flags);
}
dlen = strlen(fname);
save_filters = push_local_filters(fname, dlen);
non_perishable_cnt = 0;
dirlist = get_dirlist(fname, dlen, 0);
ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
if (!dirlist->used)
goto done;
if (!(flags & DEL_RECURSE)) {
ret = DR_NOT_EMPTY;
goto done;
}
p = fname + dlen;
if (dlen != 1 || *fname != '/')
*p++ = '/';
remainder = MAXPATHLEN - (p - fname);
/* We do our own recursion, so make delete_item() non-recursive. */
flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM|DEL_NO_UID_WRITE))
| DEL_DIR_IS_EMPTY;
for (j = dirlist->used; j--; ) {
struct file_struct *fp = dirlist->files[j];
if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) {
if (DEBUG_GTE(DEL, 1)) {
rprintf(FINFO,
"mount point, %s, pins parent directory\n",
f_name(fp, NULL));
}
ret = DR_NOT_EMPTY;
continue;
}
strlcpy(p, fp->basename, remainder);
if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
do_chmod(fname, fp->mode | S_IWUSR);
/* Save stack by recursing to ourself directly. */
if (S_ISDIR(fp->mode)) {
if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
fname[dlen] = '\0';
done:
flist_free(dirlist);
pop_local_filters(save_filters);
if (ret == DR_NOT_EMPTY) {
rprintf(FINFO, "cannot delete non-empty directory: %s\n",
fname);
}
return ret;
}
/* Delete a file or directory. If DEL_RECURSE is set in the flags, this will
* delete recursively.
*
* Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
* a directory! (The buffer is used for recursion, but returned unchanged.)
*/
enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
{
enum delret ret;
char *what;
int ok;
if (DEBUG_GTE(DEL, 2)) {
rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n",
fbuf, (int)mode, (int)flags);
}
if (flags & DEL_NO_UID_WRITE)
do_chmod(fbuf, mode | S_IWUSR);
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
/* This only happens on the first call to delete_item() since
* delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
ignore_perishable = 1;
/* If DEL_RECURSE is not set, this just reports emptiness. */
ret = delete_dir_contents(fbuf, flags);
ignore_perishable = 0;
if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
goto check_ret;
/* OK: try to delete the directory. */
}
if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && stats.deleted_files >= max_delete) {
skipped_deletes++;
return DR_AT_LIMIT;
}
if (S_ISDIR(mode)) {
what = "rmdir";
ok = do_rmdir(fbuf) == 0;
} else {
if (make_backups > 0 && !(flags & DEL_FOR_BACKUP) && (backup_dir || !is_backup_file(fbuf))) {
what = "make_backup";
ok = make_backup(fbuf, True);
if (ok == 2) {
what = "unlink";
ok = robust_unlink(fbuf) == 0;
}
} else {
what = "unlink";
ok = robust_unlink(fbuf) == 0;
}
}
if (ok) {
if (!(flags & DEL_MAKE_ROOM)) {
log_delete(fbuf, mode);
stats.deleted_files++;
if (S_ISREG(mode)) {
/* Nothing more to count */
} else if (S_ISDIR(mode))
stats.deleted_dirs++;
#ifdef SUPPORT_LINKS
else if (S_ISLNK(mode))
stats.deleted_symlinks++;
#endif
else if (IS_DEVICE(mode))
stats.deleted_symlinks++;
else
stats.deleted_specials++;
}
ret = DR_SUCCESS;
} else {
if (S_ISDIR(mode) && errno == ENOTEMPTY) {
rprintf(FINFO, "cannot delete non-empty directory: %s\n",
fbuf);
ret = DR_NOT_EMPTY;
} else if (errno != ENOENT) {
rsyserr(FERROR_XFER, errno, "delete_file: %s(%s) failed",
what, fbuf);
ret = DR_FAILURE;
} else
ret = DR_SUCCESS;
}
check_ret:
if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {
const char *desc;
switch (flags & DEL_MAKE_ROOM) {
case DEL_FOR_FILE: desc = "regular file"; break;
case DEL_FOR_DIR: desc = "directory"; break;
case DEL_FOR_SYMLINK: desc = "symlink"; break;
case DEL_FOR_DEVICE: desc = "device file"; break;
case DEL_FOR_SPECIAL: desc = "special file"; break;
default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
}
rprintf(FERROR_XFER, "could not make way for %s %s: %s\n",
flags & DEL_FOR_BACKUP ? "backup" : "new",
desc, fbuf);
}
return ret;
}
uint16 get_del_for_flag(uint16 mode)
{
if (S_ISREG(mode))
return DEL_FOR_FILE;
if (S_ISDIR(mode))
return DEL_FOR_DIR;
if (S_ISLNK(mode))
return DEL_FOR_SYMLINK;
if (IS_DEVICE(mode))
return DEL_FOR_DEVICE;
if (IS_SPECIAL(mode))
return DEL_FOR_SPECIAL;
exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
}

View File

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

772
exclude.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004-2008 Wayne Davison
* Copyright (C) 2004-2015 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
@@ -20,46 +20,58 @@
*/
#include "rsync.h"
#include "inums.h"
#ifndef ENODATA
#define ENODATA EAGAIN
#endif
/* We want all reads to be aligned on 1K boundries. */
#define ALIGN_BOUNDRY 1024
/* How far past the boundary is an offset? */
#define ALIGNED_OVERSHOOT(oft) ((oft) & (ALIGN_BOUNDRY-1))
/* Round up a length to the next boundary */
#define ALIGNED_LENGTH(len) ((((len) - 1) | (ALIGN_BOUNDRY-1)) + 1)
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)
@@ -72,11 +84,14 @@ static int write_sparse(int f, char *buf, size_t len)
while ((ret = write(f, buf + l1, len - (l1+l2))) <= 0) {
if (ret < 0 && errno == EINTR)
continue;
sparse_seek = 0;
return ret;
}
if (ret != (int)(len - (l1+l2)))
if (ret != (int)(len - (l1+l2))) {
sparse_seek = 0;
return l1+ret;
}
return len;
}
@@ -108,7 +123,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 +140,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;
@@ -154,8 +169,7 @@ int write_file(int f,char *buf,size_t len)
* It gives sliding window access to a file. mmap() is not used because of
* the possibility of another program (such as a mailer) truncating the
* file thus giving us a SIGBUS. */
struct map_struct *map_file(int fd, OFF_T len, int32 read_size,
int32 blk_size)
struct map_struct *map_file(int fd, OFF_T len, int32 read_size, int32 blk_size)
{
struct map_struct *map;
@@ -167,7 +181,7 @@ struct map_struct *map_file(int fd, OFF_T len, int32 read_size,
map->fd = fd;
map->file_size = len;
map->def_window_size = read_size;
map->def_window_size = ALIGNED_LENGTH(read_size);
return map;
}
@@ -176,9 +190,8 @@ struct map_struct *map_file(int fd, OFF_T len, int32 read_size,
/* slide the read window in the file */
char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
{
int32 nread;
OFF_T window_start, read_start;
int32 window_size, read_size, read_offset;
int32 window_size, read_size, read_offset, align_fudge;
if (len == 0)
return NULL;
@@ -193,12 +206,13 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
return map->p + (offset - map->p_offset);
/* nope, we are going to have to do a read. Work out our desired window */
window_start = offset;
align_fudge = (int32)ALIGNED_OVERSHOOT(offset);
window_start = offset - align_fudge;
window_size = map->def_window_size;
if (window_start + window_size > map->file_size)
window_size = (int32)(map->file_size - window_start);
if (len > window_size)
window_size = len;
if (window_size < len + align_fudge)
window_size = ALIGNED_LENGTH(len + align_fudge);
/* make sure we have allocated enough memory for the window */
if (window_size > map->p_size) {
@@ -208,11 +222,9 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
map->p_size = window_size;
}
/* Now try to avoid re-reading any bytes by reusing any bytes
* from the previous buffer. */
if (window_start >= map->p_offset &&
window_start < map->p_offset + map->p_len &&
window_start + window_size >= map->p_offset + map->p_len) {
/* Now try to avoid re-reading any bytes by reusing any bytes from the previous buffer. */
if (window_start >= map->p_offset && window_start < map->p_offset + map->p_len
&& window_start + window_size >= map->p_offset + map->p_len) {
read_start = map->p_offset + map->p_len;
read_offset = (int32)(read_start - window_start);
read_size = window_size - read_offset;
@@ -232,8 +244,8 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
if (map->p_fd_offset != read_start) {
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
if (ret != read_start) {
rsyserr(FERROR, errno, "lseek returned %.0f, not %.0f",
(double)ret, (double)read_start);
rsyserr(FERROR, errno, "lseek returned %s, not %s",
big_num(ret), big_num(read_start));
exit_cleanup(RERR_FILEIO);
}
map->p_fd_offset = read_start;
@@ -242,7 +254,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
map->p_len = window_size;
while (read_size > 0) {
nread = read(map->fd, map->p + read_offset, read_size);
int32 nread = read(map->fd, map->p + read_offset, read_size);
if (nread <= 0) {
if (!map->status)
map->status = nread ? errno : ENODATA;
@@ -256,7 +268,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
read_size -= nread;
}
return map->p;
return map->p + align_fudge;
}

793
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-2008 Wayne Davison
* Copyright (C) 2003-2015 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-2008 Wayne Davison
* Copyright (C) 2007-2015 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,13 +23,13 @@
struct hashtable *hashtable_create(int size, int key64)
{
int req = size;
struct hashtable *tbl;
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. */
if (size & (size-1) || size < 16) {
int req = size;
size = 16;
while (size < req)
size *= 2;
@@ -41,13 +41,27 @@ struct hashtable *hashtable_create(int size, int key64)
tbl->size = size;
tbl->entries = 0;
tbl->node_size = node_size;
tbl->key64 = key64;
tbl->key64 = key64 ? 1 : 0;
if (DEBUG_GTE(HASH, 1)) {
char buf[32];
if (req != size)
snprintf(buf, sizeof buf, "req: %d, ", req);
else
*buf = '\0';
rprintf(FINFO, "[%s] created hashtable %lx (%ssize: %d, keys: %d-bit)\n",
who_am_i(), (long)tbl, buf, size, key64 ? 64 : 32);
}
return tbl;
}
void hashtable_destroy(struct hashtable *tbl)
{
if (DEBUG_GTE(HASH, 1)) {
rprintf(FINFO, "[%s] destroyed hashtable %lx (size: %d, keys: %d-bit)\n",
who_am_i(), (long)tbl, tbl->size, tbl->key64 ? 64 : 32);
}
free(tbl->nodes);
free(tbl);
}
@@ -60,6 +74,11 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
struct ht_int32_node *node;
uint32 ndx;
if (key64 ? key == 0 : (int32)key == 0) {
rprintf(FERROR, "Internal hashtable error: illegal key supplied!\n");
exit_cleanup(RERR_MESSAGEIO);
}
if (allocate_if_missing && tbl->entries > HASH_LOAD_LIMIT(tbl->size)) {
void *old_nodes = tbl->nodes;
int size = tbl->size * 2;
@@ -70,6 +89,11 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
tbl->size = size;
tbl->entries = 0;
if (DEBUG_GTE(HASH, 1)) {
rprintf(FINFO, "[%s] growing hashtable %lx (size: %d, keys: %d-bit)\n",
who_am_i(), (long)tbl, size, key64 ? 64 : 32);
}
for (i = size / 2; i-- > 0; ) {
struct ht_int32_node *move_node = HT_NODE(tbl, old_nodes, i);
int64 move_key = HT_KEY(move_node, key64);
@@ -87,7 +111,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);
@@ -142,7 +166,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;
}

156
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-2008 Wayne Davison
* Copyright (C) 2004-2015 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
@@ -21,8 +21,9 @@
*/
#include "rsync.h"
#include "inums.h"
#include "ifuncs.h"
extern int verbose;
extern int dry_run;
extern int list_only;
extern int am_sender;
@@ -30,14 +31,14 @@ extern int inc_recurse;
extern int do_xfers;
extern int link_dest;
extern int preserve_acls;
extern int make_backups;
extern int preserve_xattrs;
extern int protocol_version;
extern int remove_source_files;
extern int stdout_format_has_i;
extern int maybe_ATTRS_REPORT;
extern int unsort_ndx;
extern char *basis_dir[];
extern struct file_list *cur_flist, *first_flist;
extern char *basis_dir[MAX_BASIS_DIRS+1];
extern struct file_list *cur_flist;
#ifdef SUPPORT_HARD_LINKS
@@ -56,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);
}
@@ -66,11 +67,18 @@ 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);
if (!(tbl = dev_node->data))
tbl = dev_node->data = hashtable_create(512, SIZEOF_INT64 == 8);
dev_node = hashtable_find(dev_tbl, dev+1, 1);
if (!(tbl = dev_node->data)) {
tbl = dev_node->data = hashtable_create(512, 1);
if (DEBUG_GTE(HLINK, 3)) {
rprintf(FINFO,
"[%s] created hashtable for dev %s\n",
who_am_i(), big_num(dev));
}
}
} else
tbl = dev_node->data;
@@ -119,14 +127,15 @@ 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;
prev = IVAL(node->data, 1);
flist = flist_for_ndx(prev);
flist = flist_for_ndx(prev, NULL);
if (flist)
flist->files[prev - flist->ndx_start]->flags &= ~FLAG_HLINK_LAST;
else {
@@ -179,7 +188,7 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
if (!list_only) {
if (!list_only && flist->used) {
int i, ndx_count = 0;
int32 *ndx_list;
@@ -203,7 +212,7 @@ void match_hard_links(struct file_list *flist)
}
static int maybe_hard_link(struct file_struct *file, int ndx,
const char *fname, int statret, stat_x *sxp,
char *fname, int statret, stat_x *sxp,
const char *oldname, STRUCT_STAT *old_stp,
const char *realname, int itemizing, enum logcode code)
{
@@ -215,31 +224,24 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
0, "");
}
if (verbose > 1 && maybe_ATTRS_REPORT)
if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT)
rprintf(FCLIENT, "%s is uptodate\n", fname);
file->flags |= FLAG_HLINK_DONE;
return 0;
}
if (make_backups > 0) {
if (!make_backup(fname))
return -1;
} else if (robust_unlink(fname)) {
rsyserr(FERROR_XFER, errno, "unlink %s failed",
full_fname(fname));
return -1;
}
}
if (hard_link_one(file, fname, oldname, 0)) {
if (atomic_create(file, fname, NULL, oldname, MAKEDEV(0, 0), sxp, statret == 0 ? DEL_FOR_FILE : 0)) {
if (itemizing) {
itemize(fname, file, ndx, statret, sxp,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
realname);
}
if (code != FNONE && verbose)
if (code != FNONE && INFO_GTE(NAME, 1))
rprintf(code, "%s => %s\n", fname, realname);
return 0;
}
return -1;
}
@@ -255,7 +257,7 @@ static char *check_prior(struct file_struct *file, int gnum,
while (1) {
struct file_list *flist;
if (prev_ndx < 0
|| (flist = flist_for_ndx(prev_ndx)) == NULL)
|| (flist = flist_for_ndx(prev_ndx, NULL)) == NULL)
break;
fp = flist->files[prev_ndx - flist->ndx_start];
if (!(fp->flags & FLAG_SKIP_HLINK)) {
@@ -285,7 +287,7 @@ static char *check_prior(struct file_struct *file, int gnum,
/* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns:
* 0 = process the file, 1 = skip the file, -1 = error occurred. */
int hard_link_check(struct file_struct *file, int ndx, const char *fname,
int hard_link_check(struct file_struct *file, int ndx, char *fname,
int statret, stat_x *sxp, int itemizing,
enum logcode code)
{
@@ -304,6 +306,10 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
if (!flist) {
/* The previous file was skipped, so this one is
* treated as if it were the first in its group. */
if (DEBUG_GTE(HLINK, 2)) {
rprintf(FINFO, "hlink for %d (%s,%d): virtual first\n",
ndx, f_name(file, NULL), gnum);
}
return 0;
}
@@ -320,8 +326,16 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
F_HL_PREV(prev_file) = ndx;
file->flags |= FLAG_FILE_SENT;
cur_flist->in_progress++;
if (DEBUG_GTE(HLINK, 2)) {
rprintf(FINFO, "hlink for %d (%s,%d): waiting for %d\n",
ndx, f_name(file, NULL), gnum, F_HL_PREV(file));
}
return 1;
}
if (DEBUG_GTE(HLINK, 2)) {
rprintf(FINFO, "hlink for %d (%s,%d): looking for a leader\n",
ndx, f_name(file, NULL), gnum);
}
return 0;
}
@@ -329,7 +343,6 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
/* The previous previous is FIRST when prev is not. */
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;
}
@@ -337,9 +350,14 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
if (!prev_name) {
int alt_dest;
assert(flist != NULL);
prev_file = flist->files[prev_ndx - flist->ndx_start];
/* F_HL_PREV() is alt_dest value when DONE && FIRST. */
alt_dest = F_HL_PREV(prev_file);
if (DEBUG_GTE(HLINK, 2)) {
rprintf(FINFO, "hlink for %d (%s,%d): found flist match (alt %d)\n",
ndx, f_name(file, NULL), gnum, alt_dest);
}
if (alt_dest >= 0 && dry_run) {
pathjoin(namebuf, MAXPATHLEN, basis_dir[alt_dest],
@@ -353,10 +371,19 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
}
}
if (DEBUG_GTE(HLINK, 2)) {
rprintf(FINFO, "hlink for %d (%s,%d): leader is %d (%s)\n",
ndx, f_name(file, NULL), gnum, prev_ndx, prev_name);
}
if (link_stat(prev_name, &prev_st, 0) < 0) {
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(prev_name));
return -1;
if (!dry_run || errno != ENOENT) {
rsyserr(FERROR_XFER, errno, "stat %s failed", full_fname(prev_name));
return -1;
}
/* A new hard-link will get a new dev & inode, so approximate
* those values in dry-run mode by zeroing them. */
memset(&prev_st, 0, sizeof prev_st);
}
if (statret < 0 && basis_dir[0] != NULL) {
@@ -364,9 +391,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
char cmpbuf[MAXPATHLEN];
stat_x alt_sx;
int j = 0;
#ifdef SUPPORT_ACLS
alt_sx.acc_acl = alt_sx.def_acl = NULL;
#endif
init_stat_x(&alt_sx);
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &alt_sx.st, 0) < 0)
@@ -377,10 +402,10 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
continue;
statret = 1;
if (stdout_format_has_i == 0
|| (verbose < 2 && stdout_format_has_i < 2)) {
|| (!INFO_GTE(NAME, 2) && stdout_format_has_i < 2)) {
itemizing = 0;
code = FNONE;
if (verbose > 1 && maybe_ATTRS_REPORT)
if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT)
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
break;
@@ -395,19 +420,29 @@ 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
free_stat_x(&alt_sx);
}
if (maybe_hard_link(file, ndx, fname, statret, sxp, prev_name, &prev_st,
@@ -426,7 +461,7 @@ int hard_link_one(struct file_struct *file, const char *fname,
if (do_link(oldname, fname) < 0) {
enum logcode code;
if (terse) {
if (!verbose)
if (!INFO_GTE(NAME, 1))
return 0;
code = FINFO;
} else
@@ -453,7 +488,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
if (stp == NULL && prev_ndx >= 0) {
if (link_stat(fname, &st, 0) < 0) {
if (link_stat(fname, &st, 0) < 0 && !dry_run) {
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return;
@@ -471,22 +506,11 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
} else
our_name = fname;
#ifdef SUPPORT_ACLS
prev_sx.acc_acl = prev_sx.def_acl = NULL;
#endif
init_stat_x(&prev_sx);
while ((ndx = prev_ndx) >= 0) {
int val;
flist = flist_for_ndx(ndx);
if (flist == NULL) {
int start1 = first_flist ? first_flist->ndx_start : 0;
int start2 = first_flist ? first_flist->prev->ndx_start : 0;
int used = first_flist ? first_flist->prev->used : 0;
rprintf(FERROR,
"File index not found: %d (%d - %d)\n",
ndx, start1 - 1, start2 + used - 1);
exit_cleanup(RERR_PROTOCOL);
}
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);
@@ -495,10 +519,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
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
free_stat_x(&prev_sx);
if (val < 0)
continue;
if (remove_source_files == 1 && do_xfers)
@@ -508,8 +529,19 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
if (inc_recurse) {
int gnum = F_HL_GNUM(file);
struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
assert(node != NULL && node->data != NULL);
assert(CVAL(node->data, 0) == 0);
if (node == NULL) {
rprintf(FERROR, "Unable to find a hlink node for %d (%s)\n", gnum, f_name(file, prev_name));
exit_cleanup(RERR_MESSAGEIO);
}
if (node->data == NULL) {
rprintf(FERROR, "Hlink node data for %d is NULL (%s)\n", gnum, f_name(file, prev_name));
exit_cleanup(RERR_MESSAGEIO);
}
if (CVAL(node->data, 0) != 0) {
rprintf(FERROR, "Hlink node data for %d already has path=%s (%s)\n",
gnum, (char*)node->data, f_name(file, prev_name));
exit_cleanup(RERR_MESSAGEIO);
}
free(node->data);
if (!(node->data = strdup(our_name)))
out_of_memory("finish_hard_link");

View File

@@ -1,6 +1,6 @@
/* Inline functions for rsync.
*
* Copyright (C) 2007-2008 Wayne Davison
* Copyright (C) 2007-2015 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,6 +35,14 @@ realloc_xbuf(xbuf *xb, size_t sz)
xb->size = sz;
}
static inline void
free_xbuf(xbuf *xb)
{
if (xb->buf)
free(xb->buf);
memset(xb, 0, sizeof (xbuf));
}
static inline int
to_wire_mode(mode_t mode)
{
@@ -67,44 +75,32 @@ d_name(struct dirent *di)
#endif
}
static inline int
isDigit(const char *ptr)
static inline void
init_stat_x(stat_x *sx_p)
{
return isdigit(*(unsigned char *)ptr);
#ifdef SUPPORT_ACLS
sx_p->acc_acl = sx_p->def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
sx_p->xattr = NULL;
#endif
}
static inline int
isPrint(const char *ptr)
static inline void
free_stat_x(stat_x *sx_p)
{
return isprint(*(unsigned char *)ptr);
}
static inline int
isSpace(const char *ptr)
{
return isspace(*(unsigned char *)ptr);
}
static inline int
isLower(const char *ptr)
{
return islower(*(unsigned char *)ptr);
}
static inline int
isUpper(const char *ptr)
{
return isupper(*(unsigned char *)ptr);
}
static inline int
toLower(const char *ptr)
{
return tolower(*(unsigned char *)ptr);
}
static inline int
toUpper(const char *ptr)
{
return toupper(*(unsigned char *)ptr);
#ifdef SUPPORT_ACLS
{
extern int preserve_acls;
if (preserve_acls)
free_acl(sx_p);
}
#endif
#ifdef SUPPORT_XATTRS
{
extern int preserve_xattrs;
if (preserve_xattrs)
free_xattr(sx_p);
}
#endif
}

57
inums.h Normal file
View File

@@ -0,0 +1,57 @@
/* Inline functions for rsync.
*
* Copyright (C) 2008-2015 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.
*/
static inline char *
big_num(int64 num)
{
return do_big_num(num, 0, NULL);
}
static inline char *
comma_num(int64 num)
{
extern int human_readable;
return do_big_num(num, human_readable != 0, NULL);
}
static inline char *
human_num(int64 num)
{
extern int human_readable;
return do_big_num(num, human_readable, NULL);
}
static inline char *
big_dnum(double dnum, int decimal_digits)
{
return do_big_dnum(dnum, 0, decimal_digits);
}
static inline char *
comma_dnum(double dnum, int decimal_digits)
{
extern int human_readable;
return do_big_dnum(dnum, human_readable != 0, decimal_digits);
}
static inline char *
human_dnum(double dnum, int decimal_digits)
{
extern int human_readable;
return do_big_dnum(dnum, human_readable, decimal_digits);
}

2585
io.c
View File

File diff suppressed because it is too large Load Diff

2
io.h
View File

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

59
itypes.h Normal file
View File

@@ -0,0 +1,59 @@
/* Inline functions for rsync.
*
* Copyright (C) 2007-2015 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.
*/
static inline int
isDigit(const char *ptr)
{
return isdigit(*(unsigned char *)ptr);
}
static inline int
isPrint(const char *ptr)
{
return isprint(*(unsigned char *)ptr);
}
static inline int
isSpace(const char *ptr)
{
return isspace(*(unsigned char *)ptr);
}
static inline int
isLower(const char *ptr)
{
return islower(*(unsigned char *)ptr);
}
static inline int
isUpper(const char *ptr)
{
return isupper(*(unsigned char *)ptr);
}
static inline int
toLower(const char *ptr)
{
return tolower(*(unsigned char *)ptr);
}
static inline int
toUpper(const char *ptr)
{
return toupper(*(unsigned char *)ptr);
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 2004-2015 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
@@ -20,6 +20,9 @@
*/
#include "rsync.h"
#include "itypes.h"
static char number_separator;
#ifndef HAVE_STRDUP
char *strdup(char *s)
@@ -151,3 +154,122 @@ int sys_gettimeofday(struct timeval *tv)
return gettimeofday(tv);
#endif
}
#define HUMANIFY(mult) \
do { \
if (num >= mult || num <= -mult) { \
double dnum = (double)num / mult; \
char units; \
if (num < 0) \
dnum = -dnum; \
if (dnum < mult) \
units = 'K'; \
else if ((dnum /= mult) < mult) \
units = 'M'; \
else if ((dnum /= mult) < mult) \
units = 'G'; \
else { \
dnum /= mult; \
units = 'T'; \
} \
if (num < 0) \
dnum = -dnum; \
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \
return bufs[n]; \
} \
} while (0)
/* Return the int64 number as a string. If the human_flag arg is non-zero,
* we may output the number in K, M, G, or T units. If we don't add a unit
* suffix, we will append the fract string, if it is non-NULL. We can
* return up to 4 buffers at a time. */
char *do_big_num(int64 num, int human_flag, const char *fract)
{
static char bufs[4][128]; /* more than enough room */
static unsigned int n;
char *s;
int len, negated;
if (human_flag && !number_separator) {
char buf[32];
snprintf(buf, sizeof buf, "%f", 3.14);
if (strchr(buf, '.') != NULL)
number_separator = ',';
else
number_separator = '.';
}
n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
if (human_flag > 1) {
if (human_flag == 2)
HUMANIFY(1000);
else
HUMANIFY(1024);
}
s = bufs[n] + sizeof bufs[0] - 1;
if (fract) {
len = strlen(fract);
s -= len;
strlcpy(s, fract, len + 1);
} else
*s = '\0';
len = 0;
if (!num)
*--s = '0';
if (num < 0) {
/* A maximum-size negated number can't fit as a positive,
* so do one digit in negated form to start us off. */
*--s = (char)(-(num % 10)) + '0';
num = -(num / 10);
len++;
negated = 1;
} else
negated = 0;
while (num) {
if (human_flag) {
if (len == 3) {
*--s = number_separator;
len = 1;
} else
len++;
}
*--s = (char)(num % 10) + '0';
num /= 10;
}
if (negated)
*--s = '-';
return s;
}
/* Return the double number as a string. If the human_flag option is > 1,
* we may output the number in K, M, G, or T units. The buffer we use for
* our result is either a single static buffer defined here, or a buffer
* we get from do_big_num(). */
char *do_big_dnum(double dnum, int human_flag, int decimal_digits)
{
static char tmp_buf[128];
#if SIZEOF_INT64 >= 8
char *fract;
snprintf(tmp_buf, sizeof tmp_buf, "%.*f", decimal_digits, dnum);
if (!human_flag || (dnum < 1000.0 && dnum > -1000.0))
return tmp_buf;
for (fract = tmp_buf+1; isDigit(fract); fract++) {}
return do_big_num((int64)dnum, human_flag, fract);
#else
/* A big number might lose digits converting to a too-short int64,
* so let's just return the raw double conversion. */
snprintf(tmp_buf, sizeof tmp_buf, "%.*f", decimal_digits, dnum);
return tmp_buf;
#endif
}

View File

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

72
lib/getpass.c Normal file
View File

@@ -0,0 +1,72 @@
/*
* An implementation of getpass for systems that lack one.
*
* Copyright (C) 2013 Roman Donchenko
*
* 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 <stdio.h>
#include <string.h>
#include <termios.h>
#include "rsync.h"
char *getpass(const char *prompt)
{
static char password[256];
BOOL tty_changed = False, read_success;
struct termios tty_old, tty_new;
FILE *in = stdin, *out = stderr;
FILE *tty = fopen("/dev/tty", "w+");
if (tty)
in = out = tty;
if (tcgetattr(fileno(in), &tty_old) == 0) {
tty_new = tty_old;
tty_new.c_lflag &= ~(ECHO | ISIG);
if (tcsetattr(fileno(in), TCSAFLUSH, &tty_new) == 0)
tty_changed = True;
}
if (!tty_changed)
fputs("(WARNING: will be visible) ", out);
fputs(prompt, out);
fflush(out);
read_success = fgets(password, sizeof password, in) != NULL;
/* Print the newline that hasn't been echoed. */
fputc('\n', out);
if (tty_changed)
tcsetattr(fileno(in), TCSAFLUSH, &tty_old);
if (tty)
fclose(tty);
if (read_success) {
/* Remove the trailing newline. */
size_t password_len = strlen(password);
if (password_len && password[password_len - 1] == '\n')
password[password_len - 1] = '\0';
return password;
}
return NULL;
}

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-2008 Wayne Davison
* Copyright (C) 2005-2015 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 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2006 Wayne Davison
* Copyright (C) 2003-2015 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

@@ -95,25 +95,39 @@ for
.I quantum
will produce a quantum that should meet maximal alignment
on most platforms.
If
.B POOL_QALIGN
Unless
.B POOL_NO_QALIGN
is set in the
.IR flags ,
allocations will be aligned to addresses that are a
multiple of
.IR quantum .
A
.B NULL
may be specified for the
.I bomb
function pointer if it is not needed. (See the
.B pool_alloc()
function for how it is used.)
If
.B POOL_CLEAR
is set in the
.IR flags ,
all allocations from the pool will be initialized to zeros.
You may specify a
.B NULL
for the
.I bomb
function pointer if you don't wish to use it. (See the
.B pool_alloc()
function for how it is used.)
If either
.B POOL_PREPEND
or
.B POOL_INTERN
is specified in the
.IR flags ,
each extent's data structure will be allocated at the start of the
.IR size -length
buffer (rather than as a separate, non-pool allocation), with the
former extending the
.I size
to hold the structure, and the latter subtracting the structure's
length from the indicated
.IR size .
.P
.B pool_destroy()
destroys an allocation
@@ -131,8 +145,8 @@ is
.BR 0 ,
.I quantum
bytes will be allocated.
If the pool has been created with
.BR POOL_QALIGN ,
If the pool has been created without
.BR POOL_NO_QALIGN ,
every chunk of memory that is returned will be suitably aligned.
You can use this with the default
.I quantum
@@ -169,7 +183,7 @@ an extent), its memory will be completely freed back to the system.
If
.I addr
is
.BR 0 ,
.BR NULL ,
no memory will be freed, but subsequent allocations will come
from a new extent.
.P

View File

@@ -2,6 +2,8 @@
#define POOL_DEF_EXTENT (32 * 1024)
#define POOL_QALIGN_P2 (1<<16) /* power-of-2 qalign */
struct alloc_pool
{
size_t size; /* extent size */
@@ -13,7 +15,7 @@ struct alloc_pool
/* statistical data */
unsigned long e_created; /* extents created */
unsigned long e_freed; /* extents detroyed */
unsigned long e_freed; /* extents destroyed */
int64 n_allocated; /* calls to alloc */
int64 n_freed; /* calls to free */
int64 b_allocated; /* cum. bytes allocated */
@@ -22,16 +24,18 @@ struct alloc_pool
struct pool_extent
{
struct pool_extent *next;
void *start; /* starting address */
size_t free; /* free bytecount */
size_t bound; /* bytes bound by padding,
* overhead and freed */
struct pool_extent *next;
size_t bound; /* trapped free bytes */
};
struct align_test {
void *foo;
int64 bar;
uchar foo;
union {
int64 i;
void *p;
} bar;
};
#define MINALIGN offsetof(struct align_test, bar)
@@ -43,20 +47,42 @@ struct align_test {
alloc_pool_t
pool_create(size_t size, size_t quantum, void (*bomb)(const char *), int flags)
{
struct alloc_pool *pool;
struct alloc_pool *pool;
if (!(pool = new(struct alloc_pool)))
return pool;
memset(pool, 0, sizeof (struct alloc_pool));
if (!(pool = new0(struct alloc_pool)))
return NULL;
pool->size = size /* round extent size to min alignment reqs */
? (size + MINALIGN - 1) & ~(MINALIGN - 1)
: POOL_DEF_EXTENT;
if (flags & POOL_INTERN) {
pool->size -= sizeof (struct pool_extent);
flags |= POOL_APPEND;
if ((MINALIGN & (MINALIGN - 1)) != 0) {
if (bomb)
(*bomb)("Compiler error: MINALIGN is not a power of 2\n");
return NULL;
}
pool->quantum = quantum ? quantum : MINALIGN;
if (!size)
size = POOL_DEF_EXTENT;
if (!quantum)
quantum = MINALIGN;
if (flags & POOL_INTERN) {
if (size <= sizeof (struct pool_extent))
size = quantum;
else
size -= sizeof (struct pool_extent);
flags |= POOL_PREPEND;
}
if (quantum <= 1)
flags = (flags | POOL_NO_QALIGN) & ~POOL_QALIGN_P2;
else if (!(flags & POOL_NO_QALIGN)) {
if (size % quantum)
size += quantum - size % quantum;
/* If quantum is a power of 2, we'll avoid using modulus. */
if (!(quantum & (quantum - 1)))
flags |= POOL_QALIGN_P2;
}
pool->size = size;
pool->quantum = quantum;
pool->bomb = bomb;
pool->flags = flags;
@@ -67,17 +93,21 @@ void
pool_destroy(alloc_pool_t p)
{
struct alloc_pool *pool = (struct alloc_pool *) p;
struct pool_extent *cur, *next;
struct pool_extent *cur, *next;
if (!pool)
return;
for (cur = pool->extents; cur; cur = next) {
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
if (pool->flags & POOL_PREPEND)
free(PTR_ADD(cur->start, -sizeof (struct pool_extent)));
else {
free(cur->start);
free(cur);
}
}
free(pool);
}
@@ -90,45 +120,40 @@ pool_alloc(alloc_pool_t p, size_t len, const char *bomb_msg)
if (!len)
len = pool->quantum;
else if (pool->quantum > 1 && len % pool->quantum)
len += pool->quantum - len % pool->quantum;
else if (pool->flags & POOL_QALIGN_P2) {
if (len & (pool->quantum - 1))
len += pool->quantum - (len & (pool->quantum - 1));
} else if (!(pool->flags & POOL_NO_QALIGN)) {
if (len % pool->quantum)
len += pool->quantum - len % pool->quantum;
}
if (len > pool->size)
goto bomb_out;
if (!pool->extents || len > pool->extents->free) {
void *start;
size_t free;
size_t bound;
size_t skew;
size_t asize;
void *start;
size_t asize;
struct pool_extent *ext;
free = pool->size;
bound = 0;
asize = pool->size;
if (pool->flags & POOL_APPEND)
if (pool->flags & POOL_PREPEND)
asize += sizeof (struct pool_extent);
if (!(start = new_array(char, asize)))
goto bomb_out;
if (pool->flags & POOL_CLEAR)
memset(start, 0, free);
memset(start, 0, asize);
if (pool->flags & POOL_APPEND)
ext = PTR_ADD(start, free);
else if (!(ext = new(struct pool_extent)))
if (pool->flags & POOL_PREPEND) {
ext = start;
start = PTR_ADD(start, sizeof (struct pool_extent));
} else if (!(ext = new(struct pool_extent)))
goto bomb_out;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
bound += skew;
free -= skew;
}
ext->start = start;
ext->free = free;
ext->bound = bound;
ext->free = pool->size;
ext->bound = 0;
ext->next = pool->extents;
pool->extents = ext;
@@ -160,10 +185,24 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
if (!pool)
return;
if (!addr) {
/* A NULL addr starts a fresh extent for new allocations. */
if ((cur = pool->extents) != NULL && cur->free != pool->size) {
cur->bound += cur->free;
cur->free = 0;
}
return;
}
if (!len)
len = pool->quantum;
else if (pool->quantum > 1 && len % pool->quantum)
len += pool->quantum - len % pool->quantum;
else if (pool->flags & POOL_QALIGN_P2) {
if (len & (pool->quantum - 1))
len += pool->quantum - (len & (pool->quantum - 1));
} else if (!(pool->flags & POOL_NO_QALIGN)) {
if (len % pool->quantum)
len += pool->quantum - len % pool->quantum;
}
pool->n_freed++;
pool->b_freed += len;
@@ -179,19 +218,12 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
if (!prev) {
/* The "live" extent is kept ready for more allocations. */
if (cur->free + cur->bound + len >= pool->size) {
size_t skew;
if (pool->flags & POOL_CLEAR) {
memset(PTR_ADD(cur->start, cur->free), 0,
pool->size - cur->free);
}
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (skew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
cur->bound += skew;
cur->free -= skew;
}
} else if (addr == PTR_ADD(cur->start, cur->free)) {
if (pool->flags & POOL_CLEAR)
memset(addr, 0, len);
@@ -203,9 +235,12 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
if (cur->free + cur->bound >= pool->size) {
prev->next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
if (pool->flags & POOL_PREPEND)
free(PTR_ADD(cur->start, -sizeof (struct pool_extent)));
else {
free(cur->start);
free(cur);
}
pool->e_freed++;
} else if (prev != pool->extents) {
/* Move the extent to be the first non-live extent. */
@@ -242,18 +277,11 @@ pool_free_old(alloc_pool_t p, void *addr)
prev->next = NULL;
next = cur;
} else {
size_t skew;
/* The most recent live extent can just be reset. */
if (pool->flags & POOL_CLEAR)
memset(addr, 0, pool->size - cur->free);
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (skew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
cur->bound += skew;
cur->free -= skew;
}
next = cur->next;
cur->next = NULL;
}
@@ -264,9 +292,12 @@ pool_free_old(alloc_pool_t p, void *addr)
while ((cur = next) != NULL) {
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
if (pool->flags & POOL_PREPEND)
free(PTR_ADD(cur->start, -sizeof (struct pool_extent)));
else {
free(cur->start);
free(cur);
}
pool->e_freed++;
}
}
@@ -295,24 +326,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;
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 +361,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

@@ -1,9 +1,9 @@
#include <stddef.h>
#define POOL_CLEAR (1<<0) /* zero fill allocations */
#define POOL_QALIGN (1<<1) /* align data to quanta */
#define POOL_NO_QALIGN (1<<1) /* don't align data to quanta */
#define POOL_INTERN (1<<2) /* Allocate extent structures */
#define POOL_APPEND (1<<3) /* or appended to extent data */
#define POOL_PREPEND (1<<3) /* or prepend to extent data */
typedef void *alloc_pool_t;

View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
* Unix SMB/CIFS implementation.
* Based on the Samba ACL support code.
* Copyright (C) Jeremy Allison 2000.
* Copyright (C) 2007-2008 Wayne Davison
* Copyright (C) 2007-2015 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.
@@ -551,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;
}
@@ -873,6 +873,10 @@ int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
#define INITIAL_ACL_SIZE 16
#ifndef NACLENTRIES
#define NACLENTRIES 0
#endif
SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
{
SMB_ACL_T acl_d;
@@ -909,7 +913,7 @@ SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
sys_acl_free_acl(acl_d);
if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
if ((count = acl(path_p, ACL_CNT, NACLENTRIES, NULL)) < 0) {
return NULL;
}
@@ -1007,7 +1011,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;
}
@@ -1638,14 +1642,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;
@@ -1815,7 +1819,11 @@ SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
/* AIX has no DEFAULT */
if ( type == SMB_ACL_TYPE_DEFAULT ) {
#ifdef ENOTSUP
errno = ENOTSUP;
#else
errno = ENOSYS;
#endif
return NULL;
}
@@ -2777,6 +2785,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,7 +3,7 @@
* Version 2.2.x
* Portable SMB ACL interface
* Copyright (C) Jeremy Allison 2000
* Copyright (C) 2007-2008 Wayne Davison
* Copyright (C) 2007-2015 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,7 +2,7 @@
* Extended attribute support for rsync.
*
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2003-2008 Wayne Davison
* Copyright (C) 2003-2015 Wayne Davison
* Written by Jay Fenlason.
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,10 @@
#ifdef SUPPORT_XATTRS
#ifdef HAVE_OSX_XATTRS
#define GETXATTR_FETCH_LIMIT (64*1024*1024)
#endif
#if defined HAVE_LINUX_XATTRS
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
@@ -55,7 +59,24 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
{
return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
ssize_t len = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
/* If we're retrieving data, handle resource forks > 64MB specially */
if (value != NULL && len == GETXATTR_FETCH_LIMIT && (size_t)len < size) {
/* getxattr will only return 64MB of data at a time, need to call again with a new offset */
u_int32_t offset = len;
size_t data_retrieved = len;
while (data_retrieved < size) {
len = getxattr(path, name, value + offset, size - data_retrieved, offset, XATTR_NOFOLLOW);
if (len <= 0)
break;
data_retrieved += len;
offset += (u_int32_t)len;
}
len = data_retrieved;
}
return len;
}
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
@@ -126,6 +147,150 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
return len;
}
#elif HAVE_SOLARIS_XATTRS
static ssize_t read_xattr(int attrfd, void *buf, size_t buflen)
{
STRUCT_STAT sb;
ssize_t ret;
if (fstat(attrfd, &sb) < 0)
ret = -1;
else if (sb.st_size > SSIZE_MAX) {
errno = ERANGE;
ret = -1;
} else if (buflen == 0)
ret = sb.st_size;
else if (sb.st_size > buflen) {
errno = ERANGE;
ret = -1;
} else {
size_t bufpos;
for (bufpos = 0; bufpos < sb.st_size; ) {
ssize_t cnt = read(attrfd, buf + bufpos, sb.st_size - bufpos);
if (cnt <= 0) {
if (cnt < 0 && errno == EINTR)
continue;
bufpos = -1;
break;
}
bufpos += cnt;
}
ret = bufpos;
}
close(attrfd);
return ret;
}
ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
{
int attrfd;
if ((attrfd = attropen(path, name, O_RDONLY)) < 0) {
errno = ENOATTR;
return -1;
}
return read_xattr(attrfd, value, size);
}
ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
{
int attrfd;
if ((attrfd = openat(filedes, name, O_RDONLY|O_XATTR, 0)) < 0) {
errno = ENOATTR;
return -1;
}
return read_xattr(attrfd, value, size);
}
int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
{
int attrfd;
size_t bufpos;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
if ((attrfd = attropen(path, name, O_CREAT|O_TRUNC|O_WRONLY, mode)) < 0)
return -1;
for (bufpos = 0; bufpos < size; ) {
ssize_t cnt = write(attrfd, value+bufpos, size);
if (cnt <= 0) {
if (cnt < 0 && errno == EINTR)
continue;
bufpos = -1;
break;
}
bufpos += cnt;
}
close(attrfd);
return bufpos > 0 ? 0 : -1;
}
int sys_lremovexattr(const char *path, const char *name)
{
int attrdirfd;
int ret;
if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0)
return -1;
ret = unlinkat(attrdirfd, name, 0);
close(attrdirfd);
return ret;
}
ssize_t sys_llistxattr(const char *path, char *list, size_t size)
{
int attrdirfd;
DIR *dirp;
struct dirent *dp;
ssize_t ret = 0;
if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0) {
errno = ENOTSUP;
return -1;
}
if ((dirp = fdopendir(attrdirfd)) == NULL) {
close(attrdirfd);
return -1;
}
while ((dp = readdir(dirp))) {
int len = strlen(dp->d_name);
if (dp->d_name[0] == '.' && (len == 1 || (len == 2 && dp->d_name[1] == '.')))
continue;
if (len == 11 && dp->d_name[0] == 'S' && strncmp(dp->d_name, "SUNWattr_r", 10) == 0
&& (dp->d_name[10] == 'o' || dp->d_name[10] == 'w'))
continue;
if ((ret += len+1) > size) {
if (size == 0)
continue;
ret = -1;
errno = ERANGE;
break;
}
memcpy(list, dp->d_name, len+1);
list += len+1;
}
closedir(dirp);
close(attrdirfd);
return ret;
}
#else
#error You need to create xattr compatibility functions.

1022
loadparm.c
View File

File diff suppressed because it is too large Load Diff

216
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-2008 Wayne Davison
* Copyright (C) 2003-2015 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
@@ -20,9 +20,9 @@
*/
#include "rsync.h"
#include "ifuncs.h"
#include "itypes.h"
#include "inums.h"
extern int verbose;
extern int dry_run;
extern int am_daemon;
extern int am_server;
@@ -31,18 +31,19 @@ extern int am_generator;
extern int local_server;
extern int quiet;
extern int module_id;
extern int msg_fd_out;
extern int checksum_len;
extern int allow_8bit_chars;
extern int protocol_version;
extern int always_checksum;
extern int preserve_times;
extern int uid_ndx;
extern int gid_ndx;
extern int progress_is_active;
extern int msgs2stderr;
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 int64 total_data_written;
extern int64 total_data_read;
extern mode_t orig_umask;
extern char *auth_user;
extern char *stdout_format;
@@ -52,11 +53,13 @@ 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;
extern char sender_file_sum[MAX_DIGEST_LEN];
extern const char undetermined_hostname[];
static int log_initialised;
static int logfile_was_closed;
@@ -64,6 +67,11 @@ static FILE *logfile_fp;
struct stats stats;
int got_xfer_error = 0;
int output_needs_newline = 0;
int send_msgs_to_gen = 0;
static int64 initial_data_written;
static int64 initial_data_read;
struct {
int code;
@@ -85,15 +93,15 @@ 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_DEL_LIMIT , "the --max-delete limit stopped deletions" },
{ 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" },
{ RERR_CMD_NOTFOUND,"remote command not found" },
{ RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" },
{ 0, NULL }
};
@@ -115,8 +123,7 @@ static void logit(int priority, const char *buf)
if (logfile_was_closed)
logfile_reopen();
if (logfile_fp) {
fprintf(logfile_fp, "%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fprintf(logfile_fp, "%s [%d] %s", timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile_fp);
} else {
syslog(priority, "%s", buf);
@@ -243,7 +250,7 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
{
int trailing_CR_or_NL;
FILE *f = NULL;
FILE *f = msgs2stderr ? stderr : stdout;
#ifdef ICONV_OPTION
iconv_t ic = is_utf8 && ic_recv != (iconv_t)-1 ? ic_recv : ic_chck;
#else
@@ -255,15 +262,28 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
if (len < 0)
exit_cleanup(RERR_MESSAGEIO);
if (am_server && msg_fd_out >= 0) {
if (msgs2stderr) {
if (!am_daemon) {
if (code == FLOG)
return;
goto output_msg;
}
if (code == FCLIENT)
return;
code = FLOG;
} else if (send_msgs_to_gen) {
assert(!is_utf8);
/* Pass the message to our sibling. */
/* Pass the message to our sibling in native charset. */
send_msg((enum msgcode)code, buf, len, 0);
return;
}
if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */
code = FERROR;
else if (code == FERROR_UTF8) {
is_utf8 = 1;
code = FERROR;
}
if (code == FCLIENT)
code = FINFO;
@@ -304,31 +324,43 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
/* TODO: can we send the error to the user somehow? */
return;
}
f = stderr;
}
output_msg:
switch (code) {
case FERROR_XFER:
got_xfer_error = 1;
/* FALL THROUGH */
case FERROR:
case FERROR_UTF8:
case FERROR_SOCKET:
case FWARNING:
f = stderr;
break;
case FLOG:
case FINFO:
f = am_server ? stderr : stdout;
case FCLIENT:
break;
default:
fprintf(stderr, "Unknown logcode in rwrite(): %d [%s]\n", (int)code, who_am_i());
exit_cleanup(RERR_MESSAGEIO);
}
if (progress_is_active && !am_server) {
if (output_needs_newline) {
fputc('\n', f);
progress_is_active = 0;
output_needs_newline = 0;
}
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;
if (len && buf[0] == '\r') {
fputc('\r', f);
buf++;
len--;
}
#ifdef ICONV_CONST
if (ic != (iconv_t)-1) {
xbuf outbuf, inbuf;
@@ -336,10 +368,10 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
int ierrno;
INIT_CONST_XBUF(outbuf, convbuf);
INIT_XBUF(inbuf, (char*)buf, len, -1);
INIT_XBUF(inbuf, (char*)buf, len, (size_t)-1);
while (inbuf.len) {
iconvbufs(ic, &inbuf, &outbuf, 0);
iconvbufs(ic, &inbuf, &outbuf, inbuf.pos ? 0 : ICB_INIT);
ierrno = errno;
if (outbuf.len) {
filtered_fwrite(f, convbuf, outbuf.len, 0);
@@ -434,12 +466,12 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
void rflush(enum logcode code)
{
FILE *f = NULL;
FILE *f;
if (am_daemon || code == FLOG)
return;
if (code == FINFO && !am_server)
if (!am_server && (code == FINFO || code == FCLIENT))
f = stdout;
else
f = stderr;
@@ -447,10 +479,15 @@ void rflush(enum logcode code)
fflush(f);
}
void remember_initial_stats(void)
{
initial_data_read = total_data_read;
initial_data_written = total_data_written;
}
/* A generic logging routine for send/recv, with parameter substitiution. */
static void log_formatted(enum logcode code, const char *format, const char *op,
struct file_struct *file, const char *fname,
struct stats *initial_stats, int iflags,
struct file_struct *file, const char *fname, int iflags,
const char *hlink)
{
char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
@@ -473,30 +510,45 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
buf[total] = '\0';
for (p = buf; (p = strchr(p, '%')) != NULL; ) {
int humanize = 0;
s = p++;
c = fmt + 1;
while (*p == '\'') {
humanize++;
p++;
}
if (*p == '-')
*c++ = *p++;
while (isDigit(p) && c - fmt < (int)(sizeof fmt) - 8)
*c++ = *p++;
while (*p == '\'') {
humanize++;
p++;
}
if (!*p)
break;
*c = '\0';
n = NULL;
/* Note for %h and %a: it doesn't matter what fd we pass to
* client_{name,addr} because rsync_module will already have
* forced the answer to be cached (assuming, of course, for %h
* that lp_reverse_lookup(module_id) is true). */
switch (*p) {
case 'h':
if (am_daemon)
n = client_name(0);
if (am_daemon) {
n = lp_reverse_lookup(module_id)
? client_name(0) : undetermined_hostname;
}
break;
case 'a':
if (am_daemon)
n = client_addr(0);
break;
case 'l':
strlcat(fmt, ".0f", sizeof fmt);
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(double)F_LENGTH(file));
do_big_num(F_LENGTH(file), humanize, NULL));
n = buf2;
break;
case 'U':
@@ -516,9 +568,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
}
break;
case 'p':
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)getpid());
strlcat(fmt, "d", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt, (int)getpid());
n = buf2;
break;
case 'M':
@@ -599,35 +650,48 @@ 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;
break;
case 'b':
if (am_sender) {
b = stats.total_written -
initial_stats->total_written;
} else {
b = stats.total_read -
initial_stats->total_read;
}
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt, (double)b);
if (!(iflags & ITEM_TRANSFER))
b = 0;
else if (am_sender)
b = total_data_written - initial_data_written;
else
b = total_data_read - initial_data_read;
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
do_big_num(b, humanize, NULL));
n = buf2;
break;
case 'c':
if (!am_sender) {
b = stats.total_written -
initial_stats->total_written;
} else {
b = stats.total_read -
initial_stats->total_read;
}
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt, (double)b);
if (!(iflags & ITEM_TRANSFER))
b = 0;
else if (!am_sender)
b = total_data_written - initial_data_written;
else
b = total_data_read - initial_data_read;
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
do_big_num(b, humanize, NULL));
n = buf2;
break;
case 'C':
if (protocol_version >= 30
&& (iflags & ITEM_TRANSFER
|| (always_checksum && S_ISREG(file->mode)))) {
const char *sum = iflags & ITEM_TRANSFER
? sender_file_sum : F_SUM(file);
n = sum_as_hex(sum);
} else {
memset(buf2, ' ', checksum_len*2);
buf2[checksum_len*2] = '\0';
n = buf2;
}
break;
case 'i':
if (iflags & ITEM_DELETED) {
n = "*deleting ";
@@ -726,10 +790,12 @@ int log_format_has(const char *format, char esc)
return 0;
for (p = format; (p = strchr(p, '%')) != NULL; ) {
if (*++p == '-')
for (p++; *p == '\''; p++) {} /*SHARED ITERATOR*/
if (*p == '-')
p++;
while (isDigit(p))
p++;
while (*p == '\'') p++;
if (!*p)
break;
if (*p == esc)
@@ -741,19 +807,14 @@ int log_format_has(const char *format, char esc)
/* Log the transfer of a file. If the code is FCLIENT, the output just goes
* to stdout. If it is FLOG, it just goes to the log file. Otherwise we
* output to both. */
void log_item(enum logcode code, struct file_struct *file,
struct stats *initial_stats, int iflags, const char *hlink)
void log_item(enum logcode code, struct file_struct *file, int iflags, const char *hlink)
{
const char *s_or_r = am_sender ? "send" : "recv";
if (code != FLOG && stdout_format && !am_server) {
log_formatted(FCLIENT, stdout_format, s_or_r,
file, NULL, initial_stats, iflags, hlink);
}
if (code != FCLIENT && logfile_format && *logfile_format) {
log_formatted(FLOG, logfile_format, s_or_r,
file, NULL, initial_stats, iflags, hlink);
}
if (code != FLOG && stdout_format && !am_server)
log_formatted(FCLIENT, stdout_format, s_or_r, file, NULL, iflags, hlink);
if (code != FCLIENT && logfile_format && *logfile_format)
log_formatted(FLOG, logfile_format, s_or_r, file, NULL, iflags, hlink);
}
void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
@@ -761,16 +822,16 @@ void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
{
int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS;
int see_item = itemizing && (significant_flags || *buf
|| stdout_format_has_i > 1 || (verbose > 1 && stdout_format_has_i));
|| stdout_format_has_i > 1 || (INFO_GTE(NAME, 2) && stdout_format_has_i));
int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
if (am_server) {
if (logfile_name && !dry_run && see_item
&& (significant_flags || logfile_format_has_i))
log_item(FLOG, file, &stats, iflags, buf);
log_item(FLOG, file, iflags, buf);
} else if (see_item || local_change || *buf
|| (S_ISDIR(file->mode) && significant_flags)) {
enum logcode code = significant_flags || logfile_format_has_i ? FINFO : FCLIENT;
log_item(code, file, &stats, iflags, buf);
log_item(code, file, iflags, buf);
}
}
@@ -779,29 +840,28 @@ void log_delete(const char *fname, int mode)
static struct {
union file_extras ex[4]; /* just in case... */
struct file_struct file;
} x;
} x; /* Zero-initialized due to static declaration. */
int len = strlen(fname);
const char *fmt;
x.file.mode = mode;
if (!verbose && !stdout_format)
;
else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
if (S_ISDIR(mode))
len++; /* directories include trailing null */
send_msg(MSG_DELETED, fname, len, am_generator);
} else {
} else if (!INFO_GTE(DEL, 1) && !stdout_format)
;
else {
fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n";
log_formatted(FCLIENT, fmt, "del.", &x.file, fname, &stats,
ITEM_DELETED, NULL);
log_formatted(FCLIENT, fmt, "del.", &x.file, fname, ITEM_DELETED, NULL);
}
if (!logfile_name || dry_run || !logfile_format)
return;
fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
log_formatted(FLOG, fmt, "del.", &x.file, fname, &stats, ITEM_DELETED, NULL);
log_formatted(FLOG, fmt, "del.", &x.file, fname, ITEM_DELETED, NULL);
}
/*
@@ -813,10 +873,10 @@ void log_delete(const char *fname, int mode)
void log_exit(int code, const char *file, int line)
{
if (code == 0) {
rprintf(FLOG,"sent %.0f bytes received %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
rprintf(FLOG,"sent %s bytes received %s bytes total size %s\n",
big_num(stats.total_written),
big_num(stats.total_read),
big_num(stats.total_size));
} else if (am_server != 2) {
const char *name;

22
m4/have_type.m4 Normal file
View File

@@ -0,0 +1,22 @@
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
])

View File

@@ -1,27 +1,3 @@
dnl AC_VALIDATE_CACHE_SYSTEM_TYPE[(cmd)]
dnl if the cache file is inconsistent with the current host,
dnl target and build system types, execute CMD or print a default
dnl error message.
AC_DEFUN(AC_VALIDATE_CACHE_SYSTEM_TYPE, [
AC_REQUIRE([AC_CANONICAL_SYSTEM])
AC_MSG_CHECKING([config.cache system type])
if { test x"${ac_cv_host_system_type+set}" = x"set" &&
test x"$ac_cv_host_system_type" != x"$host"; } ||
{ test x"${ac_cv_build_system_type+set}" = x"set" &&
test x"$ac_cv_build_system_type" != x"$build"; } ||
{ test x"${ac_cv_target_system_type+set}" = x"set" &&
test x"$ac_cv_target_system_type" != x"$target"; }; then
AC_MSG_RESULT([different])
ifelse($#, 1, [$1],
[AC_MSG_ERROR(["you must remove config.cache and restart configure"])])
else
AC_MSG_RESULT([same])
fi
ac_cv_host_system_type="$host"
ac_cv_build_system_type="$build"
ac_cv_target_system_type="$target"
])
dnl Check for socklen_t: historically on BSD it is an int, and in
dnl POSIX 1g it is a type of its own, but some platforms use different
dnl types for the argument to getsockopt, getpeername, etc. So we
@@ -67,26 +43,3 @@ AC_DEFUN([TYPE_SOCKLEN_T],
[#include <sys/types.h>
#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
])

View File

@@ -0,0 +1,23 @@
dnl AC_VALIDATE_CACHE_SYSTEM_TYPE[(cmd)]
dnl if the cache file is inconsistent with the current host,
dnl target and build system types, execute CMD or print a default
dnl error message.
AC_DEFUN([AC_VALIDATE_CACHE_SYSTEM_TYPE], [
AC_REQUIRE([AC_CANONICAL_SYSTEM])
AC_MSG_CHECKING([config.cache system type])
if { test x"${ac_cv_host_system_type+set}" = x"set" &&
test x"$ac_cv_host_system_type" != x"$host"; } ||
{ test x"${ac_cv_build_system_type+set}" = x"set" &&
test x"$ac_cv_build_system_type" != x"$build"; } ||
{ test x"${ac_cv_target_system_type+set}" = x"set" &&
test x"$ac_cv_target_system_type" != x"$target"; }; then
AC_MSG_RESULT([different])
ifelse($#, 1, [$1],
[AC_MSG_ERROR(["you must remove config.cache and restart configure"])])
else
AC_MSG_RESULT([same])
fi
ac_cv_host_system_type="$host"
ac_cv_build_system_type="$build"
ac_cv_target_system_type="$target"
])

389
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-2008 Wayne Davison
* Copyright (C) 2003-2015 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
@@ -21,28 +21,30 @@
*/
#include "rsync.h"
#include "ifuncs.h"
#include "inums.h"
#include "io.h"
#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
#include <locale.h>
#endif
extern int verbose;
extern int dry_run;
extern int list_only;
extern int io_timeout;
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;
extern int always_checksum;
extern int remove_source_files;
extern int output_needs_newline;
extern int need_messages_from_generator;
extern int kluge_around_eof;
extern int do_stats;
extern int got_xfer_error;
extern int msgs2stderr;
extern int module_id;
extern int read_only;
extern int copy_links;
extern int copy_dirlinks;
extern int copy_unsafe_links;
@@ -63,28 +65,44 @@ extern int whole_file;
extern int read_batch;
extern int write_batch;
extern int batch_fd;
extern int sock_f_in;
extern int sock_f_out;
extern int filesfrom_fd;
extern int connect_timeout;
extern int send_msgs_to_gen;
extern dev_t filesystem_dev;
extern pid_t cleanup_child_pid;
extern size_t bwlimit_writemax;
extern unsigned int module_dirlen;
extern BOOL flist_receiving_enabled;
extern BOOL shutting_down;
extern int basis_dir_cnt;
extern struct stats stats;
extern char *stdout_format;
extern char *logfile_format;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *dest_option;
extern char *basis_dir[];
extern char *rsync_path;
extern char *shell_cmd;
extern char *batch_name;
extern char *password_file;
extern char *backup_dir;
extern char curr_dir[MAXPATHLEN];
extern char backup_dir_buf[MAXPATHLEN];
extern char *basis_dir[MAX_BASIS_DIRS+1];
extern struct file_list *first_flist;
extern struct filter_list_struct daemon_filter_list;
extern filter_rule_list daemon_filter_list;
uid_t our_uid;
gid_t our_gid;
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;
int batch_gen_fd = -1;
int sender_keeps_checksum = 0;
/* There's probably never more than at most 2 outstanding child processes,
* but set it higher, just in case. */
@@ -114,7 +132,7 @@ static void show_malloc_stats(void);
pid_t wait_process(pid_t pid, int *status_ptr, int flags)
{
pid_t waited_pid;
do {
waited_pid = waitpid(pid, status_ptr, flags);
} while (waited_pid == -1 && errno == EINTR);
@@ -167,6 +185,30 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
*exit_code_ptr = WEXITSTATUS(status);
}
void write_del_stats(int f)
{
if (read_batch)
write_int(f, NDX_DEL_STATS);
else
write_ndx(f, NDX_DEL_STATS);
write_varint(f, stats.deleted_files - stats.deleted_dirs
- stats.deleted_symlinks - stats.deleted_devices
- stats.deleted_specials);
write_varint(f, stats.deleted_dirs);
write_varint(f, stats.deleted_symlinks);
write_varint(f, stats.deleted_devices);
write_varint(f, stats.deleted_specials);
}
void read_del_stats(int f)
{
stats.deleted_files = read_varint(f);
stats.deleted_files += stats.deleted_dirs = read_varint(f);
stats.deleted_files += stats.deleted_symlinks = read_varint(f);
stats.deleted_files += stats.deleted_devices = read_varint(f);
stats.deleted_files += stats.deleted_specials = read_varint(f);
}
/* This function gets called from all 3 processes. We want the client side
* to actually output the text, but the sender is the only process that has
* all the stats we need. So, if we're a client sender, we do the report.
@@ -183,7 +225,7 @@ static void handle_stats(int f)
total_read = stats.total_read;
total_written = stats.total_written;
if (do_stats && verbose > 1) {
if (INFO_GTE(STATS, 3)) {
/* These come out from every process */
show_malloc_stats();
show_flist_stats();
@@ -237,13 +279,39 @@ static void handle_stats(int f)
}
}
static void output_itemized_counts(const char *prefix, int *counts)
{
static char *labels[] = { "reg", "dir", "link", "dev", "special" };
char buf[1024], *pre = " (";
int j, len = 0;
int total = counts[0];
if (total) {
counts[0] -= counts[1] + counts[2] + counts[3] + counts[4];
for (j = 0; j < 5; j++) {
if (counts[j]) {
len += snprintf(buf+len, sizeof buf - len - 2,
"%s%s: %s",
pre, labels[j], comma_num(counts[j]));
pre = ", ";
}
}
buf[len++] = ')';
}
buf[len] = '\0';
rprintf(FINFO, "%s: %s%s\n", prefix, comma_num(total), buf);
}
static void output_summary(void)
{
if (do_stats) {
if (INFO_GTE(STATS, 2)) {
rprintf(FCLIENT, "\n");
rprintf(FINFO,"Number of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
stats.num_transferred_files);
output_itemized_counts("Number of files", &stats.num_files);
if (protocol_version >= 29)
output_itemized_counts("Number of created files", &stats.created_files);
if (protocol_version >= 31)
output_itemized_counts("Number of deleted files", &stats.deleted_files);
rprintf(FINFO,"Number of regular files transferred: %s\n",
comma_num(stats.xferred_files));
rprintf(FINFO,"Total file size: %s bytes\n",
human_num(stats.total_size));
rprintf(FINFO,"Total transferred file size: %s bytes\n",
@@ -256,11 +324,11 @@ static void output_summary(void)
human_num(stats.flist_size));
if (stats.flist_buildtime) {
rprintf(FINFO,
"File list generation time: %.3f seconds\n",
(double)stats.flist_buildtime / 1000);
"File list generation time: %s seconds\n",
comma_dnum((double)stats.flist_buildtime / 1000, 3));
rprintf(FINFO,
"File list transfer time: %.3f seconds\n",
(double)stats.flist_xfertime / 1000);
"File list transfer time: %s seconds\n",
comma_dnum((double)stats.flist_xfertime / 1000, 3));
}
rprintf(FINFO,"Total bytes sent: %s\n",
human_num(total_written));
@@ -268,15 +336,15 @@ static void output_summary(void)
human_num(total_read));
}
if (verbose || do_stats) {
if (INFO_GTE(STATS, 1)) {
rprintf(FCLIENT, "\n");
rprintf(FINFO,
"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%s\n",
rprintf(FINFO, "total size is %s speedup is %s%s\n",
human_num(stats.total_size),
(double)stats.total_size / (total_written+total_read),
comma_dnum((double)stats.total_size / (total_written+total_read), 2),
write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
}
@@ -297,7 +365,7 @@ static void show_malloc_stats(void)
rprintf(FCLIENT, "\n");
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
getpid(), am_server ? "server " : "",
(int)getpid(), am_server ? "server " : "",
am_daemon ? "daemon " : "", who_am_i());
rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
(long)mi.arena);
@@ -330,7 +398,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
int *f_in_p, int *f_out_p)
{
int i, argc = 0;
char *args[MAX_ARGS];
char *args[MAX_ARGS], *need_to_free = NULL;
pid_t pid;
int dash_l_set = 0;
@@ -341,7 +409,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); /* MEMORY LEAK */
cmd = need_to_free = strdup(cmd);
if (!cmd)
goto oom;
@@ -427,14 +495,18 @@ 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--;
}
}
args[argc] = NULL;
if (verbose > 3) {
if (DEBUG_GTE(CMD, 2)) {
for (i = 0; i < argc; i++)
rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]);
rprintf(FCLIENT, "\n");
@@ -469,10 +541,13 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
#ifdef ICONV_CONST
setup_iconv();
#endif
if (protect_args)
if (protect_args && !daemon_over_rsh)
send_protected_args(*f_out_p, args);
}
if (need_to_free)
free(need_to_free);
return pid;
oom:
@@ -499,7 +574,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
int statret;
char *cp;
if (verbose > 2) {
if (DEBUG_GTE(RECV, 1)) {
rprintf(FINFO, "get_local_name count=%d %s\n",
file_total, NS(dest_path));
}
@@ -507,6 +582,10 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (!dest_path || list_only)
return NULL;
/* Treat an empty string as a copy into the current directory. */
if (!*dest_path)
dest_path = ".";
if (daemon_filter_list.head) {
char *slash = strrchr(dest_path, '/');
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
@@ -516,7 +595,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if ((*dest_path != '.' || dest_path[1] != '\0')
&& (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
rprintf(FERROR, "ERROR: daemon has excluded destination \"%s\"\n",
dest_path);
exit_cleanup(RERR_FILESELECT);
}
@@ -533,6 +612,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
return NULL;
}
if (file_total > 1) {
@@ -570,7 +650,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
exit_cleanup(RERR_SYNTAX);
}
if (mkdir_defmode(dest_path) != 0) {
if (do_mkdir(dest_path, ACCESSPERMS) != 0) {
rsyserr(FERROR, errno, "mkdir %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILEIO);
@@ -580,7 +660,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
&& strcmp(flist->files[flist->low]->basename, ".") == 0)
flist->files[0]->flags |= FLAG_DIR_CREATED;
if (verbose)
if (INFO_GTE(NAME, 1))
rprintf(FINFO, "created directory %s\n", dest_path);
if (dry_run) {
@@ -626,48 +706,63 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
static void check_alt_basis_dirs(void)
{
STRUCT_STAT st;
char **dir_p, *slash = strrchr(curr_dir, '/');
char *slash = strrchr(curr_dir, '/');
int j;
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;
for (j = 0; j < basis_dir_cnt; j++) {
char *bdir = basis_dir[j];
int bd_len = strlen(bdir);
if (bd_len > 1 && bdir[bd_len-1] == '/')
bdir[--bd_len] = '\0';
if (dry_run > 1 && *bdir != '/') {
int len = curr_dir_len + 1 + bd_len + 1;
char *new = new_array(char, len);
if (!new)
out_of_memory("check_alt_basis_dirs");
if (slash && strncmp(*dir_p, "../", 3) == 0) {
if (slash && strncmp(bdir, "../", 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);
pathjoin(new, len, curr_dir, bdir + 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);
pathjoin(new, len, curr_dir, bdir);
basis_dir[j] = bdir = new;
}
if (do_stat(bdir, &st) < 0)
rprintf(FWARNING, "%s arg does not exist: %s\n", dest_option, bdir);
else if (!S_ISDIR(st.st_mode))
rprintf(FWARNING, "%s arg is not a dir: %s\n", dest_option, bdir);
}
}
/* This is only called by the sender. */
static void read_final_goodbye(int f_in)
static void read_final_goodbye(int f_in, int f_out)
{
int i, iflags, xlen;
uchar fnamecmp_type;
char xname[MAXPATHLEN];
shutting_down = True;
if (protocol_version < 29)
i = read_int(f_in);
else {
i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
xname, &xlen);
i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
if (protocol_version >= 31 && i == NDX_DONE) {
if (am_sender)
write_ndx(f_out, NDX_DONE);
else {
if (batch_gen_fd >= 0) {
while (read_int(batch_gen_fd) != NDX_DEL_STATS) {}
read_del_stats(batch_gen_fd);
}
write_int(f_out, NDX_DONE);
}
i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
}
}
if (i != NDX_DONE) {
@@ -682,17 +777,15 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
struct file_list *flist;
char *dir = argv[0];
if (verbose > 2) {
rprintf(FINFO, "server_sender starting pid=%ld\n",
(long)getpid());
}
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "server_sender starting pid=%d\n", (int)getpid());
if (am_daemon && lp_write_only(module_id)) {
rprintf(FERROR, "ERROR: module is write only\n");
exit_cleanup(RERR_SYNTAX);
return;
}
if (am_daemon && lp_read_only(module_id) && remove_source_files) {
if (am_daemon && read_only && remove_source_files) {
rprintf(FERROR,
"ERROR: --remove-%s-files cannot be used with a read-only module\n",
remove_source_files == 1 ? "source" : "sent");
@@ -717,8 +810,12 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
}
flist = send_file_list(f_out,argc,argv);
if (!flist || flist->used == 0)
if (!flist || flist->used == 0) {
/* Make sure input buffering is off so we can't hang in noop_io_until_death(). */
io_end_buffering_in(0);
/* TODO: we should really exit in a more controlled manner. */
exit_cleanup(0);
}
io_start_buffering_in(f_in);
@@ -726,7 +823,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
io_flush(FULL_FLUSH);
handle_stats(f_out);
if (protocol_version >= 24)
read_final_goodbye(f_in);
read_final_goodbye(f_in, f_out);
io_flush(FULL_FLUSH);
exit_cleanup(0);
}
@@ -752,7 +849,17 @@ static int do_recv(int f_in, int f_out, char *local_name)
exit_cleanup(RERR_IPC);
}
io_flush(NORMAL_FLUSH);
if (backup_dir) {
int ret = make_path(backup_dir_buf, MKP_DROP_NAME); /* drops trailing slash */
if (ret < 0)
exit_cleanup(RERR_SYNTAX);
if (ret)
rprintf(FINFO, "Created backup_dir %s\n", backup_dir_buf);
else if (INFO_GTE(BACKUP, 1))
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
}
io_flush(FULL_FLUSH);
if ((pid = do_fork()) == -1) {
rsyserr(FERROR, errno, "fork failed in do_recv");
@@ -760,37 +867,44 @@ static int do_recv(int f_in, int f_out, char *local_name)
}
if (pid == 0) {
am_receiver = 1;
send_msgs_to_gen = am_server;
close(error_pipe[0]);
/* We can't let two processes write to the socket at one time. */
io_end_multiplex_out(MPLX_SWITCHING);
if (f_in != f_out)
close(f_out);
sock_f_out = -1;
f_out = error_pipe[1];
/* we can't let two processes write to the socket at one time */
io_end_multiplex_out();
bwlimit_writemax = 0; /* receiver doesn't need to do this */
/* set place to send errors */
set_msg_fd_out(error_pipe[1]);
io_start_buffering_out(error_pipe[1]);
if (read_batch)
io_start_buffering_in(f_in);
io_start_multiplex_out(f_out);
recv_files(f_in, local_name);
recv_files(f_in, f_out, local_name);
io_flush(FULL_FLUSH);
handle_stats(f_in);
send_msg(MSG_DONE, "", 1, 0);
write_varlong(error_pipe[1], stats.total_read, 3);
if (output_needs_newline) {
fputc('\n', stdout);
output_needs_newline = 0;
}
write_int(f_out, NDX_DONE);
send_msg(MSG_STATS, (char*)&stats.total_read, sizeof stats.total_read, 0);
io_flush(FULL_FLUSH);
/* Handle any keep-alive packets from the post-processing work
* that the generator does. */
if (protocol_version >= 29) {
int iflags, xlen;
uchar fnamecmp_type;
char xname[MAXPATHLEN];
kluge_around_eof = -1;
/* This should only get stopped via a USR2 signal. */
read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
xname, &xlen);
read_final_goodbye(f_in, f_out);
rprintf(FERROR, "Invalid packet at end of run [%s]\n",
who_am_i());
@@ -805,19 +919,20 @@ static int do_recv(int f_in, int f_out, char *local_name)
}
am_generator = 1;
flist_receiving_enabled = True;
io_end_multiplex_in();
io_end_multiplex_in(MPLX_SWITCHING);
if (write_batch && !am_server)
stop_write_batch();
close(error_pipe[1]);
if (f_in != f_out)
close(f_in);
sock_f_in = -1;
f_in = error_pipe[0];
io_start_buffering_out(f_out);
set_msg_fd_in(error_pipe[0]);
io_start_buffering_in(error_pipe[0]);
io_start_multiplex_in(f_in);
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && inc_recurse) {
@@ -831,13 +946,13 @@ static int do_recv(int f_in, int f_out, char *local_name)
handle_stats(-1);
io_flush(FULL_FLUSH);
shutting_down = True;
if (protocol_version >= 24) {
/* send a final goodbye message */
write_ndx(f_out, NDX_DONE);
}
io_flush(FULL_FLUSH);
set_msg_fd_in(-1);
kill(pid, SIGUSR2);
wait_process_with_flush(pid, &exit_code);
return exit_code;
@@ -848,20 +963,20 @@ 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;
int save_verbose = verbose;
int negated_levels;
if (filesfrom_fd >= 0) {
if (filesfrom_fd >= 0 && !msgs2stderr && protocol_version < 31) {
/* We can't mix messages with files-from data on the socket,
* so temporarily turn off verbose messages. */
verbose = 0;
}
* so temporarily turn off info/debug messages. */
negate_output_levels();
negated_levels = 1;
} else
negated_levels = 0;
if (verbose > 2) {
rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
argc, (long)getpid());
}
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO, "server_recv(%d) starting pid=%d\n", argc, (int)getpid());
if (am_daemon && lp_read_only(module_id)) {
if (am_daemon && read_only) {
rprintf(FERROR,"ERROR: module is read only\n");
exit_cleanup(RERR_SYNTAX);
return;
@@ -879,7 +994,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
}
if (protocol_version >= 30)
io_start_multiplex_in();
io_start_multiplex_in(f_in);
else
io_start_buffering_in(f_in);
recv_filter_list(f_in);
@@ -890,18 +1005,20 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
* need the IO routines to automatically write out the names
* onto our f_out socket as we read the file-list. This
* avoids both deadlock and extra delays/buffers. */
io_set_filesfrom_fds(filesfrom_fd, f_out);
start_filesfrom_forwarding(filesfrom_fd);
filesfrom_fd = -1;
}
flist = recv_file_list(f_in);
flist = recv_file_list(f_in, -1);
if (!flist) {
rprintf(FERROR,"server_recv: recv_file_list error\n");
exit_cleanup(RERR_FILESELECT);
}
if (inc_recurse && file_total == 1)
recv_additional_file_list(f_in);
verbose = save_verbose;
if (negated_levels)
negate_output_levels();
if (argc > 0)
local_name = get_local_name(flist,argv[0]);
@@ -919,7 +1036,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
if (daemon_filter_list.head) {
char **dir_p;
struct filter_list_struct *elp = &daemon_filter_list;
filter_rule_list *elp = &daemon_filter_list;
for (dir_p = basis_dir; *dir_p; dir_p++) {
char *dir = *dir_p;
@@ -958,12 +1075,16 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
setup_protocol(f_out, f_in);
if (protocol_version >= 23)
io_start_multiplex_out();
io_start_multiplex_out(f_out);
if (am_daemon && io_timeout && protocol_version >= 31)
send_msg_int(MSG_IO_TIMEOUT, io_timeout);
if (am_sender) {
keep_dirlinks = 0; /* Must be disabled on the sender. */
if (need_messages_from_generator)
io_start_multiplex_in();
io_start_multiplex_in(f_in);
else
io_start_buffering_in(f_in);
recv_filter_list(f_in);
do_server_sender(f_in, f_out, argc, argv);
} else
@@ -971,11 +1092,8 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
exit_cleanup(0);
}
/*
* This is called once the connection has been negotiated. It is used
* for rsyncd, remote-shell, and local connections.
*/
/* This is called once the connection has been negotiated. It is used
* for rsyncd, remote-shell, and local connections. */
int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
{
struct file_list *flist = NULL;
@@ -1003,12 +1121,20 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (am_sender) {
keep_dirlinks = 0; /* Must be disabled on the sender. */
if (always_checksum
&& (log_format_has(stdout_format, 'C')
|| log_format_has(logfile_format, 'C')))
sender_keeps_checksum = 1;
if (protocol_version >= 30)
io_start_multiplex_out();
io_start_multiplex_out(f_out);
else
io_start_buffering_out(f_out);
if (!filesfrom_host)
set_msg_fd_in(f_in);
if (protocol_version >= 31 || (!filesfrom_host && protocol_version >= 23))
io_start_multiplex_in(f_in);
else
io_start_buffering_in(f_in);
send_filter_list(f_out);
if (filesfrom_host)
filesfrom_fd = f_in;
@@ -1016,21 +1142,20 @@ 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)
if (DEBUG_GTE(FLIST, 3))
rprintf(FINFO,"file list sent\n");
if (protocol_version >= 23)
io_start_multiplex_in();
if (protocol_version < 31 && filesfrom_host && protocol_version >= 23)
io_start_multiplex_in(f_in);
io_flush(NORMAL_FLUSH);
send_files(f_in, f_out);
io_flush(FULL_FLUSH);
handle_stats(-1);
if (protocol_version >= 24)
read_final_goodbye(f_in);
read_final_goodbye(f_in, f_out);
if (pid != -1) {
if (verbose > 3)
if (DEBUG_GTE(EXIT, 2))
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
io_flush(FULL_FLUSH);
wait_process_with_flush(pid, &exit_code);
@@ -1042,21 +1167,23 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (!read_batch) {
if (protocol_version >= 23)
io_start_multiplex_in();
io_start_multiplex_in(f_in);
if (need_messages_from_generator)
io_start_multiplex_out();
io_start_multiplex_out(f_out);
else
io_start_buffering_out(f_out);
}
send_filter_list(read_batch ? -1 : f_out);
if (filesfrom_fd >= 0) {
io_set_filesfrom_fds(filesfrom_fd, f_out);
start_filesfrom_forwarding(filesfrom_fd);
filesfrom_fd = -1;
}
if (write_batch && !am_server)
start_write_batch(f_in);
flist = recv_file_list(f_in);
flist = recv_file_list(f_in, -1);
if (inc_recurse && file_total == 1)
recv_additional_file_list(f_in);
@@ -1072,7 +1199,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
}
if (pid != -1) {
if (verbose > 3)
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
io_flush(FULL_FLUSH);
wait_process_with_flush(pid, &exit_code);
@@ -1097,14 +1224,12 @@ static int copy_argv(char *argv[])
}
/**
* Start a client for either type of remote connection. Work out
/* Start a client for either type of remote connection. Work out
* whether the arguments request a remote shell or rsyncd connection,
* and call the appropriate connection function, then run_client.
*
* Calls either start_socket_client (for sockets) or do_cmd and
* client_run (for ssh).
**/
* client_run (for ssh). */
static int start_client(int argc, char *argv[])
{
char *p, *shell_machine = NULL, *shell_user = NULL;
@@ -1187,10 +1312,13 @@ 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 (!rsync_port && remote_argc && !**remote_argv) /* Turn an empty arg into a dot dir. */
*remote_argv = ".";
if (am_sender) {
char *dummy_host;
int dummy_port = rsync_port;
@@ -1226,6 +1354,8 @@ static int start_client(int argc, char *argv[])
rprintf(FERROR, "All source args must use the same port number.\n");
exit_cleanup(RERR_SYNTAX);
}
if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
arg = ".";
remote_argv[i] = arg;
}
}
@@ -1254,10 +1384,10 @@ static int start_client(int argc, char *argv[])
}
}
if (verbose > 3) {
if (DEBUG_GTE(CMD, 2)) {
rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
NS(shell_cmd), NS(shell_machine), NS(shell_user),
remote_argv ? NS(remote_argv[0]) : "");
NS(remote_argv[0]));
}
pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,
@@ -1281,12 +1411,12 @@ static int start_client(int argc, char *argv[])
}
static RETSIGTYPE sigusr1_handler(UNUSED(int val))
static void sigusr1_handler(UNUSED(int val))
{
exit_cleanup(RERR_SIGNAL1);
}
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
static void sigusr2_handler(UNUSED(int val))
{
if (!am_server)
output_summary();
@@ -1296,7 +1426,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
_exit(0);
}
RETSIGTYPE remember_children(UNUSED(int val))
void remember_children(UNUSED(int val))
{
#ifdef WNOHANG
int cnt, status;
@@ -1357,13 +1487,12 @@ const char *get_panic_action(void)
* should just look at the environment variable, but I'm a bit leery
* of a signal sending us into a busy loop.
**/
static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
static void rsync_panic_handler(UNUSED(int whatsig))
{
char cmd_buf[300];
int ret;
int ret, pid_int = getpid();
snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(),
getpid(), getpid());
snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(), pid_int, pid_int);
/* Unless we failed to execute gdb, we allow the process to
* continue. I'm not sure if that's right. */
@@ -1399,6 +1528,7 @@ int main(int argc,char *argv[])
starttime = time(NULL);
our_uid = MY_UID();
our_gid = MY_GID();
am_root = our_uid == 0;
memset(&stats, 0, sizeof(stats));
@@ -1408,9 +1538,10 @@ int main(int argc,char *argv[])
exit_cleanup(RERR_SYNTAX);
}
/* we set a 0 umask so that correct file permissions can be
* carried across */
orig_umask = umask(0);
/* Get the umask for use in permission calculations. We no longer set
* it to zero; that is ugly and pointless now that all the callers that
* relied on it have been reeducated to work with default ACLs. */
umask(orig_umask = umask(0));
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");

178
match.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2008 Wayne Davison
* Copyright (C) 2003-2015 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
@@ -20,13 +20,14 @@
*/
#include "rsync.h"
#include "inums.h"
extern int verbose;
extern int do_progress;
extern int checksum_seed;
extern int append_mode;
extern int checksum_len;
int updating_basis_file;
char sender_file_sum[MAX_DIGEST_LEN];
static int false_alarms;
static int hash_hits;
@@ -90,8 +91,7 @@ static void build_hash_table(struct sum_struct *s)
static OFF_T last_match;
/**
* Transmit a literal and/or match token.
/* Transmit a literal and/or match token.
*
* This delightfully-named function is called either when we find a
* match and need to transmit all the unmatched data leading up to it,
@@ -99,19 +99,19 @@ 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)
{
int32 n = (int32)(offset - last_match); /* max value: block_size (int32) */
int32 j;
if (verbose > 2 && i >= 0) {
if (DEBUG_GTE(DELTASUM, 2) && i >= 0) {
rprintf(FINFO,
"match at %.0f last_match=%.0f j=%d len=%ld n=%ld\n",
(double)offset, (double)last_match, i,
"match at %s last_match=%s j=%d len=%ld n=%ld\n",
big_num(offset), big_num(last_match), i,
(long)s->sums[i].len, (long)n);
}
@@ -133,7 +133,7 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
else
last_match = offset;
if (buf && do_progress)
if (buf && INFO_GTE(PROGRESS, 1))
show_progress(last_match, buf->file_size);
}
@@ -141,8 +141,8 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf, OFF_T len)
{
OFF_T offset, end;
int32 k, want_i, backup;
OFF_T offset, aligned_offset, end;
int32 k, want_i, aligned_i, backup;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
int more;
@@ -152,9 +152,9 @@ static void hash_search(int f,struct sum_struct *s,
* coding of the output to work more efficiently. */
want_i = 0;
if (verbose > 2) {
rprintf(FINFO, "hash search b=%ld len=%.0f\n",
(long)s->blength, (double)len);
if (DEBUG_GTE(DELTASUM, 2)) {
rprintf(FINFO, "hash search b=%ld len=%s\n",
(long)s->blength, big_num(len));
}
k = (int32)MIN(len, (OFF_T)s->blength);
@@ -164,41 +164,55 @@ static void hash_search(int f,struct sum_struct *s,
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
if (DEBUG_GTE(DELTASUM, 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;
if (verbose > 3) {
rprintf(FINFO, "hash search s->blength=%ld len=%.0f count=%.0f\n",
(long)s->blength, (double)len, (double)s->count);
if (DEBUG_GTE(DELTASUM, 3)) {
rprintf(FINFO, "hash search s->blength=%ld len=%s count=%s\n",
(long)s->blength, big_num(len), big_num(s->count));
}
do {
int done_csum2 = 0;
int32 i;
uint32 hash_entry;
int32 i, *prev;
if (verbose > 4) {
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
if (DEBUG_GTE(DELTASUM, 4)) {
rprintf(FINFO, "offset=%s sum=%04x%04x\n",
big_num(offset), s2 & 0xFFFF, s1 & 0xFFFF);
}
if (tablesize == TRADITIONAL_TABLESIZE) {
if ((i = hash_table[SUM2HASH2(s1,s2)]) < 0)
hash_entry = SUM2HASH2(s1,s2);
if ((i = hash_table[hash_entry]) < 0)
goto null_hash;
sum = (s1 & 0xffff) | (s2 << 16);
} else {
sum = (s1 & 0xffff) | (s2 << 16);
if ((i = hash_table[BIG_SUM2HASH(sum)]) < 0)
hash_entry = BIG_SUM2HASH(sum);
if ((i = hash_table[hash_entry]) < 0)
goto null_hash;
}
prev = &hash_table[hash_entry];
hash_hits++;
do {
int32 l;
/* When updating in-place, the chunk's offset must be
* either >= our offset or identical data at that offset.
* Remove any bypassed entries that we can never use. */
if (updating_basis_file && s->sums[i].offset < offset
&& !(s->sums[i].flags & SUMFLG_SAME_OFFSET)) {
*prev = s->sums[i].chain;
continue;
}
prev = &s->sums[i].chain;
if (sum != s->sums[i].sum1)
continue;
@@ -207,16 +221,10 @@ static void hash_search(int f,struct sum_struct *s,
if (l != s->sums[i].len)
continue;
/* in-place: ensure chunk's offset is either >= our
* offset or that the data didn't move. */
if (updating_basis_file && s->sums[i].offset < offset
&& !(s->sums[i].flags & SUMFLG_SAME_OFFSET))
continue;
if (verbose > 3) {
if (DEBUG_GTE(DELTASUM, 3)) {
rprintf(FINFO,
"potential match at %.0f i=%ld sum=%08x\n",
(double)offset, (long)i, sum);
"potential match at %s i=%ld sum=%08x\n",
big_num(offset), (long)i, sum);
}
if (!done_csum2) {
@@ -232,27 +240,51 @@ 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
|| (sum == 0 && l == s->blength && aligned_offset + l <= len))
&& 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. */
if (offset != aligned_offset) {
/* We've matched some zeros in a spot that is also zeros
* further along in the basis file, if we find zeros ahead
* in the sender's file, we'll output enough literal data
* to re-align with the basis file, and get back to seeking
* instead of writing. */
backup = (int32)(aligned_offset - last_match);
if (backup < 0)
backup = 0;
map = (schar *)map_ptr(buf, aligned_offset - backup, l + backup)
+ backup;
sum = get_checksum1((char *)map, l);
if (sum != s->sums[i].sum1)
goto check_want_i;
get_checksum2((char *)map, l, sum2);
if (memcmp(sum2, s->sums[i].sum2, s->s2length) != 0)
goto check_want_i;
/* OK, we have a re-alignment match. Bump the offset
* forward to the new match point. */
offset = aligned_offset;
}
/* This identical chunk is in the same spot in the old and new file. */
s->sums[i].flags |= SUMFLG_SAME_OFFSET;
goto set_want_i;
want_i = i;
}
}
check_want_i:
/* we've found a match, but now check to see
* if want_i can hint at a better match. */
if (i != want_i && want_i < s->count
@@ -264,7 +296,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);
@@ -329,9 +360,6 @@ static void hash_search(int f,struct sum_struct *s,
**/
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
{
char file_sum[MAX_DIGEST_LEN];
int sum_len;
last_match = 0;
false_alarms = 0;
hash_hits = 0;
@@ -344,7 +372,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
if (append_mode == 2) {
OFF_T j = 0;
for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
if (buf && do_progress)
if (buf && INFO_GTE(PROGRESS, 1))
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
CHUNK_SIZE);
@@ -352,7 +380,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
}
if (last_match < s->flength) {
int32 n = (int32)(s->flength - last_match);
if (buf && do_progress)
if (buf && INFO_GTE(PROGRESS, 1))
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, n), n);
}
@@ -364,12 +392,12 @@ 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)
if (DEBUG_GTE(DELTASUM, 2))
rprintf(FINFO,"built hash table\n");
hash_search(f, s, buf, len);
if (verbose > 2)
if (DEBUG_GTE(DELTASUM, 2))
rprintf(FINFO,"done hash search\n");
} else {
OFF_T j;
@@ -379,18 +407,28 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
matched(f, s, buf, len, -1);
}
sum_len = sum_end(file_sum);
/* If we had a read error, send a bad checksum. */
if (buf && buf->status != 0)
file_sum[0]++;
if (sum_end(sender_file_sum) != checksum_len)
overflow_exit("checksum_len"); /* Impossible... */
if (verbose > 2)
/* If we had a read error, send a bad checksum. We use all bits
* off as long as the checksum doesn't happen to be that, in
* which case we turn the last 0 bit into a 1. */
if (buf && buf->status != 0) {
int i;
for (i = 0; i < checksum_len && sender_file_sum[i] == 0; i++) {}
memset(sender_file_sum, 0, checksum_len);
if (i == checksum_len)
sender_file_sum[i-1]++;
}
if (DEBUG_GTE(DELTASUM, 2))
rprintf(FINFO,"sending file_sum\n");
write_buf(f, file_sum, sum_len);
write_buf(f, sender_file_sum, checksum_len);
if (verbose > 2)
if (DEBUG_GTE(DELTASUM, 2)) {
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
false_alarms, hash_hits, matches);
}
total_hash_hits += hash_hits;
total_false_alarms += false_alarms;
@@ -400,11 +438,11 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
void match_report(void)
{
if (verbose <= 1)
if (!DEBUG_GTE(DELTASUM, 1))
return;
rprintf(FINFO,
"total: matches=%d hash_hits=%d false_alarms=%d data=%.0f\n",
"total: matches=%d hash_hits=%d false_alarms=%d data=%s\n",
total_matches, total_hash_hits, total_false_alarms,
(double)stats.literal_data);
big_num(stats.literal_data));
}

1063
options.c
View File

File diff suppressed because it is too large Load Diff

180
packaging/branch-from-patch Executable file
View File

@@ -0,0 +1,180 @@
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'branch|b=s' => \( my $master_branch = 'master' ),
'skip-check' => \( my $skip_branch_check ),
'delete' => \( my $delete_local_branches ),
'help|h' => \( my $help_opt ),
);
&usage if $help_opt;
require 'packaging/git-status.pl';
check_git_state($master_branch, !$skip_branch_check, 1);
my %local_branch;
open PIPE, '-|', 'git branch -l' or die "Unable to fork: $!\n";
while (<PIPE>) {
if (m# patch/\Q$master_branch\E/(.*)#o) {
$local_branch{$1} = 1;
}
}
close PIPE;
if ($delete_local_branches) {
foreach my $name (sort keys %local_branch) {
my $branch = "patch/$master_branch/$name";
system 'git', 'branch', '-D', $branch and exit 1;
}
%local_branch = ( );
}
my @patch_list;
foreach (@ARGV) {
if (!-f $_) {
die "File not found: $_\n";
}
die "Filename is not a .diff file: $_\n" unless /\.diff$/;
push @patch_list, $_;
}
exit unless @patch_list;
my(%scanned, %created, %info);
foreach my $patch (@patch_list) {
my($where, $name) = $patch =~ m{^(.*?)([^/]+)\.diff$};
next if $scanned{$name}++;
open IN, '<', $patch or die "Unable to open $patch: $!\n";
my $info = '';
my $commit;
while (<IN>) {
if (m#^based-on: (\S+)#) {
$commit = $1;
last;
}
last if m#^index .*\.\..* \d#;
last if m#^diff --git #;
last if m#^--- (old|a)/#;
$info .= $_;
}
close IN;
$info =~ s/\s+\Z/\n/;
my $parent = $master_branch;
my @patches = $info =~ m#patch -p1 <patches/(\S+)\.diff#g;
if (@patches) {
if ($patches[-1] eq $name) {
pop @patches;
} else {
warn "No identity patch line in $patch\n";
}
if (@patches) {
$parent = pop @patches;
if (!$scanned{$parent}) {
unless (-f "$where$parent.diff") {
die "Unknown parent of $patch: $parent\n";
}
# Add parent to @patch_list so that we will look for the
# parent's parent. Any duplicates will just be ignored.
push @patch_list, "$where$parent.diff";
}
}
} else {
warn "No patch lines found in $patch\n";
}
$info{$name} = [ $parent, $info, $commit ];
}
foreach my $patch (@patch_list) {
create_branch($patch);
}
system 'git', 'checkout', $master_branch and exit 1;
exit;
sub create_branch
{
my($patch) = @_;
my($where, $name) = $patch =~ m{^(.*?)([^/]+)\.diff$};
return if $created{$name}++;
my $ref = $info{$name};
my($parent, $info, $commit) = @$ref;
my $parent_branch;
if ($parent eq $master_branch) {
$parent_branch = $master_branch;
$parent_branch = $commit if defined $commit;
} else {
create_branch("$where/$parent.diff");
$parent_branch = "patch/$master_branch/$parent";
}
my $branch = "patch/$master_branch/$name";
print "\n", '=' x 64, "\nProcessing $branch ($parent_branch)\n";
if ($local_branch{$name}) {
system 'git', 'branch', '-D', $branch and exit 1;
}
system 'git', 'checkout', '-b', $branch, $parent_branch and exit 1;
open OUT, '>', "PATCH.$name" or die $!;
print OUT $info;
close OUT;
system 'git', 'add', "PATCH.$name" and exit 1;
open IN, '<', $patch or die "Unable to open $patch: $!\n";
$_ = join('', <IN>);
close IN;
open PIPE, '|-', 'patch -p1' or die $!;
print PIPE $_;
close PIPE;
system 'rm -f *.orig */*.orig';
while (m#\nnew file mode (\d+)\s+--- /dev/null\s+\Q+++\E b/(.*)#g) {
chmod oct($1), $2;
system 'git', 'add', $2;
}
while (1) {
system 'git status';
print 'Press Enter to commit, Ctrl-C to abort, or type a wild-name to add a new file: ';
$_ = <STDIN>;
last if /^$/;
chomp;
system "git add $_";
}
while (system 'git', 'commit', '-a', '-m', "Creating branch from $name.diff.") {
exit 1 if system '/bin/zsh';
}
}
sub usage
{
die <<EOT;
Usage branch-from-patch [OPTIONS] patches/DIFF...
Options:
-b, --branch=BRANCH Create branches relative to BRANCH if no "based-on"
header was found in the patch file.
--skip-check Skip the check that ensures starting with a clean branch.
--delete Delete all the local patch/BASE/* branches, not just the ones
that are being recreated.
-h, --help Output this help message.
EOT
}

View File

@@ -6,10 +6,23 @@ use strict;
our %short_no_arg;
our %short_with_num;
our %long_opt = (
'no-i-r' => 0,
our %long_opt = ( # These include some extra long-args that BackupPC uses:
'block-size' => 1,
'daemon' => -1,
'debug' => 1,
'fake-super' => 0,
'fuzzy' => 0,
'group' => 0,
'hard-links' => 0,
'ignore-times' => 0,
'info' => 1,
'links' => 0,
'log-file' => 3,
'one-file-system' => 0,
'owner' => 0,
'perms' => 0,
'recursive' => 0,
'times' => 0,
);
our $last_long_opt;
@@ -24,7 +37,7 @@ while (<IN>) {
undef $last_long_opt;
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
$last_long_opt = $1;
$long_opt{$1} = 0;
$long_opt{$1} = 0 unless exists $long_opt{$1};
} elsif (defined($last_long_opt)
&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
$long_opt{$last_long_opt} = 2;

View File

@@ -1,18 +0,0 @@
#!/usr/bin/perl
# This script finds extraneous "extern" variables in the *.c files.
# Run it from inside the main rsync directory.
use strict;
my @files = glob('*.c');
foreach my $fn (@files) {
open(IN, '<', $fn) or die;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
my @externs = /^extern .*?([^[\s(*;&.]+)(?:\[.*?\])?;/mg;
foreach my $find (@externs) {
my @matches = /(?<!\sstruct )\b(\Q$find\E)\b/g;
print $fn, ': ', $find, "\n" if @matches == 1;
}
}

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

@@ -0,0 +1,51 @@
# 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);
(my $branch = $cur_branch) =~ s{^patch/([^/]+)/[^/]+$}{$1}; # change patch/BRANCH/PATCH_NAME into BRANCH
if ($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=$branch? [n] ";
$_ = <STDIN>;
exit 1 unless /^y/i;
$_[0] = $master_branch = $branch; # Updates caller's $master_branch too.
}
if ($check_patches_dir && -d 'patches/.git') {
($branch) = check_git_status($fatal_unless_clean, 'patches');
if ($branch ne $master_branch) {
print "The *patches* checkout is on branch $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'";
}
}
return $cur_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,17 +1,27 @@
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.3
%define fullversion %{version}
Release: 1
%define srcdir src
Version: 3.1.2
%define fullversion %{version}pre1
Release: 0.1.pre1
%define srcdir src-previews
Group: Applications/Internet
License: GPL
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}
BuildRoot: /var/tmp/%{name}-root
License: GPL
%package ssl-client
Summary: Provides rsync-ssl
Group: Applications/Internet
Requires: rsync, stunnel >= 4
%package ssl-daemon
Summary: An stunnel config file to support ssl rsync daemon connections.
Group: Applications/Internet
Requires: rsync, stunnel >= 4
%description
Rsync is a fast and extraordinarily versatile file copying tool. It can
@@ -24,12 +34,22 @@ differences between the source files and the existing files in the
destination. Rsync is widely used for backups and mirroring and as an
improved copy command for everyday use.
%description ssl-client
Provides the rsync-ssl script that makes use of stunnel 4 to open an ssl
connection to an rsync daemon (on port 874). This setup does NOT require
any local stunnel daemon to be running to connect to the remote ssl rsyncd.
%description ssl-daemon
Provides a config file for stunnel that will (if you start your stunnel
service) cause stunnel to listen for ssl rsync-daemon connections and run
"rsync --daemon" to handle them.
%prep
# 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:
# 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
@@ -46,14 +66,11 @@ make
%install
rm -rf $RPM_BUILD_ROOT
make install install-ssl-client install-ssl-daemon DESTDIR=$RPM_BUILD_ROOT
%makeinstall
mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d
mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d $RPM_BUILD_ROOT/etc/rsync-ssl/certs
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
@@ -61,13 +78,21 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root)
%doc COPYING NEWS OLDNEWS README support/ tech_report.tex
%config(noreplace) /etc/xinetd.d/rsync
%{_prefix}/bin/rsync*
%{_prefix}/bin/rsync
%{_mandir}/man1/rsync.1*
%{_mandir}/man5/rsyncd.conf.5*
%files ssl-client
%{_prefix}/bin/rsync-ssl
%{_prefix}/bin/stunnel-rsync
%files ssl-daemon
%config(noreplace) /etc/stunnel/rsyncd.conf
%dir /etc/rsync-ssl/certs
%changelog
* Sun Jun 29 2008 Wayne Davison <wayned@samba.org>
Released 3.0.3.
* Sat Aug 08 2015 Wayne Davison <wayned@samba.org>
Released 3.1.2pre1.
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
Added installation of /etc/xinetd.d/rsync file and some commented-out

View File

@@ -3,8 +3,8 @@ use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. It also requires a
# pristine CVS checkout of rsync (don't use your normal rsync build dir
# unless you're 100% sure that there are not unchecked-in changes).
# git checkout of rsync (feel free to use your normal rsync build dir as
# long as it doesn't have any uncommitted changes).
#
# If this is run with -ctu, it will make an updated "nightly" tar file in
# the nightly dir. It will also remove any old tar files, regenerate the
@@ -16,6 +16,7 @@ use Date::Format;
# Where the local copy of /home/ftp/pub/rsync/dev/nightly should be updated.
our $dest = $ENV{HOME} . '/samba-rsync-ftp/dev/nightly';
our $samba_host = $ENV{SAMBA_HOST} || 'samba.org';
our $nightly_symlink = "$dest/rsync-HEAD.tar.gz";
our($make_tar, $upload, $help_opt);
@@ -39,8 +40,8 @@ if ($make_tar) {
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
die "The checkout is not 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;
@@ -56,6 +57,58 @@ if ($make_tar) {
}
close IN;
my $confversion;
open(IN, '<', 'configure.ac') or die "Unable to open configure.ac: $!\n";
while (<IN>) {
if (/^AC_INIT\(\[rsync\],\s*\[(\d.+?)\]/) {
$confversion = $1;
last;
}
}
close IN;
die "Unable to find AC_INIT with 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 -";
@@ -104,7 +157,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/dev/nightly";
system "rsync$opt -aviHP --delete-after . $samba_host\:/home/ftp/pub/rsync/dev/nightly";
}
exit;

View File

@@ -1,18 +1,21 @@
#!/usr/bin/perl -w
# This script is used to turn one or more of the "patch/*" branches
#!/usr/bin/perl
# This script is used to turn one or more of the "patch/BASE/*" branches
# into one or more diffs in the "patches" directory. Pass the option
# --gen if you want generated files in the diffs. Pass the name of
# one or more diffs if you want to just update a subset of all the
# diffs.
use strict;
use warnings;
use Getopt::Long;
my $patches_dir = 'patches';
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 ),
@@ -20,6 +23,8 @@ my $tmp_dir = "patches.$$";
);
&usage if $help_opt;
$ENV{GIT_MERGE_AUTOEDIT} = 'no';
if (defined $incl_generated_files) {
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
$incl_generated_files = 1;
@@ -28,40 +33,35 @@ if (defined $incl_generated_files) {
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
die "No '.git' directory present in the current dir.\n" unless -d '.git';
my($status, $is_clean, $starting_branch) = &check_git_status;
if (!$skip_branch_check && !$is_clean) {
die "The checkout is not clean:\n", $status;
}
require 'packaging/git-status.pl';
my $starting_branch = check_git_state($master_branch, !$skip_branch_check, 1);
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(' ', $_);
my $master_commit;
open PIPE, '-|', "git log -1 --no-color $master_branch" or die $!;
while (<PIPE>) {
if (/^commit (\S+)/) {
$master_commit = $1;
last;
}
}
close IN;
close PIPE;
die "Unable to determine commit hash for master branch: $master_branch\n" unless defined $master_commit;
if ($incl_generated_files) {
my @extra_files = get_extra_files();
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/master/" and exit 1;
}
our $last_touch = time;
my(%patches, %local_patch);
my %patches;
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
while (<PIPE>) {
if (m# origin/patch/(.*)#) {
if (m# patch/\Q$master_branch\E/(.*)#o) {
$patches{$1} = 1;
} elsif (m# patch/(.*)#) {
$patches{$1} = $local_patch{$1} = 1;
}
}
close PIPE;
@@ -70,19 +70,23 @@ my @patches = sort keys %patches;
my(%parent, %description);
foreach my $patch (@patches) {
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
my $branch = "patch/$master_branch/$patch";
my $desc = '';
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
open(PIPE, '-|', 'git', 'diff', '-U1000', "$master_branch...$branch", '--', "PATCH.$patch") or die $!;
while (<PIPE>) {
last if /^@@ /;
}
while (<PIPE>) {
next unless s/^[ +]//;
if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
$parent{$patch} = $1;
my $parent = $parent{$patch} = $1;
if (!$patches{$parent}) {
die "Parent of $patch is not a local branch: $parent\n";
}
}
$desc .= $_;
}
close PIPE;
$description{$patch} = $desc;
}
@@ -90,8 +94,11 @@ if (@ARGV) {
# Limit the list of patches to actually process based on @ARGV.
@patches = ( );
foreach (@ARGV) {
s{^(patches|patch|origin/patch)/} {};
s{^patch(es)?/} {};
s{\.diff$} {};
if (!$patches{$_}) {
die "Local branch not available for patch: $_\n";
}
push(@patches, $_);
}
}
@@ -117,28 +124,27 @@ sub update_patch
my($patch) = @_;
my $parent = $parent{$patch};
my $based_on;
if (defined $parent) {
unless ($completed{$parent}++) {
update_patch($parent);
}
$parent = "patch/$parent";
$based_on = $parent = "patch/$master_branch/$parent";
} else {
$parent = 'master';
$parent = $master_branch;
$based_on = $master_commit;
}
print "======== $patch ========\n";
sleep 1 while $incl_generated_files && $last_touch >= time;
if ($local_patch{$patch}) {
system "git checkout patch/$patch" and return 0;
} else {
system "git checkout --track -b patch/$patch origin/patch/$patch" and return 0;
}
system "git checkout patch/$master_branch/$patch" and return 0;
my $ok = system("git merge $parent") == 0;
my $ok = system("git merge $based_on") == 0;
if (!$ok || $launch_shell) {
print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
$ENV{PS1} = "[$parent] patch/$patch: ";
my($parent_dir) = $parent =~ m{([^/]+)$};
print qq|"git merge $based_on" incomplete -- please fix.\n| if !$ok;
$ENV{PS1} = "[$parent_dir] $patch: ";
while (1) {
if (system($ENV{SHELL}) != 0) {
print "Abort? [n/y] ";
@@ -146,21 +152,23 @@ sub update_patch
next unless /^y/i;
return 0;
}
($status, $is_clean) = &check_git_status;
my($cur_branch, $is_clean, $status) = check_git_status(0);
last if $is_clean;
print $status;
}
}
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
print OUT $description{$patch}, "\n";
print OUT $description{$patch}, "\nbased-on: $based_on\n";
my @extra_files;
if ($incl_generated_files) {
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
@extra_files = get_extra_files();
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
open(PIPE, '-|', 'git', 'diff', $based_on) or die $!;
DIFF: while (<PIPE>) {
while (m{^diff --git a/PATCH}) {
while (<PIPE>) {
@@ -174,15 +182,21 @@ sub update_patch
close PIPE;
if ($incl_generated_files) {
$parent =~ s#.*/##;
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
my $parent_dir;
if ($parent eq $master_branch) {
$parent_dir = 'master';
} else {
($parent_dir) = $parent =~ m{([^/]+)$};
}
open(PIPE, '-|', 'diff', '-Nurp', "$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#^(diff -Nurp) $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;
unlink @extra_files;
}
close OUT;
@@ -192,22 +206,37 @@ sub update_patch
exit;
sub check_git_status
sub get_extra_files
{
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
my @extras;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extras = split(' ', $_);
last;
}
}
close IN;
my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
my($starting_branch) = $status =~ /^# On branch (.+)\n/;
($status, $is_clean, $starting_branch);
return @extras;
}
sub usage
{
die <<EOT;
Usage: patch-update [OPTIONS]
Usage: patch-update [OPTIONS] [patches/DIFF...]
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
--skip-check Skip the check that ensures starting with a clean branch.
Options:
-b, --branch=BRANCH The master branch to merge into the patch/BASE/* branches.
--gen[=DIR] Include generated files. Optional destination DIR
arg overrides the default of using the "patches" dir.
--skip-check Skip the check that ensures starting with a clean branch.
-s, --shell Launch a shell for every patch/BASE/* branch updated, not
just when a conflict occurs.
-h, --help Output this help message.
EOT
}

View File

@@ -1,18 +1,27 @@
#!/usr/bin/perl
use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
# the git repository in the current directory will be updated, and the local
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
use strict;
use warnings;
use Cwd;
use Getopt::Long;
use Term::ReadKey;
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $passfile = $ENV{HOME} . '/.rsyncpass';
my $path = $ENV{PATH};
my $make_gen_cmd = 'make -f prepare-source.mak conf && ./config.status && make gen';
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'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);
@@ -52,27 +61,43 @@ die "There is no .git dir in the current directory.\n" unless -d '.git';
die "'a' must not exist in the current directory.\n" if -e 'a';
die "'b' must not exist in the current directory.\n" if -e 'b';
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
require 'packaging/git-status.pl';
check_git_state($master_branch, 1, 1);
my $confversion;
open(IN, '<', 'configure.in') or die $!;
open(IN, '<', 'configure.ac') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
if (/^AC_INIT\(\[rsync\],\s*\[(\d.+?)\]/) {
$confversion = $1;
last;
}
}
close IN;
die "Unable to find RSYNC_VERSION in configure.in\n" unless defined $confversion;
die "Unable to find AC_INIT with version in configure.ac\n" unless defined $confversion;
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
my($lastversion) = /(\d+\.\d+\.\d+)/;
my($last_protocol_version, %pdate);
while (<IN>) {
if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
$pdate{$ver} = $pdate if defined $pdate;
$last_protocol_version = $pver if $ver eq $lastversion;
}
}
close IN;
die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
my $protocol_version;
open(IN, '<', 'rsync.h') or die $!;
while (<IN>) {
if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
$protocol_version = $1;
last;
}
}
close IN;
die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
my $version = $confversion;
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
@@ -110,6 +135,23 @@ chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
$release .= ".$pre" if $pre;
(my $finalversion = $version) =~ s/pre\d+//;
my($proto_changed,$proto_change_date);
if ($protocol_version eq $last_protocol_version) {
$proto_changed = 'unchanged';
$proto_change_date = "\t\t";
} else {
$proto_changed = 'changed';
if (!defined($proto_change_date = $pdate{$finalversion})) {
while (1) {
print "On what date did the protocol change to $protocol_version get checked in? (dd Mmm yyyy) ";
chomp($_ = <STDIN>);
last if /^\d\d \w\w\w \d\d\d\d$/;
}
$proto_change_date = "$_\t";
}
}
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
if ($lastversion =~ /pre/) {
if (!$pre) {
@@ -138,9 +180,9 @@ print "\n", $break, <<EOT;
\$release is "$release"
About to:
- make sure that SUBPROTOCOL_VERSION is 0$skipping
- tweak the version in configure.in and the spec files
- tweak NEWS and OLDNEWS to update the release date$skipping
- tweak SUBPROTOCOL_VERSION in rsync.h, if needed
- tweak the version in configure.ac and the spec files
- tweak NEWS and OLDNEWS to ensure header values are correct
- tweak the date in the *.yo files and generate the manpages
- generate configure.sh, config.h.in, and proto.h
- page through the differences
@@ -149,20 +191,19 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
(my $finalversion = $version) =~ s/pre\d+//;
my %specvars = ( 'Version:' => $finalversion, 'Release:' => $release,
'%define fullversion' => "\%{version}$pre", 'Released' => "$version.",
'%define srcdir' => $srcdir );
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'), glob('*.yo'),
qw( configure.in rsync.h NEWS OLDNEWS options.c ) );
qw( configure.ac rsync.h NEWS OLDNEWS options.c ) );
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
if ($fn =~ /configure/) {
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m
or die "Unable to update RSYNC_VERSION in $fn\n";
s/^(AC_INIT\(\[rsync\],\s*\[)\d.+?(\])/$1$version$2/m
or die "Unable to update AC_INIT with version in $fn\n";
} elsif ($fn =~ /\.spec/) {
while (my($str, $val) = each %specvars) {
s/^\Q$str\E .*/$str $val/m
@@ -176,18 +217,19 @@ foreach my $fn (@tweak_files) {
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m
or die "Unable to update current version info in $fn\n";
} elsif ($fn eq 'rsync.h') {
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/
s{(#define\s+SUBPROTOCOL_VERSION)\s+(\d+)}
{ $1 . ' ' . get_subprotocol_version($2) }e
or die "Unable to find SUBPROTOCOL_VERSION define in $fn\n";
next if $pre;
} elsif ($fn eq 'NEWS') {
s/^(NEWS for rsync \Q$finalversion\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
or die "The first line of $fn is not in the right format. It must be:\n"
. "NEWS for rsync $finalversion (UNRELEASED)\n";
next if $pre;
s{^(NEWS for rsync \Q$finalversion\E )(\(UNRELEASED\))\s*(\nProtocol: )(\d+) (\([^)]+\))\n}
{ $1 . ($pre ? $2 : "($today)") . "$3$protocol_version ($proto_changed)\n" }ei
or die "The first 2 lines of $fn are not in the right format. They must be:\n"
. "NEWS for rsync $finalversion (UNRELEASED)\n"
. "Protocol: $protocol_version ($proto_changed)\n";
} elsif ($fn eq 'OLDNEWS') {
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$finalversion\E)/\t$ztoday$1/m
s{^(\t\S\S\s\S\S\S\s\d\d\d\d)(\t\Q$finalversion\E\t).*}
{ ($pre ? $1 : "\t$ztoday") . $2 . $proto_change_date . $protocol_version }em
or die "Unable to find \"?? ??? $year\t$finalversion\" line in $fn\n";
next if $pre;
} elsif ($fn eq 'options.c') {
if (s/(Copyright \(C\) 2002-)(\d+)( Wayne Davison)/$1$year$3/
&& $2 ne $year) {
@@ -221,7 +263,7 @@ print $break, <<EOT;
About to:
- commit all version changes
- merge the master branch into the patch/* branches
- merge the $master_branch branch into the patch/$master_branch/* branches
- update the files in the "patches" dir and OPTIONALLY
(if you type 'y') to launch a shell for each patch
@@ -232,11 +274,15 @@ my $ans = <STDIN>;
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
print "Updating files in \"patches\" dir ...\n";
system "packaging/patch-update";
system "packaging/patch-update --branch=$master_branch";
if ($ans =~ /^y/i) {
print "\nVisiting all \"patch/*\" branches ...\n";
system "packaging/patch-update --shell";
print "\nVisiting all \"patch/$master_branch/*\" branches ...\n";
system "packaging/patch-update --branch=$master_branch --skip-check --shell";
}
if (-d 'patches/.git') {
system "cd patches && git commit -a -m 'The patches for $version.'" and exit 1;
}
print $break, <<EOT;
@@ -256,6 +302,9 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
$ENV{PATH} = "$curdir/packaging/bin:$path";
my $passphrase;
while (1) {
ReadMode('noecho');
@@ -273,17 +322,23 @@ while (1) {
umask $oldmask;
$ENV{'GPG_PASSFILE'} = $passfile;
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
$ENV{PATH} = "packaging/bin:$path";
$_ = `git tag -s -m 'Version $version.' v$version 2>&1`;
$ENV{PATH} = $path;
unlink($passfile);
print $_;
next if /bad passphrase/;
last unless /failed/;
exit 1;
exit 1 if /failed/;
if (-d 'patches/.git') {
$_ = `cd patches && git tag -s -m 'Version $version.' v$version 2>&1`;
print $_;
exit 1 if /bad passphrase|failed/;
}
unlink($passfile);
last;
}
$ENV{PATH} = $path;
# Extract the generated files from the old tar.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
@@ -291,7 +346,7 @@ system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
print "Creating $diff_file ...\n";
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
system "$make_gen_cmd && rsync -a @extra_files b/" and exit 1;
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "rm -rf a";
@@ -305,7 +360,7 @@ 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 --gen=rsync-$version/patches";
system "packaging/patch-update --skip-check --branch=$master_branch --gen=rsync-$version/patches";
print "Creating $pattar_file ...\n";
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
@@ -343,3 +398,24 @@ 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
}

View File

@@ -0,0 +1,9 @@
[Unit]
Description=fast remote file copy program daemon
ConditionPathExists=/etc/rsyncd.conf
[Service]
ExecStart=/usr/bin/rsync --daemon --no-detach
[Install]
WantedBy=multi-user.target

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

159
params.c
View File

@@ -75,6 +75,7 @@
#include "rsync.h"
#include "ifuncs.h"
#include "itypes.h"
/* -------------------------------------------------------------------------- **
* Constants...
@@ -93,6 +94,8 @@
static char *bufr = NULL;
static int bSize = 0;
static BOOL (*the_sfunc)(char *);
static BOOL (*the_pfunc)(char *, char *);
/* -------------------------------------------------------------------------- **
* Functions...
@@ -223,7 +226,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
bufr[end] = '\0';
if( 0 == end ) /* Don't allow an empty name. */
{
rprintf(FLOG, "%s Empty section name in configuration file.\n", func );
rprintf(FLOG, "%s Empty section name in config file.\n", func );
return( False );
}
if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */
@@ -236,7 +239,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
if( i < 0 )
{
bufr[end] = '\0';
rprintf(FLOG, "%s Badly formed line in configuration file: %s\n",
rprintf(FLOG, "%s Badly formed line in config file: %s\n",
func, bufr );
return( False );
}
@@ -261,7 +264,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
}
/* We arrive here if we've met the EOF before the closing bracket. */
rprintf(FLOG, "%s Unexpected EOF in the configuration file: %s\n", func, bufr );
rprintf(FLOG, "%s Unexpected EOF in the config file: %s\n", func, bufr );
return( False );
} /* Section */
@@ -315,13 +318,12 @@ 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(FLOG, "%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. */
i = end; /* New string starts here. */
vstart = end; /* New string is parameter value. */
bufr[i] = '\0'; /* New string is nul, for now. */
i = vstart = end; /* New string starts here. */
c = EatWhitespace(InFile);
break;
case '\n': /* Find continuation char, else error. */
@@ -329,7 +331,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
if( i < 0 )
{
bufr[end] = '\0';
rprintf(FLOG, "%s Ignoring badly formed line in configuration file: %s\n",
rprintf(FLOG, "%s Ignoring badly formed line in config file: %s\n",
func, bufr );
return( True );
}
@@ -343,6 +345,19 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr );
return( True );
case ' ':
case '\t':
/* A directive divides at the first space or tab. */
if (*bufr == '&') {
bufr[end++] = '\0';
i = vstart = end;
c = EatWhitespace(InFile);
if (c == '=')
c = EatWhitespace(InFile);
break;
}
/* FALL THROUGH */
default:
if( isspace( c ) ) /* One ' ' per whitespace region. */
{
@@ -360,7 +375,6 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
}
/* Now parse the value. */
c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */
while( (EOF !=c) && (c > 0) )
{
@@ -406,7 +420,88 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */
} /* Parameter */
static BOOL Parse( FILE *InFile,
static int name_cmp(const void *n1, const void *n2)
{
return strcmp(*(char * const *)n1, *(char * const *)n2);
}
static int include_config(char *include, int manage_globals)
{
STRUCT_STAT sb;
char *match = manage_globals ? "*.conf" : "*.inc";
int ret;
if (do_stat(include, &sb) < 0) {
rsyserr(FLOG, errno, "unable to stat config file \"%s\"", include);
return 0;
}
if (S_ISREG(sb.st_mode)) {
if (manage_globals && the_sfunc)
the_sfunc("]push");
ret = pm_process(include, the_sfunc, the_pfunc);
if (manage_globals && the_sfunc)
the_sfunc("]pop");
} else if (S_ISDIR(sb.st_mode)) {
char buf[MAXPATHLEN], **bpp;
item_list conf_list;
struct dirent *di;
size_t j;
DIR *d;
if (!(d = opendir(include))) {
rsyserr(FLOG, errno, "unable to open config dir \"%s\"", include);
return 0;
}
memset(&conf_list, 0, sizeof conf_list);
while ((di = readdir(d)) != NULL) {
char *dname = d_name(di);
if (!wildmatch(match, dname))
continue;
bpp = EXPAND_ITEM_LIST(&conf_list, char *, 32);
pathjoin(buf, sizeof buf, include, dname);
*bpp = strdup(buf);
}
closedir(d);
if (!(bpp = conf_list.items))
return 1;
if (conf_list.count > 1)
qsort(bpp, conf_list.count, sizeof (char *), name_cmp);
for (j = 0, ret = 1; j < conf_list.count; j++) {
if (manage_globals && the_sfunc)
the_sfunc(j == 0 ? "]push" : "]reset");
if ((ret = pm_process(bpp[j], the_sfunc, the_pfunc)) != 1)
break;
}
if (manage_globals && the_sfunc)
the_sfunc("]pop");
for (j = 0; j < conf_list.count; j++)
free(bpp[j]);
free(bpp);
} else
ret = 0;
return ret;
}
static int parse_directives(char *name, char *val)
{
if (strcasecmp(name, "&include") == 0)
return include_config(val, 1);
if (strcasecmp(name, "&merge") == 0)
return include_config(val, 0);
rprintf(FLOG, "Unknown directive: %s.\n", name);
return 0;
}
static int Parse( FILE *InFile,
BOOL (*sfunc)(char *),
BOOL (*pfunc)(char *, char *) )
/* ------------------------------------------------------------------------ **
@@ -418,7 +513,8 @@ static BOOL Parse( FILE *InFile,
* pfunc - Function to be called when a parameter is scanned.
* See Parameter().
*
* Output: True if the file was successfully scanned, else False.
* Output: 1 if the file was successfully scanned, 2 if the file was
* scanned until a section header with no section function, else 0.
*
* Notes: The input can be viewed in terms of 'lines'. There are four
* types of lines:
@@ -427,7 +523,7 @@ static BOOL Parse( FILE *InFile,
* The remainder of the line is ignored.
* Section - First non-whitespace character is a '['.
* Parameter - The default case.
*
*
* ------------------------------------------------------------------------ **
*/
{
@@ -448,29 +544,39 @@ static BOOL Parse( FILE *InFile,
break;
case '[': /* Section Header. */
if (!sfunc) return True;
if( !Section( InFile, sfunc ) )
return( False );
c = EatWhitespace( InFile );
break;
if (!sfunc)
return 2;
if( !Section( InFile, sfunc ) )
return 0;
c = EatWhitespace( InFile );
break;
case '\\': /* Bogus backslash. */
c = EatWhitespace( InFile );
break;
case '&': /* Handle directives */
the_sfunc = sfunc;
the_pfunc = pfunc;
c = Parameter( InFile, parse_directives, c );
if (c != 1)
return c;
c = EatWhitespace( InFile );
break;
default: /* Parameter line. */
if( !Parameter( InFile, pfunc, c ) )
return( False );
return 0;
c = EatWhitespace( InFile );
break;
}
}
return( True );
return 1;
} /* Parse */
static FILE *OpenConfFile( char *FileName )
/* ------------------------------------------------------------------------ **
* Open a configuration file.
* Open a config file.
*
* Input: FileName - The pathname of the config file to be opened.
*
@@ -485,21 +591,21 @@ static FILE *OpenConfFile( char *FileName )
if( NULL == FileName || 0 == *FileName )
{
rprintf(FLOG, "%s No configuration filename specified.\n", func);
rprintf(FLOG, "%s No config filename specified.\n", func);
return( NULL );
}
OpenedFile = fopen( FileName, "r" );
if( NULL == OpenedFile )
{
rsyserr(FLOG, errno, "unable to open configuration file \"%s\"",
rsyserr(FLOG, errno, "unable to open config file \"%s\"",
FileName);
}
return( OpenedFile );
} /* OpenConfFile */
BOOL pm_process( char *FileName,
int pm_process( char *FileName,
BOOL (*sfunc)(char *),
BOOL (*pfunc)(char *, char *) )
/* ------------------------------------------------------------------------ **
@@ -511,7 +617,8 @@ BOOL pm_process( char *FileName,
* pfunc - A pointer to a function that will be called when
* a parameter name and value are discovered.
*
* Output: TRUE if the file was successfully parsed, else FALSE.
* Output: 1 if the file was successfully parsed, 2 if parsing ended at a
* section header w/o a section function, else 0.
*
* ------------------------------------------------------------------------ **
*/
@@ -549,10 +656,10 @@ BOOL pm_process( char *FileName,
if( !result ) /* Generic failure. */
{
rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func);
return( False );
return 0;
}
return( True ); /* Generic success. */
return result;
} /* pm_process */
/* -------------------------------------------------------------------------- */

19
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-2008 Wayne Davison
* Copyright (C) 2004-2015 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,8 +26,10 @@ extern int am_sender;
extern int am_server;
extern int blocking_io;
extern int filesfrom_fd;
extern mode_t orig_umask;
extern int munge_symlinks;
extern char *logfile_name;
extern int remote_option_cnt;
extern const char **remote_options;
extern struct chmod_mode_struct *chmod_modes;
/**
@@ -49,7 +51,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
int to_child_pipe[2];
int from_child_pipe[2];
if (verbose >= 2)
if (DEBUG_GTE(CMD, 1))
print_child_argv("opening connection using:", command);
if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
@@ -75,7 +77,6 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO)
close(from_child_pipe[1]);
umask(orig_umask);
set_blocking(STDIN_FILENO);
if (blocking_io > 0)
set_blocking(STDOUT_FILENO);
@@ -131,6 +132,7 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
am_sender = 0;
am_server = 1;
filesfrom_fd = -1;
munge_symlinks = 0; /* Each side needs its own option. */
chmod_modes = NULL; /* Let the sending side handle this. */
/* Let the client side handle this. */
@@ -139,6 +141,15 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
logfile_close();
}
if (remote_option_cnt) {
int rc = remote_option_cnt + 1;
const char **rv = remote_options;
if (!parse_arguments(&rc, &rv)) {
option_error();
exit_cleanup(RERR_SYNTAX);
}
}
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||

View File

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

View File

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

View File

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

@@ -27,9 +27,9 @@ for action in "${@}"; do
;;
fetch)
if perl --version >/dev/null 2>/dev/null; then
files='c*'
files='[ca]*'
else
files='[cp]*'
files='[cap]*'
fi
rsync -pvz rsync://rsync.samba.org/rsyncftp/generated-files/"$files" .
;;

View File

@@ -1,7 +1,10 @@
conf: configure.sh config.h.in
configure.sh: configure.in aclocal.m4
aclocal.m4:
aclocal -I m4
configure.sh: configure.ac aclocal.m4
autoconf -o configure.sh
config.h.in: configure.in aclocal.m4
config.h.in: configure.ac aclocal.m4
autoheader && touch config.h.in

View File

@@ -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-2008 Wayne Davison
* Copyright (C) 2003-2015 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
@@ -21,9 +21,12 @@
*/
#include "rsync.h"
#include "inums.h"
extern int am_server;
extern int flist_eof;
extern int need_unsorted_flist;
extern int output_needs_newline;
extern struct stats stats;
extern struct file_list *cur_flist;
@@ -40,8 +43,6 @@ 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;
@@ -66,11 +67,26 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
{
char rembuf[64], eol[128];
const char *units;
int pct = ofs == size ? 100 : (int) (100.0 * ofs / size);
unsigned long diff;
double rate, remain;
int pct;
if (is_last) {
int len = snprintf(eol, sizeof eol,
" (xfr#%d, %s-chk=%d/%d)\n",
stats.xferred_files, flist_eof ? "to" : "ir",
stats.num_files - current_file_index - 1,
stats.num_files);
if (INFO_GTE(PROGRESS, 2)) {
static int last_len = 0;
/* Drop \n and pad with spaces if line got shorter. */
if (last_len < --len)
last_len = len;
eol[last_len] = '\0';
while (last_len > len)
eol[--last_len] = ' ';
is_last = 0;
}
/* Compute stats based on the starting info. */
if (!ph_start.time.tv_sec
|| !(diff = msdiff(&ph_start.time, now)))
@@ -79,6 +95,7 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
/* Switch to total time taken for our last update. */
remain = (double) diff / 1000.0;
} else {
strlcpy(eol, " ", sizeof eol);
/* Compute stats based on recent progress. */
if (!(diff = msdiff(&ph_list[oldest_hpos].time, now)))
diff = 1;
@@ -106,23 +123,21 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
(int) remain % 60);
}
if (is_last) {
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
stats.num_transferred_files,
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",
output_needs_newline = 0;
pct = ofs == size ? 100 : (int) (100.0 * ofs / size);
rprintf(FCLIENT, "\r%15s %3d%% %7.2f%s %s%s",
human_num(ofs), pct, rate, units, rembuf, eol);
if (!is_last)
progress_is_active = 1;
if (!is_last) {
output_needs_newline = 1;
rflush(FCLIENT);
}
}
void set_current_file_index(struct file_struct *file, int ndx)
{
if (need_unsorted_flist)
if (!file)
current_file_index = cur_flist->used + cur_flist->ndx_start - 1;
else if (need_unsorted_flist)
current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start;
else
current_file_index = ndx;
@@ -134,9 +149,14 @@ void end_progress(OFF_T size)
if (!am_server) {
struct timeval now;
gettimeofday(&now, NULL);
rprint_progress(size, size, &now, True);
if (INFO_GTE(PROGRESS, 2)) {
rprint_progress(stats.total_transferred_size,
stats.total_size, &now, True);
} else {
rprint_progress(size, size, &now, True);
memset(&ph_start, 0, sizeof ph_start);
}
}
memset(&ph_start, 0, sizeof ph_start);
}
void show_progress(OFF_T ofs, OFF_T size)
@@ -157,6 +177,11 @@ void show_progress(OFF_T ofs, OFF_T size)
gettimeofday(&now, NULL);
if (INFO_GTE(PROGRESS, 2)) {
ofs = stats.total_transferred_size - size + ofs;
size = stats.total_size;
}
if (!ph_start.time.tv_sec) {
int i;

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2008 Wayne Davison
* Copyright (C) 2003-2015 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
@@ -20,16 +20,17 @@
*/
#include "rsync.h"
#include "inums.h"
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;
extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int want_xattr_optim;
extern int csum_length;
extern int read_batch;
extern int write_batch;
@@ -45,48 +46,58 @@ extern int cleanup_got_literal;
extern int remove_source_files;
extern int append_mode;
extern int sparse_files;
extern int preallocate_files;
extern int keep_partial;
extern int checksum_len;
extern int checksum_seed;
extern int inplace;
extern int allowed_lull;
extern int delay_updates;
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 char sender_file_sum[MAX_DIGEST_LEN];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct daemon_filter_list;
extern filter_rule_list daemon_filter_list;
static struct bitbag *delayed_bits = NULL;
static int phase = 0, redoing = 0;
static flist_ndx_list batch_redo_list;
/* We're either updating the basis file or an identical copy: */
static int updating_basis_or_equiv;
/*
* 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)
#define MAX_UNIQUE_NUMBER 999999
#define MAX_UNIQUE_LOOP 100
int get_tmpname(char *fnametmp, const 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.
*
* If the make_unique arg is True, the XXXXXX string is replaced with a unique
* string that doesn't exist at the time of the check. This is intended to be
* used for creating hard links, symlinks, devices, and special files, since
* normal files should be handled by mkstemp() for safety.
*
* 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, BOOL make_unique)
{
int maxname, added, length = 0;
int maxname, length = 0;
const char *f;
char *suf;
if (tmpdir) {
/* Note: this can't overflow, so the return value is safe */
@@ -103,22 +114,68 @@ int get_tmpname(char *fnametmp, const char *fname)
}
} else
f = fname;
fnametmp[length++] = '.';
if (!tmpdir) { /* using a tmpdir avoids the leading dot on our temp names */
if (*f == '.') /* avoid an extra leading dot for OS X's sake */
f++;
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) {
if (maxname < 0) {
rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
fnametmp[0] = '\0';
return 0;
}
added = strlcpy(fnametmp + length, f, maxname);
if (added >= maxname)
added = maxname - 1;
memcpy(fnametmp + length + added, ".XXXXXX", 8);
if (maxname) {
int added = strlcpy(fnametmp + length, f, maxname);
if (added >= maxname)
added = maxname - 1;
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--;
}
/* trim one trailing dot before our suffix's dot */
if (suf[-1] == '.')
suf--;
} else
suf = fnametmp + length - 1; /* overwrite the leading dot with suffix's dot */
if (make_unique) {
static unsigned counter_limit;
unsigned counter;
if (!counter_limit) {
counter_limit = (unsigned)getpid() + MAX_UNIQUE_LOOP;
if (counter_limit > MAX_UNIQUE_NUMBER || counter_limit < MAX_UNIQUE_LOOP)
counter_limit = MAX_UNIQUE_LOOP;
}
counter = counter_limit - MAX_UNIQUE_LOOP;
/* This doesn't have to be very good because we don't need
* to worry about someone trying to guess the values: all
* a conflict will do is cause a device, special file, hard
* link, or symlink to fail to be created. Also: avoid
* using mktemp() due to gcc's annoying warning. */
while (1) {
snprintf(suf, TMPNAME_SUFFIX_LEN+1, ".%d", counter);
if (access(fnametmp, 0) < 0)
break;
if (++counter >= counter_limit)
return 0;
}
} else
memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);
return 1;
}
@@ -130,25 +187,35 @@ int get_tmpname(char *fnametmp, const char *fname)
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
{
int fd;
mode_t added_perms;
if (!get_tmpname(fnametmp, fname))
if (!get_tmpname(fnametmp, fname, False))
return -1;
if (am_root < 0) {
/* For --fake-super, the file must be useable by the copying
* user, just like it would be for root. */
added_perms = S_IRUSR|S_IWUSR;
} else {
/* For a normal copy, we need to be able to tweak things like xattrs. */
added_perms = S_IWUSR;
}
/* We initially set the perms without the setuid/setgid bits or group
* access to ensure that there is no race condition. They will be
* correctly updated after the right owner and group info is set.
* (Thanks to snabb@epipe.fi for pointing this out.) */
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
#if 0
/* In most cases parent directories will already exist because their
* 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) {
&& make_path(fnametmp, MKP_SKIP_SLASH | MKP_DROP_NAME) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
get_tmpname(fnametmp, fname, False);
fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
}
#endif
@@ -165,24 +232,39 @@ 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)
{
static char file_sum1[MAX_DIGEST_LEN];
static char file_sum2[MAX_DIGEST_LEN];
struct map_struct *mapbuf;
struct sum_struct sum;
int32 len, sum_len;
int32 len;
OFF_T offset = 0;
OFF_T offset2;
char *data;
int32 i;
char *map = NULL;
#ifdef SUPPORT_PREALLOCATION
#ifdef PREALLOCATE_NEEDS_TRUNCATE
OFF_T preallocated_len = 0;
#endif
if (preallocate_files && fd != -1 && total_size > 0 && (!inplace || total_size > size_r)) {
/* Try to preallocate enough space for file's eventual length. Can
* reduce fragmentation on filesystems like ext4, xfs, and NTFS. */
if (do_fallocate(fd, 0, total_size) == 0) {
#ifdef PREALLOCATE_NEEDS_TRUNCATE
preallocated_len = total_size;
#endif
} else
rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(fname));
}
#endif
read_sum_head(f_in, &sum);
if (fd_r >= 0 && size_r > 0) {
int32 read_size = MAX(sum.blength * 2, 16*1024);
mapbuf = map_file(fd_r, size_r, read_size, sum.blength);
if (verbose > 2) {
rprintf(FINFO, "recv mapped %s of size %.0f\n",
fname_r, (double)size_r);
if (DEBUG_GTE(DELTASUM, 2)) {
rprintf(FINFO, "recv mapped %s of size %s\n",
fname_r, big_num(size_r));
}
} else
mapbuf = NULL;
@@ -194,9 +276,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum.flength = (OFF_T)sum.count * sum.blength;
if (sum.remainder)
sum.flength -= sum.blength - sum.remainder;
if (append_mode == 2) {
if (append_mode == 2 && mapbuf) {
for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
if (do_progress)
if (INFO_GTE(PROGRESS, 1))
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
CHUNK_SIZE);
@@ -204,27 +286,30 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
}
if (offset < sum.flength) {
int32 len = (int32)(sum.flength - offset);
if (do_progress)
if (INFO_GTE(PROGRESS, 1))
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, len), len);
}
}
offset = sum.flength;
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
full_fname(fname), (double)j, (double)offset);
rsyserr(FERROR_XFER, errno, "lseek of %s returned %s, not %s",
full_fname(fname), big_num(j), big_num(offset));
exit_cleanup(RERR_FILEIO);
}
}
while ((i = recv_token(f_in, &data)) != 0) {
if (do_progress)
if (INFO_GTE(PROGRESS, 1))
show_progress(offset, total_size);
if (allowed_lull)
maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH | MSK_ACTIVE_RECEIVER);
if (i > 0) {
if (verbose > 3) {
rprintf(FINFO,"data recv %d at %.0f\n",
i,(double)offset);
if (DEBUG_GTE(DELTASUM, 3)) {
rprintf(FINFO,"data recv %d at %s\n",
i, big_num(offset));
}
stats.literal_data += i;
@@ -246,10 +331,11 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
stats.matched_data += len;
if (verbose > 3) {
if (DEBUG_GTE(DELTASUM, 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 %s offset=%s%s\n",
i, (long)len, big_num(offset2), big_num(offset),
updating_basis_or_equiv && offset == offset2 ? " (seek)" : "");
}
if (mapbuf) {
@@ -267,9 +353,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
offset += len;
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
rsyserr(FERROR_XFER, errno,
"lseek of %s returned %.0f, not %.0f",
"lseek of %s returned %s, not %s",
full_fname(fname),
(double)pos, (double)offset);
big_num(pos), big_num(offset));
exit_cleanup(RERR_FILEIO);
}
continue;
@@ -284,29 +370,39 @@ 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);
/* inplace: New data could be shorter than old data.
* preallocate_files: total_size could have been an overestimate.
* Cut off any extra preallocated zeros from dest file. */
if ((inplace
#ifdef PREALLOCATE_NEEDS_TRUNCATE
|| preallocated_len > offset
#endif
) && fd != -1 && do_ftruncate(fd, offset) < 0) {
rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
full_fname(fname));
}
#endif
if (do_progress)
if (INFO_GTE(PROGRESS, 1))
end_progress(total_size);
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {
report_write_error:
rsyserr(FERROR_XFER, errno, "write failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
sum_len = sum_end(file_sum1);
if (sum_end(file_sum1) != checksum_len)
overflow_exit("checksum_len"); /* Impossible... */
if (mapbuf)
unmap_file(mapbuf);
read_buf(f_in, file_sum2, sum_len);
if (verbose > 2)
read_buf(f_in, sender_file_sum, checksum_len);
if (DEBUG_GTE(DELTASUM, 2))
rprintf(FINFO,"got file_sum\n");
if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
if (fd != -1 && memcmp(file_sum1, sender_file_sum, checksum_len) != 0)
return 0;
return 1;
}
@@ -326,9 +422,9 @@ static void handle_delayed_updates(char *local_name)
struct file_struct *file = cur_flist->files[ndx];
fname = local_name ? local_name : f_name(file, NULL);
if ((partialptr = partial_dir_fname(fname)) != NULL) {
if (make_backups > 0 && !make_backup(fname))
if (make_backups > 0 && !make_backup(fname, False))
continue;
if (verbose > 2) {
if (DEBUG_GTE(RECV, 1)) {
rprintf(FINFO, "renaming %s to %s\n",
partialptr, fname);
}
@@ -348,34 +444,78 @@ static void handle_delayed_updates(char *local_name)
}
}
static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
static void no_batched_update(int ndx, BOOL is_redo)
{
while (next_gen_ndx < desired_ndx) {
if (next_gen_ndx >= 0) {
struct file_struct *file = cur_flist->files[next_gen_ndx];
rprintf(FERROR_XFER,
"(No batched update for%s \"%s\")\n",
file->flags & FLAG_FILE_SENT ? " resend of" : "",
f_name(file, NULL));
}
next_gen_ndx = read_int(fd);
if (next_gen_ndx == -1) {
if (inc_recurse)
next_gen_ndx = first_flist->prev->used + first_flist->prev->ndx_start;
else
next_gen_ndx = cur_flist->used;
struct file_list *flist = flist_for_ndx(ndx, "no_batched_update");
struct file_struct *file = flist->files[ndx - flist->ndx_start];
rprintf(FERROR_XFER, "(No batched update for%s \"%s\")\n",
is_redo ? " resend of" : "", f_name(file, NULL));
if (inc_recurse && !dry_run)
send_msg_int(MSG_NO_SEND, ndx);
}
static int we_want_redo(int desired_ndx)
{
static int redo_ndx = -1;
while (redo_ndx < desired_ndx) {
if (redo_ndx >= 0)
no_batched_update(redo_ndx, True);
if ((redo_ndx = flist_ndx_pop(&batch_redo_list)) < 0)
return 0;
}
if (redo_ndx == desired_ndx) {
redo_ndx = -1;
return 1;
}
return 0;
}
static int gen_wants_ndx(int desired_ndx, int flist_num)
{
static int next_ndx = -1;
static int done_cnt = 0;
static BOOL got_eof = False;
if (got_eof)
return 0;
/* TODO: integrate gen-reading I/O into perform_io() so this is not needed? */
io_flush(FULL_FLUSH);
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;
}
/**
* main routine for receiver process.
*
* Receiver process runs on the same host as the generator process. */
int recv_files(int f_in, char *local_name)
int recv_files(int f_in, int f_out, char *local_name)
{
int next_gen_ndx = -1;
int fd1,fd2;
STRUCT_STAT st;
int iflags, xlen;
@@ -386,7 +526,6 @@ int recv_files(int f_in, char *local_name)
char fnamecmpbuf[MAXPATHLEN];
uchar fnamecmp_type;
struct file_struct *file;
struct stats initial_stats;
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
int max_phase = protocol_version >= 29 ? 2 : 1;
@@ -396,7 +535,7 @@ int recv_files(int f_in, char *local_name)
#endif
int ndx, recv_ok;
if (verbose > 2)
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
if (delay_updates)
@@ -406,28 +545,32 @@ int recv_files(int f_in, char *local_name)
cleanup_disable();
/* This call also sets cur_flist. */
ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
ndx = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type,
xname, &xlen);
if (ndx == NDX_DONE) {
if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) {
set_current_file_index(NULL, 0);
end_progress(0);
}
if (inc_recurse && first_flist) {
if (read_batch) {
ndx = first_flist->used + first_flist->ndx_start;
gen_wants_ndx(ndx, first_flist->flist_num);
}
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) {
ndx = first_flist->used;
gen_wants_ndx(ndx, first_flist->flist_num);
}
if (++phase > max_phase)
break;
if (verbose > 2)
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO, "recv_files phase=%d\n", phase);
if (phase == 2 && delay_updates)
handle_delayed_updates(local_name);
send_msg(MSG_DONE, "", 0, 0);
write_int(f_out, NDX_DONE);
continue;
}
@@ -437,20 +580,37 @@ int recv_files(int f_in, char *local_name)
file = dir_flist->files[cur_flist->parent_ndx];
fname = local_name ? local_name : f_name(file, fbuf);
if (verbose > 2)
if (DEBUG_GTE(RECV, 1))
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
&& !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
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
if (iflags & ITEM_IS_NEW) {
stats.created_files++;
if (S_ISREG(file->mode)) {
/* Nothing further to count. */
} else if (S_ISDIR(file->mode))
stats.created_dirs++;
#ifdef SUPPORT_LINKS
else if (S_ISLNK(file->mode))
stats.created_symlinks++;
#endif
else if (IS_DEVICE(file->mode))
stats.created_devices++;
else
stats.created_specials++;
}
continue;
}
if (phase == 2) {
@@ -480,11 +640,13 @@ int recv_files(int f_in, char *local_name)
csum_length = SHORT_SUM_LENGTH;
redoing = 0;
}
if (iflags & ITEM_IS_NEW)
stats.created_files++;
}
if (!am_server && do_progress)
if (!am_server && INFO_GTE(PROGRESS, 1))
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.xferred_files++;
stats.total_transferred_size += F_LENGTH(file);
cleanup_got_literal = 0;
@@ -495,33 +657,39 @@ int recv_files(int f_in, char *local_name)
exit_cleanup(RERR_PROTOCOL);
}
if (read_batch) {
int wanted = redoing
? we_want_redo(ndx)
: gen_wants_ndx(ndx, cur_flist->flist_num);
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 (!log_before_transfer)
remember_initial_stats();
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
log_item(FCLIENT, file, iflags, NULL);
if (read_batch)
discard_receive_data(f_in, F_LENGTH(file));
continue;
}
if (write_batch < 0) {
log_item(FCLIENT, file, &stats, iflags, NULL);
log_item(FCLIENT, file, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, F_LENGTH(file));
if (inc_recurse)
send_msg_int(MSG_SUCCESS, ndx);
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) {
@@ -537,21 +705,26 @@ int recv_files(int f_in, char *local_name)
break;
case FNAMECMP_FUZZY:
if (file->dirname) {
pathjoin(fnamecmpbuf, MAXPATHLEN,
file->dirname, xname);
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, file->dirname, xname);
fnamecmp = fnamecmpbuf;
} else
fnamecmp = xname;
break;
default:
if (fnamecmp_type >= basis_dir_cnt) {
if (fnamecmp_type > FNAMECMP_FUZZY && fnamecmp_type-FNAMECMP_FUZZY <= basis_dir_cnt) {
fnamecmp_type -= FNAMECMP_FUZZY + 1;
if (file->dirname) {
stringjoin(fnamecmpbuf, sizeof fnamecmpbuf,
basis_dir[fnamecmp_type], "/", file->dirname, "/", xname, NULL);
} else
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], xname);
} else if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
fnamecmp_type);
exit_cleanup(RERR_PROTOCOL);
}
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
basis_dir[fnamecmp_type], fname);
} else
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], fname);
fnamecmp = fnamecmpbuf;
break;
}
@@ -574,8 +747,6 @@ int recv_files(int f_in, char *local_name)
fnamecmp = fname;
}
initial_stats = stats;
/* open the file */
fd1 = do_open(fnamecmp, O_RDONLY, 0);
@@ -652,7 +823,8 @@ int recv_files(int f_in, char *local_name)
if (fd2 == -1) {
rsyserr(FERROR_XFER, errno, "open %s failed",
full_fname(fname));
}
} else if (updating_basis_or_equiv)
cleanup_set(NULL, NULL, file, fd1, fd2);
} else {
fd2 = open_tmpfile(fnametmp, fname, file);
if (fd2 != -1)
@@ -670,15 +842,15 @@ int recv_files(int f_in, char *local_name)
/* log the transfer */
if (log_before_transfer)
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
log_item(FCLIENT, file, iflags, NULL);
else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
rprintf(FINFO, "%s\n", fname);
/* recv file data */
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
fname, fd2, F_LENGTH(file));
log_item(log_code, file, &initial_stats, iflags, NULL);
log_item(log_code, file, iflags, NULL);
if (fd1 != -1)
close(fd1);
@@ -698,23 +870,33 @@ int recv_files(int f_in, char *local_name)
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
} else if (keep_partial && partialptr) {
if (!handle_partial_dir(partialptr, PDIR_CREATE)) {
rprintf(FERROR,
"Unable to create partial-dir for %s -- discarding %s.\n",
local_name ? local_name : f_name(file, NULL),
recv_ok ? "completed file" : "partial file");
do_unlink(fnametmp);
recv_ok = -1;
} else if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
recv_ok = -1;
else if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
recv_ok = 2;
}
} else {
partialptr = NULL;
} else
partialptr = NULL;
} else
do_unlink(fnametmp);
}
cleanup_disable();
if (read_batch)
file->flags |= FLAG_FILE_SENT;
switch (recv_ok) {
case 2:
break;
case 1:
if (remove_source_files || inc_recurse
|| (preserve_hard_links && F_IS_HLINKED(file)))
@@ -722,7 +904,7 @@ int recv_files(int f_in, char *local_name)
break;
case 0: {
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
if (msgtype == FERROR_XFER || verbose) {
if (msgtype == FERROR_XFER || INFO_GTE(NAME, 1)) {
char *errstr, *redostr, *keptstr;
if (!(keep_partial && partialptr) && !inplace)
keptstr = "discarded";
@@ -744,6 +926,8 @@ int recv_files(int f_in, char *local_name)
keptstr, redostr);
}
if (!redoing) {
if (read_batch)
flist_ndx_push(&batch_redo_list, ndx);
send_msg_int(MSG_REDO, ndx);
file->flags |= FLAG_FILE_SENT;
} else if (inc_recurse)
@@ -762,7 +946,7 @@ int recv_files(int f_in, char *local_name)
if (phase == 2 && delay_updates) /* for protocol_version < 29 */
handle_delayed_updates(local_name);
if (verbose > 2)
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO,"recv_files finished\n");
return 0;

View File

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

12
rsync-ssl.in Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
# This script supports using stunnel to secure an rsync daemon connection.
# Note that this requires at least version 4.x of stunnel.
case "$@" in
*rsync://*) ;;
*::*) ;;
*)
echo "You must use rsync-ssl with a daemon-style hostname." 0>&1
exit 1
;;
esac
exec @bindir@/rsync --rsh=@bindir@/stunnel-rsync "${@}"

384
rsync.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2008 Wayne Davison
* Copyright (C) 2003-2015 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,7 +27,6 @@
#include <langinfo.h>
#endif
extern int verbose;
extern int dry_run;
extern int preserve_acls;
extern int preserve_xattrs;
@@ -36,16 +35,18 @@ extern int preserve_executability;
extern int preserve_times;
extern int am_root;
extern int am_server;
extern int am_daemon;
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 got_kill_signal;
extern int inc_recurse;
extern int inplace;
extern int flist_eof;
extern int file_old_total;
extern int keep_dirlinks;
extern int make_backups;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
@@ -80,23 +81,23 @@ void setup_iconv(void)
# endif
if (!am_server && !allow_8bit_chars) {
/* It's OK if this fails... */
ic_chck = iconv_open(defset, defset);
if (verbose > 3) {
if (DEBUG_GTE(ICONV, 2)) {
if (ic_chck == (iconv_t)-1) {
rprintf(FINFO,
"note: iconv_open(\"%s\", \"%s\") failed (%d)"
" -- using isprint() instead of iconv().\n",
"msg checking via isprint()"
" (iconv_open(\"%s\", \"%s\") errno: %d)\n",
defset, defset, errno);
} else {
rprintf(FINFO,
"note: iconv_open(\"%s\", \"%s\") succeeded.\n",
defset, defset);
"msg checking charset: %s\n",
defset);
}
}
}
} else
ic_chck = (iconv_t)-1;
# ifdef ICONV_OPTION
if (!iconv_opt)
@@ -126,47 +127,82 @@ void setup_iconv(void)
exit_cleanup(RERR_UNSUPPORTED);
}
if (verbose > 1) {
rprintf(FINFO, "%s charset: %s\n",
am_server ? "server" : "client",
*charset ? charset : "[LOCALE]");
if (DEBUG_GTE(ICONV, 1)) {
rprintf(FINFO, "[%s] charset: %s\n",
who_am_i(), *charset ? charset : "[LOCALE]");
}
# endif
}
/* This function converts the characters in the "in" xbuf into characters
* in the "out" xbuf. The "len" of the "in" xbuf is used starting from its
* "pos". The "size" of the "out" xbuf restricts how many characters can be
* stored, starting at its "pos+len" position. Note that the last byte of
* the buffer is never used, which reserves space for a terminating '\0'.
/* This function converts the chars in the "in" xbuf into characters in the
* "out" xbuf. The ".len" chars of the "in" xbuf is used starting from its
* ".pos". The ".size" of the "out" xbuf restricts how many characters can
* be stored, starting at its ".pos+.len" position. Note that the last byte
* of the "out" xbuf is not used, which reserves space for a trailing '\0'
* (though it is up to the caller to store a trailing '\0', as needed).
*
* We return a 0 on success or a -1 on error. An error also sets errno to
* E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0.
* The "in" xbuf is altered to update "pos" and "len". The "out" xbuf has
* data appended, and its "len" incremented. If ICB_EXPAND_OUT is set in
* "flags", the "out" xbuf will also be allocated if empty, and expanded if
* too small (so E2BIG will not be returned). If ICB_INCLUDE_BAD is set in
* "flags", any badly-encoded chars are included verbatim in the "out" xbuf,
* so EILSEQ will not be returned. Likewise for ICB_INCLUDE_INCOMPLETE with
* respect to an incomplete multi-byte char at the end, which ensures that
* EINVAL is not returned. Anytime "in.pos" is 0 we will reset the iconv()
* state prior to processing the characters. */
* The "in" xbuf is altered to update ".pos" and ".len". The "out" xbuf has
* data appended, and its ".len" incremented (see below for a ".size" note).
*
* If ICB_CIRCULAR_OUT is set in "flags", the chars going into the "out" xbuf
* can wrap around to the start, and the xbuf may have its ".size" reduced
* (presumably by 1 byte) if the iconv code doesn't have space to store a
* multi-byte character at the physical end of the ".buf" (though no reducing
* happens if ".pos" is <= 1, since there is no room to wrap around).
*
* If ICB_EXPAND_OUT is set in "flags", the "out" xbuf will be allocated if
* empty, and (as long as ICB_CIRCULAR_OUT is not set) expanded if too small.
* This prevents the return of E2BIG (except for a circular xbuf).
*
* If ICB_INCLUDE_BAD is set in "flags", any badly-encoded chars are included
* verbatim in the "out" xbuf, so EILSEQ will not be returned.
*
* If ICB_INCLUDE_INCOMPLETE is set in "flags", any incomplete multi-byte
* chars are included, which ensures that EINVAL is not returned.
*
* If ICB_INIT is set, the iconv() conversion state is initialized prior to
* processing the characters. */
int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
{
ICONV_CONST char *ibuf;
size_t icnt, ocnt;
size_t icnt, ocnt, opos;
char *obuf;
if (!out->size && flags & ICB_EXPAND_OUT)
alloc_xbuf(out, 1024);
if (!out->size && flags & ICB_EXPAND_OUT) {
size_t siz = ROUND_UP_1024(in->len * 2);
alloc_xbuf(out, siz);
} else if (out->len+1 >= out->size) {
/* There is no room to even start storing data. */
if (!(flags & ICB_EXPAND_OUT) || flags & ICB_CIRCULAR_OUT) {
errno = E2BIG;
return -1;
}
realloc_xbuf(out, out->size + ROUND_UP_1024(in->len * 2));
}
if (!in->pos)
if (flags & ICB_INIT)
iconv(ic, NULL, 0, NULL, 0);
ibuf = in->buf + in->pos;
icnt = in->len;
obuf = out->buf + (out->pos + out->len);
ocnt = out->size - (out->pos + out->len) - 1;
opos = out->pos + out->len;
if (flags & ICB_CIRCULAR_OUT) {
if (opos >= out->size) {
opos -= out->size;
/* We know that out->pos is not 0 due to the "no room" check
* above, so this can't go "negative". */
ocnt = out->pos - opos - 1;
} else {
/* Allow the use of all bytes to the physical end of the buffer
* unless pos is 0, in which case we reserve our trailing '\0'. */
ocnt = out->size - opos - (out->pos ? 0 : 1);
}
} else
ocnt = out->size - opos - 1;
obuf = out->buf + opos;
while (icnt) {
while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) {
@@ -175,31 +211,58 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
if (errno == EINVAL) {
if (!(flags & ICB_INCLUDE_INCOMPLETE))
goto finish;
if (!ocnt)
goto e2big;
} else if (errno == EILSEQ) {
if (!(flags & ICB_INCLUDE_BAD))
goto finish;
} else {
size_t opos = obuf - out->buf;
if (!(flags & ICB_EXPAND_OUT)) {
if (!ocnt)
goto e2big;
} else if (errno == E2BIG) {
size_t siz;
e2big:
opos = obuf - out->buf;
if (flags & ICB_CIRCULAR_OUT && out->pos > 1 && opos > out->pos) {
/* We are in a divided circular buffer at the physical
* end with room to wrap to the start. If iconv() refused
* to use one or more trailing bytes in the buffer, we
* set the size to ignore the unused bytes. */
if (opos < out->size)
reduce_iobuf_size(out, opos);
obuf = out->buf;
ocnt = out->pos - 1;
continue;
}
if (!(flags & ICB_EXPAND_OUT) || flags & ICB_CIRCULAR_OUT) {
errno = E2BIG;
goto finish;
}
realloc_xbuf(out, out->size + 1024);
siz = ROUND_UP_1024(in->len * 2);
realloc_xbuf(out, out->size + siz);
obuf = out->buf + opos;
ocnt += 1024;
ocnt += siz;
continue;
} else {
rsyserr(FERROR, errno, "unexpected error from iconv()");
exit_cleanup(RERR_UNSUPPORTED);
}
*obuf++ = *ibuf++;
ocnt--, icnt--;
if (!icnt)
break;
}
}
errno = 0;
finish:
opos = obuf - out->buf;
if (flags & ICB_CIRCULAR_OUT && opos < out->pos)
opos += out->size;
out->len = opos - out->pos;
in->len = icnt;
in->pos = ibuf - in->buf;
out->len = obuf - out->buf - out->pos;
return errno ? -1 : 0;
}
@@ -218,19 +281,22 @@ void send_protected_args(int fd, char *args[])
for (i = 0; args[i]; i++) {} /* find first NULL */
args[i] = "rsync"; /* set a new arg0 */
if (verbose > 1)
if (DEBUG_GTE(CMD, 1))
print_child_argv("protected args:", args + i + 1);
do {
if (!args[i][0])
write_buf(fd, ".", 2);
#ifdef ICONV_OPTION
if (convert) {
else if (convert) {
INIT_XBUF_STRLEN(inbuf, args[i]);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT);
outbuf.buf[outbuf.len] = '\0';
write_buf(fd, outbuf.buf, outbuf.len + 1);
outbuf.len = 0;
} else
}
#endif
else
write_buf(fd, args[i], strlen(args[i]) + 1);
} while (args[++i]);
write_byte(fd, 0);
@@ -241,13 +307,13 @@ void send_protected_args(int fd, char *args[])
#endif
}
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
int read_ndx_and_attrs(int f_in, int f_out, 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, save_verbose = verbose;
int ndx;
read_loop:
while (1) {
@@ -257,59 +323,71 @@ 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 (ndx == NDX_DEL_STATS) {
read_del_stats(f_in);
if (am_sender && am_server)
write_del_stats(f_out);
continue;
}
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);
if (DEBUG_GTE(FLIST, 3))
rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i());
write_int(f_out, NDX_FLIST_EOF);
continue;
}
ndx = NDX_FLIST_OFFSET - ndx;
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. */
if (verbose > 3) {
if (DEBUG_GTE(FLIST, 2)) {
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);
/* Send all the data we read for this flist to the generator. */
start_flist_forward(ndx);
flist = recv_file_list(f_in, ndx);
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();
maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
goto read_loop;
}
if (!(flist = flist_for_ndx(ndx))) {
int start, used;
invalid_ndx:
start = first_flist ? first_flist->ndx_start : 0;
used = first_flist ? first_flist->used : 0;
rprintf(FERROR,
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
ndx, start - 1, start + used -1, iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
flist = flist_for_ndx(ndx, "read_ndx_and_attrs");
if (flist != cur_flist) {
cur_flist = flist;
if (am_sender) {
file_old_total = cur_flist->used;
for (flist = first_flist; flist != cur_flist; flist = flist->next)
file_old_total += flist->used;
}
}
cur_flist = flist;
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
@@ -391,12 +469,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
full_fname(fname));
return 0;
}
#ifdef SUPPORT_ACLS
sx2.acc_acl = sx2.def_acl = NULL;
#endif
#ifdef SUPPORT_XATTRS
sx2.xattr = NULL;
#endif
init_stat_x(&sx2);
sxp = &sx2;
inherit = !preserve_perms;
} else
@@ -416,39 +489,16 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *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);
#endif
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
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_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
#endif
if (change_uid || change_gid) {
if (verbose > 2) {
if (DEBUG_GTE(OWN, 1)) {
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %u to %u\n",
@@ -461,9 +511,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
}
}
if (am_root >= 0) {
if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
if (do_lchown(fname, uid, gid) != 0) {
/* We shouldn't have attempted to change uid
* or gid unless have the privilege. */
rsyserr(FERROR_XFER, errno, "%s %s failed",
@@ -471,6 +521,10 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
full_fname(fname));
goto cleanup;
}
if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
/* A lchown had been done, so we need to re-stat if
* the destination had the setuid or setgid bits set
* (due to the side effect of the chown call). */
@@ -482,6 +536,35 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
updated = 1;
}
#ifdef SUPPORT_XATTRS
if (am_root < 0)
set_stat_xattr(fname, file, new_mode);
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
#endif
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)
&& (sxp->st.st_mtime != file->modtime
#ifdef ST_MTIME_NSEC
|| (NSEC_BUMP(file) && (uint32)sxp->st.ST_MTIME_NSEC != F_MOD_NSEC(file))
#endif
)) {
int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
if (ret < 0) {
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;
}
#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.
@@ -489,8 +572,10 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
* If set_acl() changes permission bits in the process of setting
* an access ACL, it changes sxp->st.st_mode so we know whether we
* need to chmod(). */
if (preserve_acls && !S_ISLNK(new_mode) && set_acl(fname, file, sxp) == 0)
updated = 1;
if (preserve_acls && !S_ISLNK(new_mode)) {
if (set_acl(fname, file, sxp, new_mode) > 0)
updated = 1;
}
#endif
#ifdef HAVE_CHMOD
@@ -507,27 +592,20 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
}
#endif
if (verbose > 1 && flags & ATTRS_REPORT) {
if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
if (updated)
rprintf(FCLIENT, "%s\n", fname);
else
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
cleanup:
if (sxp == &sx2) {
#ifdef SUPPORT_ACLS
if (preserve_acls)
free_acl(&sx2);
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
free_xattr(&sx2);
#endif
}
if (sxp == &sx2)
free_stat_x(&sx2);
return updated;
}
RETSIGTYPE sig_int(UNUSED(int val))
/* This is only called for SIGINT, SIGHUP, and SIGTERM. */
void sig_int(int sig_num)
{
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
* for a password, then our cleanup's sending of a SIGUSR1
@@ -538,6 +616,23 @@ RETSIGTYPE sig_int(UNUSED(int val))
* not ssh waiting for a password, then this tiny delay
* shouldn't hurt anything. */
msleep(400);
/* If we're an rsync daemon listener (not a daemon server),
* we'll exit with status 0 if we received SIGTERM. */
if (am_daemon && !am_server && sig_num == SIGTERM)
exit_cleanup(0);
/* If the signal arrived on the server side (or for the receiver
* process on the client), we want to try to do a controlled shutdown
* that lets the client side (generator process) know what happened.
* To do this, we set a flag and let the normal process handle the
* shutdown. We only attempt this if multiplexed IO is in effect and
* we didn't already set the flag. */
if (!got_kill_signal && (am_server || am_receiver)) {
got_kill_signal = sig_num;
return;
}
exit_cleanup(RERR_SIGNAL);
}
@@ -555,16 +650,17 @@ int finish_transfer(const char *fname, const char *fnametmp,
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
if (inplace) {
if (verbose > 2)
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO, "finishing %s\n", fname);
fnametmp = fname;
goto do_set_file_attrs;
}
if (make_backups > 0 && overwriting_basis) {
if (!make_backup(fname))
int ok = make_backup(fname, False);
if (!ok)
return 1;
if (fnamecmp == fname)
if (ok == 1 && fnamecmp == fname)
fnamecmp = get_backup_name(fname);
}
@@ -573,17 +669,15 @@ int finish_transfer(const char *fname, const char *fnametmp,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
/* move tmp file over real file */
if (verbose > 2)
if (DEBUG_GTE(RECV, 1))
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
ret = robust_rename(fnametmp, fname, temp_copy_name,
file->mode & INITACCESSPERMS);
ret = robust_rename(fnametmp, fname, temp_copy_name, file->mode);
if (ret < 0) {
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname);
if (!partialptr || (ret == -2 && temp_copy_name)
|| robust_rename(fnametmp, partialptr, NULL,
file->mode & INITACCESSPERMS) < 0)
|| robust_rename(fnametmp, partialptr, NULL, file->mode) < 0)
do_unlink(fnametmp);
return 0;
}
@@ -610,28 +704,48 @@ int finish_transfer(const char *fname, const char *fnametmp,
return 1;
}
struct file_list *flist_for_ndx(int ndx)
struct file_list *flist_for_ndx(int ndx, const char *fatal_error_loc)
{
struct file_list *flist = cur_flist;
if (!flist && !(flist = first_flist))
return NULL;
goto not_found;
while (ndx < flist->ndx_start-1) {
if (flist == first_flist)
return NULL;
goto not_found;
flist = flist->prev;
}
while (ndx >= flist->ndx_start + flist->used) {
if (!(flist = flist->next))
return NULL;
goto not_found;
}
return flist;
not_found:
if (fatal_error_loc) {
int first, last;
if (first_flist) {
first = first_flist->ndx_start - 1;
last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
} else {
first = 0;
last = -1;
}
rprintf(FERROR,
"File-list index %d not in %d - %d (%s) [%s]\n",
ndx, first, last, fatal_error_loc, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
return NULL;
}
const char *who_am_i(void)
{
if (am_starting_up)
return am_server ? "server" : "client";
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
return am_sender ? "sender"
: am_generator ? "generator"
: am_receiver ? "receiver"
: "Receiver"; /* pre-forked receiver */
}

276
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-2008 Wayne Davison
* Copyright (C) 2003-2015 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
#define URL_PREFIX "rsync://"
#define SYMLINK_PREFIX "/rsyncd-munged/"
#define SYMLINK_PREFIX "/rsyncd-munged/" /* This MUST have a trailing slash! */
#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
#define BACKUP_SUFFIX "~"
@@ -60,10 +60,13 @@
#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) */
#define XMIT_MOD_NSEC (1<<13) /* protocols 31 - now */
/* 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 */
@@ -79,22 +82,27 @@
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
#define FLAG_TIME_FAILED (1<<11)/* generator */
#define FLAG_MOD_NSEC (1<<12) /* sender/receiver/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)) \
== ((unsigned)(b2) & (unsigned)(mask)))
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 30
#define PROTOCOL_VERSION 31
/* This is used when working on a new protocol version in CVS, and should
* be a new non-zero value for each CVS change that affects the protocol.
* It must ALWAYS be 0 when the protocol goes final! */
* It must ALWAYS be 0 when the protocol goes final (and NEVER before)! */
#define SUBPROTOCOL_VERSION 0
/* We refuse to interoperate with versions that are not in this range.
@@ -118,7 +126,8 @@
#define OLD_PROTOCOL_VERSION 25
#define MAX_PROTOCOL_VERSION 40
#define FILECNT_LOOKAHEAD 1000
#define MIN_FILECNT_LOOKAHEAD 1000
#define MAX_FILECNT_LOOKAHEAD 10000
#define RSYNC_PORT 873
@@ -126,12 +135,14 @@
#define WRITE_SIZE (32*1024)
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (256*1024)
#define IO_BUFFER_SIZE (4092)
#define IO_BUFFER_SIZE (32*1024)
#define MAX_BLOCK_SIZE ((int32)1 << 17)
/* For compatibility with older rsyncs */
#define OLD_MAX_BLOCK_SIZE ((int32)1 << 29)
#define ROUND_UP_1024(siz) ((siz) & (1024-1) ? ((siz) | (1024-1)) + 1 : (siz))
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
#define IOERR_VANISHED (1<<1)
#define IOERR_DEL_LIMIT (1<<2)
@@ -197,6 +208,7 @@
#define CFN_KEEP_TRAILING_SLASH (1<<1)
#define CFN_DROP_TRAILING_DOT_DIR (1<<2)
#define CFN_COLLAPSE_DOT_DOT_DIRS (1<<3)
#define CFN_REFUSE_DOT_DOT_DIRS (1<<4)
#define SP_DEFAULT 0
#define SP_KEEP_DOT_DIRS (1<<0)
@@ -211,6 +223,7 @@ enum logcode {
FERROR_XFER=1, FINFO=2, /* sent over socket for any protocol */
FERROR=3, FWARNING=4, /* sent over socket for protocols >= 30 */
FERROR_SOCKET=5, FLOG=6, /* only sent via receiver -> generator pipe */
FERROR_UTF8=8, /* only sent via receiver -> generator pipe */
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
};
@@ -221,22 +234,49 @@ enum msgcode {
MSG_ERROR_XFER=FERROR_XFER, MSG_INFO=FINFO, /* remote logging */
MSG_ERROR=FERROR, MSG_WARNING=FWARNING, /* protocol-30 remote logging */
MSG_ERROR_SOCKET=FERROR_SOCKET, /* sibling logging */
MSG_ERROR_UTF8=FERROR_UTF8, /* sibling logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
MSG_FLIST=20, /* extra file list over sibling socket */
MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
MSG_STATS=10, /* message has stats data for generator */
MSG_IO_ERROR=22,/* the sending side had an I/O error */
MSG_NOOP=42, /* a do-nothing message */
MSG_IO_TIMEOUT=33,/* tell client about a daemon's timeout value */
MSG_NOOP=42, /* a do-nothing message (legacy protocol-30 only) */
MSG_ERROR_EXIT=86, /* synchronize an error exit (siblings and protocol >= 31) */
MSG_SUCCESS=100,/* successfully updated indicated flist index */
MSG_DELETED=101,/* successfully deleted a file on receiving side */
MSG_NO_SEND=102,/* sender failed to open a file we wanted */
MSG_DONE=86 /* current phase is done */
};
#define NDX_DONE -1
#define NDX_FLIST_EOF -2
#define NDX_DEL_STATS -3
#define NDX_FLIST_OFFSET -101
/* For calling delete_item() and delete_dir_contents(). */
#define DEL_NO_UID_WRITE (1<<0) /* file/dir has our uid w/o write perm */
#define DEL_RECURSE (1<<1) /* if dir, delete all contents */
#define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */
#define DEL_FOR_FILE (1<<3) /* making room for a replacement file */
#define DEL_FOR_DIR (1<<4) /* making room for a replacement dir */
#define DEL_FOR_SYMLINK (1<<5) /* making room for a replacement symlink */
#define DEL_FOR_DEVICE (1<<6) /* making room for a replacement device */
#define DEL_FOR_SPECIAL (1<<7) /* making room for a replacement special */
#define DEL_FOR_BACKUP (1<<8) /* the delete is for a backup operation */
#define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
enum delret {
DR_SUCCESS = 0, DR_FAILURE, DR_AT_LIMIT, DR_NOT_EMPTY
};
/* Defines for make_path() */
#define MKP_DROP_NAME (1<<0) /* drop trailing filename or trailing slash */
#define MKP_SKIP_SLASH (1<<1) /* skip one or more leading slashes */
/* Defines for maybe_send_keepalive() */
#define MSK_ALLOW_FLUSH (1<<0)
#define MSK_ACTIVE_RECEIVER (1<<1)
#include "errcode.h"
#include "config.h"
@@ -332,6 +372,26 @@ enum msgcode {
#include <utime.h>
#endif
#if defined HAVE_UTIMENSAT || defined HAVE_LUTIMES
#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_UTIMENSAT
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
#define ST_MTIME_NSEC st_mtim.tv_nsec
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
#define ST_MTIME_NSEC st_mtimensec
#endif
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -394,7 +454,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
@@ -427,6 +487,8 @@ typedef unsigned int mode_t;
#endif
#ifndef HAVE_OFF_T
typedef long off_t;
#undef SIZEOF_OFF_T
#define SIZEOF_OFF_T SIZEOF_LONG
#endif
#ifndef HAVE_SIZE_T
typedef unsigned int size_t;
@@ -551,7 +613,7 @@ struct hashtable {
void *nodes;
int32 size, entries;
uint32 node_size;
int key64;
short key64;
};
struct ht_int32_node {
@@ -612,6 +674,23 @@ struct ht_int64_node {
#define ACLS_NEED_MASK 1
#endif
#if defined HAVE_FALLOCATE || HAVE_SYS_FALLOCATE
#ifdef HAVE_LINUX_FALLOC_H
#include <linux/falloc.h>
#endif
#ifdef FALLOC_FL_KEEP_SIZE
#define SUPPORT_PREALLOCATION 1
#elif defined HAVE_FTRUNCATE
#define SUPPORT_PREALLOCATION 1
#define PREALLOCATE_NEEDS_TRUNCATE 1
#endif
#else /* !fallocate */
#if defined HAVE_EFFICIENT_POSIX_FALLOCATE && defined HAVE_FTRUNCATE
#define SUPPORT_PREALLOCATION 1
#define PREALLOCATE_NEEDS_TRUNCATE 1
#endif
#endif
union file_extras {
int32 num;
uint32 unum;
@@ -643,7 +722,9 @@ extern int xattrs_ndx;
#define REQ_EXTRA(f,ndx) ((union file_extras*)(f) - (ndx))
#define OPT_EXTRA(f,bump) ((union file_extras*)(f) - file_extra_cnt - 1 - (bump))
#define NSEC_BUMP(f) ((f)->flags & FLAG_MOD_NSEC ? 1 : 0)
#define LEN64_BUMP(f) ((f)->flags & FLAG_LENGTH64 ? 1 : 0)
#define START_BUMP(f) (NSEC_BUMP(f) + LEN64_BUMP(f))
#define HLINK_BUMP(f) ((f)->flags & (FLAG_HLINKED|FLAG_HLINK_DONE) ? inc_recurse+1 : 0)
#define ACL_BUMP(f) (acls_ndx ? 1 : 0)
@@ -652,9 +733,11 @@ extern int xattrs_ndx;
#define F_LENGTH(f) ((int64)(f)->len32)
#else
#define F_LENGTH(f) ((int64)(f)->len32 + ((f)->flags & FLAG_LENGTH64 \
? (int64)OPT_EXTRA(f, 0)->unum << 32 : 0))
? (int64)OPT_EXTRA(f, NSEC_BUMP(f))->unum << 32 : 0))
#endif
#define F_MOD_NSEC(f) ((f)->flags & FLAG_MOD_NSEC ? OPT_EXTRA(f, 0)->unum : 0)
/* If there is a symlink string, it is always right after the basename */
#define F_SYMLINK(f) ((f)->basename + strlen((f)->basename) + 1)
@@ -672,22 +755,21 @@ extern int xattrs_ndx;
#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 */
#define F_HL_PREV(f) OPT_EXTRA(f, LEN64_BUMP(f)+inc_recurse)->num /* non-dirs */
#define F_DIR_NODE_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) \
#define F_HL_GNUM(f) OPT_EXTRA(f, START_BUMP(f))->num /* non-dirs */
#define F_HL_PREV(f) OPT_EXTRA(f, START_BUMP(f)+inc_recurse)->num /* non-dirs */
#define F_DIR_NODE_P(f) (&OPT_EXTRA(f, START_BUMP(f) \
+ DIRNODE_EXTRA_CNT - 1)->num) /* sender dirs */
#define F_DIR_RELNAMES_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) + DIRNODE_EXTRA_CNT \
#define F_DIR_RELNAMES_P(f) (&OPT_EXTRA(f, START_BUMP(f) + DIRNODE_EXTRA_CNT \
+ PTR_EXTRA_CNT - 1)->num) /* sender dirs */
#define F_DIR_DEFACL(f) OPT_EXTRA(f, LEN64_BUMP(f))->unum /* receiver dirs */
#define F_DIR_DEV_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) + ACL_BUMP(f) \
#define F_DIR_DEFACL(f) OPT_EXTRA(f, START_BUMP(f))->unum /* receiver dirs */
#define F_DIR_DEV_P(f) (&OPT_EXTRA(f, START_BUMP(f) + ACL_BUMP(f) \
+ DEV_EXTRA_CNT - 1)->unum) /* receiver dirs */
/* 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) + DEV_EXTRA_CNT - 1)->unum)
/* This optional item might follow an F_HL_*() item. */
#define F_RDEV_P(f) (&OPT_EXTRA(f, START_BUMP(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) \
#define F_SUM(f) ((char*)OPT_EXTRA(f, START_BUMP(f) + HLINK_BUMP(f) \
+ SUM_EXTRA_CNT - 1))
/* Some utility defines: */
@@ -706,6 +788,8 @@ extern int xattrs_ndx;
#define DIR_FIRST_CHILD(a) (a)[1]
#define DIR_NEXT_SIBLING(a) (a)[2]
#define IS_MISSING_FILE(statbuf) ((statbuf).st_mode == 0)
/*
* Start the flist array at FLIST_START entries and grow it
* by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
@@ -772,47 +856,44 @@ struct map_struct {
int status; /* first errno from read errors */
};
#define MATCHFLG_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
#define MATCHFLG_WILD2 (1<<1) /* pattern has '**' */
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with "**" */
#define MATCHFLG_WILD3_SUFFIX (1<<3) /* pattern ends with "***" */
#define MATCHFLG_ABS_PATH (1<<4) /* path-match on absolute path */
#define MATCHFLG_INCLUDE (1<<5) /* this is an include, not an exclude */
#define MATCHFLG_DIRECTORY (1<<6) /* this matches only directories */
#define MATCHFLG_WORD_SPLIT (1<<7) /* split rules on whitespace */
#define MATCHFLG_NO_INHERIT (1<<8) /* don't inherit these rules */
#define MATCHFLG_NO_PREFIXES (1<<9) /* parse no prefixes from patterns */
#define MATCHFLG_MERGE_FILE (1<<10)/* specifies a file to merge */
#define MATCHFLG_PERDIR_MERGE (1<<11)/* merge-file is searched per-dir */
#define MATCHFLG_EXCLUDE_SELF (1<<12)/* merge-file name should be excluded */
#define MATCHFLG_FINISH_SETUP (1<<13)/* per-dir merge file needs setup */
#define MATCHFLG_NEGATE (1<<14)/* rule matches when pattern does not */
#define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
#define MATCHFLG_CLEAR_LIST (1<<18)/* this item is the "!" token */
#define MATCHFLG_PERISHABLE (1<<19)/* perishable if parent dir goes away */
#define FILTRULE_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
#define FILTRULE_WILD2 (1<<1) /* pattern has '**' */
#define FILTRULE_WILD2_PREFIX (1<<2) /* pattern starts with "**" */
#define FILTRULE_WILD3_SUFFIX (1<<3) /* pattern ends with "***" */
#define FILTRULE_ABS_PATH (1<<4) /* path-match on absolute path */
#define FILTRULE_INCLUDE (1<<5) /* this is an include, not an exclude */
#define FILTRULE_DIRECTORY (1<<6) /* this matches only directories */
#define FILTRULE_WORD_SPLIT (1<<7) /* split rules on whitespace */
#define FILTRULE_NO_INHERIT (1<<8) /* don't inherit these rules */
#define FILTRULE_NO_PREFIXES (1<<9) /* parse no prefixes from patterns */
#define FILTRULE_MERGE_FILE (1<<10)/* specifies a file to merge */
#define FILTRULE_PERDIR_MERGE (1<<11)/* merge-file is searched per-dir */
#define FILTRULE_EXCLUDE_SELF (1<<12)/* merge-file name should be excluded */
#define FILTRULE_FINISH_SETUP (1<<13)/* per-dir merge file needs setup */
#define FILTRULE_NEGATE (1<<14)/* rule matches when pattern does not */
#define FILTRULE_CVS_IGNORE (1<<15)/* rule was -C or :C */
#define FILTRULE_SENDER_SIDE (1<<16)/* rule applies to the sending side */
#define FILTRULE_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
#define FILTRULE_CLEAR_LIST (1<<18)/* this item is the "!" token */
#define FILTRULE_PERISHABLE (1<<19)/* perishable if parent dir goes away */
#define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
| MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
| MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE \
| MATCHFLG_PERISHABLE)
#define FILTRULES_SIDES (FILTRULE_SENDER_SIDE | FILTRULE_RECEIVER_SIDE)
struct filter_struct {
typedef struct filter_struct {
struct filter_struct *next;
char *pattern;
uint32 match_flags;
uint32 rflags;
union {
int slash_cnt;
struct filter_list_struct *mergelist;
} u;
};
} filter_rule;
struct filter_list_struct {
struct filter_struct *head;
struct filter_struct *tail;
typedef struct filter_list_struct {
filter_rule *head;
filter_rule *tail;
char *debug_type;
};
} filter_rule_list;
struct stats {
int64 total_size;
@@ -824,12 +905,23 @@ struct stats {
int64 flist_buildtime;
int64 flist_xfertime;
int64 flist_size;
int num_files;
int num_transferred_files;
int num_files, num_dirs, num_symlinks, num_devices, num_specials;
int created_files, created_dirs, created_symlinks, created_devices, created_specials;
int deleted_files, deleted_dirs, deleted_symlinks, deleted_devices, deleted_specials;
int xferred_files;
};
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 {
@@ -851,13 +943,22 @@ typedef struct {
} xbuf;
#define INIT_XBUF(xb, str, ln, sz) (xb).buf = (str), (xb).len = (ln), (xb).size = (sz), (xb).pos = 0
#define INIT_XBUF_STRLEN(xb, str) (xb).buf = (str), (xb).len = strlen((xb).buf), (xb).size = (-1), (xb).pos = 0
#define INIT_XBUF_STRLEN(xb, str) (xb).buf = (str), (xb).len = strlen((xb).buf), (xb).size = (size_t)-1, (xb).pos = 0
/* This one is used to make an output xbuf based on a char[] buffer: */
#define INIT_CONST_XBUF(xb, bf) (xb).buf = (bf), (xb).size = sizeof (bf), (xb).len = (xb).pos = 0
#define ICB_EXPAND_OUT (1<<0)
#define ICB_INCLUDE_BAD (1<<1)
#define ICB_INCLUDE_INCOMPLETE (1<<2)
#define ICB_CIRCULAR_OUT (1<<3)
#define ICB_INIT (1<<4)
#define IOBUF_KEEP_BUFS 0
#define IOBUF_FREE_BUFS 1
#define MPLX_SWITCHING IOBUF_KEEP_BUFS
#define MPLX_ALL_DONE IOBUF_FREE_BUFS
#define MPLX_TO_BUFFERED 2
#define RL_EOL_NULLS (1<<0)
#define RL_DUMP_COMMENTS (1<<1)
@@ -945,6 +1046,9 @@ extern int errno;
#ifdef HAVE_READLINK
#define SUPPORT_LINKS 1
#if !defined NO_SYMLINK_XATTRS && !defined NO_SYMLINK_USER_XATTRS
#define do_readlink(path, buf, bufsiz) readlink(path, buf, bufsiz)
#endif
#endif
#ifdef HAVE_LINK
#define SUPPORT_HARD_LINKS 1
@@ -1055,6 +1159,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 */
@@ -1120,7 +1228,53 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#define FD_ZERO(fdsetp) memset(fdsetp, 0, sizeof (fd_set))
#endif
extern int verbose;
extern short info_levels[], debug_levels[];
#define INFO_GTE(flag, lvl) (info_levels[INFO_##flag] >= (lvl))
#define INFO_EQ(flag, lvl) (info_levels[INFO_##flag] == (lvl))
#define DEBUG_GTE(flag, lvl) (debug_levels[DEBUG_##flag] >= (lvl))
#define DEBUG_EQ(flag, lvl) (debug_levels[DEBUG_##flag] == (lvl))
#define INFO_BACKUP 0
#define INFO_COPY (INFO_BACKUP+1)
#define INFO_DEL (INFO_COPY+1)
#define INFO_FLIST (INFO_DEL+1)
#define INFO_MISC (INFO_FLIST+1)
#define INFO_MOUNT (INFO_MISC+1)
#define INFO_NAME (INFO_MOUNT+1)
#define INFO_PROGRESS (INFO_NAME+1)
#define INFO_REMOVE (INFO_PROGRESS+1)
#define INFO_SKIP (INFO_REMOVE+1)
#define INFO_STATS (INFO_SKIP+1)
#define INFO_SYMSAFE (INFO_STATS+1)
#define COUNT_INFO (INFO_SYMSAFE+1)
#define DEBUG_ACL 0
#define DEBUG_BACKUP (DEBUG_ACL+1)
#define DEBUG_BIND (DEBUG_BACKUP+1)
#define DEBUG_CHDIR (DEBUG_BIND+1)
#define DEBUG_CONNECT (DEBUG_CHDIR+1)
#define DEBUG_CMD (DEBUG_CONNECT+1)
#define DEBUG_DEL (DEBUG_CMD+1)
#define DEBUG_DELTASUM (DEBUG_DEL+1)
#define DEBUG_DUP (DEBUG_DELTASUM+1)
#define DEBUG_EXIT (DEBUG_DUP+1)
#define DEBUG_FILTER (DEBUG_EXIT+1)
#define DEBUG_FLIST (DEBUG_FILTER+1)
#define DEBUG_FUZZY (DEBUG_FLIST+1)
#define DEBUG_GENR (DEBUG_FUZZY+1)
#define DEBUG_HASH (DEBUG_GENR+1)
#define DEBUG_HLINK (DEBUG_HASH+1)
#define DEBUG_ICONV (DEBUG_HLINK+1)
#define DEBUG_IO (DEBUG_ICONV+1)
#define DEBUG_OWN (DEBUG_IO+1)
#define DEBUG_PROTO (DEBUG_OWN+1)
#define DEBUG_RECV (DEBUG_PROTO+1)
#define DEBUG_SEND (DEBUG_RECV+1)
#define DEBUG_TIME (DEBUG_SEND+1)
#define COUNT_DEBUG (DEBUG_TIME+1)
#ifndef HAVE_INET_NTOP
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
@@ -1130,6 +1284,10 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size);
int inet_pton(int af, const char *src, void *dst);
#endif
#ifndef HAVE_GETPASS
char *getpass(const char *prompt);
#endif
#ifdef MAINTAINER_MODE
const char *get_panic_action(void);
#endif

960
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)(29 Jun 2008)()()
manpage(rsyncd.conf)(5)(8 Aug 2015)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -28,8 +28,9 @@ whitespace in module and parameter names is irrelevant. Leading and
trailing whitespace in a parameter value is discarded. Internal whitespace
within a parameter value is retained verbatim.
Any line beginning with a hash (#) is ignored, as are lines containing
only whitespace.
Any line bf(beginning) with a hash (#) is ignored, as are lines containing
only whitespace. (If a hash occurs after anything other than leading
whitespace, it is considered a part of the line's content.)
Any line ending in a \ is "continued" on the next line in the
customary UNIX fashion.
@@ -73,20 +74,38 @@ manpagesection(GLOBAL PARAMETERS)
The first parameters in the file (before a [module] header) are the
global parameters.
Rsync also allows for the use of a "[global]" module name to indicate the
start of one or more global-parameter sections (the name must be lower case).
You may also include any module parameters in the global part of the
config file in which case the supplied value will override the
default for that parameter.
You may use references to environment variables in the values of parameters.
String parameters will have %VAR% references expanded as late as possible (when
the string is used in the program), allowing for the use of variables that
rsync sets at connection time, such as RSYNC_USER_NAME. Non-string parameters
(such as true/false settings) are expanded when read from the config file. If
a variable does not exist in the environment, or if a sequence of characters is
not a valid reference (such as an un-paired percent sign), the raw characters
are passed through unchanged. This helps with backward compatibility and
safety (e.g. expanding a non-existent %VAR% to an empty string in a path could
result in a very unsafe path). The safest way to insert a literal % into a
value is to use %%.
startdit()
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.
This can be overridden by the bf(--dparam=motdfile=FILE)
command-line option when starting the daemon.
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.
This can be overridden by the bf(--dparam=pidfile=FILE)
command-line option when starting the daemon.
dit(bf(port)) You can override the default port the daemon will listen on
by specifying this value (defaults to 873). This is ignored if the daemon
@@ -101,12 +120,14 @@ 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.
dit(bf(listen backlog)) You can override the default backlog value when the
daemon listens for connections. It defaults to 5.
enddit()
manpagesection(MODULE PARAMETERS)
After the global parameters you should define a number of modules, each
@@ -117,6 +138,11 @@ 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.
Also, the name cannot be "global" as that exact name indicates that
global parameters follow (see above).
As with GLOBAL PARAMETERS, you may use references to environment variables in
the values of parameters. See the GLOBAL PARAMETERS section for more details.
startdit()
@@ -128,6 +154,19 @@ 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).
You may base the path's value off of an environment variable by surrounding
the variable name with percent signs. You can even reference a variable
that is set by rsync when the user connects.
For example, this would use the authorizing user's name in the path:
verb( path = /home/%RSYNC_USER_NAME% )
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
@@ -192,8 +231,9 @@ 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
all symlinks in the same way as the (non-daemon-affecting)
bf(--munge-links) command-line option (using a method described 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.
@@ -213,7 +253,8 @@ to the exclude setting for the module so that
a user can't try to create it.
Note: rsync makes no attempt to verify that any pre-existing symlinks in
the hierarchy are as safe as you want them to be. If you setup an rsync
the module's hierarchy are as safe as you want them to be (unless, of
course, it just copied in the whole hierarchy). If you setup an rsync
daemon on a new area or locally add symlinks, you can manually protect your
symlinks from being abused by prefixing "/rsyncd-munged/" to the start of
every symlink's value. There is a perl script in the support directory
@@ -256,10 +297,16 @@ 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.)
This setting can be overridden by using the bf(--log-file=FILE) or
bf(--dparam=logfile=FILE) command-line options. The former overrides
all the log-file parameters of the daemon and all module settings.
The latter sets the daemon's log file and the default for all the
modules, which still allows modules to override the default setting.
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
@@ -275,6 +322,13 @@ 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.
This also affects the user's ability to request higher levels of bf(--info) and
bf(--debug) logging. If the max value is 2, then no info and/or debug value
that is higher than what would be set by bf(-vv) will be honored by the daemon
in its logging. To see how high of a verbosity level you need to accept for a
particular info/debug level, refer to "rsync --info=help" and "rsync --debug=help".
For instance, it takes max-verbosity 4 to be able to output debug TIME2 and FLIST3.
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
@@ -287,30 +341,49 @@ 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.
Note that "auth users" can override this setting on a per-user basis.
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 parameter to be disabled.
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(list)) This parameter determines whether this module is
listed when the client asks for a listing of available modules. In addition,
if this is false, the daemon will pretend the module does not exist
when a client denied by "hosts allow" or "hosts deny" attempts to access it.
Realize that if "reverse lookup" is disabled globally but enabled for the
module, the resulting reverse lookup to a potentially client-controlled DNS
server may still reveal to the client that it hit an existing module.
The default is for modules to be listable.
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" parameter this determines what
file permissions are available. The default is uid -2, which is normally
the user "nobody".
file permissions are available. The default when run by a super-user is to
switch to the system's "nobody" user. The default for a non-super-user is to
not try to change the user. See also the "gid" parameter.
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" parameter. The default is gid -2,
which is normally the group "nobody".
The RSYNC_USER_NAME environment variable may be used to request that rsync run
as the authorizing user. For example, if you want a rsync to run as the same
user that was received for the rsync authentication, this setup is useful:
verb( uid = %RSYNC_USER_NAME%
gid = * )
dit(bf(gid)) This parameter specifies one or more group names/IDs that will be
used when accessing the module. The first one will be the default group, and
any extra ones be set as supplemental groups. You may also specify a "*" as
the first gid in the list, which will be replaced by all the normal groups for
the transfer's user (see "uid"). The default when run by a super-user is to
switch to your OS's "nobody" (or perhaps "nogroup") group with no other
supplementary groups. The default for a non-super-user is to not change any
group attributes (and indeed, your OS may not allow a non-super-user to try to
change their group settings).
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.
@@ -382,10 +455,12 @@ 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)) This parameter specifies a comma and
space-separated list of usernames that will be allowed to connect to
dit(bf(auth users)) This parameter specifies a comma and/or space-separated
list of authorization rules. In its simplest form, you list the 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
system. The rules may contain shell wildcard characters that will be matched
against the username provided by the client for authentication. If
"auth users" is set then the client will be challenged to supply a
username and password to connect to the module. A challenge response
authentication protocol is used for this exchange. The plain text
@@ -393,24 +468,65 @@ usernames and passwords are stored in the file specified by the
"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
In addition to username matching, you can specify groupname matching via a '@'
prefix. When using groupname matching, the authenticating username must be a
real user on the system, or it will be assumed to be a member of no groups.
For example, specifying "@rsync" will match the authenticating user if the
named user is a member of the rsync group.
Finally, options may be specified after a colon (:). The options allow you to
"deny" a user or a group, set the access to "ro" (read-only), or set the access
to "rw" (read/write). Setting an auth-rule-specific ro/rw setting overrides
the module's "read only" setting.
Be sure to put the rules in the order you want them to be matched, because the
checking stops at the first matching user or group, and that is the only auth
that is checked. For example:
verb( auth users = joe:deny @guest:deny admin:rw @rsync:ro susan joe sam )
In the above rule, user joe will be denied access no matter what. Any user
that is in the group "guest" is also denied access. The user "admin" gets
access in read/write mode, but only if the admin user is not in group "guest"
(because the admin user-matching rule would never be reached if the user is in
group "guest"). Any other user who is in group "rsync" will get read-only
access. Finally, users susan, joe, and sam get the ro/rw setting of the
module, but only if the user didn't match an earlier group-matching rule.
See the description of the secrets file for how you can have per-user passwords
as well as per-group passwords. It also explains how a user can authenticate
using their user password or (when applicable) a group password, depending on
what rule is being authenticated.
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)) 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" 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.
dit(bf(secrets file)) This parameter specifies the name of a file that contains
the username:password and/or @groupname:password pairs used for authenticating
this module. This file is only consulted if the "auth users" parameter is
specified. The file is line-based and contains one name:password pair per
line. Any line has a hash (#) as the very first character on the line 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.
The use of group-specific lines are only relevant when the module is being
authorized using a matching "@groupname" rule. When that happens, the user
can be authorized via either their "username:password" line or the
"@groupname:password" line for the group that triggered the authentication.
It is up to you what kind of password entries you want to include, either
users, groups, or both. The use of group rules in "auth users" does not
require that you specify a group password if you do not want to use shared
passwords.
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".
by "other"; see "strict modes". If the file is not found or is rejected, no
logins for a "user auth" module will be possible.
dit(bf(strict modes)) This parameter determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
@@ -437,12 +553,14 @@ quote(itemization(
IP address and maskaddr is the netmask in dotted decimal notation for IPv4,
or similar for IPv6, e.g. ffff:ffff:ffff:ffff:: instead of /64. All IP
addresses which match the masked IP address will be allowed in.
it() a hostname. The hostname as determined by a reverse lookup will
be matched (case insensitive) against the pattern. Only an exact
match is allowed in.
it() a hostname pattern using wildcards. These are matched using the
same rules as normal unix filename matching. If the pattern matches
then the client is allowed in.
it() a hostname pattern using wildcards. If the hostname of the connecting IP
(as determined by a reverse lookup) matches the wildcarded name (using the
same rules as normal unix filename matching), the client is allowed in. This
only works if "reverse lookup" is enabled (the default).
it() a hostname. A plain hostname is matched against the reverse DNS of the
connecting IP (if "reverse lookup" is enabled), and/or the IP of the given
hostname is matched against the connecting IP (if "forward lookup" is
enabled, as it is by default). Any match will be allowed in.
))
Note IPv6 link-local addresses can have a scope in the address specification:
@@ -470,6 +588,23 @@ rejected. See the "hosts allow" parameter for more information.
The default is no "hosts deny" parameter, which means all hosts can connect.
dit(bf(reverse lookup)) Controls whether the daemon performs a reverse lookup
on the client's IP address to determine its hostname, which is used for
"hosts allow"/"hosts deny" checks and the "%h" log escape. This is enabled by
default, but you may wish to disable it to save time if you know the lookup will
not return a useful result, in which case the daemon will use the name
"UNDETERMINED" instead.
If this parameter is enabled globally (even by default), rsync performs the
lookup as soon as a client connects, so disabling it for a module will not
avoid the lookup. Thus, you probably want to disable it globally and then
enable it for modules that need the information.
dit(bf(forward lookup)) Controls whether the daemon performs a forward lookup
on any hostname specified in an hosts allow/deny setting. By default this is
enabled, allowing the use of an explicit hostname that would not be returned
by reverse DNS of the connecting IP.
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
@@ -496,6 +631,11 @@ The format is a text string containing embedded single-character escape
sequences prefixed with a percent (%) character. An optional numeric
field width may also be specified between the percent and the escape
letter (e.g. "bf(%-50n %8l %07p)").
In addition, one or more apostrophes may be specified prior to a numerical
escape to indicate that the numerical value should be made more human-readable.
The 3 supported levels are the same as for the bf(--human-readable)
command-line option, though the default is for human-readability to be off.
Each added apostrophe increases the level (e.g. "bf(%''l %'b %f)").
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
is always prefixed when using the "log file" parameter.
@@ -506,13 +646,14 @@ rsyncstats.)
The single-character escapes that are understood are as follows:
quote(itemization(
it() %a the remote IP address
it() %a the remote IP address (only available for a daemon)
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() %C the full-file MD5 checksum if bf(--checksum) is enabled or a file was transferred (only for protocol 30 or above).
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
it() %h the remote host name (only available for a daemon)
it() %i an itemized list of what is being updated
it() %l the length of the file in bytes
it() %L the string " -> SYMLINK", " => HARDLINK", or "" (where bf(SYMLINK) or bf(HARDLINK) is a filename)
@@ -583,7 +724,12 @@ the sender.
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
before and/or after the transfer. If the bf(pre-xfer exec) command fails, the
transfer is aborted before it begins.
transfer is aborted before it begins. Any output from the script on stdout (up
to several KB) will be displayed to the user when aborting, but is NOT
displayed if the script returns success. Any output from the script on stderr
goes to the daemon's stderr, which is typically discarded (though see
--no-detatch option for a way to see the stderr output, which can assist with
debugging).
The following environment variables will be set, though some are
specific to the pre-xfer or the post-xfer environment:
@@ -596,11 +742,14 @@ quote(itemization(
it() bf(RSYNC_USER_NAME): The accessing user's name (empty if no user).
it() bf(RSYNC_PID): A unique number for this transfer.
it() bf(RSYNC_REQUEST): (pre-xfer only) The module/path info specified
by the user (note that the user can specify multiple source files,
so the request can be something like "mod/path1 mod/path2", etc.).
by the user. Note that the user can specify multiple source files,
so the request can be something like "mod/path1 mod/path2", etc.
it() bf(RSYNC_ARG#): (pre-xfer only) The pre-request arguments are set
in these numbered values. RSYNC_ARG0 is always "rsyncd", and the last
value contains a single period.
in these numbered values. RSYNC_ARG0 is always "rsyncd", followed by
the options that were used in RSYNC_ARG1, and so on. There will be a
value of "." indicating that the options are done and the path args
are beginning -- these contain similar information to RSYNC_REQUEST,
but with values separated and the module name stripped off.
it() bf(RSYNC_EXIT_STATUS): (post-xfer only) the server side's exit value.
This will be 0 for a successful run, a positive value for an error that the
server generated, or a -1 if rsync failed to exit properly. Note that an
@@ -615,6 +764,62 @@ module's uid/gid setting) without any chroot restrictions.
enddit()
manpagesection(CONFIG DIRECTIVES)
There are currently two config directives available that allow a config file to
incorporate the contents of other files: bf(&include) and bf(&merge). Both
allow a reference to either a file or a directory. They differ in how
segregated the file's contents are considered to be.
The bf(&include) directive treats each file as more distinct, with each one
inheriting the defaults of the parent file, starting the parameter parsing
as globals/defaults, and leaving the defaults unchanged for the parsing of
the rest of the parent file.
The bf(&merge) directive, on the other hand, treats the file's contents as
if it were simply inserted in place of the directive, and thus it can set
parameters in a module started in another file, can affect the defaults for
other files, etc.
When an bf(&include) or bf(&merge) directive refers to a directory, it will read
in all the bf(*.conf) or bf(*.inc) files (respectively) that are contained inside
that directory (without any
recursive scanning), with the files sorted into alpha order. So, if you have a
directory named "rsyncd.d" with the files "foo.conf", "bar.conf", and
"baz.conf" inside it, this directive:
verb( &include /path/rsyncd.d )
would be the same as this set of directives:
verb( &include /path/rsyncd.d/bar.conf
&include /path/rsyncd.d/baz.conf
&include /path/rsyncd.d/foo.conf )
except that it adjusts as files are added and removed from the directory.
The advantage of the bf(&include) directive is that you can define one or more
modules in a separate file without worrying about unintended side-effects
between the self-contained module files.
The advantage of the bf(&merge) directive is that you can load config snippets
that can be included into multiple module definitions, and you can also set
global values that will affect connections (such as bf(motd file)), or globals
that will affect other include files.
For example, this is a useful /etc/rsyncd.conf file:
verb( port = 873
log file = /var/log/rsync.log
pid file = /var/lock/rsync.lock
&merge /etc/rsyncd.d
&include /etc/rsyncd.d )
This would merge any /etc/rsyncd.d/*.inc files (for global values that should
stay in effect), and then include any /etc/rsyncd.d/*.conf files (defining
modules without any global-value cross-talk).
manpagesection(AUTHENTICATION STRENGTH)
The authentication protocol used in rsync is a 128 bit MD4 based
@@ -700,11 +905,11 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.3 of rsync.
This man page is current for version 3.1.2pre1 of rsync.
manpagesection(CREDITS)
rsync is distributed under the GNU public license. See the file
rsync is distributed under the GNU General Public License. See the file
COPYING for details.
The primary ftp site for rsync is

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
@@ -229,8 +232,9 @@ echo " scratchbase=$scratchbase"
[ -d "$scratchbase" ] || mkdir "$scratchbase"
suitedir="$srcdir/testsuite"
TESTRUN_TIMEOUT=300
export scratchdir suitedir
export scratchdir suitedir TESTRUN_TIMEOUT
prep_scratch() {
[ -d "$scratchdir" ] && chmod -R u+rwX "$scratchdir" && rm -rf "$scratchdir"
@@ -261,8 +265,13 @@ do
prep_scratch
case "$testscript" in
*hardlinks*) TESTRUN_TIMEOUT=600 ;;
*) TESTRUN_TIMEOUT=300 ;;
esac
set +e
sh $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
"$TOOLDIR/"testrun $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
result=$?
set -e

158
sender.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2008 Wayne Davison
* Copyright (C) 2003-2015 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
@@ -20,9 +20,8 @@
*/
#include "rsync.h"
#include "inums.h"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_server;
extern int am_daemon;
@@ -30,22 +29,26 @@ extern int inc_recurse;
extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int want_xattr_optim;
extern int csum_length;
extern int append_mode;
extern int io_error;
extern int flist_eof;
extern int allowed_lull;
extern int preserve_xattrs;
extern int protocol_version;
extern int remove_source_files;
extern int updating_basis_file;
extern int make_backups;
extern int do_progress;
extern int inplace;
extern int batch_fd;
extern int write_batch;
extern int file_old_total;
extern struct stats stats;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
BOOL extra_flist_sending_enabled;
/**
* @file
*
@@ -61,7 +64,7 @@ static struct sum_struct *receive_sums(int f)
{
struct sum_struct *s;
int32 i;
int lull_mod = allowed_lull * 5;
int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
OFF_T offset = 0;
if (!(s = new(struct sum_struct)))
@@ -71,9 +74,9 @@ static struct sum_struct *receive_sums(int f)
s->sums = NULL;
if (verbose > 3) {
rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n",
(double)s->count, (long)s->blength, (long)s->remainder);
if (DEBUG_GTE(DELTASUM, 3)) {
rprintf(FINFO, "count=%s n=%ld rem=%ld\n",
big_num(s->count), (long)s->blength, (long)s->remainder);
}
if (append_mode > 0) {
@@ -102,13 +105,13 @@ static struct sum_struct *receive_sums(int f)
s->sums[i].len = s->blength;
offset += s->sums[i].len;
if (allowed_lull && !(i % lull_mod))
maybe_send_keepalive();
if (lull_mod && !(i % lull_mod))
maybe_send_keepalive(time(NULL), True);
if (verbose > 3) {
if (DEBUG_GTE(DELTASUM, 3)) {
rprintf(FINFO,
"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
i, s->sums[i].len, (double)s->sums[i].offset,
"chunk[%d] len=%d offset=%s sum1=%08x\n",
i, s->sums[i].len, big_num(s->sums[i].offset),
s->sums[i].sum1);
}
}
@@ -121,29 +124,46 @@ static struct sum_struct *receive_sums(int f)
void successful_send(int ndx)
{
char fname[MAXPATHLEN];
char *failed_op;
struct file_struct *file;
struct file_list *flist;
STRUCT_STAT st;
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 (!change_pathname(file, NULL, 0))
return;
f_name(file, fname);
if (do_unlink(fname) == 0) {
if (verbose > 1)
if (do_lstat(fname, &st) < 0) {
failed_op = "re-lstat";
goto failed;
}
if (S_ISREG(file->mode) /* Symlinks & devices don't need this check: */
&& (st.st_size != F_LENGTH(file) || st.st_mtime != file->modtime
#ifdef ST_MTIME_NSEC
|| (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file))
#endif
)) {
rprintf(FERROR_XFER, "ERROR: Skipping sender remove for changed file: %s\n", fname);
return;
}
if (do_unlink(fname) < 0) {
failed_op = "remove";
failed:
if (errno == ENOENT)
rprintf(FINFO, "sender file already removed: %s\n", fname);
else
rsyserr(FERROR_XFER, errno, "sender failed to %s %s", failed_op, fname);
} else {
if (INFO_GTE(REMOVE, 1))
rprintf(FINFO, "sender removed %s\n", fname);
} else
rsyserr(FERROR, errno, "sender failed to remove %s", fname);
}
}
static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
@@ -159,7 +179,8 @@ 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
&& !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
send_xattr_request(fname, file, f_out);
#endif
}
@@ -176,40 +197,51 @@ void send_files(int f_in, int f_out)
int iflags, xlen;
struct file_struct *file;
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
struct stats initial_stats;
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)
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "send_files starting\n");
while (1) {
if (inc_recurse)
send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
if (inc_recurse) {
send_extra_file_list(f_out, MIN_FILECNT_LOOKAHEAD);
extra_flist_sending_enabled = !flist_eof;
}
/* This call also sets cur_flist. */
ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
ndx = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type,
xname, &xlen);
extra_flist_sending_enabled = False;
if (ndx == NDX_DONE) {
if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) {
set_current_file_index(NULL, 0);
end_progress(0);
}
if (inc_recurse && first_flist) {
file_old_total -= first_flist->used;
flist_free(first_flist);
if (first_flist) {
if (first_flist == cur_flist)
file_old_total = cur_flist->used;
write_ndx(f_out, NDX_DONE);
continue;
}
}
if (++phase > max_phase)
break;
if (verbose > 2)
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "send_files phase=%d\n", phase);
write_ndx(f_out, NDX_DONE);
continue;
}
if (inc_recurse)
send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
send_extra_file_list(f_out, MIN_FILECNT_LOOKAHEAD);
if (ndx - cur_flist->ndx_start >= 0)
file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -225,11 +257,12 @@ void send_files(int f_in, int f_out)
continue;
f_name(file, fname);
if (verbose > 2)
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
&& !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
recv_xattr_request(file, f_in);
#endif
@@ -237,6 +270,21 @@ void send_files(int f_in, int f_out)
maybe_log_item(file, iflags, itemizing, xname);
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
if (iflags & ITEM_IS_NEW) {
stats.created_files++;
if (S_ISREG(file->mode)) {
/* Nothing further to count. */
} else if (S_ISDIR(file->mode))
stats.created_dirs++;
#ifdef SUPPORT_LINKS
else if (S_ISLNK(file->mode))
stats.created_symlinks++;
#endif
else if (IS_DEVICE(file->mode))
stats.created_devices++;
else
stats.created_specials++;
}
continue;
}
if (phase == 2) {
@@ -260,28 +308,31 @@ void send_files(int f_in, int f_out)
append_mode = -append_mode;
csum_length = SHORT_SUM_LENGTH;
}
if (iflags & ITEM_IS_NEW)
stats.created_files++;
}
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
if (!am_server && do_progress)
if (!am_server && INFO_GTE(PROGRESS, 1))
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.xferred_files++;
stats.total_transferred_size += F_LENGTH(file);
if (!log_before_transfer)
remember_initial_stats();
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
log_item(FCLIENT, file, iflags, NULL);
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
continue;
}
initial_stats = stats;
if (!(s = receive_sums(f_in))) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "receive_sums failed\n");
rprintf(FERROR_XFER, "receive_sums failed\n");
exit_cleanup(RERR_PROTOCOL);
}
@@ -309,10 +360,10 @@ 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);
exit_cleanup(RERR_FILEIO);
}
if (st.st_size) {
@@ -321,30 +372,30 @@ void send_files(int f_in, int f_out)
} else
mbuf = NULL;
if (verbose > 2) {
rprintf(FINFO, "send_files mapped %s%s%s of size %.0f\n",
path,slash,fname, (double)st.st_size);
if (DEBUG_GTE(DELTASUM, 2)) {
rprintf(FINFO, "send_files mapped %s%s%s of size %s\n",
path,slash,fname, big_num(st.st_size));
}
write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
fnamecmp_type, xname, xlen);
write_sum_head(f_xfer, s);
if (verbose > 2)
if (DEBUG_GTE(DELTASUM, 2))
rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname);
if (log_before_transfer)
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
log_item(FCLIENT, file, iflags, NULL);
else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
rprintf(FCLIENT, "%s\n", fname);
set_compression(fname);
match_sums(f_xfer, s, mbuf, st.st_size);
if (do_progress)
if (INFO_GTE(PROGRESS, 1))
end_progress(st.st_size);
log_item(log_code, file, &initial_stats, iflags, NULL);
log_item(log_code, file, iflags, NULL);
if (mbuf) {
j = unmap_file(mbuf);
@@ -359,7 +410,7 @@ void send_files(int f_in, int f_out)
free_sums(s);
if (verbose > 2)
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "sender finished %s%s%s\n", path,slash,fname);
/* Flag that we actually sent this entry. */
@@ -368,7 +419,10 @@ void send_files(int f_in, int f_out)
if (make_backups < 0)
make_backups = -make_backups;
if (verbose > 2)
if (io_error != save_io_error && protocol_version >= 30)
send_msg_int(MSG_IO_ERROR, io_error);
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "send files finished\n");
match_report();

View File

@@ -8,5 +8,8 @@
ECHO_T="@ECHO_T@"
ECHO_N="@ECHO_N@"
ECHO_C="@ECHO_C@"
HOST_OS="@host_os@"
SHELL_PATH="@SHELL_PATH@"
FAKEROOT_PATH="@FAKEROOT_PATH@"
export ECHO_T ECHO_N ECHO_C
export ECHO_T ECHO_N ECHO_C HOST_OS SHELL_PATH FAKEROOT_PATH

195
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-2008 Wayne Davison
* Copyright (C) 2003-2015 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,9 +25,13 @@
* emulate it using the KAME implementation. */
#include "rsync.h"
#include "ifuncs.h"
#include "itypes.h"
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
#include <netinet/tcp.h>
extern char *bind_address;
@@ -39,12 +43,11 @@ extern int connect_timeout;
static struct sigaction sigact;
#endif
/**
* Establish a proxy connection on an open socket to a web proxy by
* using the CONNECT method. If proxy_user and proxy_pass are not NULL,
* they are used to authenticate to the proxy using the "Basic"
* proxy-authorization protocol
**/
static int sock_exec(const char *prog);
/* Establish a proxy connection on an open socket to a web proxy by using the
* CONNECT method. If proxy_user and proxy_pass are not NULL, they are used to
* authenticate to the proxy using the "Basic" proxy-authorization protocol. */
static int establish_proxy_connection(int fd, char *host, int port,
char *proxy_user, char *proxy_pass)
{
@@ -125,10 +128,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
}
/**
* Try to set the local address for a newly-created socket. Return -1
* if this fails.
**/
/* Try to set the local address for a newly-created socket.
* Return -1 if this fails. */
int try_bind_local(int s, int ai_family, int ai_socktype,
const char *bind_addr)
{
@@ -160,36 +161,32 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
}
/* connect() timeout handler based on alarm() */
static RETSIGTYPE contimeout_handler(UNUSED(int val))
static void 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;
@@ -232,7 +229,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
}
*cp++ = '\0';
strlcpy(portbuf, cp, sizeof portbuf);
if (verbose >= 2) {
if (DEBUG_GTE(CONNECT, 1)) {
rprintf(FINFO, "connection via http proxy %s port %s\n",
h, portbuf);
}
@@ -251,12 +248,17 @@ int open_socket_out(char *host, int port, const char *bind_addr,
return -1;
}
for (res = res0, addr_cnt = 0; res; res = res->ai_next, addr_cnt++) {}
errnos = new_array0(int, addr_cnt);
if (!errnos)
out_of_memory("open_socket_out");
s = -1;
/* Try to connect to all addresses for this machine until we get
* through. It might e.g. be multi-homed, or have both IPv4 and IPv6
* addresses. We need to create a socket for each record, since the
* address record tells us what protocol to use to try to connect. */
for (res = res0; res; res = res->ai_next) {
for (res = res0, j = 0; res; res = res->ai_next, j++) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0)
continue;
@@ -287,8 +289,10 @@ int open_socket_out(char *host, int port, const char *bind_addr,
if (connect_timeout > 0)
alarm(0);
if (s < 0)
if (s < 0) {
errnos[j] = errno;
continue;
}
if (proxied
&& establish_proxy_connection(s, host, port,
@@ -297,19 +301,36 @@ int open_socket_out(char *host, int port, const char *bind_addr,
s = -1;
continue;
}
if (DEBUG_GTE(CONNECT, 2)) {
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 || DEBUG_GTE(CONNECT, 2)) {
char buf[2048];
for (res = res0, j = 0; res; res = res->ai_next, j++) {
if (errnos[j] == 0)
continue;
if ((error = getnameinfo(res->ai_addr, res->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST)) != 0)
snprintf(buf, sizeof buf, "*getnameinfo failure: %s*", gai_strerror(error));
rsyserr(FERROR, errnos[j], "failed to connect to %s (%s)", h, buf);
}
if (s < 0)
s = -1;
}
freeaddrinfo(res0);
free(errnos);
return s;
}
/**
* Open an outgoing socket, but allow for it to be intercepted by
/* Open an outgoing socket, but allow for it to be intercepted by
* $RSYNC_CONNECT_PROG, which will execute a program across a TCP
* socketpair rather than really opening a socket.
*
@@ -318,8 +339,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
*
* This is based on the Samba LIBSMB_PROG feature.
*
* @param bind_addr Local address to use. Normally NULL to get the stack default.
**/
* bind_addr: local address to use. Normally NULL to get the stack default. */
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
int af_hint)
{
@@ -361,7 +381,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
*t = '\0';
}
if (verbose >= 2) {
if (DEBUG_GTE(CONNECT, 1)) {
rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
host, port);
@@ -372,9 +392,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
}
/**
* Open one or more sockets for incoming data using the specified type,
/* Open one or more sockets for incoming data using the specified type,
* port, and address.
*
* The getaddrinfo() call may return several address results, e.g. for
@@ -383,9 +401,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
* We return an array of file-descriptors to the sockets, with a trailing
* -1 value to indicate the end of the list.
*
* @param bind_addr Local address to bind, or NULL to allow it to
* default.
**/
* bind_addr: local address to bind, or NULL to allow it to default. */
static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
@@ -473,7 +489,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Only output the socket()/bind() messages if we were totally
* unsuccessful, or if the daemon is being run with -vv. */
for (s = 0; s < ecnt; s++) {
if (!i || verbose > 1)
if (!i || DEBUG_GTE(BIND, 1))
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0);
free(errmsgs[s]);
}
@@ -490,9 +506,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
}
/*
* Determine if a file descriptor is in fact a socket
*/
/* Determine if a file descriptor is in fact a socket. */
int is_a_socket(int fd)
{
int v;
@@ -515,7 +529,7 @@ int is_a_socket(int fd)
}
static RETSIGTYPE sigchld_handler(UNUSED(int val))
static void sigchld_handler(UNUSED(int val))
{
#ifdef WNOHANG
while (waitpid(-1, NULL, WNOHANG) > 0) {}
@@ -543,7 +557,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
/* ready to listen */
FD_ZERO(&deffds);
for (i = 0, maxfd = -1; sp[i] >= 0; i++) {
if (listen(sp[i], 5) < 0) {
if (listen(sp[i], lp_listen_backlog()) < 0) {
rsyserr(FERROR, errno, "listen() on socket failed");
#ifdef INET6
if (errno == EADDRINUSE && i > 0) {
@@ -578,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++) {
@@ -632,7 +646,9 @@ struct
} socket_options[] = {
{"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
{"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
#ifdef SO_BROADCAST
{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
#endif
#ifdef TCP_NODELAY
{"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
#endif
@@ -660,13 +676,11 @@ struct
#ifdef SO_RCVTIMEO
{"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
#endif
{NULL,0,0,0,0}};
{NULL,0,0,0,0}
};
/**
* Set user socket options
**/
/* Set user socket options. */
void set_socket_options(int fd, char *options)
{
char *tok;
@@ -732,15 +746,10 @@ void set_socket_options(int fd, char *options)
}
/**
* This is like socketpair but uses tcp. It is used by the Samba
* regression test code.
*
* The function guarantees that nobody else can attach to the socket,
* or if they do that this function fails and the socket gets closed
* returns 0 on success, -1 on failure the resulting file descriptors
* are symmetrical.
**/
/* This is like socketpair but uses tcp. The function guarantees that nobody
* else can attach to the socket, or if they do that this function fails and
* the socket gets closed. Returns 0 on success, -1 on failure. The resulting
* file descriptors are symmetrical. Currently only for RSYNC_CONNECT_PROG. */
static int socketpair_tcp(int fd[2])
{
int listener;
@@ -761,16 +770,12 @@ static int socketpair_tcp(int fd[2])
sock2.sin_len = sizeof sock2;
#endif
sock2.sin_family = PF_INET;
sock2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
if (listen(listener, 1) != 0)
goto failed;
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
goto failed;
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
if (bind(listener, (struct sockaddr *)&sock2, sizeof sock2) != 0
|| listen(listener, 1) != 0
|| getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0
|| (fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
goto failed;
set_nonblocking(fd[1]);
@@ -783,7 +788,7 @@ static int socketpair_tcp(int fd[2])
} else
connect_done = 1;
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
if ((fd[0] = accept(listener, (struct sockaddr *)&sock2, &socklen)) == -1)
goto failed;
close(listener);
@@ -811,34 +816,40 @@ 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) {
rsyserr(FERROR, errno, "socketpair_tcp failed");
return -1;
}
if (verbose >= 2)
if (DEBUG_GTE(CMD, 1))
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];
}

52
stunnel-rsync.in Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
# This must be called as (note the trailing dot):
#
# stunnel-rsync HOSTNAME rsync --server --daemon .
#
# ... which is typically done via the rsync-ssl script, which results in something like this:
#
# rsync --rsh=stunnel-rsync -aiv HOSTNAME::module [ARGS]
#
# This SSL setup based on the files by: http://dozzie.jarowit.net/trac/wiki/RsyncSSL
# Note that this requires at least version 4.x of stunnel.
# The current environment can override using the RSYNC_SSL_* values:
if [ x"$RSYNC_SSL_CERT" = x ]; then
cert=""
else
cert="cert = $RSYNC_SSL_CERT"
fi
if [ x"$RSYNC_SSL_CA_CERT" ]; then
cafile=""
verify=0
else
cafile="CAfile = $RSYNC_SSL_CA_CERT"
verify=3
fi
port=${RSYNC_SSL_PORT:-874}
# If the user specified USER@HOSTNAME::module, then rsync passes us
# the -l USER option too, so we must be prepared to ignore it.
if [ x"$1" = x"-l" ]; then
shift 2
fi
hostname=$1
shift
if [ x"$hostname" = x -o x"$1" != x"rsync" -o x"$2" != x"--server" -o x"$3" != x"--daemon" ]; then
echo "Usage: stunnel-rsync HOSTNAME rsync --server --daemon ." 1>&2
exit 1
fi
# devzero@web.de came up with this no-tmpfile calling syntax:
@stunnel4@ -fd 10 11<&0 <<EOF 10<&0 0<&11 11<&-
foreground = yes
debug = crit
connect = $hostname:$port
client = yes
TIMEOUTclose = 0
verify = $verify
$cert
$cafile
EOF

30
stunnel-rsyncd.conf.in Normal file
View File

@@ -0,0 +1,30 @@
# This config for stunnel will start up rsync for an incoming ssl connection.
foreground = no
#output = /var/log/stunnel-rsyncd.log
pid = /var/run/stunnel-rsyncd.pid
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
compression = rle
# This must be root for rsync to use chroot -- rsync will drop permissions:
setuid = root
setgid = root
[rsync]
accept = 874
# You can set the cert to a combo *.pem file and omit the key, if you like.
cert = /etc/rsync-ssl/certs/server.crt
key = /etc/rsync-ssl/certs/server.key
client = no
# To allow anyone to try an ssl connection, use this:
verify = 0
CAfile = /etc/ssl/ca-bundle.pem
# To allow only cert-authorized clients, use something like this instead of the above:
#verify = 3
#CAfile = /etc/rsync-ssl/certs/allowed-clients.cert.pem
exec = @bindir@/rsync
# You can either share the same config as a normal daemon, or specify a separate config:
execargs = rsync --server --daemon .
#execargs = rsync --server --daemon --config=/etc/rsync-ssl/rsyncd.conf .

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

View File

@@ -1,5 +1,6 @@
#!/usr/bin/perl -w
#!/usr/bin/perl
use strict;
use warnings;
# Sets mtime and atime of files to the latest commit time in git.
#

126
support/instant-rsyncd Executable file
View File

@@ -0,0 +1,126 @@
#!/bin/bash
# instant-rsyncd lets you quickly set up and start a simple, unprivileged rsync
# daemon with a single module in the current directory. I've found it
# invaluable for quick testing, and I use it when writing a list of commands
# that people can paste into a terminal to reproduce a daemon-related bug.
# Sysadmins deploying an rsync daemon for the first time may find it helpful as
# a starting point.
#
# Usage: instant-rsyncd MODULE PORT RSYNCD-USERNAME [RSYNC-PATH]
# The script asks for the rsyncd user's password twice on stdin, once to set it
# and once to log in to test the daemon.
# -- Matt McCutchen <matt@mattmccutchen.net>
set -e
dir="$(pwd)"
echo
echo "This will setup an rsync daemon in $dir"
if [ $# = 0 ]; then
IFS='' read -p 'Module name to create (or return to exit): ' module
[ ! "$module" ] && exit
else
module="$1"
shift
fi
if [ $# = 0 ]; then
IFS='' read -p 'Port number the daemon should listen on [873]: ' port
else
port="$1"
shift
fi
[ "$port" ] || port=873
if [ $# = 0 ]; then
IFS='' read -p 'User name for authentication (empty for none): ' user
else
user="$1"
shift
fi
if [ "$user" ]; then
IFS='' read -s -p 'Desired password: ' password
echo
fi
rsync="$1"
[ "$rsync" ] || rsync=rsync
moduledir="${dir%/}/$module"
mkdir "$module"
cat >rsyncd.conf <<EOF
log file = rsyncd.log
pid file = rsyncd.pid
port = $port
use chroot = no
[$module]
path = $module
read only = false
EOF
if [ "$user" ]; then
cat >>rsyncd.conf <<-EOF
auth users = $user
secrets file = $module.secrets
EOF
touch "$module".secrets
chmod go-rwx "$module".secrets
echo "$user:$password" >"$module".secrets
user="$user@"
fi
cat >start <<EOF
#!/bin/bash
set -e
cd \`dirname \$0\`
! [ -e rsyncd.pid ] || {
echo "Is the daemon already running? If not, delete rsyncd.pid."
exit 1
}
$rsync --daemon --config=rsyncd.conf
EOF
chmod +x start
cat >stop <<"EOF"
#!/bin/bash
set -e
cd `dirname $0`
! [ -e rsyncd.pid ] || kill -s SIGTERM $(< rsyncd.pid)
EOF
chmod +x stop
path="rsync://$user$(hostname):$port/$module/"
if ./start; then
sleep .2
echo
echo "I ran the start command for the daemon. The log file rsyncd.log says:"
echo
cat rsyncd.log
echo
echo "You can start and stop it with ./start and ./stop respectively."
echo "You can customize the configuration file rsyncd.conf."
echo
echo "Give rsync the following path to access the module:"
echo " $path"
echo
if [ "$user" ]; then
echo "Let's test the daemon now. Enter the password you chose at the prompt."
else
echo "Let's test the daemon now."
fi
echo
echo '$' $rsync --list-only "$path"
$rsync --list-only "$path"
echo
echo "You should see an empty folder; it's $moduledir."
else
echo "Something went wrong. Do you see an error message?"
fi

View File

@@ -1,35 +1,81 @@
#!/bin/sh
#!/usr/bin/perl
# This script can be used as a "remote shell" command that is only
# capable of pretending to connect to "localhost". This is useful
# for testing or for running a local copy where the sender and the
# receiver needs to use different options (e.g. --fake-super). If
# we get a -l USER option, we try to use "sudo -u USER" to run the
# command.
# we get -l USER, we try to become the USER, either directly (must
# be root) or by using "sudo -H -u USER" (requires --sudo option).
user=''
prefix=''
do_cd=y # Default path is user's home dir, just like ssh.
use strict;
use warnings;
use Getopt::Long;
use English '-no_match_vars';
while : ; do
case "$1" in
-l) user="$2"; shift; shift ;;
-l*) user=`echo $1 | sed 's/^-l//'`; shift ;;
--no-cd) do_cd=n; shift ;;
-*) shift ;;
localhost) shift; break ;;
*) echo "lsh: unable to connect to host $1" 1>&2; exit 1 ;;
esac
done
&Getopt::Long::Configure('bundling');
&Getopt::Long::Configure('require_order');
GetOptions(
'l=s' => \( my $login_name ),
'1|2|4|6|A|a|C|f|g|k|M|N|n|q|s|T|t|V|v|X|x|Y' => sub { }, # Ignore
'b|c|D|e|F|i|L|m|O|o|p|R|S|w=s' => sub { }, # Ignore
'no-cd' => \( my $no_chdir ),
'sudo' => \( my $use_sudo ),
) or &usage;
&usage unless @ARGV > 1;
if [ "$user" ]; then
prefix="sudo -H -u $user"
if [ $do_cd = y ]; then
home=`perl -e "print((getpwnam("$user"))[7])"`
# Yeah, this may fail, but attempts to get sudo to cd are harder.
cd $home
fi
elif [ $do_cd = y ]; then
cd
fi
my $host = shift;
if ($host =~ s/^([^@]+)\@//) {
$login_name = $1;
}
if ($host ne 'localhost') {
die "lsh: unable to connect to host $host\n";
}
eval $prefix "${@}"
my ($home_dir, @cmd);
if ($login_name) {
my ($uid, $gid);
if ($login_name =~ /\D/) {
$uid = getpwnam($login_name);
die "Unknown user: $login_name\n" unless defined $uid;
} else {
$uid = $login_name;
}
($login_name, $gid, $home_dir) = (getpwuid($uid))[0,3,7];
if ($use_sudo) {
unshift @ARGV, "cd '$home_dir' &&" unless $no_chdir;
unshift @cmd, qw( sudo -H -u ), $login_name;
$no_chdir = 1;
} else {
my $groups = "$gid $gid";
while (my ($grgid, $grmembers) = (getgrent)[2,3]) {
if ($grgid != $gid && $grmembers =~ /(^|\s)\Q$login_name\E(\s|$)/o) {
$groups .= " $grgid";
}
}
my ($ruid, $euid) = ($UID, $EUID);
$GID = $EGID = $groups;
$UID = $EUID = $uid;
die "Cannot set ruid: $! (use --sudo?)\n" if $UID == $ruid && $ruid != $uid;
die "Cannot set euid: $! (use --sudo?)\n" if $EUID == $euid && $euid != $uid;
$ENV{USER} = $ENV{USERNAME} = $login_name;
$ENV{HOME} = $home_dir;
}
} else {
$home_dir = (getpwuid($UID))[7];
}
unless ($no_chdir) {
chdir $home_dir or die "Unable to chdir to $home_dir: $!\n";
}
push @cmd, '/bin/sh', '-c', "@ARGV";
exec @cmd;
die "Failed to exec: $!\n";
sub usage
{
die <<EOT;
Usage: lsh [-l user] [--sudo] [--no-cd] localhost COMMAND [...]
EOT
}

35
support/lsh.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
# This script can be used as a "remote shell" command that is only
# capable of pretending to connect to "localhost". This is useful
# for testing or for running a local copy where the sender and the
# receiver needs to use different options (e.g. --fake-super). If
# we get a -l USER option, we try to use "sudo -u USER" to run the
# command.
user=''
do_cd=y # Default path is user's home dir, just like ssh.
while : ; do
case "$1" in
-l) user="$2"; shift; shift ;;
-l*) user=`echo "$1" | sed 's/^-l//'`; shift ;;
--no-cd) do_cd=n; shift ;;
-*) shift ;;
localhost) shift; break ;;
*) echo "lsh: unable to connect to host $1" 1>&2; exit 1 ;;
esac
done
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
if [ $do_cd = y ]; then
cd || exit 1
fi
eval "${@}"
fi

15
support/mapfrom Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/perl
# This helper script makes it easy to use a passwd or group file to map
# values in a LOCAL transfer. For instance, if you mount a backup that
# does not have the same passwd setup as the local machine, you can do
# a copy FROM the backup area as follows and get the differing ID values
# mapped just like a remote transfer FROM the backed-up machine would do:
#
# rsync -av --usermap=`mapfrom /mnt/backup/etc/passwd` \
# --groupmap=`mapfrom /mnt/backup/etc/group` \
# /mnt/backup/some/src/ /some/dest/
while (<>) {
push @_, "$2:$1" if /^(\w+):[^:]+:(\d+)/;
}
print join(',', @_), "\n";

15
support/mapto Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/perl
# This helper script makes it easy to use a passwd or group file to map
# values in a LOCAL transfer. For instance, if you mount a backup that
# does not have the same passwd setup as the local machine, you can do
# a copy TO the backup area as follows and get the differing ID values
# mapped just like a remote transfer TO the backed-up machine would do:
#
# rsync -av --usermap=`mapto /mnt/backup/etc/passwd` \
# --groupmap=`mapto /mnt/backup/etc/group` \
# /some/src/ /mnt/backup/some/dest/
while (<>) {
push @_, "$1:$2" if /^(\w+):[^:]+:(\d+)/;
}
print join(',', @_), "\n";

View File

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

View File

@@ -31,7 +31,7 @@ die "$0: Restricted directory does not exist!\n" if $subdir ne '/' && !-d $subdi
# command="rrsync logs/client" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAzGhEeNlPr...
# command="rrsync -ro results" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAmkHG1WCjC...
#
# Format of the envrionment variables set by sshd:
# Format of the environment variables set by sshd:
# SSH_ORIGINAL_COMMAND=rsync --server -vlogDtpr --partial . ARG # push
# SSH_ORIGINAL_COMMAND=rsync --server --sender -vlogDtpr --partial . ARGS # pull
# SSH_CONNECTION=client_addr client_port server_port
@@ -51,7 +51,7 @@ die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
# To disable a short-named option, add its letter to this string:
our $short_disabled = 's';
our $short_no_arg = 'ACDEHIKLORSWXbcdgklmnoprstuvxz'; # DO NOT REMOVE ANY
our $short_no_arg = 'ACDEHIJKLORSWXbcdgklmnoprstuvxyz'; # DO NOT REMOVE ANY
our $short_with_num = 'B'; # DO NOT REMOVE ANY
# To disable a long-named option, change its value to a -1. The values mean:
@@ -60,6 +60,7 @@ our $short_with_num = 'B'; # DO NOT REMOVE ANY
our %long_opt = (
'append' => 0,
'backup-dir' => 2,
'block-size' => 1,
'bwlimit' => 1,
'checksum-seed' => 1,
'compare-dest' => 2,
@@ -67,6 +68,7 @@ our %long_opt = (
'copy-dest' => 2,
'copy-unsafe-links' => 0,
'daemon' => -1,
'debug' => 1,
'delay-updates' => 0,
'delete' => 0,
'delete-after' => 0,
@@ -74,17 +76,25 @@ our %long_opt = (
'delete-delay' => 0,
'delete-during' => 0,
'delete-excluded' => 0,
'delete-missing-args' => 0,
'existing' => 0,
'fake-super' => 0,
'files-from' => 3,
'force' => 0,
'from0' => 0,
'fuzzy' => 0,
'group' => 0,
'groupmap' => 1,
'hard-links' => 0,
'iconv' => 1,
'ignore-errors' => 0,
'ignore-existing' => 0,
'ignore-missing-args' => 0,
'ignore-times' => 0,
'info' => 1,
'inplace' => 0,
'link-dest' => 2,
'links' => 0,
'list-only' => 0,
'log-file' => 3,
'log-format' => 1,
@@ -92,15 +102,20 @@ our %long_opt = (
'max-size' => 1,
'min-size' => 1,
'modify-window' => 1,
'no-i-r' => 0,
'new-compress' => 0,
'no-implied-dirs' => 0,
'no-r' => 0,
'no-relative' => 0,
'no-specials' => 0,
'numeric-ids' => 0,
'one-file-system' => 0,
'only-write-batch' => 1,
'owner' => 0,
'partial' => 0,
'partial-dir' => 2,
'perms' => 0,
'preallocate' => 0,
'recursive' => 0,
'remove-sent-files' => $ro ? -1 : 0,
'remove-source-files' => $ro ? -1 : 0,
'safe-links' => 0,
@@ -109,11 +124,14 @@ our %long_opt = (
'size-only' => 0,
'skip-compress' => 1,
'specials' => 0,
'stats' => 0,
'suffix' => 1,
'super' => 0,
'temp-dir' => 2,
'timeout' => 1,
'times' => 0,
'use-qsort' => 0,
'usermap' => 1,
);
### END of options data produced by the cull_options script. ###
@@ -143,7 +161,8 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
if ($_ eq '.') {
$in_options = 0;
} else {
next if /^-$short_no_arg+(e\d*\.\w*)?$/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;
@@ -174,10 +193,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));
}
@@ -204,10 +223,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;
}

15
support/rsync-no-vanished Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
IGNOREEXIT=24
IGNOREOUT='^(file has vanished: |rsync warning: some files vanished before they could be transferred)'
set -o pipefail
rsync "${@}" 2>&1 | (egrep -v "$IGNOREOUT" || true)
ret=$?
if [[ $ret == $IGNOREEXIT ]]; then
ret=0
fi
exit $ret

17
support/rsync-slash-strip Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
# This script can be used as an rsync command-line filter that strips a single
# trailing slash from each arg. That treats "src/" the same as "src", thus
# you need to use "src/." or "src//" for just the contents of the "src" dir.
# (Note that command-line dir-excludes would need to use "excl//" too.)
#
# To use this, name it something like "rs", put it somewhere in your path, and
# then use "rs" in place of "rsync" when you are typing your copy commands.
args=()
for arg in "${@}"; do
if [[ "$arg" == / ]]; then
args=("${args[@]}" /)
else
args=("${args[@]}" "${arg%/}")
fi
done
exec /usr/bin/rsync "${args[@]}"

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