Compare commits

...

170 Commits

Author SHA1 Message Date
Wayne Davison
2dfe1c37ad Preparing for release of 2.6.5 2005-06-02 03:57:58 +00:00
Wayne Davison
b9949780f4 Improved a few of the items. 2005-06-02 03:54:00 +00:00
Wayne Davison
5fe857d4be One more configure item. 2005-06-01 16:21:41 +00:00
Wayne Davison
3d86c6b18f Mention HAVE_REMSH fix. 2005-05-31 06:09:42 +00:00
Wayne Davison
0f0b2e66b8 Simplified the last change a bit. 2005-05-27 18:15:18 +00:00
Wayne Davison
5d24ee71ad Test for various past problems with --relative. 2005-05-27 18:09:34 +00:00
Wayne Davison
3a05c5d3ce If we unduplicate '.', make sure we also copy FLAG_DEL_HERE (in
addition to FLAG_TOP_DIR), so that the unduplication of a real
dir and an implied dir (implied by --relative) works right.
2005-05-27 18:04:04 +00:00
Wayne Davison
89ec535af5 - Only define HAVE_REMSH if it is going to have a non-0 value.
- Got rid of ssh warning that was added for 2.6.0.
2005-05-27 16:41:19 +00:00
Wayne Davison
e96d7972c4 Improved the opening comment. 2005-05-26 18:00:09 +00:00
Wayne Davison
962a3f0b6e Mention the latest bug-fix. 2005-05-25 15:52:03 +00:00
Wayne Davison
cbb5fa4f07 Handle nested "." dirs (caused by --relative and a trailing slash or
a trailing "/.") in f_name_cmp() when dirname is not an identical
pointer.
2005-05-25 01:24:01 +00:00
Wayne Davison
b57907efb2 Mention the output change for a mount-dir when -x is used. 2005-05-22 20:53:18 +00:00
Wayne Davison
26beb7861f - Don't stop deleting in a dir if one item fails.
- Don't skip deleting in a dir if the initial rmdir fails
  (2.6.4 only continued if it was a non-empty error).
2005-05-22 20:52:32 +00:00
Wayne Davison
6e8b9f1341 Must check FLAG_MOUNT_POINT in delete_in_dir() to avoid starting a
descent into a mounted directory when -x is specified.
2005-05-22 17:19:16 +00:00
Wayne Davison
6efe94167f Improved the SYMBOLIC LINKS section, as suggested by John. 2005-05-20 17:57:31 +00:00
Wayne Davison
51cc96e469 Improved a --files-from example (as suggested by Paul). 2005-05-20 17:39:10 +00:00
Wayne Davison
bdedced84b Tweaked a sentence. 2005-05-19 22:16:50 +00:00
Wayne Davison
f497ad722d Preparing for release of 2.6.5pre2 2005-05-19 21:45:41 +00:00
Wayne Davison
339eb8943e Tweaked the opening comments. 2005-05-19 21:42:20 +00:00
Wayne Davison
c36864e40e Mentioned the improved keep-alive code. 2005-05-19 21:38:25 +00:00
Wayne Davison
af6155bb0e Clarifications related to --dirs. 2005-05-19 21:36:30 +00:00
Wayne Davison
605fed4b46 Periodically call maybe_send_keepalive() when timeouts are in effect
(this ensures that the receiver doesn't timeout when we're still
doing work reading data from the generator).
2005-05-19 08:52:24 +00:00
Wayne Davison
ac40b74788 The global allowed_lull is now already set, so just set lull_mod. 2005-05-19 08:52:22 +00:00
Wayne Davison
3e6ddb3738 - Call the new set_io_timeout() function to set the timeout value.
- If the user specified a shorter timeout than the config-file,
  don't override the shorter value.
2005-05-19 08:52:19 +00:00
Wayne Davison
9ac756c6ea - The variable allowed_lull is now our global.
- Tweaked the --timeout option handling to call set_io_timeout().
2005-05-19 08:52:17 +00:00
Wayne Davison
3b0a30eba8 - Added set_io_timeout(), which sets all the timeout-dependent
variables when the timeout value changes.
- Split last_io into last_io_in and last_io_out.
- Made select_timeout static.
2005-05-19 08:52:13 +00:00
Wayne Davison
bac7259081 The latest bug-fix. 2005-05-19 00:02:29 +00:00
Wayne Davison
4d474ad513 One place that was testing errno for ENOTEMPTY was failing to
also test for EEXIST (which is returned by some OSes).
2005-05-19 00:00:28 +00:00
Wayne Davison
e50e82ab40 Fixed a typo. 2005-05-18 23:59:12 +00:00
Wayne Davison
4922175589 Two more items. 2005-05-17 15:08:05 +00:00
Wayne Davison
a289f89fbe Treat a trailing ".." dir-name as if "../" had been specified so
that we don't use the name in the destination path and save files
into a higher destination directory.
2005-05-14 18:44:57 +00:00
Wayne Davison
ba64001df8 Mention the latest bug fix. 2005-05-13 23:03:00 +00:00
Wayne Davison
b225b089b8 Have do_delete_pass() immediately return if list_only is set. 2005-05-13 23:00:20 +00:00
Wayne Davison
557a35f55b If adding a trailing dot to a directory name overflows
MAXPATHLEN, die with an overflow error.
2005-05-13 22:02:24 +00:00
Wayne Davison
1848fd6fa1 An example filter script to maintain .cvsinclude files. 2005-05-13 18:37:11 +00:00
Wayne Davison
f2a4853c93 Improved the use of the "remaining" var in readfd_unbuffered() to
make certain that the static value is always set correctly anytime
we call out to another function.
2005-05-12 17:36:29 +00:00
Wayne Davison
e65154085c Got rid of some code from writefd_unbuffered() that was only needed
back when the generator had a writeable pipe to the receiver.
2005-05-12 07:45:21 +00:00
Wayne Davison
e4676bb59b Make the --stats output come out after any delete-after messages. 2005-05-12 07:43:14 +00:00
Wayne Davison
3b968014c9 Improved a few sentences. 2005-05-12 07:34:45 +00:00
Wayne Davison
21b9b93377 Fixed a typo. 2005-05-10 18:31:46 +00:00
Wayne Davison
c4d1b2983d Preparing for release of 2.6.5pre1 2005-05-10 17:28:34 +00:00
Wayne Davison
7d7a34aeb2 Added more missing NEWS items. 2005-05-10 17:27:39 +00:00
Wayne Davison
65c84700fc Mention two more changes. 2005-05-10 16:55:22 +00:00
Wayne Davison
5a727522f0 Refer to the rsync daemon as a "daemon", not a "server". This is
to avoid confusion with the server that rsync runs in a normal
remote-shell transfer.
2005-05-10 16:14:26 +00:00
Wayne Davison
1599754727 - Improved the GENERAL section.
- Improved the description of --list-only.
- Added a VERSION section, like the rsyncd.conf manpage.
2005-05-10 16:04:02 +00:00
Wayne Davison
d90338cec6 Refer to the rsync daemon as a "daemon", not a "server". This is
to avoid confusion with the server that rsync runs in a normal
remote-shell transfer.
2005-05-10 16:00:24 +00:00
Wayne Davison
d0e94abb40 Fixed one synopsis line to make the DEST arg optional. 2005-05-09 15:39:24 +00:00
Wayne Davison
d8c4d6de10 Use new MAX_SERVER_ARGS define instead of hard-wired "100". 2005-05-03 17:04:26 +00:00
Wayne Davison
74ba98a51b There was no reason to have MAX_BASIS_DIRS factored into the
length of the argstr[] array.
2005-05-03 17:01:59 +00:00
Wayne Davison
c296031d9f Added MAX_SERVER_ARGS. 2005-05-03 17:00:47 +00:00
Wayne Davison
81c453b16a A few minor doc tweaks. 2005-05-03 16:47:03 +00:00
Wayne Davison
4a34c6f176 - Moved the --version option in the help text.
- Tweaked the --log-format option's description.
- Added a comment.
2005-05-03 16:46:49 +00:00
Wayne Davison
9b3150bd2e Mention the change in error message and exit status when we pull an
empty file list.
2005-05-03 16:45:40 +00:00
Wayne Davison
6f2245c8fa Tweaked the checking of the "limit" in safe_fname(). 2005-05-03 16:44:47 +00:00
Wayne Davison
0f9941dc5a Fixed a typo. 2005-05-03 16:03:31 +00:00
Wayne Davison
060f31500b - Improved the comments on the backslash-escaped output, and moved it
to the top in an "OUTPUT CHANGES" section.
- Added a mention of the generator's new output-flushing optimization.
2005-05-03 15:59:24 +00:00
Wayne Davison
7c2a83c635 Improved a sentence. 2005-05-03 15:58:06 +00:00
Wayne Davison
97e3c50cd9 Mention the '?'-in-filenames change. 2005-05-02 18:04:32 +00:00
Wayne Davison
b2360dabf6 Fixed some misspellings. 2005-05-02 17:27:20 +00:00
Wayne Davison
723160280f Tweaked the description of --from0. 2005-05-02 17:23:08 +00:00
Wayne Davison
fa92818af3 Tweaked the doc for --from0. 2005-05-02 17:22:42 +00:00
Wayne Davison
289a32167c Moved the max-size checking code down so that it only checks
regular files.
2005-04-28 16:26:23 +00:00
Wayne Davison
95e107db96 Moved the size-parsing code for --max-size into its own function. 2005-04-28 16:11:32 +00:00
Wayne Davison
513fd04d21 Set ignore_timeout before starting the transfer, regardless of
what protocol level is in effect.  This guards against the
generator timing out when the output pipe is full and the input
pipe (to the receiver) is slow.
2005-04-27 22:58:06 +00:00
Wayne Davison
7a16e12207 If the user specified --relative and a source dir with a trailing
slash, make sure we strip of the trailing "/." from the dir's len
(in del_hier_name_len) so that its subdirs get marked with
FLAG_DEL_HERE.
2005-04-27 22:56:47 +00:00
Wayne Davison
de8252f67f Added a new test to check how we interact with --link-dest and
--copy-dest.
2005-04-26 16:25:01 +00:00
Wayne Davison
98e4741463 A slightly better fix than the last one (though it won't make any
difference in how the code behaves due to how it is called).
2005-04-26 16:09:03 +00:00
Wayne Davison
028245a57b Mention newest fix. 2005-04-26 15:25:43 +00:00
Wayne Davison
2765f2e4a7 Fixed problem with -C when we're the sender, the remote is using an
older protocol, and we're not sending the exclude list (i.e. the
user didn't specify --delete or they specified --delete-ignored).
2005-04-26 15:24:40 +00:00
Wayne Davison
79db59d1a7 Try to make rsync's behavior w/o "--perms" a little clearer. 2005-04-25 19:30:29 +00:00
Wayne Davison
c48cff9fbe Fixed two typos. 2005-04-25 19:23:43 +00:00
Wayne Davison
f4b8e829e9 Mention fix for --one-file-system. 2005-04-24 22:35:03 +00:00
Wayne Davison
468d766819 Simplified the last change a little using a fix derived from
Mike Castle's suggestion.
2005-04-24 22:34:20 +00:00
Wayne Davison
f3ab64d3a8 When deleting files, we need to take any local FLAG_MOUNT_POINT
flag-bit and put it into the regular flist's flags for that dir,
and delete_in_dir() now refuses to delete a directory that has
that bit set.
2005-04-24 22:11:26 +00:00
Wayne Davison
a234bca4ef Reject any --remove-* options when read-only, just in case there
are new ones added in the future.
2005-04-24 16:19:16 +00:00
Wayne Davison
42e9c7eb56 Mention the latest fixes. 2005-04-24 00:34:39 +00:00
Wayne Davison
9d19f8a5fe When rsync encountered an empty file list, it behaved differently
when pulling files than when pushing files:  pulling it output a
(mostly) unhelpful error message and then exited with a 0 status,
even when the remote side exited with an error code.  I changed this
to output the normal end summary (when verbose) and to exit with the
status intact (just like when pushing files).
2005-04-23 22:30:08 +00:00
Wayne Davison
24e61cffe3 For those rare individuals without web access, mention how to
send bug reports via email.
2005-04-23 22:17:10 +00:00
Wayne Davison
3556fe5d86 Fixed a problem where a --link-dest hard-link could cause us to
miss out on the hard_link_cluster() call.
2005-04-23 19:46:22 +00:00
Wayne Davison
ee887d98f6 Two more tests:
- Update the hard-linked cluster and copy over the old versions.
- Add a new hard-linked item down in a new subdir to make sure that
  the new file doesn't get handled before the subdir gets created.
2005-04-23 18:20:47 +00:00
Wayne Davison
5c7b1feb4c Added --no-whole-file option to one of the runs. 2005-04-23 18:17:25 +00:00
Wayne Davison
3cd5301f40 - Added a new function, maybe_hard_link(), which now holds the code
(moved from hard_link_cluster()) that checks the inode/dev of an
  existing file and either does nothing (when properly linked), or
  removes the existing file before calling hard_link_one().
- Changed hard_link_check() so that it checks if the master item is
  marked with FINISHED_LINK (in its hlindex int), and if so, it
  finishes the current file by calling maybe_hard_link() (and
  marking it as finished too).  Otherwise it marks the item as
  skipped by setting hlindex to SKIPPED_LINK.
- Fixed the outputting of an error in hard_link_one() so that the
  message is always output when the caller did not request "terse"
  processing.
- Changed hard_link_cluster() so that it marks the master item with
  FINISHED_LINK and then links only the skipped items (marking them
  with FINISHED_LINK too).
2005-04-23 17:48:34 +00:00
Wayne Davison
d8169e6f6b - Call hard_link_check() with its new args.
- Got rid of a duplicate error after the hard_link_one() call.
2005-04-23 17:48:31 +00:00
Wayne Davison
c4833b024e Mention how a module reference doesn't need a trailing slash
to copy its contents.
2005-04-22 17:17:18 +00:00
Wayne Davison
2a5d5a8cc4 If we're outputting a message about the remote file in a
single-file transfer, we need to make sure that the file's
name is the generic-transfer name and not a local name.
2005-04-22 16:45:33 +00:00
Wayne Davison
f7112154e9 Moved "port" and "address" into the global section where they
belong.
2005-04-22 15:19:10 +00:00
Wayne Davison
f83051b2e3 Updated FSF's address and some minor non-license tweaks taken
from the latest GPL file on the web.
2005-04-17 08:25:50 +00:00
Wayne Davison
2e42adb302 Simplified the newly added test so that it should stop sporadically
failing.
2005-04-16 07:34:49 +00:00
Wayne Davison
c09ebb8c04 Call rsync via $RSYNC. 2005-04-15 17:39:35 +00:00
Wayne Davison
042dc7360e Make sure that the $chkdir has the same mtime/etc. as the
$fromdir.
2005-04-15 17:26:27 +00:00
Wayne Davison
7a6e294f7b Added a test that copies a single file with -H specified. 2005-04-15 08:28:02 +00:00
Wayne Davison
97e786c331 - Fixed a potential crash/infinite-loop bug if -H was used
when sending a single file.
- Made a couple variable improvements in link_idev_data().
- Got rid of the non-NULL check of hlink_list in init_hard_links()
  because is enough to just check file->link_u.links these days.
2005-04-15 08:26:58 +00:00
Wayne Davison
8ee6adefe3 Call logfile_close() and logfile_reopen() (tweaked function names). 2005-04-14 16:08:12 +00:00
Wayne Davison
64c37826e4 - Changed log_open() into two functions, logfile_open() and
logfile_reopen().
- Changed log_close() into logfile_close().
- Improved the logic in logit().
2005-04-14 16:08:10 +00:00
Wayne Davison
2e8015e0da Mention that less data is sent over the wire when --only-write-batch
is used and we're pushing files to a remote system.
2005-04-14 01:47:47 +00:00
Wayne Davison
5b6281afcf Got rid of ITEM_DUMMY_BIT. 2005-04-14 01:46:08 +00:00
Wayne Davison
e732fb0c4f - Got rid of the iflag kluge for 2.6.4pre3.
- When we're handling --only-write-batch on the client side, we now
  send all index/header info to the receiver (not just to the batch
  file, like we do with the xfer data) so that the connection cannot
  timeout.
2005-04-14 01:45:47 +00:00
Wayne Davison
b10917a426 Support the reception of a file-transfer header without xfer data
when we're on the server side and --only-write-batch was specified.
2005-04-14 01:42:13 +00:00
Wayne Davison
7ae64260e0 Mention how the daemon handles a failure to open a user-specified
"log file".
2005-04-12 23:09:35 +00:00
Wayne Davison
f97f6bcd3a Mention how we now handle a log-file that the daemon can't open. 2005-04-12 23:06:45 +00:00
Wayne Davison
e86d98cbaa Got rid of RERR_LOG_FAILURE. 2005-04-12 23:04:10 +00:00
Wayne Davison
6afb90778b If we can't open the daemon's log file, fall-back to using
syslog (rather than trying to output an error on stderr,
which would usually be lost, and then exiting).
2005-04-12 23:03:49 +00:00
Wayne Davison
32c7f91a14 A couple improvements for the --only-write-batch section. 2005-04-12 03:55:56 +00:00
Wayne Davison
b28a27e9e9 Mention the latest bug-fix. 2005-04-10 20:08:00 +00:00
Wayne Davison
15164c0aa9 Paul's patch to improve the "not creating new ..." message
for directories.
2005-04-10 19:44:16 +00:00
Wayne Davison
bf011fedfc Made the code a little cleaner by having gen_challenge() return
the challenge string base64-encoded (instead of forcing the caller
to handle this).  Also improved a couple comments.
2005-04-10 17:09:10 +00:00
Wayne Davison
d7d11b7ebd Mention fix for SUPPORT{,_HARD}_LINKS defines. 2005-04-10 07:17:47 +00:00
Wayne Davison
9a929c8f68 - Don't define HAVE_READLINK unless HAVE_READLINK is defined.
- Don't define SUPPORT_HARD_LINKS unless HAVE_LINK is defined.
2005-04-10 06:24:14 +00:00
Wayne Davison
298d8c0a9b Mention the new --only-write-batch=FILE option. 2005-04-09 18:59:59 +00:00
Wayne Davison
a054570942 - Use the new do_xfers variable in place of some dry_run checks
(with appropriate negation).
- If write_batch is < 0, we write out the file-transfer data to
  just the batch file, not the socket.
2005-04-09 18:59:57 +00:00
Wayne Davison
a0009fc30d - Use the new do_xfers variable in place of some dry_run checks
(with appropriate negation).
- If we get a transfer when write_batch is < 0, discard it.
2005-04-09 18:59:55 +00:00
Wayne Davison
beb51aa09e Use the new do_xfers variable in place of some dry_run checks
(with appropriate negation).
2005-04-09 18:59:52 +00:00
Wayne Davison
e8a96e275e - Only do read-/write-batch processing if we're not the server (needed
now that write_batch is no longer forced to 0 for the server).
- If write_batch is < 0, force "dry_run = 1" (but only after we've
  finished any appropriate write-batch file creation).
2005-04-09 18:59:49 +00:00
Wayne Davison
11e758a430 - Added do_xfers variable.
- Handle the new --only-write-batch=FILE option.
2005-04-09 18:59:47 +00:00
Wayne Davison
d630f53e0d Also change --only-write-batch to --read-batch (in addition to
changing --write-batch).
2005-04-09 18:59:44 +00:00
Wayne Davison
5918daf8a4 We no longer force write_batch to 0 for the server. 2005-04-09 18:59:42 +00:00
Wayne Davison
326bb56e40 Document the new --only-write-batch=FILE option. 2005-04-09 18:59:40 +00:00
Wayne Davison
f96154f44c Mention the latest changes. 2005-04-09 18:15:22 +00:00
Wayne Davison
45c5b903eb - Call auth_server() with its new "host" arg.
- Don't log an auth-failed error -- auth_server() now handles that.
2005-04-09 18:11:25 +00:00
Wayne Davison
5037cf3adf - Use the MD4_SUM_LENGTH define in place of some hard-wired values.
- Pass the hostname in to auth_server().
- Generate a unique error for each failure type in auth_server() so
  that the log-file contains why the authorization failed.
- Don't use sscanf() to parse the client's auth-challenge response.
2005-04-09 18:11:23 +00:00
Wayne Davison
180443af42 The "@ERROR" handler in start_inband_exchange() was not returning
the right value.
2005-04-09 16:49:51 +00:00
Wayne Davison
4f3f97fbde Fixed one typo and improved another sentence. 2005-04-08 01:40:57 +00:00
Wayne Davison
664cf3278a Make sure that "- !" or "+ !" aren't interpreted as a list-clearing
token.
2005-04-07 18:06:06 +00:00
Wayne Davison
cd36049cd1 Combine one of the backup tests with --delete-after. 2005-04-07 09:09:17 +00:00
Wayne Davison
c2523a0541 Don't call maybe_flush_socket() quite so often. 2005-04-07 08:32:32 +00:00
Wayne Davison
92739a0aa7 Mention the latest changes. 2005-04-07 08:28:06 +00:00
Wayne Davison
cd908ef4ff Fix a bug with --delete-after combined with --backup. 2005-04-07 08:13:44 +00:00
Wayne Davison
ebd33e0cea Use the new HAVE_LSEEK64 define. 2005-04-06 02:08:21 +00:00
Wayne Davison
5f2c5bf110 Added skipping of mkstemp() on HP-UX. 2005-04-06 02:07:21 +00:00
Wayne Davison
417099fa20 Periodically call maybe_flush_socket(). 2005-04-05 20:08:51 +00:00
Wayne Davison
626bec8e84 - Added maybe_flush_socket() for use by the generator.
- Always maintain the last_io value for the generator.
2005-04-05 20:07:42 +00:00
Wayne Davison
a06e2b7cab When doing a delete pass with do_progress output, get rid of the
temporary output (it used to always be covered up by output in
older versions, but it might be followed by a newline in newer
versions).
2005-04-05 19:51:13 +00:00
Wayne Davison
3ae5367ff2 Document the use of --address in client mode. 2005-04-05 06:00:17 +00:00
Wayne Davison
b4ef0bca47 Allows --address to be used in client mode. 2005-04-05 05:59:49 +00:00
Wayne Davison
4313d6f9c0 Changed the bind_address local variables to be named bind_addr
in order to avoid confusion with the bind_address global.
2005-04-05 05:52:49 +00:00
Wayne Davison
2a0dd9bd70 Make sure that the line buffer in readfd_unbuffered() is large
enough to handle long-filename messages on a system that has a
really short MAXPATHLEN value.  Also, make it large enough to
be able to comment on a MAXPATHLEN filename.
2005-04-04 17:27:56 +00:00
Wayne Davison
3eeac9bc7e In writefd_unbuffered(), make sure that we don't look at the r_fds
variable when we're ignoring msg_fd_in.
2005-04-04 00:48:39 +00:00
Wayne Davison
67de72bd9b Mention fix for --compare-dest. 2005-04-01 18:18:17 +00:00
Wayne Davison
552a218468 Make a local-copy caused by a not-quite-up-to-date --compare-dest
or --link-dest file be output as a 'c' (local change) when itemizing
or as transfered file when not itemizing.
2005-04-01 18:12:22 +00:00
Wayne Davison
d940151496 - Conditionally include <locale.h>.
- Conditionally call setlocale(LC_CTYPE, "").
2005-04-01 17:25:37 +00:00
Wayne Davison
f5c7f4abe7 - Changed version to 2.6.5cvs.
- Look for setlocale(), locale.h, and honor --disable-locale.
2005-04-01 17:25:34 +00:00
Wayne Davison
3ae6c1875d Starting the 2.6.5 news. 2005-04-01 17:25:28 +00:00
Wayne Davison
1ad6a7f611 Moved the 2.6.4 news here. 2005-04-01 17:25:26 +00:00
Wayne Davison
89d26123ff Changed safe_fname() to output \### (octal) to escape non-printable
characters (not ?) and \\ to escape \ itself.
2005-04-01 16:48:54 +00:00
Wayne Davison
46bffd98cb Fix the setting of module_dirlen for a module path of "/".
This fixes a crash in the exclude code when chroot is off.
2005-04-01 00:18:40 +00:00
Wayne Davison
41b84ce012 Don't try to tweak read-only dest-dir permissions in list-only mode. 2005-03-31 23:30:03 +00:00
Wayne Davison
de392f1e5c Preparing for release of 2.6.4 2005-03-31 03:14:34 +00:00
Wayne Davison
0455cd933d - Made the handling of adjacent percents (e.g. "%%b") work like it
did in older versions.
- Added a comment for log_format_has().
2005-03-31 03:01:26 +00:00
Wayne Davison
d9c0051fae In log_formatted(), add the newline to the format string so
that we can call rwrite() instead of rprintf().
2005-03-31 01:09:18 +00:00
Wayne Davison
126e7affb7 Enabled width-sizing for %L. 2005-03-31 00:50:58 +00:00
Wayne Davison
624d6be2a5 Use new log_format_has() function instead of strstr(). 2005-03-31 00:21:15 +00:00
Wayne Davison
16f960feb5 Added log_format_has(). 2005-03-31 00:19:13 +00:00
Wayne Davison
e145d51ba6 Make sure that we can't scan past the end of the format string. 2005-03-30 23:39:00 +00:00
Wayne Davison
dcbae65444 Optimized '%f' a little more. 2005-03-30 20:41:11 +00:00
Wayne Davison
b4bf2b5a7e Allow %i to have a field width. 2005-03-30 20:18:48 +00:00
Wayne Davison
9baed7609c - Allow the infix field width to start with a '-'.
- Apply the field width to all escapes, not just numeric ones.
2005-03-30 19:44:29 +00:00
Wayne Davison
1c2efa1706 Mention the numeric field width now possible in the % escapes. 2005-03-30 19:41:51 +00:00
Wayne Davison
80a24d52d4 Mention that the % escapes can now have a numeric infix. 2005-03-30 19:39:11 +00:00
Wayne Davison
af9f56a09d dropped the "const" from the return value of safe_fname() because
some callers would like to manipulate the string in the buffer.
2005-03-30 19:34:20 +00:00
Wayne Davison
ddd74b67be Allow the escapes in the log-format string to contain a numeric
field width (e.g. %8l %07p).
2005-03-30 18:27:09 +00:00
Wayne Davison
7b558d7f8b Fixed a comment. 2005-03-30 17:31:35 +00:00
Wayne Davison
c87ae64a82 Moved a call to output_summary() up a line. 2005-03-30 16:55:11 +00:00
Wayne Davison
b9f0ca7274 Tweaked a couple sentences. 2005-03-30 16:51:33 +00:00
Wayne Davison
c1759b9fa2 Changed %i to output '>' for a local copy. 2005-03-30 16:35:01 +00:00
Wayne Davison
9c63d83d3d Got rid of a useless extern. 2005-03-30 16:33:41 +00:00
Wayne Davison
1ed91a04fe - Fixed a potential crash if the receiver couldn't open the basis file
and the sender (possibly via a batch) tells us to use basis data.
- Enhanced the batched-update skipping message to indicate what phase
  is being skipped.
2005-03-29 22:05:33 +00:00
Wayne Davison
154cdaaa40 - Warn about missing batched updates the generator wants but the
batch doesn't have.
- Tweaked the "skipping ..." message that is output for already-
  applied batched updates.
2005-03-29 19:49:40 +00:00
Wayne Davison
33c4b445ef Split report() into handle_stats() and output_report() so that (1)
the report happens after all --delete-after activity has ceased when
pulling, and (2) a batch-file created when pushing gets the stats
values written out prior to any end-of-run keep-alive packets.
2005-03-29 11:11:35 +00:00
Wayne Davison
53135fe89a Changed maybe_emit_filelist_progress() and emit_filelist_progress()
to take an integer count instead of a struct file_list so that we
can pass in a file-list-count offset for delete's separate calls
to send_directory().
2005-03-29 10:57:31 +00:00
Wayne Davison
083acd496d Turn off do_progress during the file-update phase so that
--delete-during and --fuzzy don't get any superfluous
" N files..." lines output in the middle of the processing.
2005-03-29 10:41:26 +00:00
35 changed files with 1609 additions and 972 deletions

11
COPYING
View File

@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
Copyright (C) <year> <name of author>
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
@@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

466
NEWS
View File

@@ -1,381 +1,181 @@
NEWS for rsync 2.6.4 (30 March 2005)
Protocol: 29 (changed)
Changes since 2.6.3:
NEWS for rsync 2.6.5 (1 Jun 2005)
Protocol: 29 (unchanged)
Changes since 2.6.4:
OUTPUT CHANGES:
- When rsync deletes a directory and outputs a verbose message about
it, it now appends a trailing slash to the name instead of (only
sometimes) outputting a preceding "directory " string.
- Non-printable chars in filenames are now output using backslash-
escaped characters rather than '?'s. Any non-printable character is
output using 3 digits of octal (e.g. "\n" -> "\012"), and a backslash
is now output as "\\". Rsync also uses your locale setting, which
can make it treat fewer high-bit characters as non-printable.
- The --stats output will contain file-list time-statistics if both
sides are 2.6.4, or if the local side is 2.6.4 and the files are
being pushed (since the stats come from the sending side).
(Requires protocol 29 for a pull.)
- If rsync received an empty file-list when pulling files, it would
output a "nothing to do" message and exit with a 0 (success) exit
status, even if the remote rsync returned an error (it did not do
this under the same conditions when pushing files). This was changed
to make the pulling behavior the same as the pushing behavior: we
now do the normal end-of-run outputting (depending on options) and
exit with the appropriate exit status.
- The "%o" (operation) log-format escape now has a third value (besides
"send" and "recv"): "del." (with trailing dot to make it 4 chars).
This changes the way deletions are logged in the daemon's log file.
- When the --log-format option is combined with --verbose, rsync now
avoids outputting the name of the file twice in most circumstances.
As long as the --log-format item does not refer to any post-transfer
items (such as %b or %c), the --log-format message is output prior to
the transfer, so --verbose is now the equivalent of a --log-format of
'%n%L' (which outputs the name and any link info). If the log output
must occur after the transfer to be complete, the only time the name
is also output prior to the transfer is when --progress was specified
(so that the name will precede the progress stats, and the full
--log-format output will come after).
BUG FIXES:
- Restore the list-clearing behavior of "!" in a .cvsignore file (2.6.3
was only treating it as a special token in an rsync include/exclude
file).
- A crash bug was fixed when a daemon had its "path" set to "/", did
not have chroot enabled, and used some anchored excludes in the
rsyncd.conf file.
- The combination of --verbose and --dry-run now mentions the full list
of changes that would be output without --dry-run.
- Fixed a bug in the transfer of a single file when -H is specified
(rsync would either infinite loop or perhaps crash).
- Avoid a mkdir warning when removing a directory in the destination
that already exists in the --backup-dir.
- Fixed a case where the generator might try (and fail) to tweak the
write-permissions of a read-only directory in list-only mode (this
only caused an annoying warning message).
- An OS that has a binary mode for its files (such as cygwin) needed
setmode(fd, O_BINARY) called on the temp-file we opened with
mkstemp(). (Fix derived from the cygwin's 2.6.3 rsync package.)
- If --compare-dest or --link-dest uses a locally-copied file as the
basis for an updated version, log this better when --verbose or -i
is in effect.
- Fixed a potential hang when verbosity is high, the client side is
the sender, and the file-list is large.
- Fixed the accidental disabling of --backup during the --delete-after
processing.
- Fixed a potential protocol-corrupting bug where the generator could
merge a message from the receiver into the middle of a multiplexed
packet of data if only part of that data had been written out to the
socket when the message from the generator arrived.
- Restored the ability to use the --address option in client mode (in
addition to its use in daemon mode).
- We now check if the OS doesn't support using mknod() for creating
FIFOs and sockets, and compile-in some compatibility code using
mkfifo() and socket() when necessary.
- Make sure that some temporary progress information from the delete
processing does not get left on the screen when it is followed by a
newline.
- Fixed an off-by-one error in the handling of --max-delete=N. Also,
if the --max-delete limit is exceeded during a run, we now output a
warning about this at the end of the run and exit with a new error
code (25).
- When --existing skips a directory with extra verbosity, refer to it
as a "directory", not a "file".
- One place in the code wasn't checking if fork() failed.
- When transferring a single file to a different-named file, any
generator messages that are source-file related no longer refer to
the file by the destination filename.
- The "ignore nonreadable" daemon parameter used to erroneously affect
readable symlinks that pointed to a non-existent file.
- Fixed a bug where hard-linking a group of files might fail if the
generator hasn't created a needed destination directory yet.
- If the OS does not have lchown() and a chown() of a symlink will
affect the referent of a symlink (as it should), we no longer try
to set the user and group of a symlink.
- Fixed a bug where a hard-linked group of files that is newly-linked
to a file in a --link-dest dir doesn't link the files from the rest
of the cluster.
- The generator now properly runs the hard-link loop and the dir-time
rewriting loop after we're sure that the redo phase is complete.
- When deleting files with the --one-file-system (-x) option set, rsync
no longer tries to remove files from inside a mount-point on the
receiving side. Also, we don't complain about being unable to remove
the mount-point dir.
- When --backup was specified with --partial-dir=DIR, where DIR is a
relative path, the backup code was erroneously trying to backup a
file that was put into the partial-dir.
- Fixed a compatibility problem when using --cvs-ignore (-C) and
sending files to an older rsync without using --delete.
- If a file gets resent in a single transfer and the --backup option is
enabled along with --inplace, rsync no longer performs a duplicate
backup (it used to overwrite the first backup with the failed file).
- Make sure that a "- !" or "+ !" include/exclude pattern does not
trigger the list-clearing action that is reserved for "!".
- One call to flush_write_file() was not being checked for an error.
- Avoid a timeout in the generator when the sender/receiver aren't
handling the generator's checksum output quickly enough.
- The --no-relative option was not being sent from the client to a
server sender.
- Fixed the omission of some directories in the delete processing when
--relative (-R) was combined with a source path that had a trailing
slash.
- If an rsync daemon specified "dont compress = ..." for a file and the
client tried to specify --compress, the libz code was not handling a
compression level of 0 properly. This could cause a transfer failure
if the block-size for a file was large enough (e.g. rsync might have
exited with an error for large files).
- Fixed a case where rsync would erroneously delete some files and then
re-transfer them when the options --relative (-R) and --recursive
(-r) were both enabled (along with --delete) and a source path had a
trailing slash.
- Fixed a bug that would sometimes surface when using --compress and
sending a file with a block-size larger than 64K (either manually
specified, or computed due to the file being really large). Prior
versions of rsync would sometimes fail to decompress the data
properly, and thus the transferred file would fail its verification.
- Make sure that --max-size doesn't affect a device or a symlink.
- If a daemon can't open the specified log file (i.e. syslog is not
being used), die without crashing. We also output an error about
the failure on stderr (which will only be seen if --no-detach was
specified) and exit with a new error code (6).
- Make sure that a system with a really small MAXPATHLEN does not cause
the buffers in readfd_unbuffered() to be too small to receive normal
messages. (This mainly affected Cygwin.)
- A local transfer no longer duplicates all its include/exclude options
(since the forked process already has a copy of the exclude list,
there's no need to send them a set of duplicates).
- If a source pathname ends with a filename of "..", treat it as if
"../" had been specified (so that we don't copy files to the parent
dir of the destination).
- When --progress is specified, the output of items that the generator
is creating (e.g. dirs, symlinks) is now integrated into the progress
output without overlapping it. (Requires protocol 29.)
- If --delete is combined with a file-listing rsync command (i.e. no
transfer is happening), avoid outputting a warning that we couldn't
delete anything.
- When --timeout is specified, lulls that occur in the transfer while
the generator is doing work that does not generate socket traffic
(looking for changed files, deleting files, doing directory-time
touch-ups, etc.) will cause a new keep-alive packet to be sent that
should keep the transfer going as long as the generator continues to
make progress. (Requires protocol 29.)
- If --stats is specified with --delete-after, ensure that all the
"deleting" messages are output before the statistics.
- The stat size of a device is not added to the total file size of the
items in the transfer (the size might be undefined on some OSes).
- Fixed a problem with refused-option messages sometimes not making it
back to the client side when a remote --files-from was in effect and
the daemon was the receiver.
- The --compare-dest option was not updating a file that differred in
(the preserved) attributes from the version in the compare-dest DIR.
- When rsync is copying files into a write-protected directory, fixed
the change-report output for the directory so that we don't report
an identical directory as changed.
- Improved one "if" in the deletion code that was only checking errno
for ENOTEMPTY when it should have also been checking for EEXIST (for
compatibility with OS variations).
ENHANCEMENTS:
- Rsync now supports popt's option aliases, which means that you can
use /etc/popt and/or ~/.popt to create your own option aliases.
- Added the --only-write-batch=FILE option that may be used (instead
of --write-batch=FILE) to create a batch file without doing any
actual updating of the destination. This allows you to divert all
the file-updating data away from a slow data link (as long as you
are pushing the data to the remote server when creating the batch).
- Added the --delete-during (--del) option which will delete files
from the receiving side incrementally as each directory in the
transfer is being processed. This makes it more efficient than the
default, before-the-transfer behavior, which is now also available as
--delete-before (and is still the default --delete-WHEN option that
will be chosen if --delete or --delete-excluded is specified without
a --delete-WHEN choice). All the --del* options infer --delete, so
an rsync daemon that refuses "delete" will still refuse to allow any
file-deleting options (including the new --remove-sent-files option).
- When the generator is taking a long time to fill up its output buffer
(e.g. if the transferred files are few, small, or missing), it now
periodically flushes the output buffer so that the sender/receiver
can get started on the files sooner rather than later.
- All the --delete-WHEN options are now more memory efficient:
Previously an duplicate set of file-list objects was created on the
receiving side for the entire destination hierarchy. The new
algorithm only creates one directory of objects at a time (for files
inside the transfer).
- Improved the keep-alive code to handle a long silence between the
sender and the receiver that can occur when the sender is receiving
the checksum data for a large file.
- Added the --copy-dest option, which works like --link-dest except
that it locally copies identical files instead of hard-linking them.
- Improved the auth-errors that are logged by the daemon to include
some information on why the authorization failed: wrong user,
password mismatch, etc. (The client-visible message is unchanged!)
- Added support for specifying multiple --compare-dest, --copy-dest, or
--link-dest options, but only of a single type. (Promoted from the
patches dir and enhanced.) (Requires protocol 29.)
- Improved the client's handling of an "@ERROR" from a daemon so that
it does not complain about an unexpectedly closed socket (since we
really did expect the socket to close).
- Added the --max-size option. (Promoted from the patches dir.)
- If the daemon can't open the log-file specified in rsyncd.conf, fall
back to using syslog and log an appropriate warning. This is better
than what was typically a totally silent (and fatal) failure (since a
daemon is not usually run with the --no-detach option that was
necessary to see the error on stderr).
- The daemon-mode options are now separated from the normal rsync
options so that they can't be mixed together. This makes it
impossible to start a daemon that has improper default option values
(which could cause problems when a client connects, such as hanging
or crashing).
- The man pages now consistently refer to an rsync daemon as a "daemon"
instead of a "server" (to distinguish it from the server process in a
non-daemon transfer).
- The --bwlimit option may now be used in combination with --daemon
to specify both a default value for the daemon side and a value
that cannot be exceeded by a user-specified --bwlimit option.
- Added the "port" parameter to the rsyncd.conf file. (Promoted from
the patches dir.) Also added "address". The command-line options
take precedence over a config-file option, as expected.
- In _exit_cleanup(): when we are exiting with a partially-received
file, we now flush any data in the write-cache before closing the
partial file.
- The --inplace support was enhanced to work with --compare-dest,
--link-dest, and (the new) --copy-dest options. (Requires protocol
29.)
- Added the --dirs (-d) option for an easier way to copy directories
without recursion.
- Added the --list-only option, which is mainly a way for the client to
put the server into listing mode without needing to resort to any
internal option kluges (e.g. the age-old use of "-r --exclude="/*/*"
for a non-recursive listing). This option is used automatically
(behind the scenes) when a modern rsync speaks to a modern daemon,
but may also be specified manually if you want to force the use of
the --list-only option over a remote-shell connection.
- Added the --omit-dir-times (-O) option, which will avoid updating
the modified time for directories when --times was specified. This
option will avoid an extra pass through the file-list at the end of
the transfer (to tweak all the directory times), which may provide
an appreciable speedup for a really large transfer. (Promoted from
the patches dir.)
- Added the --filter (-f) option and its helper option, -F. Filter
rules are an extension to the existing include/exclude handling
that also supports nested filter files as well as per-directory
filter files (like .cvsignore, but with full filter-rule parsing).
This new option was chosen in order to ensure that all existing
include/exclude processing remained 100% compatible with older
versions. Protocol 29 is needed for full filter-rule support, but
backward-compatible rules work with earlier protocol versions.
(Promoted from the patches dir and enhanced.)
- Added the --delay-updates option that puts all updated files into
a temporary directory (by default ".~tmp~", but settable via the
--partial-dir=DIR option) until the end of the transfer. This
makes the updates a little more atomic for a large transfer.
- If rsync is put into the background, any output from --progress is
reduced.
- Documented the "max verbosity" setting for rsyncd.conf. (This
setting was added a couple releases ago, but left undocumented.)
- The sender and the generator now double-check the file-list index
they are given, and refuse to try to do a file transfer on a
non-file index (since that would indicate that something had gone
very wrong).
- Added the --itemize-changes (-i) option, which is a way to output a
more detailed list of what files changed and in what way. The effect
is the same as specifying a --log-format of "%i %n%L" (see both the
rsync and rsyncd.conf manpages). Works with --dry-run too.
- Added the --fuzzy (-y) option, which attempts to find a basis file
for a file that is being created from scratch. The current algorithm
only looks in the destination directory for the created file, but it
does attempt to find a match based on size/mod-time (in case the file
was renamed with no other changes) as well as based on a fuzzy
name-matching algorithm. This option requires protocol 29 because it
needs the new file-sorting order. (Promoted from patches dir and
enhanced.) (Requires protocol 29.)
- Added the --remove-sent-files option, which lets you move files
between systems.
- The hostname in HOST:PATH or HOST::PATH may now be an IPv6 literal
enclosed in '[' and ']' (e.g. "[::1]"). (We already allowed IPv6
literals in the rsync://HOST:PORT/PATH format.)
- When rsync recurses to build the file list, it no longer keeps open
one or more directory handles from the dir's parent dirs.
- When building under windows, the default for --daemon is now to
avoid detaching, requiring the new --detach option to force rsync
to detach.
- The --dry-run option can now be combined with either --write-batch or
--read-batch, allowing you to run a do-nothing test command to see
what would happen without --dry-run.
- The daemon's "read only" config item now sets an internal read_only
variable that makes extra sure that no write/delete calls on the
read-only side can succeed.
- Improved the option descriptions in the --help text.
SUPPORT FILES:
- Added atomic-rsync to the support dir: a perl script that will
transfer some files using rsync, and then move the updated files into
place all at once at the end of the transfer. Only works when
pulling, and uses --link-dest and a parallel hierarchy of files to
effect its update.
- Added mnt-excl to the support dir: a perl script that takes the
/proc/mounts file and translates it into a set of excludes that will
exclude all mount points (even mapped mounts to the same disk). The
excludes are made relative to the specified source dir and properly
anchored.
- Added savetransfer.c to the support dir: a C program that can make
a copy of all the data that flows over the wire. This lets you test
for data corruption (by saving the data on both the sending side and
the receiving side) and provides one way to debug a protocol error.
- Added rrsync to the support dir: this is an updated version of Joe
Smith's restricted rsync perl script. This helps to ensure that only
certain rsync commands can be run by an ssh invocation.
- Made a small change to the rrsync script (restricted rsync -- in the
support dir) to make a read-only server reject all --remove-* options
when sending files (to future-proof it against the possibility of
other similar options being added at some point).
INTERNAL:
- Added better checking of the checksum-header values that come over
the socket.
- Rsync now calls setlocale(LC_CTYPE, ""). This enables isprint() to
better discern which filename characters need to be escaped in
messages (which should result in fewer escaped characters in some
locales).
- Merged a variety of file-deleting functions into a single function so
that it is easier to maintain.
- Improved the naming of the log-file open/reopen/close functions.
- Improved the type of some variables (particularly blocksize vars) for
consistency and proper size.
- Got rid of the uint64 type (which we didn't need).
- Use a slightly more compatible set of core #include directives.
- Defined int32 in a way that ensures that the build dies if we can't
find a variable with at least 32 bits.
PROTOCOL DIFFERENCES FOR VERSION 29:
- A 16-bit flag-word is transmitted after every file-list index. This
indicates what is changing between the sender and the receiver. The
generator now transmits an index and a flag-word to indicate when
dirs and symlinks have changed (instead of producing a message),
which makes the outputting of the information more consistent and
less prone to screen corruption (because the local receiver/sender is
now outputting all the file-change info messages).
- If a file is being hard-linked, the ITEM_XNAME_FOLLOWS bit is enabled
in the flag-word and the name of the file that was linked immediately
follows in vstring format (see below).
- If a file is being transferred with an alternate-basis file, the
ITEM_BASIS_TYPE_FOLLOWS bit is enabled in the flag-word and a single
byte follows, indicating what type of basis file was chosen. If that
indicates that a fuzzy-match was selected, the ITEM_XNAME_FOLLOWS bit
is set in the flag-word and the name of the match in vstring format
follows the basis byte. A vstring is a variable length string that
has its size written prior to the string, and no terminating null.
If the string is from 1-127 bytes, the length is a single byte. If
it is from 128-32767 bytes, the length is written as ((len >> 8) |
0x80) followed by (len % 0x100).
- The sending of exclude names is done using filter-rule syntax. This
means that all names have a prefixed rule indicator, even excludes
(which used to be sent as a bare pattern, when possible). The -C
option will include the per-dir .cvsignore merge file in the list of
filter rules so it is positioned correctly (unlike in some older
transfer scenarios).
- Rsync sorts the filename list in a different way: it sorts the subdir
names after the non-subdir names for each dir's contents, and it
always puts a dir's contents immediately after the dir's name in the
list. (Previously an item named "foo.txt" would sort in between
directory "foo/" and "foo/bar".)
- When talking to a protocol 29 rsync daemon, a list-only request
is able to note this before the options are sent over the wire and
the new --list-only option is included in the options.
- When the --stats bytes are sent over the wire (or stored in a batch),
they now include two elapsed-time values: one for how long it took to
build the file-list, and one for how long it took to send it over the
wire (each expressed in thousandths of a second).
- When --delete-excluded is specified with some filter rules (AKA
excludes), a client sender will now initiate a send of the rules to
the receiver (older protocols used to omit the sending of excludes in
this situation since there were no receiver-specific rules that
survived --delete-excluded back then). Note that, as with all the
filter-list sending, only items that are significant to the other
side will actually be sent over the wire, so the filter-rule list
that is sent in this scenario is often empty.
- An index equal to the file-list count is sent as a keep-alive packet
from the generator to the sender, which then forwards it on to the
receiver. This normally invalid index is only a valid keep-alive
packet if the 16-bit flag-word that follows it contains a single bit
(ITEM_IS_NEW, which is normally an illegal flag to appear alone).
- A protocol-29 batch file includes a bit for the setting of the --dirs
option and for the setting of the --compress option. Also, the shell
script created by --write-batch will use the --filter option instead
of --exclude-from to capture any filter rules.
- Removed some protocol-compatibility code that was only needed to help
someone running a pre-release of 2.6.4.
BUILD CHANGES:
- Handle an operating system that use mkdev() in place of makedev().
- Added configure option "--disable-locale" to disable any use of
setlocale() in the binary.
- Improved configure to better handle cross-compiling.
- Fixed a bug in the SUPPORT{,_HARD}_LINKS #defines which prevented
rsync from being built without symlink or hard-link support.
- Only #define HAVE_REMSH if it is going to be set to 1.
- Configure now disables the use of mkstemp() under HP-UX (since they
refuse to fix its broken handling of large files).
- Configure now explicitly checks for the lseek64() function so that
the code can use HAVE_LSEEK64 instead of inferring lseek64()'s
presence based on the presence of the off64_t type.
- Configure no longer mentions the change in the default remote-shell
(from rsh to ssh) that occurred for the 2.6.0 release.
- Some minor enhancements to the test scripts.
- Added a few new *.diff files to the patches dir, including a patch
that enables the optional copying of extended attributes.

392
OLDNEWS
View File

@@ -1,3 +1,394 @@
NEWS for rsync 2.6.4 (30 March 2005)
Protocol: 29 (changed)
Changes since 2.6.3:
OUTPUT CHANGES:
- When rsync deletes a directory and outputs a verbose message about
it, it now appends a trailing slash to the name instead of (only
sometimes) outputting a preceding "directory " string.
- The --stats output will contain file-list time-statistics if both
sides are 2.6.4, or if the local side is 2.6.4 and the files are
being pushed (since the stats come from the sending side).
(Requires protocol 29 for a pull.)
- The "%o" (operation) log-format escape now has a third value (besides
"send" and "recv"): "del." (with trailing dot to make it 4 chars).
This changes the way deletions are logged in the daemon's log file.
- When the --log-format option is combined with --verbose, rsync now
avoids outputting the name of the file twice in most circumstances.
As long as the --log-format item does not refer to any post-transfer
items (such as %b or %c), the --log-format message is output prior to
the transfer, so --verbose is now the equivalent of a --log-format of
'%n%L' (which outputs the name and any link info). If the log output
must occur after the transfer to be complete, the only time the name
is also output prior to the transfer is when --progress was specified
(so that the name will precede the progress stats, and the full
--log-format output will come after).
- Non-printable characters in filenames are replaced with a '?' to
avoid corrupting the screen or generating empty lines in the output.
BUG FIXES:
- Restore the list-clearing behavior of "!" in a .cvsignore file (2.6.3
was only treating it as a special token in an rsync include/exclude
file).
- The combination of --verbose and --dry-run now mentions the full list
of changes that would be output without --dry-run.
- Avoid a mkdir warning when removing a directory in the destination
that already exists in the --backup-dir.
- An OS that has a binary mode for its files (such as cygwin) needed
setmode(fd, O_BINARY) called on the temp-file we opened with
mkstemp(). (Fix derived from the cygwin's 2.6.3 rsync package.)
- Fixed a potential hang when verbosity is high, the client side is
the sender, and the file-list is large.
- Fixed a potential protocol-corrupting bug where the generator could
merge a message from the receiver into the middle of a multiplexed
packet of data if only part of that data had been written out to the
socket when the message from the generator arrived.
- We now check if the OS doesn't support using mknod() for creating
FIFOs and sockets, and compile-in some compatibility code using
mkfifo() and socket() when necessary.
- Fixed an off-by-one error in the handling of --max-delete=N. Also,
if the --max-delete limit is exceeded during a run, we now output a
warning about this at the end of the run and exit with a new error
code (25).
- One place in the code wasn't checking if fork() failed.
- The "ignore nonreadable" daemon parameter used to erroneously affect
readable symlinks that pointed to a non-existent file.
- If the OS does not have lchown() and a chown() of a symlink will
affect the referent of a symlink (as it should), we no longer try
to set the user and group of a symlink.
- The generator now properly runs the hard-link loop and the dir-time
rewriting loop after we're sure that the redo phase is complete.
- When --backup was specified with --partial-dir=DIR, where DIR is a
relative path, the backup code was erroneously trying to backup a
file that was put into the partial-dir.
- If a file gets resent in a single transfer and the --backup option is
enabled along with --inplace, rsync no longer performs a duplicate
backup (it used to overwrite the first backup with the failed file).
- One call to flush_write_file() was not being checked for an error.
- The --no-relative option was not being sent from the client to a
server sender.
- If an rsync daemon specified "dont compress = ..." for a file and the
client tried to specify --compress, the libz code was not handling a
compression level of 0 properly. This could cause a transfer failure
if the block-size for a file was large enough (e.g. rsync might have
exited with an error for large files).
- Fixed a bug that would sometimes surface when using --compress and
sending a file with a block-size larger than 64K (either manually
specified, or computed due to the file being really large). Prior
versions of rsync would sometimes fail to decompress the data
properly, and thus the transferred file would fail its verification.
- If a daemon can't open the specified log file (i.e. syslog is not
being used), die without crashing. We also output an error about
the failure on stderr (which will only be seen if --no-detach was
specified) and exit with a new error code (6).
- A local transfer no longer duplicates all its include/exclude options
(since the forked process already has a copy of the exclude list,
there's no need to send them a set of duplicates).
- When --progress is specified, the output of items that the generator
is creating (e.g. dirs, symlinks) is now integrated into the progress
output without overlapping it. (Requires protocol 29.)
- When --timeout is specified, lulls that occur in the transfer while
the generator is doing work that does not generate socket traffic
(looking for changed files, deleting files, doing directory-time
touch-ups, etc.) will cause a new keep-alive packet to be sent that
should keep the transfer going as long as the generator continues to
make progress. (Requires protocol 29.)
- The stat size of a device is not added to the total file size of the
items in the transfer (the size might be undefined on some OSes).
- Fixed a problem with refused-option messages sometimes not making it
back to the client side when a remote --files-from was in effect and
the daemon was the receiver.
- The --compare-dest option was not updating a file that differed in
(the preserved) attributes from the version in the compare-dest DIR.
- When rsync is copying files into a write-protected directory, fixed
the change-report output for the directory so that we don't report
an identical directory as changed.
ENHANCEMENTS:
- Rsync now supports popt's option aliases, which means that you can
use /etc/popt and/or ~/.popt to create your own option aliases.
- Added the --delete-during (--del) option which will delete files
from the receiving side incrementally as each directory in the
transfer is being processed. This makes it more efficient than the
default, before-the-transfer behavior, which is now also available as
--delete-before (and is still the default --delete-WHEN option that
will be chosen if --delete or --delete-excluded is specified without
a --delete-WHEN choice). All the --del* options infer --delete, so
an rsync daemon that refuses "delete" will still refuse to allow any
file-deleting options (including the new --remove-sent-files option).
- All the --delete-WHEN options are now more memory efficient:
Previously an duplicate set of file-list objects was created on the
receiving side for the entire destination hierarchy. The new
algorithm only creates one directory of objects at a time (for files
inside the transfer).
- Added the --copy-dest option, which works like --link-dest except
that it locally copies identical files instead of hard-linking them.
- Added support for specifying multiple --compare-dest, --copy-dest, or
--link-dest options, but only of a single type. (Promoted from the
patches dir and enhanced.) (Requires protocol 29.)
- Added the --max-size option. (Promoted from the patches dir.)
- The daemon-mode options are now separated from the normal rsync
options so that they can't be mixed together. This makes it
impossible to start a daemon that has improper default option values
(which could cause problems when a client connects, such as hanging
or crashing).
- The --bwlimit option may now be used in combination with --daemon
to specify both a default value for the daemon side and a value
that cannot be exceeded by a user-specified --bwlimit option.
- Added the "port" parameter to the rsyncd.conf file. (Promoted from
the patches dir.) Also added "address". The command-line options
take precedence over a config-file option, as expected.
- In _exit_cleanup(): when we are exiting with a partially-received
file, we now flush any data in the write-cache before closing the
partial file.
- The --inplace support was enhanced to work with --compare-dest,
--link-dest, and (the new) --copy-dest options. (Requires protocol
29.)
- Added the --dirs (-d) option for an easier way to copy directories
without recursion. Any directories that are encountered are created
on the destination. Specifying a directory with a trailing slash
copies its immediate contents to the destination.
- The --files-from option now implies --dirs (-d).
- Added the --list-only option, which is mainly a way for the client to
put the server into listing mode without needing to resort to any
internal option kluges (e.g. the age-old use of "-r --exclude="/*/*"
for a non-recursive listing). This option is used automatically
(behind the scenes) when a modern rsync speaks to a modern daemon,
but may also be specified manually if you want to force the use of
the --list-only option over a remote-shell connection.
- Added the --omit-dir-times (-O) option, which will avoid updating
the modified time for directories when --times was specified. This
option will avoid an extra pass through the file-list at the end of
the transfer (to tweak all the directory times), which may provide
an appreciable speedup for a really large transfer. (Promoted from
the patches dir.)
- Added the --filter (-f) option and its helper option, -F. Filter
rules are an extension to the existing include/exclude handling
that also supports nested filter files as well as per-directory
filter files (like .cvsignore, but with full filter-rule parsing).
This new option was chosen in order to ensure that all existing
include/exclude processing remained 100% compatible with older
versions. Protocol 29 is needed for full filter-rule support, but
backward-compatible rules work with earlier protocol versions.
(Promoted from the patches dir and enhanced.)
- Added the --delay-updates option that puts all updated files into
a temporary directory (by default ".~tmp~", but settable via the
--partial-dir=DIR option) until the end of the transfer. This
makes the updates a little more atomic for a large transfer.
- If rsync is put into the background, any output from --progress is
reduced.
- Documented the "max verbosity" setting for rsyncd.conf. (This
setting was added a couple releases ago, but left undocumented.)
- The sender and the generator now double-check the file-list index
they are given, and refuse to try to do a file transfer on a
non-file index (since that would indicate that something had gone
very wrong).
- Added the --itemize-changes (-i) option, which is a way to output a
more detailed list of what files changed and in what way. The effect
is the same as specifying a --log-format of "%i %n%L" (see both the
rsync and rsyncd.conf manpages). Works with --dry-run too.
- Added the --fuzzy (-y) option, which attempts to find a basis file
for a file that is being created from scratch. The current algorithm
only looks in the destination directory for the created file, but it
does attempt to find a match based on size/mod-time (in case the file
was renamed with no other changes) as well as based on a fuzzy
name-matching algorithm. This option requires protocol 29 because it
needs the new file-sorting order. (Promoted from patches dir and
enhanced.) (Requires protocol 29.)
- Added the --remove-sent-files option, which lets you move files
between systems.
- The hostname in HOST:PATH or HOST::PATH may now be an IPv6 literal
enclosed in '[' and ']' (e.g. "[::1]"). (We already allowed IPv6
literals in the rsync://HOST:PORT/PATH format.)
- When rsync recurses to build the file list, it no longer keeps open
one or more directory handles from the dir's parent dirs.
- When building under windows, the default for --daemon is now to
avoid detaching, requiring the new --detach option to force rsync
to detach.
- The --dry-run option can now be combined with either --write-batch or
--read-batch, allowing you to run a do-nothing test command to see
what would happen without --dry-run.
- The daemon's "read only" config item now sets an internal read_only
variable that makes extra sure that no write/delete calls on the
read-only side can succeed.
- The log-format % escapes can now have a numeric field width in
between the % and the escape letter (e.g. "%-40n %08p").
- Improved the option descriptions in the --help text.
SUPPORT FILES:
- Added atomic-rsync to the support dir: a perl script that will
transfer some files using rsync, and then move the updated files into
place all at once at the end of the transfer. Only works when
pulling, and uses --link-dest and a parallel hierarchy of files to
effect its update.
- Added mnt-excl to the support dir: a perl script that takes the
/proc/mounts file and translates it into a set of excludes that will
exclude all mount points (even mapped mounts to the same disk). The
excludes are made relative to the specified source dir and properly
anchored.
- Added savetransfer.c to the support dir: a C program that can make
a copy of all the data that flows over the wire. This lets you test
for data corruption (by saving the data on both the sending side and
the receiving side) and provides one way to debug a protocol error.
- Added rrsync to the support dir: this is an updated version of Joe
Smith's restricted rsync perl script. This helps to ensure that only
certain rsync commands can be run by an ssh invocation.
INTERNAL:
- Added better checking of the checksum-header values that come over
the socket.
- Merged a variety of file-deleting functions into a single function so
that it is easier to maintain.
- Improved the type of some variables (particularly blocksize vars) for
consistency and proper size.
- Got rid of the uint64 type (which we didn't need).
- Use a slightly more compatible set of core #include directives.
- Defined int32 in a way that ensures that the build dies if we can't
find a variable with at least 32 bits.
PROTOCOL DIFFERENCES FOR VERSION 29:
- A 16-bit flag-word is transmitted after every file-list index. This
indicates what is changing between the sender and the receiver. The
generator now transmits an index and a flag-word to indicate when
dirs and symlinks have changed (instead of producing a message),
which makes the outputting of the information more consistent and
less prone to screen corruption (because the local receiver/sender is
now outputting all the file-change info messages).
- If a file is being hard-linked, the ITEM_XNAME_FOLLOWS bit is enabled
in the flag-word and the name of the file that was linked immediately
follows in vstring format (see below).
- If a file is being transferred with an alternate-basis file, the
ITEM_BASIS_TYPE_FOLLOWS bit is enabled in the flag-word and a single
byte follows, indicating what type of basis file was chosen. If that
indicates that a fuzzy-match was selected, the ITEM_XNAME_FOLLOWS bit
is set in the flag-word and the name of the match in vstring format
follows the basis byte. A vstring is a variable length string that
has its size written prior to the string, and no terminating null.
If the string is from 1-127 bytes, the length is a single byte. If
it is from 128-32767 bytes, the length is written as ((len >> 8) |
0x80) followed by (len % 0x100).
- The sending of exclude names is done using filter-rule syntax. This
means that all names have a prefixed rule indicator, even excludes
(which used to be sent as a bare pattern, when possible). The -C
option will include the per-dir .cvsignore merge file in the list of
filter rules so it is positioned correctly (unlike in some older
transfer scenarios).
- Rsync sorts the filename list in a different way: it sorts the subdir
names after the non-subdir names for each dir's contents, and it
always puts a dir's contents immediately after the dir's name in the
list. (Previously an item named "foo.txt" would sort in between
directory "foo/" and "foo/bar".)
- When talking to a protocol 29 rsync daemon, a list-only request
is able to note this before the options are sent over the wire and
the new --list-only option is included in the options.
- When the --stats bytes are sent over the wire (or stored in a batch),
they now include two elapsed-time values: one for how long it took to
build the file-list, and one for how long it took to send it over the
wire (each expressed in thousandths of a second).
- When --delete-excluded is specified with some filter rules (AKA
excludes), a client sender will now initiate a send of the rules to
the receiver (older protocols used to omit the sending of excludes in
this situation since there were no receiver-specific rules that
survived --delete-excluded back then). Note that, as with all the
filter-list sending, only items that are significant to the other
side will actually be sent over the wire, so the filter-rule list
that is sent in this scenario is often empty.
- An index equal to the file-list count is sent as a keep-alive packet
from the generator to the sender, which then forwards it on to the
receiver. This normally invalid index is only a valid keep-alive
packet if the 16-bit flag-word that follows it contains a single bit
(ITEM_IS_NEW, which is normally an illegal flag to appear alone).
- A protocol-29 batch file includes a bit for the setting of the --dirs
option and for the setting of the --compress option. Also, the shell
script created by --write-batch will use the --filter option instead
of --exclude-from to capture any filter rules.
BUILD CHANGES:
- Handle an operating system that use mkdev() in place of makedev().
- Improved configure to better handle cross-compiling.
NEWS for rsync 2.6.3 (30 Sep 2004)
Protocol: 28 (unchanged)
Changes since 2.6.2:
@@ -1043,6 +1434,7 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
01 Jun 2005 2.6.5 29
30 Mar 2005 2.6.4 17 Jan 2005 29
30 Sep 2004 2.6.3 28
30 Apr 2004 2.6.2 28

3
README
View File

@@ -89,6 +89,9 @@ mailing list archives at
To send a bug report, follow the instructions on the bug-tracking
page of the web site.
If you don't have web access, email your bug report to
rsync@lists.samba.org.
CVS TREE
--------

View File

@@ -51,10 +51,11 @@ void base64_encode(char *buf, int len, char *out)
}
}
/* create a 16 byte challenge buffer */
/* Generate a challenge buffer and return it base64-encoded. */
static void gen_challenge(char *addr, char *challenge)
{
char input[32];
char md4_out[MD4_SUM_LENGTH];
struct timeval tv;
memset(input, 0, sizeof input);
@@ -67,7 +68,9 @@ static void gen_challenge(char *addr, char *challenge)
sum_init(0);
sum_update(input, sizeof input);
sum_end(challenge);
sum_end(md4_out);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge);
}
@@ -195,17 +198,18 @@ static char *getpassf(char *filename)
return NULL;
}
/* generate a 16 byte hash from a password and challenge */
/* Generate an MD4 hash created from the combination of the password
* and the challenge string and return it base64-encoded. */
static void generate_hash(char *in, char *challenge, char *out)
{
char buf[16];
char buf[MD4_SUM_LENGTH];
sum_init(0);
sum_update(in, strlen(in));
sum_update(challenge, strlen(challenge));
sum_end(buf);
base64_encode(buf, 16, out);
base64_encode(buf, MD4_SUM_LENGTH, out);
}
/* Possibly negotiate authentication with the client. Use "leader" to
@@ -214,17 +218,15 @@ static void generate_hash(char *in, char *challenge, char *out)
* Return NULL if authentication failed. Return "" if anonymous access.
* Otherwise return username.
*/
char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
char *leader)
{
char *users = lp_auth_users(module);
char challenge[16];
char b64_challenge[30];
char challenge[MD4_SUM_LENGTH*2];
char line[MAXPATHLEN];
static char user[100];
char secret[100];
char pass[30];
char pass2[30];
char *tok;
char secret[512];
char pass2[MD4_SUM_LENGTH*2];
char *tok, *pass;
/* if no auth list then allow anyone in! */
if (!users || !*users)
@@ -232,52 +234,60 @@ char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
gen_challenge(addr, challenge);
base64_encode(challenge, 16, b64_challenge);
io_printf(f_out, "%s%s\n", leader, challenge);
io_printf(f_out, "%s%s\n", leader, b64_challenge);
if (!read_line(f_in, line, sizeof line - 1))
if (!read_line(f_in, line, sizeof line - 1)
|| (pass = strchr(line, ' ')) == NULL) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"invalid challenge response\n",
lp_name(module), host, addr);
return NULL;
}
*pass++ = '\0';
memset(user, 0, sizeof user);
memset(pass, 0, sizeof pass);
if (!(users = strdup(users)))
out_of_memory("auth_server");
if (sscanf(line,"%99s %29s", user, pass) != 2)
return NULL;
users = strdup(users);
if (!users)
return NULL;
for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
if (wildmatch(tok, user))
for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
if (wildmatch(tok, line))
break;
}
free(users);
if (!tok)
return NULL;
memset(secret, 0, sizeof secret);
if (!get_secret(module, user, secret, sizeof secret - 1)) {
memset(secret, 0, sizeof secret);
if (!tok) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"unauthorized user\n",
lp_name(module), host, addr);
return NULL;
}
generate_hash(secret, b64_challenge, pass2);
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)
return user;
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;
}
return NULL;
return strdup(line);
}
void auth_client(int fd, char *user, char *challenge)
{
char *pass;
char pass2[30];
char pass2[MD4_SUM_LENGTH*2];
if (!user || !*user)
user = "nobody";
@@ -302,5 +312,3 @@ void auth_client(int fd, char *user, char *challenge)
generate_hash(pass, challenge, pass2);
io_printf(fd, "%s %s\n", user, pass2);
}

View File

@@ -139,7 +139,7 @@ static void write_filter_rules(int fd)
* (hopefully) work. */
void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
{
int fd, i;
int fd, i, len;
char *p, filename[MAXPATHLEN];
stringjoin(filename, sizeof filename,
@@ -175,11 +175,12 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
continue;
}
write(fd, " ", 1);
if (strncmp(p, "--write-batch", 13) == 0) {
if (strncmp(p, "--write-batch", len = 13) == 0
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
write(fd, "--read-batch", 12);
if (p[13] == '=') {
if (p[len] == '=') {
write(fd, "=", 1);
write_arg(fd, p + 14);
write_arg(fd, p + len + 1);
}
} else
write_arg(fd, p);

View File

@@ -41,7 +41,6 @@ extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern int io_timeout;
extern int select_timeout;
extern int orig_umask;
extern int no_detach;
extern int default_af_hint;
@@ -100,7 +99,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
ret = start_inband_exchange(user, path, fd, fd, argc);
return ret < 0? ret : client_run(fd, fd, -1, argc, argv);
return ret ? ret : client_run(fd, fd, -1, argc, argv);
}
int start_inband_exchange(char *user, char *path, int f_in, int f_out,
@@ -196,10 +195,10 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
rprintf(FERROR, "%s\n", line);
/* This is always fatal; the server will now
* close the socket. */
return RERR_STARTCLIENT;
} else {
rprintf(FINFO,"%s\n", line);
return -1;
}
rprintf(FINFO, "%s\n", line);
}
kluge_around_eof = 0;
@@ -268,11 +267,9 @@ static int rsync_module(int f_in, int f_out, int i)
return -1;
}
auth_user = auth_server(f_in, f_out, i, addr, "@RSYNCD: AUTHREQD ");
auth_user = auth_server(f_in, f_out, i, host, addr, "@RSYNCD: AUTHREQD ");
if (!auth_user) {
rprintf(FLOG, "auth failed on module %s from %s (%s)\n",
name, host, addr);
io_printf(f_out, "@ERROR: auth failed on module %s\n", name);
return -1;
}
@@ -283,10 +280,10 @@ static int rsync_module(int f_in, int f_out, int i)
read_only = 1;
if (lp_transfer_logging(i)) {
if (strstr(lp_log_format(i), "%i") != NULL)
if (log_format_has(lp_log_format(i), 'i'))
daemon_log_format_has_i = 1;
if (daemon_log_format_has_i
|| strstr(lp_log_format(i), "%o") != NULL)
|| log_format_has(lp_log_format(i), 'o'))
daemon_log_format_has_o_or_i = 1;
}
@@ -321,13 +318,11 @@ static int rsync_module(int f_in, int f_out, int i)
/* TODO: Perhaps take a list of gids, and make them into the
* supplementary groups. */
if (use_chroot) {
if (use_chroot || (module_dirlen = strlen(lp_path(i))) == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else {
module_dirlen = strlen(lp_path(i));
} else
set_filter_dir(lp_path(i), module_dirlen);
}
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
@@ -522,11 +517,8 @@ static int rsync_module(int f_in, int f_out, int i)
exit_cleanup(RERR_UNSUPPORTED);
}
if (lp_timeout(i)) {
io_timeout = lp_timeout(i);
if (io_timeout < select_timeout)
select_timeout = io_timeout;
}
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
set_io_timeout(lp_timeout(i));
start_server(f_in, f_out, argc, argp);

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=2.6.4pre4
RSYNC_VERSION=2.6.5
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -122,7 +122,9 @@ AC_ARG_WITH(rsh,
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
if test x$HAVE_REMSH = x1; then
AC_DEFINE(HAVE_REMSH, 1, [Define to 1 if remote shell is remsh, not rsh])
fi
if test x"$with_rsh" != x
then
@@ -181,6 +183,17 @@ ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
dnl Do you want to disable use of locale functions
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you don't want locale features. By default this is defined.])
AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale], [turn off locale features]),
[if test x$enableval = xyes; then
AC_DEFINE(CONFIG_LOCALE)
fi],
AC_DEFINE(CONFIG_LOCALE)
)
if test "x$enable_ipv6" != xno
then
AC_MSG_CHECKING([ipv6 stack type])
@@ -287,7 +300,7 @@ AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h \
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
netdb.h malloc.h float.h)
AC_HEADER_MAJOR
@@ -478,7 +491,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
fchmod fstat strchr readlink link utime utimes strftime mtrace ftruncate \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setmode open64 mkstemp64 va_copy __va_copy)
setlocale setmode open64 lseek64 mkstemp64 va_copy __va_copy)
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
@@ -621,7 +634,17 @@ 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
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [Define to 1 if mkstemp() is available and works right])
case $target_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
dnl for details. (sbonds)
AC_MSG_WARN(Skipping broken HP-UX mkstemp() -- using mktemp() instead)
;;
*)
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [Define to 1 if mkstemp() is available and works right])
;;
esac
fi
@@ -716,21 +739,6 @@ AC_SUBST(BUILD_POPT)
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT
if test x"$with_rsh" = x; then
if test x"$HAVE_REMSH" = x1; then
rmsh1='remsh:'
rmsh2='=remsh'
else
rmsh1='rsh: '
rmsh2='=rsh '
fi
AC_MSG_RESULT()
AC_MSG_RESULT([ **********************************************************************])
AC_MSG_RESULT([ * As of v2.6.0, the default remote shell is ssh instead of rsh!! *])
AC_MSG_RESULT([ * To use previous default of $rmsh1 ./configure --with-rsh$rmsh2 *])
AC_MSG_RESULT([ **********************************************************************])
fi
AC_MSG_RESULT()
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
AC_MSG_RESULT()

View File

@@ -28,7 +28,6 @@
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
#define RERR_UNSUPPORTED 4 /* requested action not supported */
#define RERR_STARTCLIENT 5 /* error starting client-server protocol */
#define RERR_LOG_FAILURE 6 /* daemon unable to append to log-file */
#define RERR_SOCKETIO 10 /* error in socket IO */
#define RERR_FILEIO 11 /* error in file IO */

View File

@@ -674,8 +674,7 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
} else if (*s == '+' && s[1] == ' ') {
new_mflags |= MATCHFLG_INCLUDE;
s += 2;
}
if (*s == '!')
} else if (*s == '!')
new_mflags |= MATCHFLG_CLEAR_LIST; /* Tentative! */
} else {
char ch = 0, *mods = "";
@@ -716,7 +715,6 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
if ((s = RULE_STRCMP(s, "show")) != NULL)
ch = 'S';
break;
default:
ch = *s;
if (s[1] == ',')
@@ -1107,9 +1105,9 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
continue;
if (ent->match_flags & MATCHFLG_CVS_IGNORE
&& !(ent->match_flags & MATCHFLG_MERGE_FILE)) {
int f = am_sender || protocol_version < 29 ? f_out : -1;
int f = am_sender || protocol_version < 29 ? f_out : -2;
send_rules(f, &cvs_filter_list);
if (f >= 0)
if (f == f_out)
continue;
}
p = get_rule_prefix(ent->match_flags, ent->pattern, 1, &plen);

52
flist.c
View File

@@ -69,6 +69,7 @@ int io_error;
dev_t filesystem_dev; /* used to implement -x */
static char empty_sum[MD4_SUM_LENGTH];
static int flist_count_offset;
static unsigned int file_struct_len;
static struct file_list *sorting_flist;
@@ -98,16 +99,16 @@ static void start_filelist_progress(char *kind)
}
static void emit_filelist_progress(const struct file_list *flist)
static void emit_filelist_progress(int count)
{
rprintf(FINFO, " %d files...\r", flist->count);
rprintf(FINFO, " %d files...\r", count);
}
static void maybe_emit_filelist_progress(const struct file_list *flist)
static void maybe_emit_filelist_progress(int count)
{
if (do_progress && show_filelist_p() && (flist->count % 100) == 0)
emit_filelist_progress(flist);
if (do_progress && show_filelist_p() && (count % 100) == 0)
emit_filelist_progress(count);
}
@@ -654,6 +655,9 @@ static struct file_struct *receive_file_entry(struct file_list *flist,
if (flags & XMIT_TOP_DIR) {
in_del_hier = 1;
del_hier_name_len = file->dir.depth == 0 ? 0 : l1 + l2;
if (relative_paths && del_hier_name_len > 2
&& basename_len == 1+1 && *basename == '.')
del_hier_name_len -= 2;
file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE;
} else if (in_del_hier) {
if (!relative_paths || !del_hier_name_len
@@ -971,7 +975,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
if (!file)
return NULL;
maybe_emit_filelist_progress(flist);
maybe_emit_filelist_progress(flist->count + flist_count_offset);
flist_expand(flist);
@@ -1007,7 +1011,7 @@ static void send_if_directory(int f, struct file_list *flist,
/* This function is normally called by the sender, but the receiving side also
* calls it from delete_in_dir() with f set to -1 so that we just construct the
* calls it from get_dirlist() with f set to -1 so that we just construct the
* file list in memory without sending it over the wire. Also, get_dirlist()
* might call this with f set to -2, which also indicates that local filter
* rules should be ignored. */
@@ -1116,11 +1120,21 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (l == 2 && fname[0] == '.') {
/* Turn "./" into just "." rather than "./." */
fname[1] = '\0';
} else if (l < MAXPATHLEN) {
} else {
if (l + 1 >= MAXPATHLEN)
overflow("send_file_list");
fname[l++] = '.';
fname[l] = '\0';
}
is_dot_dir = 1;
} else if (l > 1 && fname[l-1] == '.' && fname[l-2] == '.'
&& (l == 2 || fname[l-3] == '/')) {
if (l + 2 >= MAXPATHLEN)
overflow("send_file_list");
fname[l++] = '/';
fname[l++] = '.';
fname[l] = '\0';
is_dot_dir = 1;
} else {
is_dot_dir = fname[l-1] == '.'
&& (l == 1 || fname[l-2] == '/');
@@ -1309,7 +1323,7 @@ struct file_list *recv_file_list(int f)
flist->files[flist->count++] = file;
maybe_emit_filelist_progress(flist);
maybe_emit_filelist_progress(flist->count);
if (verbose > 2) {
rprintf(FINFO, "recv_file_name(%s)\n",
@@ -1510,8 +1524,8 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
}
/* Make sure that if we unduplicate '.', that we don't
* lose track of a user-specified top directory. */
if (flist->files[drop]->flags & FLAG_TOP_DIR)
flist->files[keep]->flags |= FLAG_TOP_DIR;
flist->files[keep]->flags |= flist->files[drop]->flags
& (FLAG_TOP_DIR|FLAG_DEL_HERE);
clear_file(drop, flist);
@@ -1666,8 +1680,13 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2)
break;
case s_SLASH:
type1 = S_ISDIR(f1->mode) ? t_path : t_ITEM;
state1 = s_BASE;
c1 = (uchar*)f1->basename;
if (type1 == t_PATH && *c1 == '.' && !c1[1]) {
type1 = t_ITEM;
state1 = s_TRAILING;
c1 = (uchar*)"";
} else
state1 = s_BASE;
break;
case s_BASE:
state1 = s_TRAILING;
@@ -1691,8 +1710,13 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2)
break;
case s_SLASH:
type2 = S_ISDIR(f2->mode) ? t_path : t_ITEM;
state2 = s_BASE;
c2 = (uchar*)f2->basename;
if (type2 == t_PATH && *c2 == '.' && !c2[1]) {
type2 = t_ITEM;
state2 = s_TRAILING;
c2 = (uchar*)"";
} else
state2 = s_BASE;
break;
case s_BASE:
state2 = s_TRAILING;
@@ -1772,6 +1796,8 @@ struct file_list *get_dirlist(char *dirname, int dlen,
recurse = 0;
send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen);
recurse = save_recurse;
if (do_progress)
flist_count_offset += dirlist->count;
clean_flist(dirlist, 0, 0);

View File

@@ -25,12 +25,14 @@
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int log_format_has_i;
extern int log_format_has_o_or_i;
extern int daemon_log_format_has_i;
extern int am_root;
extern int am_server;
extern int am_daemon;
extern int do_progress;
extern int recurse;
extern int relative_paths;
extern int keep_dirlinks;
@@ -57,8 +59,8 @@ extern int csum_length;
extern int ignore_times;
extern int size_only;
extern OFF_T max_size;
extern int io_timeout;
extern int io_error;
extern int allowed_lull;
extern int sock_f_out;
extern int ignore_timeout;
extern int protocol_version;
@@ -70,7 +72,6 @@ extern int compare_dest;
extern int copy_dest;
extern int link_dest;
extern int whole_file;
extern int local_server;
extern int list_only;
extern int read_batch;
extern int only_existing;
@@ -88,8 +89,6 @@ extern int backup_suffix_len;
extern struct file_list *the_file_list;
extern struct filter_list_struct server_filter_list;
int allowed_lull = 0;
static int deletion_count = 0; /* used to implement --max-delete */
@@ -151,7 +150,7 @@ static int delete_item(char *fname, int mode, int flags)
deletion_count--;
return 0;
}
if (!zap_dir || (errno != ENOTEMPTY && errno != EEXIST)) {
if (!zap_dir) {
rsyserr(FERROR, errno, "delete_file: rmdir %s failed",
full_fname(fname));
return -1;
@@ -170,10 +169,7 @@ static int delete_item(char *fname, int mode, int flags)
continue;
f_name_to(fp, buf);
if (delete_item(buf, fp->mode, flags & ~DEL_TERSE) != 0) {
flist_free(dirlist);
return -1;
}
delete_item(buf, fp->mode, flags & ~DEL_TERSE);
}
flist_free(dirlist);
@@ -185,7 +181,7 @@ static int delete_item(char *fname, int mode, int flags)
if (do_rmdir(fname) == 0) {
if (!(flags & DEL_TERSE))
log_delete(fname, mode);
} else if (errno != ENOTEMPTY && errno != ENOENT) {
} else if (errno != ENOTEMPTY && errno != EEXIST && errno != ENOENT) {
rsyserr(FERROR, errno, "delete_file: rmdir %s failed",
full_fname(fname));
return -1;
@@ -248,21 +244,25 @@ static void delete_in_dir(struct file_list *flist, char *fbuf,
if (link_stat(fbuf, &st, keep_dirlinks) < 0)
return;
if (one_file_system && file->flags & FLAG_TOP_DIR)
filesystem_dev = st.st_dev;
if (one_file_system) {
if (file->flags & FLAG_TOP_DIR)
filesystem_dev = st.st_dev;
else if (filesystem_dev != st.st_dev)
return;
}
dirlist = get_dirlist(fbuf, dlen, 0);
/* If an item in dirlist is not found in flist, delete it
* from the filesystem. */
for (i = dirlist->count; i--; ) {
if (!dirlist->files[i]->basename)
struct file_struct *fp = dirlist->files[i];
if (!fp->basename || fp->flags & FLAG_MOUNT_POINT)
continue;
if (flist_find(flist, dirlist->files[i]) < 0) {
int mode = dirlist->files[i]->mode;
f_name_to(dirlist->files[i], delbuf);
if (delete_item(delbuf, mode, DEL_FORCE_RECURSE) < 0)
break;
if (flist_find(flist, fp) < 0) {
int mode = fp->mode;
f_name_to(fp, delbuf);
delete_item(delbuf, mode, DEL_FORCE_RECURSE);
}
}
@@ -276,7 +276,8 @@ static void do_delete_pass(struct file_list *flist)
char fbuf[MAXPATHLEN];
int j;
if (dry_run > 1) /* destination doesn't exist yet */
if (dry_run > 1 /* destination doesn't exist yet */
|| list_only)
return;
for (j = 0; j < flist->count; j++) {
@@ -291,6 +292,8 @@ static void do_delete_pass(struct file_list *flist)
delete_in_dir(flist, fbuf, file);
}
if (do_progress && !am_server)
rprintf(FINFO, " \r");
}
static int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st)
@@ -665,7 +668,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (only_existing && statret == -1 && stat_errno == ENOENT) {
/* we only want to update existing files */
if (verbose > 1) {
rprintf(FINFO, "not creating new file \"%s\"\n",
rprintf(FINFO, "not creating new %s \"%s\"\n",
S_ISDIR(file->mode) ? "directory" : "file",
safe_fname(fname));
}
return;
@@ -717,18 +721,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
return;
}
if (max_size && file->length > max_size) {
if (verbose > 1) {
rprintf(FINFO, "%s is over max-size\n",
safe_fname(fname));
}
return;
}
if (preserve_links && S_ISLNK(file->mode)) {
#ifdef SUPPORT_LINKS
if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
if (verbose) {
if (the_file_list->count == 1)
fname = f_name(file);
rprintf(FINFO,
"ignoring unsafe symlink %s -> \"%s\"\n",
full_fname(fname),
@@ -821,15 +819,29 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
return;
}
if (preserve_hard_links && hard_link_check(file, ndx, HL_CHECK_MASTER))
if (preserve_hard_links
&& hard_link_check(file, ndx, fname, statret, &st,
itemizing, code, HL_CHECK_MASTER))
return;
if (!S_ISREG(file->mode)) {
if (the_file_list->count == 1)
fname = f_name(file);
rprintf(FINFO, "skipping non-regular file \"%s\"\n",
safe_fname(fname));
return;
}
if (max_size && file->length > max_size) {
if (verbose > 1) {
if (the_file_list->count == 1)
fname = f_name(file);
rprintf(FINFO, "%s is over max-size\n",
safe_fname(fname));
}
return;
}
if (opt_ignore_existing && statret == 0) {
if (verbose > 1)
rprintf(FINFO, "%s exists\n", safe_fname(fname));
@@ -902,12 +914,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (hard_link_one(file, ndx, fname, -1, &st,
fnamecmpbuf, 1,
itemizing && verbose > 1,
code) == 0)
code) == 0) {
if (preserve_hard_links
&& file->link_u.links) {
hard_link_cluster(file, ndx,
itemizing,
code);
}
return;
if (verbose) {
rsyserr(FINFO, errno, "link %s => %s",
full_fname(fnamecmpbuf),
safe_fname(fname));
}
match_level = 2;
}
@@ -923,8 +937,25 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
match_level = 0;
statret = -1;
} else
set_perms(fname, file, NULL, 0);
} else {
if (itemizing) {
itemize(file, ndx, 0, &st,
ITEM_LOCAL_CHANGE, 0,
NULL);
} else if (verbose && code) {
rprintf(code, "%s\n",
safe_fname(fname));
}
set_perms(fname, file, NULL,
maybe_PERMS_REPORT);
if (preserve_hard_links
&& file->link_u.links) {
hard_link_cluster(file, ndx,
itemizing,
code);
}
return;
}
} else if (compare_dest || match_level == 1) {
fnamecmp = fnamecmpbuf;
fnamecmp_type = i;
@@ -960,7 +991,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
if (statret != 0) {
if (preserve_hard_links && hard_link_check(file, ndx, HL_SKIP))
if (preserve_hard_links
&& hard_link_check(file, ndx, fname, statret, &st,
itemizing, code, HL_SKIP))
return;
if (stat_errno == ENOENT)
goto notify_others;
@@ -1001,7 +1034,7 @@ prepare_to_open:
statret = 0;
}
if (dry_run || read_batch || whole_file)
if (!do_xfers || read_batch || whole_file)
goto notify_others;
if (fuzzy_basis) {
@@ -1018,7 +1051,9 @@ prepare_to_open:
full_fname(fnamecmp));
pretend_missing:
/* pretend the file didn't exist */
if (preserve_hard_links && hard_link_check(file, ndx, HL_SKIP))
if (preserve_hard_links
&& hard_link_check(file, ndx, fname, statret, &st,
itemizing, code, HL_SKIP))
return;
statret = real_ret = -1;
goto notify_others;
@@ -1073,7 +1108,7 @@ notify_others:
fuzzy_file ? fuzzy_file->basename : NULL);
}
if (dry_run) {
if (!do_xfers) {
if (preserve_hard_links && file->link_u.links)
hard_link_cluster(file, ndx, itemizing, code);
return;
@@ -1104,26 +1139,26 @@ notify_others:
void generate_files(int f_out, struct file_list *flist, char *local_name)
{
int i, lull_mod;
int i;
char fbuf[MAXPATHLEN];
int itemizing, maybe_PERMS_REPORT;
enum logcode code;
int lull_mod = allowed_lull * 5;
int need_retouch_dir_times = preserve_times && !omit_dir_times;
int need_retouch_dir_perms = 0;
int save_only_existing = only_existing;
int save_opt_ignore_existing = opt_ignore_existing;
allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
lull_mod = allowed_lull * 5;
int save_do_progress = do_progress;
int save_make_backups = make_backups;
if (protocol_version >= 29) {
itemizing = 1;
maybe_PERMS_REPORT = log_format_has_i ? 0 : PERMS_REPORT;
code = daemon_log_format_has_i ? 0 : FLOG;
} else if (am_daemon) {
itemizing = daemon_log_format_has_i && !dry_run;
itemizing = daemon_log_format_has_i && do_xfers;
maybe_PERMS_REPORT = PERMS_REPORT;
code = itemizing || dry_run ? FCLIENT : FINFO;
code = itemizing || !do_xfers ? FCLIENT : FINFO;
} else if (!am_server) {
itemizing = log_format_has_i;
maybe_PERMS_REPORT = log_format_has_i ? 0 : PERMS_REPORT;
@@ -1141,6 +1176,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
if (delete_before && !local_name && flist->count > 0)
do_delete_pass(flist);
do_progress = 0;
if (whole_file < 0)
whole_file = 0;
@@ -1151,8 +1187,11 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
: "enabled");
}
if (protocol_version < 29)
ignore_timeout = 1;
/* Since we often fill up the outgoing socket and then just sit around
* waiting for the other 2 processes to do their thing, we don't want
* to exit on a timeout. If the data stops flowing, the receiver will
* notice that and let us know via the redo pipe (or its closing). */
ignore_timeout = 1;
for (i = 0; i < flist->count; i++) {
struct file_struct *file = flist->files[i];
@@ -1167,7 +1206,8 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
/* We need to ensure that any dirs we create have writeable
* permissions during the time we are putting files within
* them. This is then fixed after the transfer is done. */
if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)
&& !list_only) {
int mode = file->mode | S_IWUSR; /* user write */
char *fname = local_name ? local_name : fbuf;
if (do_chmod(fname, mode & CHMOD_BITS) < 0) {
@@ -1183,6 +1223,8 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
if (allowed_lull && !(i % lull_mod))
maybe_send_keepalive();
else if (!(i % 200))
maybe_flush_socket();
}
recv_generator(NULL, NULL, 0, 0, 0, code, -1);
if (delete_during)
@@ -1195,10 +1237,6 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
ignore_times = 1;
make_backups = 0; /* avoid a duplicate backup for inplace processing */
/* We expect to just sit around now, so don't exit on a timeout.
* If we really get a timeout then the other process should exit. */
ignore_timeout = 1;
if (verbose > 2)
rprintf(FINFO,"generate_files phase=%d\n",phase);
@@ -1216,6 +1254,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
phase++;
only_existing = save_only_existing;
opt_ignore_existing = save_opt_ignore_existing;
make_backups = save_make_backups;
if (verbose > 2)
rprintf(FINFO,"generate_files phase=%d\n",phase);
@@ -1238,6 +1277,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
get_redo_num(itemizing, code);
}
do_progress = save_do_progress;
if (delete_after && !local_name && flist->count > 0)
do_delete_pass(flist);
@@ -1255,8 +1295,10 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
continue;
recv_generator(f_name(file), file, i, itemizing,
maybe_PERMS_REPORT, code, -1);
if (allowed_lull && !(j++ % lull_mod))
if (allowed_lull && !(++j % lull_mod))
maybe_send_keepalive();
else if (!(j % 200))
maybe_flush_socket();
}
}
recv_generator(NULL, NULL, 0, 0, 0, code, -1);

142
hlink.c
View File

@@ -27,6 +27,9 @@ extern struct file_list *the_file_list;
#ifdef SUPPORT_HARD_LINKS
#define SKIPPED_LINK (-1)
#define FINISHED_LINK (-2)
#define FPTR(i) (the_file_list->files[i])
#define LINKED(p1,p2) (FPTR(p1)->F_DEV == FPTR(p2)->F_DEV \
&& FPTR(p1)->F_INODE == FPTR(p2)->F_INODE)
@@ -52,7 +55,7 @@ static int hlink_count;
* linked, and replace the dev+inode data with the hlindex+next linked list. */
static void link_idev_data(void)
{
int head, from, to, start;
int cur, from, to, start;
alloc_pool_t hlink_pool;
alloc_pool_t idev_pool = the_file_list->hlink_pool;
@@ -62,31 +65,31 @@ static void link_idev_data(void)
for (from = to = 0; from < hlink_count; from++) {
start = from;
head = hlink_list[start];
while (from < hlink_count-1
&& LINKED(hlink_list[from], hlink_list[from+1])) {
pool_free(idev_pool, 0, FPTR(hlink_list[from])->link_u.idev);
FPTR(hlink_list[from])->link_u.links = pool_talloc(hlink_pool,
while (1) {
cur = hlink_list[from];
if (from == hlink_count-1
|| !LINKED(cur, hlink_list[from+1]))
break;
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
struct hlink, 1, "hlink_list");
FPTR(hlink_list[from])->F_HLINDEX = to;
FPTR(hlink_list[from])->F_NEXT = hlink_list[from+1];
from++;
FPTR(cur)->F_HLINDEX = to;
FPTR(cur)->F_NEXT = hlink_list[++from];
}
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
if (from > start) {
pool_free(idev_pool, 0, FPTR(hlink_list[from])->link_u.idev);
FPTR(hlink_list[from])->link_u.links = pool_talloc(hlink_pool,
int head = hlink_list[start];
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
struct hlink, 1, "hlink_list");
FPTR(head)->flags |= FLAG_HLINK_TOL;
FPTR(hlink_list[from])->F_HLINDEX = to;
FPTR(hlink_list[from])->F_NEXT = head;
FPTR(hlink_list[from])->flags |= FLAG_HLINK_EOL;
FPTR(cur)->F_HLINDEX = to;
FPTR(cur)->F_NEXT = head;
FPTR(cur)->flags |= FLAG_HLINK_EOL;
hlink_list[to++] = head;
} else {
pool_free(idev_pool, 0, FPTR(head)->link_u.idev);
FPTR(head)->link_u.idev = NULL;
}
} else
FPTR(cur)->link_u.links = NULL;
}
if (!to) {
@@ -110,9 +113,6 @@ void init_hard_links(void)
#ifdef SUPPORT_HARD_LINKS
int i;
if (the_file_list->count < 2)
return;
if (hlink_list)
free(hlink_list);
@@ -136,18 +136,67 @@ void init_hard_links(void)
#endif
}
int hard_link_check(struct file_struct *file, int ndx, int skip)
#ifdef SUPPORT_HARD_LINKS
static int maybe_hard_link(struct file_struct *file, int ndx,
char *fname, int statret, STRUCT_STAT *st,
char *toname, STRUCT_STAT *to_st,
int itemizing, enum logcode code)
{
if (statret == 0) {
if (st->st_dev == to_st->st_dev
&& st->st_ino == to_st->st_ino) {
if (itemizing) {
itemize(file, ndx, statret, st,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
0, "");
}
return 0;
}
if (make_backups) {
if (!make_backup(fname))
return -1;
} else if (robust_unlink(fname)) {
rsyserr(FERROR, errno, "unlink %s failed",
full_fname(fname));
return -1;
}
}
return hard_link_one(file, ndx, fname, statret, st, toname,
0, itemizing, code);
}
#endif
int hard_link_check(struct file_struct *file, int ndx, char *fname,
int statret, STRUCT_STAT *st, int itemizing,
enum logcode code, int skip)
{
#ifdef SUPPORT_HARD_LINKS
if (!hlink_list || !file->link_u.links)
int head;
if (!file->link_u.links)
return 0;
if (skip && !(file->flags & FLAG_HLINK_EOL))
hlink_list[file->F_HLINDEX] = file->F_NEXT;
if (hlink_list[file->F_HLINDEX] != ndx) {
head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
else
head = hlink_list[file->F_HLINDEX];
if (ndx != head) {
struct file_struct *head_file = FPTR(head);
if (verbose > 2) {
rprintf(FINFO, "\"%s\" is a hard link\n",
safe_fname(f_name(file)));
}
if (head_file->F_HLINDEX == FINISHED_LINK) {
STRUCT_STAT st2;
char *toname = f_name(head_file);
if (link_stat(toname, &st2, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(toname));
return -1;
}
maybe_hard_link(file, ndx, fname, statret, st,
toname, &st2, itemizing, code);
file->F_HLINDEX = FINISHED_LINK;
} else
file->F_HLINDEX = SKIPPED_LINK;
return 1;
}
#endif
@@ -160,10 +209,14 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
int itemizing, enum logcode code)
{
if (do_link(toname, fname)) {
if (verbose) {
rsyserr(FERROR, errno, "link %s => %s failed",
full_fname(fname), safe_fname(toname));
}
if (terse) {
if (!verbose)
return -1;
code = FINFO;
} else
code = FERROR;
rsyserr(code, errno, "link %s => %s failed",
full_fname(fname), safe_fname(toname));
return -1;
}
@@ -190,6 +243,7 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
STRUCT_STAT st1, st2;
int statret, ndx = master;
file->F_HLINDEX = FINISHED_LINK;
if (link_stat(f_name_to(file, hlink1), &st1, 0) < 0)
return;
if (!(file->flags & FLAG_HLINK_TOL)) {
@@ -201,33 +255,13 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
do {
ndx = file->F_NEXT;
file = FPTR(ndx);
if (ndx == master)
if (file->F_HLINDEX != SKIPPED_LINK)
continue;
hlink2 = f_name(file);
if ((statret = link_stat(hlink2, &st2, 0)) == 0) {
if (st2.st_dev == st1.st_dev
&& st2.st_ino == st1.st_ino) {
if (itemizing) {
itemize(file, ndx, statret, &st2,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
0, "");
}
continue;
}
if (make_backups) {
if (!make_backup(hlink2))
continue;
} else if (robust_unlink(hlink2)) {
if (verbose > 0) {
rsyserr(FINFO, errno,
"unlink %s failed",
full_fname(hlink2));
}
continue;
}
}
hard_link_one(file, ndx, hlink2, statret,
&st2, hlink1, 0, itemizing, code);
statret = link_stat(hlink2, &st2, 0);
maybe_hard_link(file, ndx, hlink2, statret, &st2,
hlink1, &st1, itemizing, code);
file->F_HLINDEX = FINISHED_LINK;
} while (!(file->flags & FLAG_HLINK_EOL));
#endif
}

109
io.c
View File

@@ -49,6 +49,7 @@ extern int am_daemon;
extern int am_sender;
extern int am_generator;
extern int eol_nulls;
extern int read_batch;
extern int csum_length;
extern int checksum_seed;
extern int protocol_version;
@@ -59,7 +60,6 @@ extern struct stats stats;
extern struct file_list *the_file_list;
const char phase_unknown[] = "unknown";
int select_timeout = SELECT_TIMEOUT;
int ignore_timeout = 0;
int batch_fd = -1;
int batch_gen_fd = -1;
@@ -90,7 +90,8 @@ int sock_f_out = -1;
static int io_multiplexing_out;
static int io_multiplexing_in;
static time_t last_io;
static time_t last_io_in;
static time_t last_io_out;
static int no_flush;
static int write_batch_monitor_in = -1;
@@ -103,6 +104,7 @@ static char *io_filesfrom_bp;
static char io_filesfrom_lastchar;
static int io_filesfrom_buflen;
static size_t contiguous_write_len = 0;
static int select_timeout = SELECT_TIMEOUT;
static void read_loop(int fd, char *buf, size_t len);
@@ -166,17 +168,17 @@ static void check_timeout(void)
if (!io_timeout || ignore_timeout)
return;
if (!last_io) {
last_io = time(NULL);
if (!last_io_in) {
last_io_in = time(NULL);
return;
}
t = time(NULL);
if (t - last_io >= io_timeout) {
if (t - last_io_in >= io_timeout) {
if (!am_server && !am_daemon) {
rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
(int)(t-last_io));
(int)(t-last_io_in));
}
exit_cleanup(RERR_TIMEOUT);
}
@@ -190,6 +192,18 @@ void io_set_sock_fds(int f_in, int f_out)
sock_f_out = f_out;
}
void set_io_timeout(int secs)
{
io_timeout = secs;
if (!io_timeout || io_timeout > SELECT_TIMEOUT)
select_timeout = SELECT_TIMEOUT;
else
select_timeout = io_timeout;
allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
}
/* Setup the fd used to receive MSG_* messages. Only needed during the
* early stages of being a local sender (up through the sending of the
* file list) or when we're the generator (to fetch the messages from
@@ -574,8 +588,8 @@ static int read_timeout(int fd, char *buf, size_t len)
len -= n;
ret += n;
if (io_timeout && fd == sock_f_in)
last_io = time(NULL);
if (fd == sock_f_in && io_timeout)
last_io_in = time(NULL);
}
return ret;
@@ -665,9 +679,16 @@ void io_end_buffering(void)
}
void maybe_flush_socket(void)
{
if (iobuf_out && iobuf_out_cnt && time(NULL) - last_io_out >= 5)
io_flush(NORMAL_FLUSH);
}
void maybe_send_keepalive(void)
{
if (time(NULL) - last_io >= allowed_lull) {
if (time(NULL) - last_io_out >= allowed_lull) {
if (!iobuf_out || !iobuf_out_cnt) {
if (protocol_version < 29)
return; /* there's nothing we can do */
@@ -705,8 +726,13 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
{
static size_t remaining;
static size_t iobuf_in_ndx;
size_t msg_bytes;
int tag, ret = 0;
char line[MAXPATHLEN+1];
#if MAXPATHLEN < 4096
char line[4096+1024];
#else
char line[MAXPATHLEN+1024];
#endif
if (!iobuf_in || fd != sock_f_in)
return read_timeout(fd, buf, len);
@@ -729,56 +755,52 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
read_loop(fd, line, 4);
tag = IVAL(line, 0);
remaining = tag & 0xFFFFFF;
msg_bytes = tag & 0xFFFFFF;
tag = (tag >> 24) - MPLEX_BASE;
switch (tag) {
case MSG_DATA:
if (remaining > iobuf_in_siz) {
if (msg_bytes > iobuf_in_siz) {
if (!(iobuf_in = realloc_array(iobuf_in, char,
remaining)))
msg_bytes)))
out_of_memory("readfd_unbuffered");
iobuf_in_siz = remaining;
iobuf_in_siz = msg_bytes;
}
read_loop(fd, iobuf_in, remaining);
read_loop(fd, iobuf_in, msg_bytes);
remaining = msg_bytes;
iobuf_in_ndx = 0;
break;
case MSG_DELETED:
if (remaining >= sizeof line) {
rprintf(FERROR, "invalid multi-message %d:%ld\n",
tag, (long)remaining);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
line[remaining] = '\0';
if (msg_bytes >= sizeof line)
goto overflow;
read_loop(fd, line, msg_bytes);
line[msg_bytes] = '\0';
/* A directory name was sent with the trailing null */
if (remaining > 0 && !line[remaining-1])
if (msg_bytes > 0 && !line[msg_bytes-1])
log_delete(line, S_IFDIR);
else
log_delete(line, S_IFREG);
remaining = 0;
break;
case MSG_SUCCESS:
if (remaining != 4) {
if (msg_bytes != 4) {
rprintf(FERROR, "invalid multi-message %d:%ld [%s]\n",
tag, (long)remaining, who_am_i());
tag, (long)msg_bytes, who_am_i());
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
read_loop(fd, line, msg_bytes);
successful_send(IVAL(line, 0));
remaining = 0;
break;
case MSG_INFO:
case MSG_ERROR:
if (remaining >= sizeof line) {
if (msg_bytes >= sizeof line) {
overflow:
rprintf(FERROR,
"multiplexing overflow %d:%ld [%s]\n",
tag, (long)remaining, who_am_i());
tag, (long)msg_bytes, who_am_i());
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
rwrite((enum logcode)tag, line, remaining);
remaining = 0;
read_loop(fd, line, msg_bytes);
rwrite((enum logcode)tag, line, msg_bytes);
break;
default:
rprintf(FERROR, "unexpected tag %d [%s]\n",
@@ -1006,7 +1028,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
{
size_t n, total = 0;
fd_set w_fds, r_fds;
int maxfd, count, ret;
int maxfd, count, ret, using_r_fds;
struct timeval tv;
no_flush++;
@@ -1021,18 +1043,15 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
FD_SET(msg_fd_in,&r_fds);
if (msg_fd_in > maxfd)
maxfd = msg_fd_in;
}
if (fd != sock_f_out && iobuf_out_cnt && no_flush == 1) {
FD_SET(sock_f_out, &w_fds);
if (sock_f_out > maxfd)
maxfd = sock_f_out;
}
using_r_fds = 1;
} else
using_r_fds = 0;
tv.tv_sec = select_timeout;
tv.tv_usec = 0;
errno = 0;
count = select(maxfd + 1, msg_fd_in >= 0 ? &r_fds : NULL,
count = select(maxfd + 1, using_r_fds ? &r_fds : NULL,
&w_fds, NULL, &tv);
if (count <= 0) {
@@ -1042,7 +1061,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
continue;
}
if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
if (using_r_fds && FD_ISSET(msg_fd_in, &r_fds))
read_msg_fd();
if (!FD_ISSET(fd, &w_fds))
@@ -1072,7 +1091,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
/* If the other side is sending us error messages, try
* to grab any messages they sent before they died. */
while (fd == sock_f_out && io_multiplexing_in) {
io_timeout = select_timeout = 30;
set_io_timeout(30);
ignore_timeout = 0;
readfd_unbuffered(sock_f_in, io_filesfrom_buf,
sizeof io_filesfrom_buf);
@@ -1083,8 +1102,8 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
total += ret;
if (fd == sock_f_out) {
if (io_timeout)
last_io = time(NULL);
if (io_timeout || am_generator)
last_io_out = time(NULL);
sleep_for_bwlimit(ret);
}
}

249
log.c
View File

@@ -32,6 +32,7 @@ extern int dry_run;
extern int am_daemon;
extern int am_server;
extern int am_sender;
extern int local_server;
extern int quiet;
extern int module_id;
extern int msg_fd_out;
@@ -43,6 +44,7 @@ extern char *auth_user;
extern char *log_format;
static int log_initialised;
static int logfile_was_closed;
static char *logfname;
static FILE *logfile;
struct stats stats;
@@ -58,7 +60,6 @@ struct {
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
{ RERR_UNSUPPORTED, "requested action not supported" },
{ RERR_STARTCLIENT, "error starting client-server protocol" },
{ RERR_LOG_FAILURE, "daemon unable to append to log-file" },
{ RERR_SOCKETIO , "error in socket IO" },
{ RERR_FILEIO , "error in file IO" },
{ RERR_STREAMIO , "error in rsync protocol data stream" },
@@ -96,9 +97,9 @@ static char const *rerr_name(int code)
static void logit(int priority, char *buf)
{
if (logfname) {
if (!logfile)
log_open();
if (logfile_was_closed)
logfile_reopen();
if (logfile) {
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
@@ -107,9 +108,48 @@ static void logit(int priority, char *buf)
}
}
static void syslog_init()
{
static int been_here = 0;
int options = LOG_PID;
if (been_here)
return;
been_here = 1;
#ifdef LOG_NDELAY
options |= LOG_NDELAY;
#endif
#ifdef LOG_DAEMON
openlog("rsyncd", options, lp_syslog_facility());
#else
openlog("rsyncd", options);
#endif
#ifndef LOG_NDELAY
logit(LOG_INFO, "rsyncd started\n");
#endif
}
static void logfile_open(void)
{
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
if (!logfile) {
int fopen_errno = errno;
/* Rsync falls back to using syslog on failure. */
syslog_init();
rsyserr(FERROR, fopen_errno,
"failed to open log-file %s", logfname);
rprintf(FINFO, "Ignoring \"log file\" setting.\n");
}
}
void log_init(void)
{
int options = LOG_PID;
time_t t;
if (log_initialised)
@@ -124,52 +164,29 @@ void log_init(void)
/* optionally use a log file instead of syslog */
logfname = lp_log_file();
if (logfname) {
if (*logfname) {
log_open();
return;
}
logfname = NULL;
}
#ifdef LOG_NDELAY
options |= LOG_NDELAY;
#endif
#ifdef LOG_DAEMON
openlog("rsyncd", options, lp_syslog_facility());
#else
openlog("rsyncd", options);
#endif
#ifndef LOG_NDELAY
logit(LOG_INFO,"rsyncd started\n");
#endif
if (logfname && *logfname)
logfile_open();
else
syslog_init();
}
void log_open(void)
{
if (logfname && !logfile) {
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
if (!logfile) {
am_daemon = 0; /* avoid trying to log again */
rsyserr(FERROR, errno, "fopen() of log-file failed");
exit_cleanup(RERR_LOG_FAILURE);
}
}
}
void log_close(void)
void logfile_close(void)
{
if (logfile) {
logfile_was_closed = 1;
fclose(logfile);
logfile = NULL;
}
}
void logfile_reopen(void)
{
if (logfile_was_closed) {
logfile_was_closed = 0;
logfile_open();
}
}
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG */
void rwrite(enum logcode code, char *buf, int len)
@@ -239,7 +256,7 @@ void rwrite(enum logcode code, char *buf, int len)
if (buf[len-1] == '\r' || buf[len-1] == '\n')
fflush(f);
}
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
@@ -319,7 +336,7 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
void rflush(enum logcode code)
{
FILE *f = NULL;
if (am_daemon) {
return;
}
@@ -351,44 +368,70 @@ static void log_formatted(enum logcode code, char *format, char *op,
struct file_struct *file, struct stats *initial_stats,
int iflags, char *hlink)
{
char buf[MAXPATHLEN+1024];
char buf2[MAXPATHLEN];
char *p, *n;
char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
char *p, *s, *n;
size_t len, total;
int64 b;
*fmt = '%';
/* We expand % codes one by one in place in buf. We don't
* copy in the terminating nul of the inserted strings, but
* rather keep going until we reach the nul of the format. */
* copy in the terminating null of the inserted strings, but
* rather keep going until we reach the null of the format. */
total = strlcpy(buf, format, sizeof buf);
for (p = buf; (p = strchr(p, '%')) != NULL && p[1]; ) {
if (total > MAXPATHLEN) {
rprintf(FERROR, "log-format string is WAY too long!\n");
exit_cleanup(RERR_MESSAGEIO);
}
buf[total++] = '\n';
buf[total] = '\0';
for (p = buf; (p = strchr(p, '%')) != NULL; ) {
s = p++;
n = fmt + 1;
if (*p == '-')
*n++ = *p++;
while (isdigit(*(uchar*)p) && n - fmt < (int)(sizeof fmt) - 8)
*n++ = *p++;
if (!*p)
break;
*n = '\0';
n = NULL;
switch (p[1]) {
switch (*p) {
case 'h': if (am_daemon) n = client_name(0); break;
case 'a': if (am_daemon) n = client_addr(0); break;
case 'l':
snprintf(buf2, sizeof buf2, "%.0f",
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(double)file->length);
n = buf2;
break;
case 'p':
snprintf(buf2, sizeof buf2, "%d",
(int)getpid());
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'f':
pathjoin(buf2, sizeof buf2,
am_sender && file->dir.root ? file->dir.root : "",
safe_fname(f_name(file)));
clean_fname(buf2, 0);
n = buf2;
if (*n == '/') n++;
n = safe_fname(f_name(file));
if (am_sender && file->dir.root) {
pathjoin(buf2, sizeof buf2,
file->dir.root, n);
/* The buffer from safe_fname() has more
* room than MAXPATHLEN, so this is safe. */
if (fmt[1])
strcpy(n, buf2);
else
n = buf2;
}
clean_fname(n, 0);
if (*n == '/')
n++;
break;
case 'n':
n = (char*)safe_fname(f_name(file));
n = safe_fname(f_name(file));
if (S_ISDIR(file->mode)) {
/* The buffer from safe_fname() has more
* room than MAXPATHLEN, so this is safe. */
@@ -397,15 +440,20 @@ static void log_formatted(enum logcode code, char *format, char *op,
break;
case 'L':
if (hlink && *hlink) {
snprintf(buf2, sizeof buf2, " => %s",
safe_fname(hlink));
n = buf2;
n = safe_fname(hlink);
strcpy(buf2, " => ");
} else if (S_ISLNK(file->mode) && file->u.link) {
snprintf(buf2, sizeof buf2, " -> %s",
safe_fname(file->u.link));
n = buf2;
} else
n = safe_fname(file->u.link);
strcpy(buf2, " -> ");
} else {
n = "";
if (!fmt[1])
break;
strcpy(buf2, " ");
}
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
n = buf2;
break;
case 'm': n = lp_name(module_id); break;
case 't': n = timestring(time(NULL)); break;
@@ -419,7 +467,8 @@ static void log_formatted(enum logcode code, char *format, char *op,
b = stats.total_read -
initial_stats->total_read;
}
snprintf(buf2, sizeof buf2, "%.0f", (double)b);
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt, (double)b);
n = buf2;
break;
case 'c':
@@ -430,7 +479,8 @@ static void log_formatted(enum logcode code, char *format, char *op,
b = stats.total_read -
initial_stats->total_read;
}
snprintf(buf2, sizeof buf2, "%.0f", (double)b);
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt, (double)b);
n = buf2;
break;
case 'i':
@@ -438,11 +488,11 @@ static void log_formatted(enum logcode code, char *format, char *op,
n = "*deleting";
break;
}
n = buf2;
n = buf2 + MAXPATHLEN - 32;
n[0] = iflags & ITEM_LOCAL_CHANGE
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
: !(iflags & ITEM_TRANSFER) ? '.'
: *op == 's' ? '<' : '>';
: !local_server && *op == 's' ? '<' : '>';
n[1] = S_ISDIR(file->mode) ? 'd'
: IS_DEVICE(file->mode) ? 'D'
: S_ISLNK(file->mode) ? 'L' : 'f';
@@ -476,17 +526,20 @@ static void log_formatted(enum logcode code, char *format, char *op,
break;
}
/* n is the string to be inserted in place of this %
* code; len is its length not including the trailing
* NUL */
if (!n) {
p += 2;
/* "n" is the string to be inserted in place of this % code. */
if (!n)
continue;
if (n != buf2 && fmt[1]) {
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt, n);
n = buf2;
}
len = strlen(n);
if (len + total - 2 >= sizeof buf) {
/* Subtract the length of the escape from the string's size. */
total -= p - s + 1;
if (len + total >= (size_t)sizeof buf) {
rprintf(FERROR,
"buffer overflow expanding %%%c -- exiting\n",
p[0]);
@@ -494,19 +547,41 @@ static void log_formatted(enum logcode code, char *format, char *op,
}
/* Shuffle the rest of the string along to make space for n */
if (len != 2)
memmove(p + len, p + 2, total - (p + 2 - buf) + 1);
total += len - 2;
if (len != (size_t)(p - s + 1))
memmove(s + len, p + 1, total - (s - buf) + 1);
total += len;
/* Insert the contents of string "n", but NOT its nul. */
/* Insert the contents of string "n", but NOT its null. */
if (len)
memcpy(p, n, len);
memcpy(s, n, len);
/* Skip over inserted string; continue looking */
p += len;
p = s + len;
}
rprintf(code, "%s\n", buf);
rwrite(code, buf, total);
}
/* Return 1 if the format escape is in the log-format string (e.g. look for
* the 'b' in the "%9b" format escape). */
int log_format_has(const char *format, char esc)
{
const char *p;
if (!format)
return 0;
for (p = format; (p = strchr(p, '%')) != NULL; ) {
if (*++p == '-')
p++;
while (isdigit(*(uchar*)p))
p++;
if (!*p)
break;
if (*p == esc)
return 1;
}
return 0;
}
/* log the transfer of a file */

71
main.c
View File

@@ -20,8 +20,9 @@
*/
#include "rsync.h"
time_t starttime = 0;
#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
#include <locale.h>
#endif
extern int verbose;
extern int dry_run;
@@ -77,6 +78,9 @@ struct pid_status {
int status;
} pid_stat_table[MAXCHILDPROCS];
static time_t starttime, endtime;
static int64 total_read, total_written;
static void show_malloc_stats(void);
/****************************************************************************
@@ -121,12 +125,13 @@ void wait_process(pid_t pid, int *status)
* the report. All processes might also generate a set of debug stats, if
* the verbose level is high enough (this is the only thing that the
* generator process and the server receiver ever do here). */
static void report(int f)
static void handle_stats(int f)
{
endtime = time(NULL);
/* Cache two stats because the read/write code can change it. */
int64 total_read = stats.total_read;
int64 total_written = stats.total_written;
time_t t = time(NULL);
total_read = stats.total_read;
total_written = stats.total_written;
if (do_stats && verbose > 1) {
/* These come out from every process */
@@ -158,7 +163,9 @@ static void report(int f)
/* this is the client */
if (!am_sender) {
if (f < 0 && !am_sender) /* e.g. when we got an empty file list. */
;
else if (!am_sender) {
/* Read the first two in opposite order because the meaning of
* read/write swaps when switching from sender to receiver. */
total_written = read_longint(f);
@@ -179,7 +186,10 @@ static void report(int f)
write_longint(batch_fd, stats.flist_xfertime);
}
}
}
static void output_summary(void)
{
if (do_stats) {
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
@@ -211,7 +221,7 @@ static void report(int f)
rprintf(FINFO,
"\nsent %.0f bytes received %.0f bytes %.2f bytes/sec\n",
(double)total_written, (double)total_read,
(total_written + total_read)/(0.5 + (t - starttime)));
(total_written + total_read)/(0.5 + (endtime - starttime)));
rprintf(FINFO, "total size is %.0f speedup is %.2f\n",
(double)stats.total_size,
(double)stats.total_size / (total_written+total_read));
@@ -283,7 +293,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
/* Comparison leaves rooms for server_options(). */
if (argc >= MAX_ARGS - 100) {
if (argc >= MAX_ARGS - MAX_SERVER_ARGS) {
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
@@ -509,7 +519,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
send_files(flist,f_out,f_in);
io_flush(FULL_FLUSH);
report(f_out);
handle_stats(f_out);
if (protocol_version >= 24)
read_final_goodbye(f_in, f_out);
io_flush(FULL_FLUSH);
@@ -555,7 +565,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
recv_files(f_in, flist, local_name);
io_flush(FULL_FLUSH);
report(f_in);
handle_stats(f_in);
send_msg(MSG_DONE, "", 0);
io_flush(FULL_FLUSH);
@@ -583,7 +593,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
am_generator = 1;
close_multiplexing_in();
if (write_batch)
if (write_batch && !am_server)
stop_write_batch();
close(error_pipe[1]);
@@ -596,7 +606,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
generate_files(f_out, flist, local_name);
report(-1);
handle_stats(-1);
io_flush(FULL_FLUSH);
if (protocol_version >= 24) {
/* send a final goodbye message */
@@ -756,7 +766,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (filesfrom_host)
filesfrom_fd = f_in;
if (write_batch)
if (write_batch && !am_server)
start_write_batch(f_out);
flist = send_file_list(f_out, argc, argv);
set_msg_fd_in(-1);
@@ -767,6 +777,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_flush(NORMAL_FLUSH);
send_files(flist,f_out,f_in);
io_flush(FULL_FLUSH);
handle_stats(-1);
if (protocol_version >= 24)
read_final_goodbye(f_in, f_out);
if (pid != -1) {
@@ -775,7 +786,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_flush(FULL_FLUSH);
wait_process(pid, &status);
}
report(-1);
output_summary();
io_flush(FULL_FLUSH);
exit_cleanup(status);
}
@@ -793,20 +804,19 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
filesfrom_fd = -1;
}
if (write_batch)
if (write_batch && !am_server)
start_write_batch(f_in);
flist = recv_file_list(f_in);
if (!flist || flist->count == 0) {
rprintf(FINFO, "client: nothing to do: "
"perhaps you need to specify some filenames or "
"the --recursive option?\n");
exit_cleanup(0);
}
the_file_list = flist;
local_name = get_local_name(flist,argv[0]);
if (flist && flist->count > 0) {
local_name = get_local_name(flist, argv[0]);
status2 = do_recv(f_in,f_out,flist,local_name);
status2 = do_recv(f_in, f_out, flist, local_name);
} else {
handle_stats(-1);
output_summary();
}
if (pid != -1) {
if (verbose > 3)
@@ -977,8 +987,11 @@ static RETSIGTYPE sigusr1_handler(UNUSED(int val))
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
{
if (!am_server)
output_summary();
close_all();
if (log_got_error) _exit(RERR_PARTIAL);
if (log_got_error)
_exit(RERR_PARTIAL);
_exit(0);
}
@@ -1103,6 +1116,10 @@ int main(int argc,char *argv[])
* see the EPIPE. */
signal(SIGPIPE, SIG_IGN);
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");
#endif
/* Initialize push_dir here because on some old systems getcwd
* (implemented by forking "pwd" and reading its output) doesn't
* work when there are other child processes. Also, on all systems
@@ -1111,7 +1128,7 @@ int main(int argc,char *argv[])
init_flist();
if (write_batch || read_batch) {
if ((write_batch || read_batch) && !am_server) {
if (write_batch)
write_batch_shell_file(orig_argc, orig_argv, argc);
@@ -1130,6 +1147,8 @@ int main(int argc,char *argv[])
if (read_batch)
read_stream_flags(batch_fd);
}
if (write_batch < 0)
dry_run = 1;
if (am_daemon && !am_server)
return daemon_main();

105
options.c
View File

@@ -23,7 +23,6 @@
extern int module_id;
extern int sanitize_paths;
extern int select_timeout;
extern struct filter_list_struct filter_list;
extern struct filter_list_struct server_filter_list;
@@ -53,6 +52,7 @@ int omit_dir_times = 0;
int update_only = 0;
int cvs_exclude = 0;
int dry_run = 0;
int do_xfers = 1;
int ignore_times = 0;
int delete_mode = 0;
int delete_during = 0;
@@ -75,6 +75,7 @@ int implied_dirs = 1;
int numeric_ids = 0;
int force_delete = 0;
int io_timeout = 0;
int allowed_lull = 0;
char *files_from = NULL;
int filesfrom_fd = -1;
char *filesfrom_host = NULL;
@@ -150,7 +151,6 @@ char *dest_option = NULL;
int verbose = 0;
int quiet = 0;
int itemize_changes = 0;
int log_before_transfer = 0;
int log_format_has_i = 0;
int log_format_has_o_or_i = 0;
@@ -163,6 +163,7 @@ char *batch_name = NULL;
static int daemon_opt; /* sets am_daemon after option error-reporting */
static int F_option_cnt = 0;
static int modify_window_set;
static int itemize_changes = 0;
static int refused_delete, refused_archive_part;
static int refused_partial, refused_progress, refused_delete_before;
static char *max_size_arg;
@@ -250,7 +251,7 @@ void usage(enum logcode F)
rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");
rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
@@ -330,8 +331,8 @@ void usage(enum logcode F)
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
rprintf(F," --include-from=FILE read include patterns from FILE\n");
rprintf(F," --files-from=FILE read list of source-file names from FILE\n");
rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n");
rprintf(F," --version print version number\n");
rprintf(F," -0, --from0 all *-from/filter files are delimited by 0s\n");
rprintf(F," --address=ADDRESS bind address for outgoing socket to daemon\n");
rprintf(F," --port=PORT specify double-colon alternate port number\n");
rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
rprintf(F," --no-blocking-io turn off blocking I/O when it is the default\n");
@@ -339,17 +340,19 @@ void usage(enum logcode F)
rprintf(F," --progress show progress during transfer\n");
rprintf(F," -P same as --partial --progress\n");
rprintf(F," -i, --itemize-changes output a change-summary for all updates\n");
rprintf(F," --log-format=FORMAT log file-transfers using specified format\n");
rprintf(F," --log-format=FORMAT output filenames using the specified format\n");
rprintf(F," --password-file=FILE read password from FILE\n");
rprintf(F," --list-only list the files instead of copying them\n");
rprintf(F," --bwlimit=KBPS limit I/O bandwidth; KBytes per second\n");
rprintf(F," --write-batch=FILE write a batched update to FILE\n");
rprintf(F," --only-write-batch=FILE like --write-batch but w/o updating destination\n");
rprintf(F," --read-batch=FILE read a batched update from FILE\n");
rprintf(F," --protocol=NUM force an older protocol version to be used\n");
#ifdef INET6
rprintf(F," -4, --ipv4 prefer IPv4\n");
rprintf(F," -6, --ipv6 prefer IPv6\n");
#endif
rprintf(F," --version print version number\n");
rprintf(F," -h, --help show this help screen\n");
rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
@@ -360,7 +363,7 @@ void usage(enum logcode F)
enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
@@ -424,7 +427,7 @@ static struct poptOption long_options[] = {
{"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 },
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
{"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
{"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
@@ -442,6 +445,7 @@ static struct poptOption long_options[] = {
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
{0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
{"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
{"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
@@ -450,6 +454,7 @@ static struct poptOption long_options[] = {
{"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
{"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
{"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
{"only-write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_ONLY_WRITE_BATCH, 0, 0 },
{"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
{"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
{"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
@@ -460,7 +465,6 @@ static struct poptOption long_options[] = {
{"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
#endif
/* All these options switch us into daemon-mode option-parsing. */
{"address", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
{"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
{"daemon", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
{"detach", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
@@ -617,6 +621,35 @@ static int count_args(const char **argv)
}
static OFF_T parse_size_arg(const char *size_arg)
{
const char *arg;
OFF_T size;
for (arg = size_arg; isdigit(*(uchar*)arg); arg++) {}
if (*arg == '.')
for (arg++; isdigit(*(uchar*)arg); arg++) {}
switch (*arg) {
case 'k': case 'K':
size = atof(size_arg) * 1024;
break;
case 'm': case 'M':
size = atof(size_arg) * 1024*1024;
break;
case 'g': case 'G':
size = atof(size_arg) * 1024*1024*1024;
break;
case '\0':
size = atof(size_arg);
break;
default:
size = 0;
break;
}
return size;
}
static void create_refuse_error(int which)
{
/* The "which" value is the index + OPT_REFUSED_BASE. */
@@ -791,33 +824,18 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
write_batch = 1;
break;
case OPT_ONLY_WRITE_BATCH:
/* batch_name is already set */
write_batch = -1;
break;
case OPT_READ_BATCH:
/* batch_name is already set */
read_batch = 1;
break;
case OPT_MAX_SIZE:
for (arg = max_size_arg; isdigit(*(uchar*)arg); arg++) {}
if (*arg == '.')
for (arg++; isdigit(*(uchar*)arg); arg++) {}
switch (*arg) {
case 'k': case 'K':
max_size = atof(max_size_arg) * 1024;
break;
case 'm': case 'M':
max_size = atof(max_size_arg) * 1024*1024;
break;
case 'g': case 'G':
max_size = atof(max_size_arg) * 1024*1024*1024;
break;
case '\0':
max_size = atof(max_size_arg);
break;
default:
max_size = 0;
break;
}
if (max_size <= 0) {
if ((max_size = parse_size_arg(max_size_arg)) <= 0) {
snprintf(err_buf, sizeof err_buf,
"--max-size value is invalid: %s\n",
max_size_arg);
@@ -825,11 +843,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
}
break;
case OPT_TIMEOUT:
if (io_timeout && io_timeout < select_timeout)
select_timeout = io_timeout;
break;
case OPT_LINK_DEST:
#ifdef HAVE_LINK
link_dest = 1;
@@ -901,7 +914,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
"--write-batch and --read-batch can not be used together\n");
return 0;
}
if (write_batch || read_batch) {
if (write_batch > 0 || read_batch) {
if (am_server) {
rprintf(FINFO,
"ignoring --%s-batch option sent to server\n",
@@ -1078,10 +1091,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
omit_dir_times = 1;
if (log_format) {
if (strstr(log_format, "%i") != NULL)
if (log_format_has(log_format, 'i'))
log_format_has_i = 1;
if (strstr(log_format, "%b") == NULL
&& strstr(log_format, "%c") == NULL)
if (!log_format_has(log_format, 'b')
&& !log_format_has(log_format, 'c'))
log_before_transfer = !am_server;
} else if (itemize_changes) {
log_format = "%i %n%L";
@@ -1093,12 +1106,16 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
&& !am_server)
verbose = 1;
if (dry_run)
do_xfers = 0;
set_io_timeout(io_timeout);
if (verbose && !log_format) {
log_format = "%n%L";
log_before_transfer = !am_server;
}
if (log_format_has_i
|| (log_format && strstr(log_format, "%o") != NULL))
if (log_format_has_i || log_format_has(log_format, 'o'))
log_format_has_o_or_i = 1;
if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
@@ -1215,7 +1232,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
**/
void server_options(char **args,int *argc)
{
static char argstr[50+MAX_BASIS_DIRS*2];
static char argstr[64];
int ac = *argc;
char *arg;
@@ -1246,7 +1263,7 @@ void server_options(char **args,int *argc)
argstr[x++] = 'b';
if (update_only)
argstr[x++] = 'u';
if (dry_run)
if (!do_xfers) /* NOT "dry_run"! */
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
@@ -1374,6 +1391,8 @@ void server_options(char **args,int *argc)
args[ac++] = "--delete-after";
if (force_delete)
args[ac++] = "--force";
if (write_batch < 0)
args[ac++] = "--only-write-batch=X";
}
if (size_only)

View File

@@ -1,6 +1,6 @@
Summary: A program for synchronizing files over a network.
Name: rsync
Version: 2.6.4pre4
Version: 2.6.5
Release: 1
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz

5
pipe.c
View File

@@ -25,7 +25,6 @@ extern int am_sender;
extern int am_server;
extern int blocking_io;
extern int orig_umask;
extern int write_batch;
extern int filesfrom_fd;
/**
@@ -128,10 +127,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
am_sender = !am_sender;
am_server = 1;
/* The server side never writes the batch, even if it
* is local (it makes the logic easier elsewhere). */
write_batch = 0;
if (!am_sender)
filesfrom_fd = -1;

View File

@@ -21,7 +21,7 @@
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_daemon;
extern int am_server;
extern int do_progress;
@@ -30,6 +30,7 @@ extern int log_format_has_i;
extern int daemon_log_format_has_i;
extern int csum_length;
extern int read_batch;
extern int write_batch;
extern int batch_gen_fd;
extern int protocol_version;
extern int relative_paths;
@@ -53,7 +54,7 @@ extern char *log_format;
extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
extern struct file_list *the_file_list;
extern struct filter_list_struct server_filter_list;
#define SLOT_SIZE (16*1024) /* Desired size in bytes */
@@ -62,6 +63,7 @@ extern struct filter_list_struct server_filter_list;
static uint32 **delayed_bits = NULL;
static int delayed_slot_cnt = 0;
static int phase = 0;
static void init_delayed_bits(int max_ndx)
{
@@ -266,7 +268,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
continue;
}
}
if (fd != -1 && write_file(fd, map, len) != (int)len)
if (fd != -1 && map && write_file(fd, map, len) != (int)len)
goto report_write_error;
offset += len;
}
@@ -343,6 +345,22 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
}
}
static int get_next_gen_i(int batch_gen_fd, int next_gen_i, int desired_i)
{
while (next_gen_i < desired_i) {
if (next_gen_i >= 0) {
rprintf(FINFO,
"(No batched update for%s \"%s\")\n",
phase ? " resend of" : "",
safe_fname(f_name(the_file_list->files[next_gen_i])));
}
next_gen_i = read_int(batch_gen_fd);
if (next_gen_i == -1)
next_gen_i = the_file_list->count;
}
return next_gen_i;
}
/**
* main routine for receiver process.
@@ -365,7 +383,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
int save_make_backups = make_backups;
int itemizing = am_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
int max_phase = protocol_version >= 29 ? 2 : 1;
int i, recv_ok;
if (verbose > 2)
@@ -385,8 +403,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
i = read_int(f_in);
if (i == -1) {
if (read_batch) {
if (next_gen_i != flist->count)
while (read_int(batch_gen_fd) != -1) {}
get_next_gen_i(batch_gen_fd, next_gen_i,
flist->count);
next_gen_i = -1;
}
if (++phase > max_phase)
@@ -435,22 +453,24 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
exit_cleanup(RERR_PROTOCOL);
}
if (dry_run) { /* log the transfer */
if (!do_xfers) { /* log the transfer */
if (!am_server && log_format)
log_item(file, &stats, iflags, NULL);
if (read_batch)
discard_receive_data(f_in, file->length);
continue;
}
if (write_batch < 0) {
log_item(file, &stats, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, file->length);
continue;
}
if (read_batch) {
while (i > next_gen_i) {
next_gen_i = read_int(batch_gen_fd);
if (next_gen_i == -1)
next_gen_i = flist->count;
}
next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i);
if (i < next_gen_i) {
rprintf(FINFO, "skipping update for \"%s\"\n",
rprintf(FINFO, "(Skipping batched update for \"%s\")\n",
safe_fname(fname));
discard_receive_data(f_in, file->length);
continue;

11
rsync.h
View File

@@ -103,8 +103,8 @@
#define IOERR_DEL_LIMIT (1<<2)
#define MAX_ARGS 1000
#define MAX_BASIS_DIRS 20
#define MAX_SERVER_ARGS (MAX_BASIS_DIRS*2 + 100)
#define MPLEX_BASE 7
@@ -139,7 +139,6 @@
#define DEL_TERSE (1<<3)
/* For use by the itemize_changes code */
#define ITEM_DUMMY_BIT (1<<0)
#define ITEM_REPORT_CHECKSUM (1<<1)
#define ITEM_REPORT_SIZE (1<<2)
#define ITEM_REPORT_TIME (1<<3)
@@ -675,8 +674,12 @@ extern char *sys_errlist[];
extern int errno;
#endif
#define SUPPORT_LINKS HAVE_READLINK
#define SUPPORT_HARD_LINKS HAVE_LINK
#ifdef HAVE_READLINK
#define SUPPORT_LINKS 1
#endif
#ifdef HAVE_LINK
#define SUPPORT_HARD_LINKS 1
#endif
#define SIGNAL_CAST (RETSIGTYPE (*)())

257
rsync.yo
View File

@@ -1,11 +1,11 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(28 Mar 2005)()()
manpage(rsync)(1)(1 Jun 2005)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpagesynopsis()
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
rsync [OPTION]... [USER@]HOST:SRC DEST
rsync [OPTION]... [USER@]HOST:SRC [DEST]
rsync [OPTION]... SRC [SRC]... DEST
@@ -38,47 +38,39 @@ itemize(
it() can use any transparent remote shell, including ssh or rsh
it() does not require root privileges
it() pipelining of file transfers to minimize latency costs
it() support for anonymous or authenticated rsync servers (ideal for
it() support for anonymous or authenticated rsync daemons (ideal for
mirroring)
)
manpagesection(GENERAL)
There are eight different ways of using rsync. They are:
Rsync copies files either to or from a remote host, or locally on the
current host (it does not support copying files between two remote hosts).
itemize(
it() for copying local files. This is invoked when neither
source nor destination path contains a : separator
it() for copying from the local machine to a remote machine using
a remote shell program as the transport (such as ssh or
rsh). This is invoked when the destination path contains a
single : separator.
it() for copying from a remote machine to the local machine
using a remote shell program. This is invoked when the source
contains a : separator.
it() for copying from a remote rsync server to the local
machine. This is invoked when the source path contains a ::
separator or an rsync:// URL.
it() for copying from the local machine to a remote rsync
server. This is invoked when the destination path contains a ::
separator or an rsync:// URL.
it() for copying from a remote machine using a remote shell
program as the transport, using rsync server on the remote
machine. This is invoked when the source path contains a ::
separator and the bf(--rsh=COMMAND) (aka "bf(-e COMMAND)") option is
also provided.
it() for copying from the local machine to a remote machine
using a remote shell program as the transport, using rsync
server on the remote machine. This is invoked when the
destination path contains a :: separator and the
bf(--rsh=COMMAND) option is also provided.
it() for listing files on a remote machine. This is done the
same way as rsync transfers except that you leave off the
local destination.
)
There are two different ways for rsync to contact a remote system: using a
remote-shell program as the transport (such as ssh or rsh) or contacting an
rsync daemon directly via TCP. The remote-shell transport is used whenever
the source or destination path contains a single colon (:) separator after
a host specification. Contacting an rsync daemon directly happens when the
source or destination path contains a double colon (::) separator after a
host specification, OR when an rsync:// URL is specified.
Note that in all cases (other than listing) at least one of the source
and destination paths must be local.
As a special case, if a remote source is specified without a destination,
the remote files are listed in an output format similar to "ls -l".
As expected, if neither the source or destination path specify a remote
host, the copy occurs locally (see also the bf(--list-only) option).
Finally, it is possible to use a remote-shell transport to contact a remote
host and then to spawn a single-use rsync daemon. This allows the use of
some of the daemon features (such as named modules) without having to run a
daemon as a service. To achieve this, invoke rsync with an explicit
bf(--rsh=COMMAND) (aka "bf(-e COMMAND)") option combined with either the
source or destination path specified as an rsync daemon (i.e. either a ::
separator or an rsync:// URL). In this case, rsync contacts the remote
host specified using the specified remote shell, and then starts a
single-use rsync daemon to deal with that copy request. See the section
"CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM" below.
manpagesection(SETUP)
@@ -139,6 +131,15 @@ tt(rsync -av /src/foo /dest)nl()
tt(rsync -av /src/foo/ /dest/foo)nl()
)
Note also that host and module references don't require a trailing slash to
copy the contents of the default directory. For example, both of these
copy the remote directory's contents into "/dest":
quote(
tt(rsync -av host: /dest)nl()
tt(rsync -av host::module /dest)nl()
)
You can also use rsync in local-only mode, where both the source and
destination don't have a ':' in the name. In this case it behaves like
an improved copy command.
@@ -178,10 +179,10 @@ tt(rsync -av host:file?name?with?spaces /dest)nl()
This latter example assumes that your shell passes through unmatched
wildcards. If it complains about "no match", put the name in quotes.
manpagesection(CONNECTING TO AN RSYNC SERVER)
manpagesection(CONNECTING TO AN RSYNC DAEMON)
It is also possible to use rsync without a remote shell as the
transport. In this case you will connect to a remote rsync server
transport. In this case you will connect to a remote rsync daemon
running on TCP port 873.
You may establish the connection via a web proxy by setting the
@@ -195,15 +196,15 @@ that:
itemize(
it() you either use a double colon :: instead of a single colon to
separate the hostname from the path, or you use an rsync:// URL.
it() the remote server may print a message of the day when you
it() the remote daemon may print a message of the day when you
connect.
it() if you specify no path name on the remote server then the
list of accessible paths on the server will be shown.
it() if you specify no path name on the remote daemon then the
list of accessible paths on the daemon will be shown.
it() if you specify no local destination then a listing of the
specified files on the remote server is provided.
specified files on the remote daemon is provided.
)
Some paths on the remote server may require authentication. If so then
Some paths on the remote daemon may require authentication. If so then
you will receive a password prompt when you connect. You can avoid the
password prompt by setting the environment variable RSYNC_PASSWORD to
the password you want to use or using the bf(--password-file) option. This
@@ -212,24 +213,24 @@ may be useful when scripting rsync.
WARNING: On some systems environment variables are visible to all
users. On those systems using bf(--password-file) is recommended.
manpagesection(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
manpagesection(CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
It is sometimes useful to be able to set up file transfers using rsync
server capabilities on the remote machine, while still using ssh or
daemon capabilities on the remote machine, while still using ssh or
rsh for transport. This is especially useful when you want to connect
to a remote machine via ssh (for encryption or to get through a
firewall), but you still want to have access to the rsync server
features (see RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM,
firewall), but you still want to have access to the rsync daemon
features (see RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM,
below).
From the user's perspective, using rsync in this way is the same as
using it to connect to an rsync server, except that you must
using it to connect to an rsync daemon, except that you must
explicitly set the remote shell program on the command line with
bf(--rsh=COMMAND). (Setting RSYNC_RSH in the environment will not turn on
this functionality.)
In order to distinguish between the remote-shell user and the rsync
server user, you can use '-l user' on your remote-shell command:
daemon user, you can use '-l user' on your remote-shell command:
verb( rsync -av --rsh="ssh -l ssh-user" \
rsync-user@host::module[/path] local-path)
@@ -237,26 +238,26 @@ verb( rsync -av --rsh="ssh -l ssh-user" \
The "ssh-user" will be used at the ssh level; the "rsync-user" will be
used to check against the rsyncd.conf on the remote host.
manpagesection(RUNNING AN RSYNC SERVER)
manpagesection(RUNNING AN RSYNC DAEMON)
An rsync server is configured using a configuration file. Please see the
An rsync daemon is configured using a configuration file. Please see the
rsyncd.conf(5) man page for more information. By default the configuration
file is called /etc/rsyncd.conf, unless rsync is running over a remote
shell program and is not running as root; in that case, the default name
is rsyncd.conf in the current directory on the remote computer
(typically $HOME).
manpagesection(RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
manpagesection(RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
See the rsyncd.conf(5) man page for full information on the rsync
server configuration file.
daemon configuration file.
Several configuration options will not be available unless the remote
user is root (e.g. chroot, setuid/setgid, etc.). There is no need to
configure inetd or the services map to include the rsync server port
if you run an rsync server only via a remote shell program.
configure inetd or the services map to include the rsync daemon port
if you run an rsync daemon only via a remote shell program.
To run an rsync server out of a single-use ssh key, see this section
To run an rsync daemon out of a single-use ssh key, see this section
in the rsyncd.conf(5) man page.
manpagesection(EXAMPLES)
@@ -365,8 +366,8 @@ to the detailed description below for a complete description. verb(
--include=PATTERN don't exclude files matching PATTERN
--include-from=FILE read include patterns from FILE
--files-from=FILE read list of source-file names from FILE
-0, --from0 all *from file lists are delimited by nulls
--version print version number
-0, --from0 all *from/filter files are delimited by 0s
--address=ADDRESS bind address for outgoing socket to daemon
--port=PORT specify double-colon alternate port number
--blocking-io use blocking I/O for the remote shell
--no-blocking-io turn off blocking I/O when it is default
@@ -374,16 +375,18 @@ to the detailed description below for a complete description. verb(
--progress show progress during transfer
-P same as --partial --progress
-i, --itemize-changes output a change-summary for all updates
--log-format=FORMAT log file-transfers using specified format
--log-format=FORMAT output filenames using the specified format
--password-file=FILE read password from FILE
--list-only list the files instead of copying them
--bwlimit=KBPS limit I/O bandwidth; KBytes per second
--write-batch=FILE write a batched update to FILE
--only-write-batch=FILE like --write-batch but w/o updating dest
--read-batch=FILE read a batched update from FILE
--protocol=NUM force an older protocol version to be used
--checksum-seed=NUM set block/file checksum seed (advanced)
-4, --ipv4 prefer IPv4
-6, --ipv6 prefer IPv6
--version print version number
-h, --help show this help screen)
Rsync can also be run as a daemon, in which case the following options are
@@ -423,7 +426,7 @@ you are debugging rsync.
Note that the names of the transferred files that are output are done using
a default bf(--log-format) of "%n%L", which tells you just the name of the
file and, if the item is a symlink, where it points. At the single bf(-v)
file and, if the item is a link, where it points. At the single bf(-v)
level of verbosity, this does not mention when a file gets its attributes
changed. If you ask for an itemized list of changed attributes (either
bf(--itemize-changes) or adding "%i" to the bf(--log-format) setting), the
@@ -620,9 +623,10 @@ default.
dit(bf(-p, --perms)) This option causes rsync to set the destination
permissions to be the same as the source permissions.
Without this option, each new file gets its permissions set based on the
source file's permissions and the umask at the receiving end, while all
other files (including updated files) retain their existing permissions
Without this option, all existing files (including updated files) retain
their existing permissions, while each new file gets its permissions set
based on the source file's permissions, but masked by the receiving end's
umask setting
(which is the same behavior as other file-copy utilities, such as cp).
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
@@ -769,11 +773,11 @@ remote copies of rsync. Typically, rsync is configured to use ssh by
default, but you may prefer to use rsh on a local network.
If this option is used with bf([user@]host::module/path), then the
remote shell em(COMMAND) will be used to run an rsync server on the
remote shell em(COMMAND) will be used to run an rsync daemon on the
remote host, and all data will be transmitted through that remote
shell connection, rather than through a direct socket connection to a
running rsync server on the remote host. See the section "CONNECTING
TO AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM" above.
running rsync daemon on the remote host. See the section "CONNECTING
TO AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM" above.
Command-line arguments are permitted in COMMAND provided that COMMAND is
presented to rsync as a single argument. For example:
@@ -905,9 +909,14 @@ command:
quote(tt( rsync -a --files-from=/tmp/foo /usr remote:/backup))
If /tmp/foo contains the string "bin" (or even "/bin"), the /usr/bin
directory will be created as /backup/bin on the remote host (but the
contents of the /usr/bin dir would not be sent unless you specified bf(-r)
or the names were explicitly listed in /tmp/foo). Also keep in mind
directory will be created as /backup/bin on the remote host. If it
contains "bin/" (note the trailing slash), the immediate contents of
the directory would also be sent (without needing to be explicitly
mentioned in the file -- this began in version 2.6.4). In both cases,
if the bf(-r) option was enabled, that dir's entire hierarchy would
also be transferred (keep in mind that bf(-r) needs to be specified
explicitly with bf(--files-from), since it is not implied by bf(-a)).
Also note
that the effect of the (enabled by default) bf(--relative) option is to
duplicate only the path info that is read from the file -- it does not
force the duplication of the source-spec path (/usr in this case).
@@ -923,7 +932,7 @@ quote(tt( rsync -a --files-from=:/path/file-list src:/ /tmp/copy))
This would copy all the files specified in the /path/file-list file that
was located on the remote "src" host.
dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
dit(bf(-0, --from0)) This tells rsync that the rules/filenames it reads from a
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
This affects bf(--exclude-from), bf(--include-from), bf(--files-from), and any
merged files specified in a bf(--filter) rule.
@@ -1032,6 +1041,11 @@ dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
timeout in seconds. If no data is transferred for the specified time
then rsync will exit. The default is 0, which means no timeout.
dit(bf(--address)) By default rsync will bind to the wildcard address when
connecting to an rsync daemon. The bf(--address) option allows you to
specify a specific IP address (or hostname) to bind to. See also this
option in the bf(--daemon) mode section.
dit(bf(--port=PORT)) This specifies an alternate TCP port number to use
rather than the default of 873. This is only needed if you are using the
double-colon (::) syntax to connect with an rsync daemon (since the URL
@@ -1064,7 +1078,7 @@ quote(itemize(
(sent).
it() A bf(>) means that a file is being transferred to the local host
(received).
it() A bf(c) means that a local change/creation is occuring for the item
it() A bf(c) means that a local change/creation is occurring for the item
(such as the creation of a directory or the changing of a symlink, etc.).
it() A bf(h) means that the item is a hard-link to another item (requires
bf(--hard-links)).
@@ -1073,33 +1087,33 @@ quote(itemize(
))
The file-types that replace the bf(X) are: bf(f) for a file, a bf(d) for a
dir, an bf(L) for a symlink, and a bf(D) for a device.
directory, an bf(L) for a symlink, and a bf(D) for a device.
The other letters in the string above are the actual letters that
will be output if the associated attribute for the item is being updated or
a "." for no change. Three exceptions to this are: (1) a newly created
item replaces each letter with a "+", (2) an identical item replaces each
letter with a space, and (3) an unknown attribute replaces each letter with
a "?" (this happens when talking to an older rsync).
item replaces each letter with a "+", (2) an identical item replaces the
dots with spaces, and (3) an unknown attribute replaces each letter with
a "?" (this can happen when talking to an older rsync).
The attribute that is associated with each letter is as follows:
quote(itemize(
it() A bf(c) means the checksum of the file is different and will be
updated by the file transfer (requries bf(--checksum)).
updated by the file transfer (requires bf(--checksum)).
it() A bf(s) means the size of the file is different and will be updated
by the file transfer.
it() A bf(t) means the modification time is different and is being updated
to the server's value (requires bf(--times)). An alternate value of bf(T)
to the sender's value (requires bf(--times)). An alternate value of bf(T)
means that the time will be set to the transfer time, which happens
anytime a symlink is transferred, or when a file or device is transferred
without bf(--times).
it() A bf(p) means the permissions are different and are being updated to
the server's value (requires bf(--perms)).
the sender's value (requires bf(--perms)).
it() An bf(o) means the owner is different and is being updated to the
server's value (requires bf(--owner) and root privileges).
sender's value (requires bf(--owner) and root privileges).
it() A bf(g) means the group is different and is being updated to the
server's value (requires bf(--group) and the authority to set the group).
sender's value (requires bf(--group) and the authority to set the group).
it() The bf(a) is reserved for a future enhanced version that supports
extended file attributes, such as ACLs.
))
@@ -1120,7 +1134,7 @@ Specifying this option will mention each file, dir, etc. that gets updated
in a significant way (a transferred file, a recreated symlink/device, or a
touched directory) unless the itemized-changes escape (%i) is included in
the string, in which case the logging of names increases to mention any
item that is updated in any way (as long as the receiving side is version
item that is changed in any way (as long as the receiving side is at least
2.6.4). See the bf(--itemized-changes) option for a description of the
output of "%i".
@@ -1188,7 +1202,7 @@ option does not look for this environment value is (1) when bf(--inplace) was
specified (since bf(--inplace) conflicts with bf(--partial-dir)), or (2) when
bf(--delay-updates) was specified (see below).
For the purposes of the server-config's "refuse options" setting,
For the purposes of the daemon-config's "refuse options" setting,
bf(--partial-dir) does em(not) imply bf(--partial). This is so that a
refusal of the bf(--partial) option can be used to disallow the overwriting
of destination files with a partial transfer, while still allowing the
@@ -1202,7 +1216,7 @@ atomic. By default the files are placed into a directory named ".~tmp~" in
each file's destination directory, but you can override this by specifying
the bf(--partial-dir) option. (Note that RSYNC_PARTIAL_DIR has no effect
on this value, nor is bf(--partial-dir) considered to be implied for the
purposes of the server-config's "refuse options" setting.)
purposes of the daemon-config's "refuse options" setting.)
Conflicts with bf(--inplace).
This option uses more memory on the receiving side (one bit per file
@@ -1246,8 +1260,8 @@ purpose is to make it much easier to specify these two options for a long
transfer that may be interrupted.
dit(bf(--password-file)) This option allows you to provide a password
in a file for accessing a remote rsync server. Note that this option
is only useful when accessing an rsync server using the built in
in a file for accessing a remote rsync daemon. Note that this option
is only useful when accessing an rsync daemon using the built in
transport, not when using a remote shell as the transport. The file
must not be world readable. It should contain just the password as a
single line.
@@ -1255,9 +1269,11 @@ single line.
dit(bf(--list-only)) This option will cause the source files to be listed
instead of transferred. This option is inferred if there is no destination
specified, so you don't usually need to use it explicitly. However, it can
come in handy for a power user that wants to avoid the "bf(-r --exclude='/*/*')"
come in handy for a user that wants to avoid the "bf(-r --exclude='/*/*')"
options that rsync might use as a compatibility kluge when generating a
non-recursive listing.
non-recursive listing, or to list the files that are involved in a local
copy (since the destination path is not optional for a local copy, you
must specify this option explicitly and still include a destination).
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
transfer rate in kilobytes per second. This option is most effective when
@@ -1269,7 +1285,24 @@ of zero specifies no limit.
dit(bf(--write-batch=FILE)) Record a file that can later be applied to
another identical destination with bf(--read-batch). See the "BATCH MODE"
section for details.
section for details, and also the bf(--only-write-batch) option.
dit(bf(--only-write-batch=FILE)) Works like bf(--write-batch), except that
no updates are made on the destination system when creating the batch.
This lets you transport the changes to the destination system via some
other means and then apply the changes via bf(--read-batch).
Note that you can feel free to write the batch directly to some portable
media: if this media fills to capacity before the end of the transfer, you
can just apply that partial transfer to the destination and repeat the
whole process to get the rest of the changes (as long as you don't mind a
partially updated destination system while the multi-update cycle is
happening).
Also note that you only save bandwidth when pushing changes to a remote
system because this allows the batched data to be diverted from the sender
into the batch file without having to flow over the wire to the receiver
(when pulling, the sender is remote, and thus can't write the batch).
dit(bf(--read-batch=FILE)) Apply all of the changes stored in FILE, a
file previously generated by bf(--write-batch).
@@ -1280,9 +1313,9 @@ dit(bf(--protocol=NUM)) Force an older protocol version to be used. This
is useful for creating a batch file that is compatible with an older
version of rsync. For instance, if rsync 2.6.4 is being used with the
bf(--write-batch) option, but rsync 2.6.3 is what will be used to run the
bf(--read-batch) option, you should use "--protocol=28" (when creating the
batch file) to force the older protocol version to be used in the batch
file (assuming you can't upgrade the rsync on the reading system to 2.6.4).
bf(--read-batch) option, you should use "--protocol=28" when creating the
batch file to force the older protocol version to be used in the batch
file (assuming you can't upgrade the rsync on the reading system).
dit(bf(-4, --ipv4) or bf(-6, --ipv6)) Tells rsync to prefer IPv4/IPv6
when creating sockets. This only affects sockets that rsync has direct
@@ -1316,12 +1349,11 @@ become a background daemon. The daemon will read the config file
requests accordingly. See the rsyncd.conf(5) man page for more
details.
dit(bf(--address)) By default rsync will bind to the wildcard address
when run as a daemon with the bf(--daemon) option or when connecting to a
rsync server. The bf(--address) option allows you to specify a specific IP
address (or hostname) to bind to. This makes virtual hosting possible
in conjunction with the bf(--config) option. See also the "address" global
option in the rsyncd.conf manpage.
dit(bf(--address)) By default rsync will bind to the wildcard address when
run as a daemon with the bf(--daemon) option. The bf(--address) option
allows you to specify a specific IP address (or hostname) to bind to. This
makes virtual hosting possible in conjunction with the bf(--config) option.
See also the "address" global option in the rsyncd.conf manpage.
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
transfer rate in kilobytes per second for the data the daemon sends.
@@ -1567,7 +1599,7 @@ itemize(
default to having that modifier set. For instance, "merge,-/ .excl" would
treat the contents of .excl as absolute-path excludes,
while "dir-merge,s .filt" and ":sC" would each make all their
per-directory rules apply only on the server side.
per-directory rules apply only on the sending side.
)
The following modifiers are accepted after a "+" or "-":
@@ -1588,7 +1620,7 @@ itemize(
being transferred. The default is for a rule to affect both sides
unless bf(--delete-excluded) was specified, in which case default rules
become sender-side only. See also the hide (H) and show (S) rules,
which are an alternate way to specify server-side includes/excludes.
which are an alternate way to specify sending-side includes/excludes.
it() An bf(r) is used to indicate that the rule applies to the receiving
side. When a rule affects the receiving side, it prevents files from
being deleted. See the bf(s) modifier for more info. See also the
@@ -1922,12 +1954,31 @@ ensure the rsync module they copy does not include symbolic links to
bf(/etc/passwd) in the public section of the site. Using
bf(--copy-unsafe-links) will cause any links to be copied as the file
they point to on the destination. Using bf(--safe-links) will cause
unsafe links to be omitted altogether.
unsafe links to be omitted altogether. (Note that you must specify
bf(--links) for bf(--safe-links) to have any effect.)
Symbolic links are considered unsafe if they are absolute symlinks
(start with bf(/)), empty, or if they contain enough bf("..")
components to ascend from the directory being copied.
Here's a summary of how the symlink options are interpreted. The list is
in order of precedence, so if your combination of options isn't mentioned,
use the first line that is a complete subset of your options:
dit(bf(--copy-links)) Turn all symlinks into normal files (leaving no
symlinks for any other options to affect).
dit(bf(--links --copy-unsafe-links)) Turn all unsafe symlinks into files
and duplicate all safe symlinks.
dit(bf(--copy-unsafe-links)) Turn all unsafe symlinks into files, noisily
skip all safe symlinks.
dit(bf(--links --safe-links)) Duplicate safe symlinks and skip unsafe
ones.
dit(bf(--links)) Duplicate all symlinks.
manpagediagnostics()
rsync occasionally produces error messages that may seem a little
@@ -1997,7 +2048,7 @@ password allows you to run authenticated rsync connections to an rsync
daemon without user intervention. Note that this does not supply a
password to a shell transport such as ssh.
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
are used to determine the default username sent to an rsync server.
are used to determine the default username sent to an rsync daemon.
If neither is set, the username defaults to "nobody".
dit(bf(HOME)) The HOME environment variable is used to find the user's
default .cvsignore file.
@@ -2027,6 +2078,10 @@ see also the comments on the bf(--delete) option
Please report bugs! See the website at
url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.6.5 of rsync.
manpagesection(CREDITS)
rsync is distributed under the GNU public license. See the file

View File

@@ -1,6 +1,6 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(28 Mar 2005)()()
manpagename(rsyncd.conf)(configuration file for rsync server)
manpage(rsyncd.conf)(5)(1 Jun 2005)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
rsyncd.conf
@@ -8,7 +8,7 @@ rsyncd.conf
manpagedescription()
The rsyncd.conf file is the runtime configuration file for rsync when
run as an rsync server.
run as an rsync daemon.
The rsyncd.conf file controls authentication, access, logging and
available modules.
@@ -53,7 +53,7 @@ You can launch it either via inetd, as a stand-alone daemon, or from
an rsync client via a remote shell. If run as a stand-alone daemon then
just run the command "bf(rsync --daemon)" from a suitable startup script.
If run from an rsync client via a remote shell (by specifying both the
bf(--rsh) (bf(-e)) option and server mode with "::" or "rsync://"), the bf(--daemon)
bf(--rsh) (bf(-e)) option and daemon mode with "::" or "rsync://"), the bf(--daemon)
option is automatically passed to the remote side.
When run via inetd you should add a line like this to /etc/services:
@@ -68,7 +68,7 @@ Replace "/usr/bin/rsync" with the path to where you have rsync installed on
your system. You will then need to send inetd a HUP signal to tell it to
reread its config file.
Note that you should not send the rsync server a HUP signal to force
Note that you should bf(not) send the rsync daemon a HUP signal to force
it to reread the tt(rsyncd.conf) file. The file is re-read on each client
connection.
@@ -90,19 +90,30 @@ is no motd file.
dit(bf(log file)) The "log file" option tells the rsync daemon to log
messages to that file rather than using syslog. This is particularly
useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs.
chrooted programs. If the daemon fails to open to specified file, it
will fall back to using syslog and output an error about the failure.
(Note that a failure to open the specified log file used to be a fatal
error.)
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process ID to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync server. You may use any standard syslog facility name which is
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is 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
is being run by inetd, and is superseded by the bf(--port) command-line option.
dit(bf(address)) You can override the default IP address the daemon
will listen on by specifying this value. This is ignored if the daemon is
being run by inetd, and is superseded by the bf(--address) command-line option.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
@@ -126,11 +137,11 @@ dit(bf(comment)) The "comment" option specifies a description string
that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the servers
dit(bf(path)) The "path" option specifies the directory in the daemon's
filesystem to make available in this module. You must specify this option
for each module in tt(rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges,
@@ -157,7 +168,7 @@ differently from your normal system. For example, you could abbreviate
the list of users and groups. Also, you can protect this information from
being downloaded/uploaded by adding an exclude rule to the rsync.conf file
(e.g. "exclude = /etc/**"). Note that having the exclusion affect uploads
is a relatively new feature in rsync, so make sure your server is running
is a relatively new feature in rsync, so make sure your daemon is
at least 2.6.3 to effect this. Also note that it is safest to exclude a
directory and all its contents combining the rule "/some/dir/" with the
rule "/some/dir/**" just to be sure that rsync will not allow deeper
@@ -165,14 +176,6 @@ access to some of the excluded files inside the directory (rsync tries to
do this automatically, but you might as well specify both to be extra
sure).
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
is being run by inetd, and is superseded by the bf(--port) command-line option.
dit(bf(address)) You can override the default IP address the daemon
will listen on by specifying this value. This is ignored if the daemon is
being run by inetd, and is superseded by the bf(--address) command-line option.
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow.
Any clients connecting when the maximum has been reached will receive a
@@ -185,7 +188,7 @@ generate (since the information goes into the log file). The default is 1,
which allows the client to request one level of verbosity.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync server uses record
support the "max connections" option. The rsync daemon uses record
locking on this file to ensure that the max connections limit is not
exceeded for the modules sharing the lock file.
The default is tt(/var/run/rsyncd.lock).
@@ -193,13 +196,13 @@ The default is tt(/var/run/rsyncd.lock).
dit(bf(read only)) The "read only" option determines whether clients
will be able to upload files or not. If "read only" is true then any
attempted uploads will fail. If "read only" is false then uploads will
be possible if file permissions on the server allow them. The default
be possible if file permissions on the daemon side allow them. The default
is for all modules to be read only.
dit(bf(write only)) The "write only" option determines whether clients
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 server allow them. The
will be possible if file permissions on the daemon side allow them. The
default is for this option to be disabled.
dit(bf(list)) The "list" option determines if this module should be
@@ -219,30 +222,30 @@ was run as root. This complements the "uid" option. The default is gid -2,
which is normally the group "nobody".
dit(bf(filter)) The "filter" option allows you to specify a space-separated
list of filter rules that the server will not allow to be read or written.
list of filter rules that the daemon will not allow to be read or written.
This is only superficially equivalent to the client specifying these
patterns with the bf(--filter) option. Only one "filter" option may be
specified, but it may contain as many rules as you like, including
merge-file rules. Note that per-directory merge-file rules do not provide
as much protection as global rules, but they can be used to make bf(--delete)
work better when a client downloads the server's files (if the per-dir
work better when a client downloads the daemon's files (if the per-dir
merge files are included in the transfer).
dit(bf(exclude)) The "exclude" option allows you to specify a
space-separated list of patterns that the server will not allow to be read
space-separated list of patterns that the daemon will not allow to be read
or written. This is only superficially equivalent to the client
specifying these patterns with the bf(--exclude) option. Only one "exclude"
option may be specified, but you can use "-" and "+" before patterns to
specify exclude/include.
Because this exclude list is not passed to the client it only applies on
the server: that is, it excludes files received by a client when receiving
from a server and files deleted on a server when sending to a server, but
the daemon: that is, it excludes files received by a client when receiving
from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a server.
from a daemon.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the server that contains exclude patterns, one per line.
on the daemon that contains exclude patterns, one per line.
This is only superficially equivalent
to the client specifying the bf(--exclude-from) option with an equivalent file.
See the "exclude" option above.
@@ -250,14 +253,14 @@ See the "exclude" option above.
dit(bf(include)) The "include" option allows you to specify a
space-separated list of patterns which rsync should not exclude. This is
only superficially equivalent to the client specifying these patterns with
the bf(--include) option because it applies only on the server. This is
the bf(--include) option because it applies only on the daemon. This is
useful as it allows you to build up quite complex exclude/include rules.
Only one "include" option may be specified, but you can use "+" and "-"
before patterns to switch include/exclude. See the "exclude" option
above.
dit(bf(include from)) The "include from" option specifies a filename
on the server that contains include patterns, one per line. This is
on the daemon that contains include patterns, one per line. This is
only superficially equivalent to the client specifying the
bf(--include-from) option with a equivalent file.
See the "exclude" option above.
@@ -273,10 +276,10 @@ usernames are passwords are stored in the file specified by the
"secrets file" option. The default is for all users to be able to
connect without a password (this is called "anonymous rsync").
See also the bf(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL
PROGRAM) section in rsync(1) for information on how handle an
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
PROGRAM" section in 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 server.
username when using a remote shell to connect to an rsync daemon.
dit(bf(secrets file)) The "secrets file" option specifies the name of
a file that contains the username:password pairs used for
@@ -351,21 +354,21 @@ rejected. See the "hosts allow" option for more information.
The default is no "hosts deny" option, which means all hosts can connect.
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
ignore I/O errors on the server when deciding whether to run the delete
ignore I/O errors on the daemon when deciding whether to run the delete
phase of the transfer. Normally rsync skips the bf(--delete) step if any
I/O errors have occurred in order to prevent disastrous deletion due
to a temporary resource shortage or other I/O error. In some cases this
test is counter productive so you can use this option to turn off this
behavior.
dit(bf(ignore nonreadable)) This tells the rsync server to completely
dit(bf(ignore nonreadable)) This tells the rsync daemon to completely
ignore files that are not readable by the user. This is useful for
public archives that may have some non-readable files among the
directories, and the sysadmin doesn't want those files to be seen at all.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. The server always logs the transfer at the end, so
used by ftp daemons. The daemon always logs the transfer at the end, so
if a transfer is aborted, no mention will be made in the log file.
If you want to customize the log lines, see the "log format" option.
@@ -373,7 +376,9 @@ If you want to customize the log lines, see the "log format" option.
dit(bf(log format)) The "log format" option allows you to specify the
format used for logging file transfers when transfer logging is enabled.
The format is a text string containing embedded single-character escape
sequences prefixed with a percent (%) character.
sequences prefixed with a percent (%) character. An optional numeric
field width may also be specified between the percent and the escape
letter (e.g. "%-50n %8l %07p").
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
is always prefixed when using the "log file" option.
@@ -408,19 +413,19 @@ For a list of what the characters mean that are output by "%i", see the
bf(--itemize-changes) option in the rsync manpage.
Note that some of the logged output changes when talking with older
rsync versions. For instance, deleted files were only logged as verbose
rsync versions. For instance, deleted files were only output as verbose
messages prior to rsync 2.6.4.
dit(bf(timeout)) The "timeout" option allows you to override the
clients choice for I/O timeout for this module. Using this option you
can ensure that rsync won't wait on a dead client forever. The timeout
is specified in seconds. A value of zero means no timeout and is the
default. A good choice for anonymous rsync servers may be 600 (giving
default. A good choice for anonymous rsync daemons may be 600 (giving
a 10 minute timeout).
dit(bf(refuse options)) The "refuse options" option allows you to
specify a space-separated list of rsync command line options that will
be refused by your rsync server.
be refused by your rsync daemon.
You may specify the full option name, its one-letter abbreviation, or a
wild-card string that matches multiple options.
For example, this would refuse bf(--checksum) (bf(-c)) and all the various
@@ -435,7 +440,7 @@ bf(remove-sent-files) when the daemon is the sender; if you want the latter
without the former, instead refuse "delete-*" -- that refuses all the
delete modes without affecting bf(--remove-sent-files).
When an option is refused, the server prints an error message and exits.
When an option is refused, the daemon prints an error message and exits.
To prevent all compression, you can use "dont compress = *" (see below)
instead of "refuse options = compress" to avoid returning an error to a
client that requests compression.
@@ -463,7 +468,7 @@ realize that this is not a "military strength" authentication system.
It should be good enough for most purposes but if you want really top
quality security then I recommend that you run rsync over ssh.
Also note that the rsync server protocol does not currently provide any
Also note that the rsync daemon protocol does not currently provide any
encryption of the data that is transferred over the connection. Only
authentication is provided. Use ssh as the transport if you want
encryption.
@@ -471,16 +476,16 @@ encryption.
Future versions of rsync may support SSL for better authentication and
encryption, but that is still being investigated.
manpagesection(RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
manpagesection(RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
If rsync is run with both the bf(--daemon) and bf(--rsh) (bf(-e)) options, it will
spawn an rsync daemon using a remote shell connection. Several
configuration options will not be available unless the remote user is
root (e.g. chroot, setuid/setgid, etc.). There is no need to configure
inetd or the services map to include the rsync server port if you run an
rsync server only via a remote shell program.
inetd or the services map to include the rsync daemon port if you run an
rsync daemon only via a remote shell program.
ADVANCED: To run an rsync server out of a single-use ssh key, use the
ADVANCED: To run an rsync daemon out of a single-use ssh key, use the
"command=em(COMMAND)" syntax in the remote user's authorized_keys entry,
where command would be
@@ -560,15 +565,12 @@ manpagediagnostics()
manpagebugs()
The rsync server does not send all types of error messages to the
client. this means a client may be mystified as to why a transfer
failed. The error will have been logged by syslog on the server.
Please report bugs! The rsync bug tracking system is online at
url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.x of rsync.
This man page is current for version 2.6.5 of rsync.
manpagesection(CREDITS)
@@ -589,7 +591,7 @@ Gailly and Mark Adler.
manpagesection(THANKS)
Thanks to Warren Stanley for his original idea and patch for the rsync
server. Thanks to Karsten Thygesen for his many suggestions and
daemon. Thanks to Karsten Thygesen for his many suggestions and
documentation!
manpageauthor()

View File

@@ -20,7 +20,7 @@
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int do_xfers;
extern int am_server;
extern int am_daemon;
extern int log_before_transfer;
@@ -28,12 +28,15 @@ extern int log_format_has_i;
extern int daemon_log_format_has_i;
extern int csum_length;
extern int io_error;
extern int allowed_lull;
extern int protocol_version;
extern int remove_sent_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 struct stats stats;
extern struct file_list *the_file_list;
extern char *log_format;
@@ -54,6 +57,7 @@ static struct sum_struct *receive_sums(int f)
{
struct sum_struct *s;
int32 i;
int lull_mod = allowed_lull * 5;
OFF_T offset = 0;
if (!(s = new(struct sum_struct)))
@@ -87,6 +91,9 @@ 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 (verbose > 3) {
rprintf(FINFO,
"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
@@ -173,10 +180,6 @@ int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
}
*len_ptr = len;
/* Temporary handling of 2.6.4pre3 */
if (iflags & ITEM_DUMMY_BIT && iflags & (ITEM_LOCAL_CHANGE|ITEM_TRANSFER))
iflags &= ~ITEM_DUMMY_BIT;
if (iflags & ITEM_TRANSFER) {
if (!S_ISREG(the_file_list->files[ndx]->mode)) {
rprintf(FERROR,
@@ -208,6 +211,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
int save_make_backups = make_backups;
int itemizing = am_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
int f_xfer = write_batch < 0 ? batch_fd : f_out;
int i, j;
if (verbose > 2)
@@ -266,7 +270,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
if (dry_run) { /* log the transfer */
if (!do_xfers) { /* log the transfer */
if (!am_server && log_format)
log_item(file, &stats, iflags, NULL);
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
@@ -323,7 +327,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
write_sum_head(f_out, s);
write_sum_head(f_xfer, s);
if (verbose > 2) {
rprintf(FINFO, "calling match_sums %s\n",
@@ -337,7 +341,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
set_compression(fname);
match_sums(f_out, s, mbuf, st.st_size);
match_sums(f_xfer, s, mbuf, st.st_size);
if (do_progress)
end_progress(st.st_size);

View File

@@ -127,7 +127,7 @@ static int establish_proxy_connection(int fd, char *host, int port,
* if this fails.
**/
int try_bind_local(int s, int ai_family, int ai_socktype,
const char *bind_address)
const char *bind_addr)
{
int error;
struct addrinfo bhints, *bres_all, *r;
@@ -136,9 +136,9 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
bhints.ai_family = ai_family;
bhints.ai_socktype = ai_socktype;
bhints.ai_flags = AI_PASSIVE;
if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
if ((error = getaddrinfo(bind_addr, NULL, &bhints, &bres_all))) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
bind_address, gai_strerror(error));
bind_addr, gai_strerror(error));
return -1;
}
@@ -172,12 +172,12 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
* reachable, perhaps because we can't e.g. route ipv6 to that network
* but we can get ip4 packets through.
*
* @param bind_address Local address to use. Normally NULL to bind
* @param 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.
**/
int open_socket_out(char *host, int port, const char *bind_address,
int open_socket_out(char *host, int port, const char *bind_addr,
int af_hint)
{
int type = SOCK_STREAM;
@@ -253,9 +253,9 @@ int open_socket_out(char *host, int port, const char *bind_address,
if (s < 0)
continue;
if (bind_address
if (bind_addr
&& try_bind_local(s, res->ai_family, type,
bind_address) == -1) {
bind_addr) == -1) {
close(s);
s = -1;
continue;
@@ -293,9 +293,9 @@ int open_socket_out(char *host, int port, const char *bind_address,
*
* This is based on the Samba LIBSMB_PROG feature.
*
* @param bind_address Local address to use. Normally NULL to get the stack default.
* @param 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_address,
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
int af_hint)
{
char *prog = getenv("RSYNC_CONNECT_PROG");
@@ -307,7 +307,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
}
if (prog)
return sock_exec(prog);
return open_socket_out(host, port, bind_address, af_hint);
return open_socket_out(host, port, bind_addr, af_hint);
}
@@ -322,10 +322,10 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
* We return an array of file-descriptors to the sockets, with a trailing
* -1 value to indicate the end of the list.
*
* @param bind_address Local address to bind, or NULL to allow it to
* @param 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_address,
static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
int one = 1;
@@ -339,10 +339,10 @@ static int *open_socket_in(int type, int port, const char *bind_address,
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE;
snprintf(portbuf, sizeof portbuf, "%d", port);
error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
error = getaddrinfo(bind_addr, portbuf, &hints, &all_ai);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
bind_address, gai_strerror(error));
bind_addr, gai_strerror(error));
return NULL;
}
@@ -478,7 +478,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
/* close log file before the potentially very long select so
* file can be trimmed by another process instead of growing
* forever */
log_close();
logfile_close();
#ifdef FD_COPY
FD_COPY(&deffds, &fds);
@@ -507,8 +507,8 @@ void start_accept_loop(int port, int (*fn)(int, int))
for (i = 0; sp[i] >= 0; i++)
close(sp[i]);
/* Re-open log file in child before possibly giving
* up privileges (see log_close() above). */
log_open();
* up privileges (see logfile_close() above). */
logfile_reopen();
ret = fn(fd, fd);
close_all();
_exit(ret);

View File

@@ -1,9 +1,9 @@
#!/usr/bin/perl
#
# This script lets you update a hierarchy of files in an atomic way by
# first creating a new hierarchy using --link-dest to rsync, and then
# swapping the hierarchy into place. See the usage message for more
# details and some important caveats!
# first creating a new hierarchy using rsync's --link-dest option, and
# then swapping the hierarchy into place. **See the usage message for
# more details and some important caveats!**
use strict;
use Cwd 'abs_path';

42
support/cvs2includes Executable file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/perl
#
# This script finds all CVS/Entries files in the current directory and below
# and creates a local .cvsinclude file with non-inherited rules including each
# checked-in file. Then, use this option whenever using --cvs-exclude (-C):
#
# -f ': .cvsinclude'
#
# That ensures that all checked-in files/dirs are included in the transfer.
# (You could alternately put ": .cvsinclude" into an .rsync-filter file and
# use the -F option, which is easier to type.)
#
# The downside is that you need to remember to re-run cvs2includes whenever
# You add a new file to the project.
use strict;
open(FIND, 'find . -name CVS -type d |') or die $!;
while (<FIND>) {
chomp;
s#^\./##;
my $entries = "$_/Entries";
s/CVS$/.cvsinclude/;
my $filter = $_;
open(ENTRIES, $entries) or die "Unable to open $entries: $!\n";
my @includes;
while (<ENTRIES>) {
push(@includes, $1) if m#/(.+?)/#;
}
close ENTRIES;
if (@includes) {
open(FILTER, ">$filter") or die "Unable to write $filter: $!\n";
print FILTER '+ /', join("\n+ /", @includes), "\n";
close FILTER;
print "Updated $filter\n";
} elsif (-f $filter) {
unlink($filter);
print "Removed $filter\n";
}
}
close FIND;

View File

@@ -20,7 +20,7 @@
# 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
# though this command:
# through this command:
#
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/

View File

@@ -31,8 +31,8 @@ die "Not invoked via sshd\n$Usage" unless defined $command;
die "SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ /^rsync\s/;
die "$0 -ro: sending to read-only server not allowed\n"
if $ro and $command !~ /^rsync --server --sender /;
die "$0 -ro: use of --remove-sent-files with read-only server not allowed\n"
if $ro and $command =~ /\s--remove-sent-files/;
die "$0 -ro: use of $1 with read-only server not allowed\n"
if $ro and $command =~ /\s(--remove-\S+)/;
my ($cmd,$dir) = $command =~ /^(rsync\s+(?:-[-a-zA-Z]+\s+)+\.) ?("[^"]*"|[^\s"]*)$/;
die "$0: invalid rsync-command syntax or options\n" if !defined $cmd;

View File

@@ -243,7 +243,7 @@ int do_fstat(int fd, STRUCT_STAT *st)
OFF_T do_lseek(int fd, OFF_T offset, int whence)
{
#if SIZEOF_OFF64_T
#ifdef HAVE_LSEEK64
off64_t lseek64();
return lseek64(fd, offset, whence);
#else

View File

@@ -35,15 +35,20 @@ for fn in name1 name2; do
mv "$todir/$fn~" "$todir/$fn"
done
checkit "$RSYNC -avv --no-whole-file --backup --backup-dir=\"$bakdir\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
echo deleted-file >"$todir/dname"
cp -p "$todir/dname" "$chkdir"
checkit "$RSYNC -avv --no-whole-file --delete-after \
--backup --backup-dir=\"$bakdir\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
| tee "$outfile"
for fn in name1 name2; do
grep "backed up $fn to .*/$fn$" "$outfile" >/dev/null || test_fail "no backup message output for $fn"
done
diff -r $diffopt "$chkdir" "$bakdir" || test_fail "backup dir contents are bogus"
rm "$bakdir/dname"
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
checkit "$RSYNC -avv --del \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
cat $srcdir/[efgr]*.[ch] > "$name1"
cat $srcdir/[ew]*.[ch] > "$name2"

View File

@@ -20,7 +20,7 @@ rm "$todir/text"
runtest "one file" 'checkit "$RSYNC -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
echo "extra line" >> "$todir/text"
runtest "extra data" 'checkit "$RSYNC -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
runtest "extra data" 'checkit "$RSYNC -avH --no-whole-file \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
cp "$fromdir/text" "$todir/ThisShouldGo"
runtest " --delete" 'checkit "$RSYNC --delete -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'

View File

@@ -30,8 +30,34 @@ echo "This is the file" > "$name1"
ln "$name1" "$name2" || fail "Can't create hardlink"
ln "$name2" "$name3" || fail "Can't create hardlink"
cp "$name2" "$name4" || fail "Can't copy file"
cat $srcdir/*.c >"$fromdir/text"
checkit "$RSYNC -aHivv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
echo "extra extra" >>"$todir/name1"
checkit "$RSYNC -aHivv --no-whole-file \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# Add a new link in a new subdirectory to test that we don't try to link
# the files before the directory gets created.
mkdir "$fromdir/subdir"
ln "$name1" "$fromdir/subdir/new-file"
rm "$todir/text"
checkit "$RSYNC -aHivv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# Do some duplicate copies using --link-dest and --copy-dest to test that
# we hard-link all locally-inherited items.
checkit "$RSYNC -aHivv --link-dest=\"$todir\" \"$fromdir/\" \"$chkdir/\"" "$todir" "$chkdir"
rm -rf "$chkdir"
checkit "$RSYNC -aHivv --copy-dest=\"$todir\" \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
# Make sure there's nothing wrong with sending a single file with -H
# enabled (this has broken twice so far, so we need this test).
rm -rf "$todir"
$RSYNC -aHivv "$name1" "$todir/"
diff $diffopt "$name1" "$todir" || test_fail "solo copy of name1 failed"
# The script would have aborted on error, so getting here means we've won.
exit 0

39
testsuite/relative.test Normal file
View File

@@ -0,0 +1,39 @@
#!/bin/sh
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
#
# This program is distributable under the terms of the GNU GPL (see COPYING)
. "$suitedir/rsync.fns"
deepstr='down/3/deep'
deepdir="$fromdir/$deepstr"
mkdir -p "$deepdir"
fromdir="$deepdir"
hands_setup
fromdir="$tmpdir/from"
outfile="$scratchdir/rsync.out"
cd "$fromdir"
# Main script starts here
echo "$fromdir"
runtest "basic relative" 'checkit "$RSYNC -avR ./$deepstr \"$todir\"" "$fromdir/" "$todir"'
ln "$deepdir/filelist" "$deepdir/dir"
runtest "hard links" 'checkit "$RSYNC -avHR ./$deepstr/ \"$todir\"" "$fromdir/" "$todir"'
cp "$deepdir/text" "$todir/$deepstr/ThisShouldGo"
cp "$deepdir/text" "$todir/$deepstr/dir/ThisShouldGoToo"
runtest "deletion" 'checkit "$RSYNC -avHR --delete ./$deepstr/ \"$todir\"" "$fromdir/" "$todir"'
runtest "non-deletion" 'checkit "$RSYNC -aiHR --delete ./$deepstr/ \"$todir\"" "$fromdir/" "$todir"' \
| tee "$outfile"
# Make sure no files were deleted
grep 'deleting ' "$outfile" && test_fail "Erroneous deletions occurred!"
# The script would have aborted on error, so getting here means we've won.
exit 0

32
util.c
View File

@@ -877,12 +877,13 @@ int pop_dir(char *dir)
return 1;
}
/* Return the filename, turning any non-printable characters into '?'s.
* This ensures that outputting it on a line of its own cannot generate an
* empty line. This function can return only MAX_SAFE_NAMES values at a
* time! The returned value can be longer than MAXPATHLEN (because we
* may be trying to output an error about a too-long filename)! */
const char *safe_fname(const char *fname)
/* Return the filename, turning any non-printable characters into escaped
* characters (e.g. \n -> \012, \ -> \\). This ensures that outputting it
* cannot generate an empty line nor corrupt the screen. This function can
* return only MAX_SAFE_NAMES values at a time! The returned value can be
* longer than MAXPATHLEN (because we may be trying to output an error about
* a too-long filename)! */
char *safe_fname(const char *fname)
{
#define MAX_SAFE_NAMES 4
static char fbuf[MAX_SAFE_NAMES][MAXPATHLEN*2];
@@ -892,12 +893,21 @@ const char *safe_fname(const char *fname)
ndx = (ndx + 1) % MAX_SAFE_NAMES;
for (t = fbuf[ndx]; *fname; fname++) {
if (!isprint(*(uchar*)fname))
*t++ = '?';
else
if (*fname == '\\') {
if ((limit -= 2) < 0)
break;
*t++ = '\\';
*t++ = '\\';
} else if (!isprint(*(uchar*)fname)) {
if ((limit -= 4) < 0)
break;
sprintf(t, "\\%03o", *(uchar*)fname);
t += 4;
} else {
if (--limit < 0)
break;
*t++ = *fname;
if (--limit == 0)
break;
}
}
*t = '\0';