Compare commits

..

1270 Commits

Author SHA1 Message Date
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
Wayne Davison
00348fd793 Preparing for release of 2.6.4pre4 2005-03-29 06:18:24 +00:00
Wayne Davison
ddb6fc696b Improved several items and preparing for final 2.6.4 release. 2005-03-29 06:15:47 +00:00
Wayne Davison
f7e48a5cb8 Add data for 2.6.4. 2005-03-29 06:15:08 +00:00
Wayne Davison
70352269ba If --delay-updates wasn't specified, write out two -1 indexes at
the same time to avoid a useless round-trip delay for an empty
delay-updates phase.
2005-03-29 01:04:20 +00:00
Wayne Davison
0b94147928 Added --protocol and made some batch-file improvements. 2005-03-28 20:54:06 +00:00
Wayne Davison
da9f59264f Added --protocol to --help output. 2005-03-28 20:40:25 +00:00
Wayne Davison
96b7b48efa Some temporary code for 2.6.4pre3 compatibility (which can be
safely removed for the next release).
2005-03-28 17:29:27 +00:00
Wayne Davison
aea4bf2894 Chaging ITEM_UNUSED back to ITEM_DUMMY_BIT for now -- we'll need
to get rid of it later on.
2005-03-28 17:08:47 +00:00
Wayne Davison
855ef72f3f Changed ITEM_DUMMY_BIT to ITEM_UNUSED. 2005-03-27 05:58:40 +00:00
Wayne Davison
98dc857b32 Got rid of temporary code that detected and rejected older 2.6.4
pre-release versions.
2005-03-27 05:58:38 +00:00
Wayne Davison
94af17a6eb Got rid of temporary code that set the ITEM_DUMMY_BIT. 2005-03-27 05:58:36 +00:00
Wayne Davison
00fd35482e --compress is now saved in a batch's option-state flags. 2005-03-27 05:49:24 +00:00
Wayne Davison
cc3e0770bc Decided that the '<' and '>' output in the %i format were
the opposite of what they should be.
2005-03-27 05:32:36 +00:00
Wayne Davison
e7f7064cc5 - Fixed a bug in the saving of the --dirs option's state.
- Added the saving of the --compress option's state.
- Deal with the xfer_dirs var in a better way for pre-29 batches.
2005-03-27 05:02:49 +00:00
Wayne Davison
7b759fe0df Mention that --dry-run no longer conflicts with the batch options. 2005-03-25 16:45:58 +00:00
Wayne Davison
254ee3baab - Don't complain if --dry-run is specified with --read-batch
or --write-batch.
- If --write-batch is combined with --dry-run, just disable
  --write-batch (that avoids trying to create a batch file
  and tells the user what would be transferred).
2005-03-24 16:41:16 +00:00
Wayne Davison
f957e8fdf9 If --dry-run is enabled with --read-batch, we must discard the
transfer data.
2005-03-24 16:38:34 +00:00
Wayne Davison
822012eea9 List /etc instead of /, but only if it exists and is readable. 2005-03-23 16:04:17 +00:00
Wayne Davison
bb21ecac5b Mention when we run fakeroot. 2005-03-18 02:10:34 +00:00
Wayne Davison
648859bda2 If we're not root and the "fakeroot" command is available, use it
to re-run the script while pretending to be root.
2005-03-18 02:07:25 +00:00
Wayne Davison
f328e0f3a8 Set a maximum distance-measure that find_fuzzy() will accept. 2005-03-17 08:59:48 +00:00
Wayne Davison
6012eaa183 Fixed a problem with the stripping of the .bak/.old/.orig suffixes
in find_filename_suffix().
2005-03-17 08:45:36 +00:00
Wayne Davison
da2a6c1f1c Fixed the -r kluge sent for pre-2.6.4 --list-only support. 2005-03-17 00:52:33 +00:00
Wayne Davison
0438f100ae We need to run our post-processing activities after the end of
the receiver's delay-update processing.
2005-03-17 00:41:18 +00:00
Wayne Davison
b95ad9ac55 Mention one other recent change. 2005-03-16 02:50:00 +00:00
Wayne Davison
828a256123 Preparing for release of 2.6.4pre3 2005-03-16 01:12:44 +00:00
Wayne Davison
ebf447ac81 Changed error message for incompatible 2.6.4 pre-release versions. 2005-03-16 01:06:33 +00:00
Wayne Davison
124f349ea1 Document error messages 6 and 25. 2005-03-15 23:23:45 +00:00
Wayne Davison
26718401fb Added the error message for RERR_LOG_FAILURE and used it when
the daemon can't open the log-file.
2005-03-15 23:23:41 +00:00
Wayne Davison
f463e20753 Added RERR_LOG_FAILURE define. 2005-03-15 23:23:39 +00:00
Wayne Davison
1129070514 - Made read_item_attrs() detect and reject a pre1/pre2 rsync (used
by both the sender and the receiver).
- Added an extra phase to the end of the transfer to better handle
  delayed updates that have hard links.
2005-03-15 19:19:44 +00:00
Wayne Davison
ac3f7b81f8 Added an extra phase to the end of the transfer to handle
delayed updates that have hard links.
2005-03-15 19:19:41 +00:00
Wayne Davison
62f9573fb3 - Added an extra phase to the end of the transfer to better handle
delayed updates that have hard links.
- Send the new ITEM_DUMMY_BIT to the sender so that we can figure
  out if the other side is pre1 or pre2 and let the receiver reject
  it.
2005-03-15 19:19:38 +00:00
Wayne Davison
6d0e5d2e62 Added ITEM_DUMMY_BIT and moved a few other 'ITEM_*'s around. 2005-03-15 19:19:36 +00:00
Wayne Davison
8b48bf1154 Tweaked the end-of-phase code. 2005-03-15 17:30:56 +00:00
Wayne Davison
42be53201f Handle --delay-updates at the end of the first phase. 2005-03-15 17:30:52 +00:00
Wayne Davison
c7791b8cb2 Mention the index number for an "invalid packet at end of run". 2005-03-15 17:30:50 +00:00
Wayne Davison
7e9059d60f Fixed a just-introduced crash bug in the --fuzzy processing. 2005-03-14 22:22:42 +00:00
Wayne Davison
f3ebe1a77e A simple test to ensure that fuzzy processing is working. 2005-03-14 22:17:25 +00:00
Wayne Davison
301fb56ce9 Split the conditional-directory sending out of send_file_name() into
a new function: send_if_directory().  This lets the code that is
recursively descending through the directories make its list of a
dir's contents and close the DIR handle before recursing into the
subdirs.  Also, the "recurse" var is just true/false once again.
2005-03-14 17:30:15 +00:00
Wayne Davison
aa7a6e878b The "recurse" value is back to being just 1 or 0 (true or false). 2005-03-14 17:30:13 +00:00
Wayne Davison
0a39837a62 Got rid of "fudged_recurse". 2005-03-14 17:30:10 +00:00
Wayne Davison
b2e8a9b293 Got rid of an unused extern. 2005-03-14 17:06:08 +00:00
Wayne Davison
a98ad81760 Got rid of some code in f_name_cmp() that tried to make all the
dirname pointers to equivalent strings have identical pointers.
2005-03-14 03:36:56 +00:00
Wayne Davison
ccc51c8331 The --fuzzy code now handles a file->dirname that has an identical
string as another file without being an identical pointer.
2005-03-14 03:35:40 +00:00
Wayne Davison
ee171c6da9 Document the latest %i output. 2005-03-13 05:36:13 +00:00
Wayne Davison
d5609e969d Output a '*' at the start of the %i string when deleting. 2005-03-13 05:35:49 +00:00
Wayne Davison
927c806841 - Improved a couple error messages.
- Improved a function name.
2005-03-13 05:34:00 +00:00
Wayne Davison
2da9dda1c0 Some misc. improvements (I hope). 2005-03-12 23:54:05 +00:00
Wayne Davison
3117bc16a5 Improved two sentences. 2005-03-12 23:52:18 +00:00
Wayne Davison
717b04306a Tweaked the name of a variable. 2005-03-12 23:52:08 +00:00
Wayne Davison
271220c542 Mention --copy-dest. 2005-03-11 19:23:09 +00:00
Wayne Davison
566a874141 Re-enabled the --copy-dest part of the test. 2005-03-11 17:36:05 +00:00
Wayne Davison
967866d4df Added --copy-dest logic, and improved the updating of --compare-dest
and --link-dest files that are up-to-date but have differing attributes.
2005-03-11 17:36:03 +00:00
Wayne Davison
1de3e99bc5 Added --copy-dest logic. 2005-03-11 17:35:59 +00:00
Wayne Davison
3e13004b6b Tweaked the comment on copy_file(). 2005-03-11 17:35:57 +00:00
Wayne Davison
2f03ce67d6 Document --copy-dest. 2005-03-11 17:35:54 +00:00
Wayne Davison
b9232d45eb - Fixed the reading of the fuzzy xname from the socket.
- Call read_item_attrs() with its new arg.
2005-03-10 00:06:01 +00:00
Wayne Davison
6087ef2a84 - Changed read_item_attrs() to return the length of the xname string.
- Tweaked the order of the args to write_item_attrs().
2005-03-10 00:05:58 +00:00
Wayne Davison
1f1d368ad5 - Improved the error-checking for some delete_item() calls.
- Move the non-regular-file delete-check above the alt-basis check
  where it belongs.
- Keep track of the real statret and real stat-struct for certain
  alt-basis scenarios (e.g. partial-dir and fuzzy) so that we send
  the right itemized change flags.
2005-03-09 23:46:28 +00:00
Wayne Davison
dd18526e5b Mention the latest protocol-29 changes. 2005-03-09 18:55:09 +00:00
Wayne Davison
4d53c4dd46 We now handle the reading and writing of extra basis-file info: the
fnamecmp_type byte, and the extra name (currently used for fuzzy
processing and hard-link status).
2005-03-09 18:54:19 +00:00
Wayne Davison
9e4a8d29b5 Got rid of the name-pipe, so we now read the fnamecmp_type data over
the socket for protocol >= 29, or handle it like the old days for
older protocol versions.  This means that we now validate this extra
data for safety (such as the fuzzy filename).
2005-03-09 18:54:16 +00:00
Wayne Davison
ef20efcbb6 Made itemize() output the fnamecmp_type and the fuzzy name based on
the new ITEM_BASIS_TYPE_FOLLOWS and ITEM_XNAME_FOLLOWS flags.  Got
rid of the name-pipe to the receiver.
2005-03-09 18:54:12 +00:00
Wayne Davison
c70e07d9ac Got rid of the name-pipe from the generator to the receiver. 2005-03-09 18:54:09 +00:00
Wayne Davison
b7d4d28bb3 When itemizing, we now set ITEM_LOCAL_CHANGE and ITEM_XNAME_FOLLOWS. 2005-03-09 18:54:06 +00:00
Wayne Davison
9a6ed83f2c - Made an overflow in read_vstring() return an error instead of dying.
- Got rid of a flush kluge that was needed for the name-pipe.
2005-03-09 18:54:02 +00:00
Wayne Davison
fd84673e54 Handle the new way that 'c' and 'h' get output by "%i". 2005-03-09 18:53:58 +00:00
Wayne Davison
57b12568e6 Complain if a feature that requires protocol 29 doesn't get it. 2005-03-09 18:53:55 +00:00
Wayne Davison
f9a9f54720 Made the dest_option string non-static. 2005-03-09 18:53:53 +00:00
Wayne Davison
3019a9bafd Changed some of the ITEM_* defines. 2005-03-09 18:53:49 +00:00
Wayne Davison
278e3d4f6e Mention the latest bug-fix. 2005-03-09 04:00:45 +00:00
Wayne Davison
9b9dd06894 We need to mention any change to a directory, not just a time change.
Yeah, this isn't very consistent with how files are treated, but it's
backward compatible.
2005-03-09 04:00:20 +00:00
Wayne Davison
1f7e29b99c Fixed the change-report output for a directory that has no
write permissions.
2005-03-09 03:49:07 +00:00
Wayne Davison
c2f0e6e5e3 Backward compatibility fix in read_iflags() (for protocols < 29). 2005-03-09 02:25:34 +00:00
Wayne Davison
c2b11ba017 Backed out the hack that reversed ITEM_REPORT_XATTRS with
ITEM_TRANSFER.  Yes, it allowed some kludge code that made backward
compatibility seamless, but it made it impossible to remove the hack
in the future.  This way, the backward compatibility is just
slightly inaccurate in the display of the first letter in the %i
output, and the only hack can be safely removed without causing
problems.
2005-03-06 23:37:42 +00:00
Wayne Davison
f75a53e71b - When --max-delete is exceeded, we now count how many deletions
would have happend, warn about the number skipped, and set
  io_error to IOERR_DEL_LIMIT.
- When dry_run > 1 (which indicates that the destinationdir is
  missing), skip deletions in that dir.  This fixes a bug in a
  copy that is creating the destination dir w/--delete enabled.
2005-03-05 18:58:42 +00:00
Wayne Davison
054abde25f Handle new IOERR_DEL_LIMIT bit in io_error. 2005-03-05 18:58:38 +00:00
Wayne Davison
24cecf1365 Define the message for RERR_DEL_LIMIT. 2005-03-05 18:58:35 +00:00
Wayne Davison
821ff7f49a Added RERR_DEL_LIMIT. 2005-03-05 18:58:32 +00:00
Wayne Davison
ff3d3c32d5 Added IOERR_DEL_LIMIT. 2005-03-05 18:58:29 +00:00
Wayne Davison
3b2ef5b11c Mention that --max-delete must be non-zero. 2005-03-05 18:58:26 +00:00
Wayne Davison
0394e34a69 Moved the end_progress() call from match.c to sender.c so that we
report progress on 0-length files when pushing files (the receiver
already called it, so we already produced progress on a 0-length
file when pulling).
2005-03-05 17:51:23 +00:00
Wayne Davison
56efa56474 Fixed the elapsed time reported for 0-length files. 2005-03-05 17:49:46 +00:00
Wayne Davison
ed7e79553e Don't try to determine the phase we're in by looking at the value
of csum_length -- it might have been computed to be SUM_LENGTH.
Instead, look at the "phase" variable directly.
2005-03-05 16:42:52 +00:00
Wayne Davison
dec71e94f3 Added a hack that uses the ITEM_REPORT_XATTRS bit (which is the old
ITEM_UPDATING bit) to make us compatible when sending/receiving bits
to/from an earlier pre-release.
2005-03-05 04:34:06 +00:00
Wayne Davison
ac4f91a5ee Added a hack that sets the ITEM_REPORT_XATTRS bit (which is the old
ITEM_UPDATING bit) when ITEM_TRANSFER or ITEM_LOCAL_CHANGE is set.
This lets us interact compatibly when sending itemized bits to an
earlier pre-release.
2005-03-05 04:34:04 +00:00
Wayne Davison
e957626347 Swapped the bit-values for ITEM_TRANSFER and ITEM_REPORT_XATTRS.
This lets us be more compatible with the earlier pre-releases
with a better heuristic for backward-compatible itemized bits.
2005-03-05 04:34:01 +00:00
Wayne Davison
b4875de45c Improved the description of when "h" is output by %i. 2005-03-05 00:34:02 +00:00
Wayne Davison
2cfe44eee4 Turned on -i for itemized output. 2005-03-05 00:23:55 +00:00
Wayne Davison
fad3dc421c - Updated to handle the new ITEM_* flags.
- Changed read_iflags() to read/write a suffixed hard-link name.
2005-03-05 00:21:59 +00:00
Wayne Davison
22907b6bd9 - Updated to handle the new ITEM_* flags.
- Send MSG_SUCCESS for hard-linked files when -H was specified.
2005-03-05 00:21:56 +00:00
Wayne Davison
3485ae8321 A few minor tweaks to improve two error messages and make better use
of the "the_file_list" global.
2005-03-05 00:21:54 +00:00
Wayne Davison
ca62acc3ca - Make use of the new ITEM_* flags to mention when things were
updated locally instead of being updated remotely.
- Added support for outputting 'a' in the itemized log-output (for
  future use in extended-attribute handling).
2005-03-05 00:21:50 +00:00
Wayne Davison
cdf236aaf5 - Made the sock_{in,out} variables non-static.
- Added hlink_list, a FIFO list of finished hard-link items.
- Made get_redo_num() check for finished hard-link items and
  call the generator when they are found.  This ensures that
  we finish all the hard-link items by the time the MSG_DONE
  is read and returned to the generator.
- Added get_hlink_num() to read the new hlink_list.
2005-03-05 00:21:48 +00:00
Wayne Davison
9f2e3c3f52 - Changed hlink_list[] to store file-list indexes instead of
pointers.
- Made hard_link_one() non-static so that the generator can call it.
  Improved it to do itemized output.
- Replaced do_hard_links() with hard_link_cluster(), which changes
  the hard-linking from a post-transfer loop into a per-cluster
  operation that occurs incrementally as the transfer updates (or
  finds unchanged) one item in the cluster.
2005-03-05 00:21:44 +00:00
Wayne Davison
ee1d11c495 - Updated itemize() to handle sending of hard-link-name info. Made
it non-static so the hard-link code can now output itemized
  messages.
- Made the locally-changed items (such as dirs and symlinks) itemize
  using a new ITEM_LOCAL_CHANGE flag instead of the (renamed)
  ITEM_TRANSFER flag (formerly ITEM_UPDATING).
- Improved the hard-link support by having a cluster of hard-linked
  files get processed as soon as we notice that a single item is
  already up-to-date, or it succssfully finishes being updated.
- The hard-linking that occurs when using --link-dest will now be
  mentioned at higher levels of verbosity IFF %i is in the log-
  format.
2005-03-05 00:21:42 +00:00
Wayne Davison
669e76717c - Changed ITEM_UPDATING to ITEM_TRANSFER.
- Added defines ITEM_HARD_LINKED, ITEM_LOCAL_CHANGE,
  ITEM_REPORT_XATTRS, and SIGNIFICANT_ITEM_FLAGS.
- Changed the "next" var in struct hlink into an int.
2005-03-05 00:21:39 +00:00
Wayne Davison
4e107712f3 Mention latest bug fixes. 2005-03-05 00:20:37 +00:00
Wayne Davison
85aa57a7dd In read_iflags(), we need to set buf to an empty string. 2005-03-04 18:01:16 +00:00
Wayne Davison
58a14ed950 Got rid of some code in the main recv_files() loop by calling the
new functions read_iflags() and maybe_log_item().
2005-03-04 16:54:08 +00:00
Wayne Davison
165e6d446c Moved some code out of the main loop in send_files() into a new
function called read_iflags() (which was made generic enough that
the receiver could use it too).  Also call the new maybe_log_item().
2005-03-04 16:53:26 +00:00
Wayne Davison
1c3e3679ef Added maybe_log_item() for use by the sender and receiver. 2005-03-04 16:52:00 +00:00
Wayne Davison
8a513e55b0 Document the new value of %L. 2005-03-04 16:11:09 +00:00
Wayne Davison
a314f7c155 Document latest format of %i. 2005-03-04 16:08:58 +00:00
Wayne Davison
9497b0d4e9 Call log_item() instead of log_recv(). 2005-03-04 16:08:16 +00:00
Wayne Davison
b694f8a245 Call log_item() instead of log_send(). 2005-03-04 16:08:02 +00:00
Wayne Davison
afc65a5acf - Replaced log_send() and log_recv() with log_item().
- Made log_formatted() and log_item() take an "hlink" arg that
  will be used to pass in a hard-link name for use in %L.
2005-03-04 16:07:50 +00:00
Wayne Davison
5f40615cd5 Use the new "the_file_list" global instead of our "the_flist" local. 2005-03-04 15:57:14 +00:00
Wayne Davison
c6816b9444 Transformed the push/pop functions for the redo-list into more
generic flist_num_{push,pop}() functions that can support other
folks caching off file-list index numbers.
2005-03-04 15:50:22 +00:00
Wayne Davison
46e99b09b9 Added read_vstring() and write_vstring() to io.c instead of
having this code in generator.c and receiver.c.
2005-03-04 15:38:58 +00:00
Wayne Davison
af436313a0 - Got rid of the checking of msg_fd_in in read_timeout() -- it was
only needed back when the generator was reading a separate redo
  pipe from the message pipe.
- Fixed a potential data corruption in the data that the generator
  is sending:  if a message comes in from the receiver, we now make
  sure that we can't put the forwarding of this message to the sender
  into the middle of a multiplexed-write record that the generator
  is trying to flush.
2005-03-04 08:58:27 +00:00
Wayne Davison
d64e6f42b4 Use the new "the_file_list" global. 2005-03-03 18:44:42 +00:00
Wayne Davison
a00628b335 - Set the new global "the_file_list".
- Got rid of test of read_batch in an am_sender section since
  there is never a sender process for --read-batch.
2005-03-03 18:44:06 +00:00
Wayne Davison
33ab4ad879 Simplified whole_file variable checking. 2005-03-03 02:58:48 +00:00
Wayne Davison
99eb41b25f Improved some text in --compare-dest and --link-dest. 2005-03-03 02:23:12 +00:00
Wayne Davison
e86ae6bc1f Don't kluge the value of statret for --whole-file. 2005-03-03 01:50:43 +00:00
Wayne Davison
c3cbcfb8ef Moved the checks for --ignore-existing and --update higher in
recv_generator() so that they don't trigger erroneously when
--link-dest is specified.
2005-03-03 01:33:51 +00:00
Wayne Davison
a1d23b5314 - Got rid of the SID_* flags -- use the ITEM_* flags directly.
- If --compare-dest find a file that is not the same in attributes,
  we need to copy the file.
2005-03-03 00:14:35 +00:00
Wayne Davison
d4d4890d4e Added ITEM_NO_DEST_AND_NO_UPDATE for use by the generator's
itemize() function.
2005-03-03 00:14:32 +00:00
Wayne Davison
30e66e53de Fixed the --compare-dest docs. 2005-03-02 18:01:23 +00:00
Wayne Davison
e224331729 When using multiple --compare-dest options, rsync should avoid
copying a file that has an exact match in any of the dirs.
2005-03-02 17:48:36 +00:00
Wayne Davison
70b54e4e43 Fixed a bug in the --dry-run output when using --link-dest. 2005-03-02 17:27:19 +00:00
Wayne Davison
9ba463435b If the multi-dest loop falls back to the best_match index,
we need to re-stat() the file to restore "st".
2005-03-02 09:51:54 +00:00
Wayne Davison
05ee48661c Tweaked the description for --rsync-path. 2005-03-02 09:17:42 +00:00
Wayne Davison
aef9882581 A little more tweaking to the multi-dest option loop. 2005-03-02 09:09:15 +00:00
Wayne Davison
78bcddcc6a Mention that specifying "/dir/**" is a safer way than "/dir/"
alone to ensure that files inside a dir are fully protected.
2005-03-02 01:48:25 +00:00
Wayne Davison
68e169ab4d Improved the description of --rsync-path. 2005-03-01 23:02:23 +00:00
Wayne Davison
f62eaa24f1 Made the multi-FOO-dest loop a little nicer. 2005-03-01 19:42:31 +00:00
Wayne Davison
d3e553b4bd Explicitly mention that "del." does include the trailing period. 2005-03-01 19:17:27 +00:00
Wayne Davison
3753975f48 Fixed two glitches Paul pointed out. 2005-03-01 17:28:46 +00:00
Wayne Davison
2d81114b23 Preparing for release of 2.6.4pre2 2005-03-01 06:22:19 +00:00
Wayne Davison
472135e0bc Mention the latest changes. 2005-03-01 06:05:23 +00:00
Wayne Davison
c60b7056b2 A few improvements to the new check_for_hostspec() function. 2005-03-01 05:49:11 +00:00
Wayne Davison
42ccb4c091 Made the argv/argc parsing a little nicer. 2005-03-01 03:39:35 +00:00
Wayne Davison
b31c92edcc - Look for last '@' in a user@host spec. 2005-03-01 03:39:32 +00:00
Wayne Davison
08b018304f Removed section on parsing IPv6 literal addresses. 2005-03-01 03:11:28 +00:00
Wayne Davison
d19320fdf6 Changed remote_filesfrom_file to filesfrom_host. 2005-03-01 03:10:59 +00:00
Wayne Davison
860236bf90 - Changes needed to handle new filesfrom_host variable.
- Changes needed to use check_for_hostspec() in place of find_colon().
2005-03-01 01:16:03 +00:00
Wayne Davison
4d3abf1360 Changes needed to use check_for_hostspec() in place of find_colon(). 2005-03-01 01:15:59 +00:00
Wayne Davison
305666bf59 - Changed find_colon() into check_for_hostspec(), extending it to
understand the rsync:://HOST:PORT/PATH format, allowing all HOSTs
  to be IPv6 literal addresses enclosed in '[' and ']', and changing
  it to return the 3 parts of the spec separately (host, port, and
  path).
- Relocated the code that handles the sanitation and validation of
  the files_from arg in order to make its placement a little more
  logical.
- Replaced remote_filesfrom_file with filesfrom_host, which makes
  the value of the files_from variable more intuitive.
2005-03-01 01:15:57 +00:00
Wayne Davison
b03c719f04 Enhanced the option-parsing failure mode to handle the situation
where the parser didn't get a chance to parse the --files-from
option yet, but we still need to know it was there in order to get
the error message back to the client.
2005-03-01 00:42:32 +00:00
Wayne Davison
62f27e3c02 Made a couple sentences about rsync:// syntax clearer. 2005-02-28 22:04:16 +00:00
Wayne Davison
4dc67d5e30 Improved a couple sentences. 2005-02-28 02:16:49 +00:00
Wayne Davison
8ebdc9724e Say "rsync 2.6.4" instead of "protocol 29". 2005-02-28 02:16:23 +00:00
Wayne Davison
9e0582f9bf Tweaked a comment. 2005-02-28 02:04:42 +00:00
Wayne Davison
705de51a73 Improved do_lseek()'s failure message. 2005-02-27 21:12:13 +00:00
Wayne Davison
1a8e5c97eb Complain if the run-terminating keep-alive packets aren't what
we expected.
2005-02-27 20:50:07 +00:00
Wayne Davison
55bb7fff14 Don't loop forever when the receiver is waiting around to be killed
at EOF -- it should be a rapidly arriving event, so only hang around
for 10 seconds, max., and then go ahead and report the "unexpectedly
closed" error.
2005-02-27 18:24:34 +00:00
Wayne Davison
662bdcd4ac Make sure that allowed_lull will not be computed as 0 if
io_timeout is 1.
2005-02-27 18:09:17 +00:00
Wayne Davison
fef101a548 Improved a couple sentences. 2005-02-27 18:01:32 +00:00
Wayne Davison
18a11cfd48 - Made the calls to maybe_send_keepalive() happen at better intervals.
- Call do_hard_links() with its new args.
2005-02-27 09:02:32 +00:00
Wayne Davison
0f80c3e886 Added 2 args to do_hard_links() so that it can call maybe_send_keepalive(). 2005-02-27 09:02:29 +00:00
Wayne Davison
f122383179 Mention the backup fix for redone files with --inplace. 2005-02-27 08:02:06 +00:00
Wayne Davison
e6bc6f4232 We need to turn off make_backups for the redo phase so that
the inplace processing doesn't make a second backup.
2005-02-27 07:50:43 +00:00
Wayne Davison
ac1cb9380d Tweaked an error message. 2005-02-27 07:34:27 +00:00
Wayne Davison
40df65fdb4 - Seems to me that sigusr2_handler() should call close_all() for
the sake of MS Windows.
- Improved some comments.
2005-02-27 07:33:01 +00:00
Wayne Davison
cb2e1f18c2 One more comment fix. 2005-02-26 22:14:40 +00:00
Wayne Davison
0ecd03e396 Fixed comment. 2005-02-26 22:02:38 +00:00
Wayne Davison
e6f5ac116b Improved a couple sentences. 2005-02-26 21:48:12 +00:00
Wayne Davison
051182cb75 Set kluge_around_eof to a -1 for the receiver's needs. 2005-02-26 20:58:08 +00:00
Wayne Davison
574c250093 If kluge_around_eof is < 0, we go into an msleep() loop instead
of exiting.
2005-02-26 20:58:05 +00:00
Wayne Davison
8dad7fc6ea Explicitly set kluge_around_eof to a 1 when it is needed. 2005-02-26 20:58:01 +00:00
Wayne Davison
b558728875 Added keep-alive checking during the directory-touching loop at
the end of the processing.
2005-02-26 20:43:14 +00:00
Wayne Davison
e777afad6f Set kludge_around_eof when the receiver is trying to read a
potential keep-alive message that may never come.
2005-02-26 20:21:12 +00:00
Wayne Davison
87703a1b1f Improved the comment for kludge_around_eof. 2005-02-26 20:21:08 +00:00
Wayne Davison
981b202661 Added "set -x". 2005-02-26 19:49:59 +00:00
Wayne Davison
13725744fd Decided I like "set -x" after all. 2005-02-26 19:47:43 +00:00
Wayne Davison
363c3ece3a Don't allow keep-alive sending if --read-batch is enabled. 2005-02-26 19:37:49 +00:00
Wayne Davison
47780ddfef Mention the new keep-alive handling and the devices-size fix. 2005-02-26 19:17:06 +00:00
Wayne Davison
251f22b5d7 Fixed a line-ordering problem. 2005-02-26 19:11:57 +00:00
Wayne Davison
4e0fcd85ae Handle keep-alive messages at the end of the transfer when
--delete-after is happening.
2005-02-26 18:57:57 +00:00
Wayne Davison
59faec8b8b - Moved all the file-deletion code here from flist.c and receiver.c.
- Call maybe_send_keepalive() from delete_in_dir() so that a really
  long delete-pass won't timeout.
- Renamed delete_files() -> do_delete_pass().
- Renamed delete_file() -> delete_item().
- Call get_dirlist() with its new arg.
2005-02-26 18:03:49 +00:00
Wayne Davison
32cbfe7b17 - Moved file-deletion code into generator.c.
- Made filesystem_dev a global that the generator can set during its
  delete pass.
- Fixed an off-by-one boundary check in send_directory().
- Added an arg to get_dirlist() so that delete_in_dir() can call it
  efficiently.
2005-02-26 18:03:46 +00:00
Wayne Davison
f08ca43472 Moved the delete-after support into generator.c. 2005-02-26 18:03:42 +00:00
Wayne Davison
8eb6cf784b Moved the delete-before support into generator.c. 2005-02-26 18:03:40 +00:00
Wayne Davison
7433d73adc - Moved the initialization of "itemizing", "maybe_PERMS_REPORT", and
"code" from recv_generator() to generate_files() so that they
  don't get recomputed for every file (we pass them as args now).
- Allow protocols < 29 to call maybe_send_keepalive() so that we can
  try to flush the output buffer if things are slow (though we can't
  send a keep-alive packet without protocol_version >= 29).
2005-02-26 06:52:55 +00:00
Wayne Davison
3221f451a0 Calling maybe_send_keepalive() for protocol_version < 29 is
now supported, though we can only try to flush the output
buffer if we're in a lull.
2005-02-26 06:43:15 +00:00
Wayne Davison
9e4536748d - Moved the description of '%i's output into the rsync manpage.
- A few minor tweaks to the "log format" setting.
2005-02-26 05:18:03 +00:00
Wayne Davison
ea67c71505 - We now mention what "%i" outputs under --itemize-changes.
- Improved the description of --log-format.
2005-02-26 05:16:26 +00:00
Wayne Davison
ea38b5af72 Mention the change in when --log-format outputs and how it
interacts with --verbose.
2005-02-26 05:11:46 +00:00
Wayne Davison
89d19eedef Call log_delete() from delete_file() anytime that DEL_TERSE is
not set (we used to only call if verbose or log_format were also
set).
2005-02-26 04:50:55 +00:00
Wayne Davison
41b5b5e756 The log_delete() function may now be called even when the client is
not getting delete messages, which ensures that the daemon's log-
file output includes all deletions when per-file logging is enabled.
2005-02-26 04:49:30 +00:00
Wayne Davison
a3e1363aaa Make sure that our protocol-28 compatibility is OK. 2005-02-26 03:22:05 +00:00
Wayne Davison
2217b30adf Fixed a problem sending include rules to an older rsync. 2005-02-26 02:56:30 +00:00
Wayne Davison
9ac2395bf0 - Call maybe_send_keepalive() if timeouts are enabled.
- Use the new ignore_timeout variable.
2005-02-25 22:01:36 +00:00
Wayne Davison
9e2409ab22 - Added variable "ignore_timeout" that lets the generator tell
us to ignore a timeout without turning off the timeout-related
  time-keeping that the keep-alive processing needs.
- Added a new function:  maybe_send_keepalive().
2005-02-25 21:58:13 +00:00
Wayne Davison
8e6cf5d189 Accept the new keep-alive (no-op) packet. 2005-02-25 21:56:00 +00:00
Wayne Davison
d17190df44 Don't add st_size from a device to stats.total_size. 2005-02-25 20:28:27 +00:00
Wayne Davison
fbe5eeb831 Mention how --backup sometimes implies --omit-dir-times. 2005-02-25 17:10:48 +00:00
Wayne Davison
ed9d969c4c Use the new am_starting_up value in who_am_i(). 2005-02-25 17:08:57 +00:00
Wayne Davison
7f2a1f651e Got rid of kluged value for am_sender, and instead added a new
variable named am_starting_up that is non-zero during the option
parsing.  This lets the who_am_i() routine output a better value
for debugging info that is output during the option parsing.
2005-02-25 17:08:31 +00:00
Wayne Davison
bbbb44ee0f Fixed some typos. 2005-02-25 02:30:38 +00:00
Wayne Davison
29fbd1eea6 Preparing for release of 2.6.4pre1 2005-02-23 03:22:53 +00:00
Wayne Davison
33f839b319 Tweaked an entry. 2005-02-23 03:17:11 +00:00
Wayne Davison
bc83274ad6 - Fixed a problem with full_fname() when curr_dir was "/".
- Made full_fname() consistently output a leading "/" for
  module paths no matter if chroot is in use or not.
2005-02-23 02:56:42 +00:00
Wayne Davison
38e3910b6f One more tweak to the need_name_pipe logic. 2005-02-23 02:14:00 +00:00
Wayne Davison
c26c51a7ee Commenting out link-dest test for now. 2005-02-23 02:13:33 +00:00
Wayne Davison
e9973668a4 Got rid of --copy-dest references. 2005-02-23 02:07:09 +00:00
Wayne Davison
4104c3bf52 Changed --copy-dest to --link-dest. 2005-02-23 02:06:33 +00:00
Wayne Davison
b7c2481933 Got rid of --copy-dest for now -- I think it should be made to do
the copying of unchanged files locally (like --link-dest does
using a hard link).
2005-02-23 02:05:34 +00:00
Wayne Davison
cfb691ac9a Fixed a problem with the last change. 2005-02-22 22:13:04 +00:00
Wayne Davison
cb8240a291 We need the name-pipe for --inplace these days. 2005-02-22 22:13:02 +00:00
Wayne Davison
352963ddc3 Always set the SID_USING_ALT_BASIS appropriately for the transfer,
even if --inplace wasn't specified.
2005-02-22 22:12:59 +00:00
Wayne Davison
8c57732324 More cleanups. 2005-02-22 21:56:32 +00:00
Wayne Davison
8a33c406b3 Trying to fix bug #2357. 2005-02-22 21:48:10 +00:00
Wayne Davison
340bd68f59 We now look for the ITEM_USING_ALT_BASIS flag for an --inplace
transer that is using an alternate basis file (instead of reading
an extra byte after the flag word).
2005-02-22 21:43:59 +00:00
Wayne Davison
8237f9305b We now set the ITEM_USING_ALT_BASIS flag for an --inplace transfer
that is using an alternate basis file (instead of sending an extra
byte after the flag word).
2005-02-22 21:43:57 +00:00
Wayne Davison
5b1c1eefda Added ITEM_USING_ALT_BASIS. 2005-02-22 21:43:54 +00:00
Wayne Davison
6258626751 Document an alternate way to achieve the effect of this script
through the use of awk and the more powerful --filter option.
2005-02-22 21:24:24 +00:00
Wayne Davison
87fd439059 When preforming a recursive delete, push/pop the per-dir merge rules. 2005-02-22 20:42:55 +00:00
Wayne Davison
564ef546a9 Sort the dir-list returned by get_dirlist() and the dir-list that
delete_in_dir() generates.
2005-02-22 03:37:18 +00:00
Wayne Davison
94dcbf8367 - Iterate through the deletion list in reverse order so that we
can't delete a backup file that we just created.
- The rename-directory-for-backup heuristic now checks the
  DEL_FORCE_RECURSE flag, not the zap_dir variable.  We also set
  the flag when we recurse so that only the root dir of a deleted
  hierarchy can be missing the flag (and thus be a call from the
  generator).
2005-02-22 03:16:41 +00:00
Wayne Davison
1bad11c759 Only rename a directory with the backup suffix if we're removing
it to replace it with a file of the same name.
2005-02-22 01:59:15 +00:00
Wayne Davison
ba679d5194 In make_simple_backup(), if the rename() failed because we tried
to rename a directory over a file or visa versa, try to handle it.
2005-02-22 01:57:58 +00:00
Wayne Davison
e1ad7fe63d A couple changes in delete_file() make us more compatible with
older versions: (1) we no longer complain if excluded files
sticking around cause us to not be able to remove a subdir, and
(2) we output the name of the removed subdir after it has been
successfully removed.
2005-02-22 00:42:12 +00:00
Wayne Davison
f18d87b6ed Added function check for vasprintf. 2005-02-21 18:58:09 +00:00
Wayne Davison
a6c15e9a38 - Added function tests for va_copy and __va_copy for snprintf.c code.
- Added AC_C_LONG_DOUBLE for snprintf.c code.
- Got rid of unneeded ino_t check.
2005-02-21 17:08:09 +00:00
Wayne Davison
64bba1465b Check SIZEOF_LONG_LONG instead of HAVE_LONG_LONG. 2005-02-21 17:02:53 +00:00
Wayne Davison
638e106568 - Moved delete_file() into flist.c.
- No need to separately test for (make_backups && !backup_dir)
  because omit_dir_times is now set under those circumstances.
2005-02-21 10:50:32 +00:00
Wayne Davison
34e18ecd61 - Moved delete_file() here from rsync.c and improved it to avoid
removing files we just backed up to the current directory and to
  rename a non-empty dir to dir~ (when no backup-dir is specified).
- Made delete_missing() static.
2005-02-21 10:50:30 +00:00
Wayne Davison
d4021b6d9b - Set omit_dir_times if backing up files w/o a backup dir.
- Only send an explicitly specified -O (--omit-dir-times)
  if it won't be inferred by the receiver.
2005-02-21 10:03:23 +00:00
Wayne Davison
40b1393880 Pass the file-diffing flag as an arg to checkit. 2005-02-21 07:27:28 +00:00
Wayne Davison
30688bf11b If checkit is passed a 4th arg, skip the file-diffing step.
This is used by the devices.test script.
2005-02-21 07:26:59 +00:00
Wayne Davison
a7d7a805dc Touch $tmpdir/do_not_diff_the_files so that checkit does not try
to diff the devices against each other.
2005-02-21 07:19:11 +00:00
Wayne Davison
4a239e98f6 Reposition log_open() and log_close(). 2005-02-21 00:38:15 +00:00
Wayne Davison
7b97c38898 Mention two more things. 2005-02-21 00:32:04 +00:00
Wayne Davison
1f35babc6b - For win32: made --no-detach the default for daemon mode.
- Added --detach (a --daemon option).
2005-02-21 00:31:31 +00:00
Wayne Davison
80ffc3de12 Updated to remove completed items and add a little more info for
other items.
2005-02-21 00:17:10 +00:00
Wayne Davison
507b61d5a6 Some minor tweaks. 2005-02-21 00:16:36 +00:00
Wayne Davison
8db3106e0b Mention the compression-mode fix for large block sizes. 2005-02-20 23:08:56 +00:00
Wayne Davison
1b1fef20b3 Tweaked the rprintf() that outputs about the delta-transmission
enablement.
2005-02-20 22:11:43 +00:00
Wayne Davison
22c7c5fb0b - Integrated the latest version from samba.
- Tweaked the order of the code in my_modf() to avoid
  a compiler warning.
2005-02-20 22:10:33 +00:00
Wayne Davison
13d00101e8 One more tweak to the "whoami" code. 2005-02-20 21:04:03 +00:00
Wayne Davison
3e7934a5fb Changed the memory implementation of --delay-updates so that it
only allocates memory to store needed bits, it sparsely allocates
the bits in 16KB chunks, and the bit-finding loop works in a more
efficient manner.
2005-02-20 20:55:24 +00:00
Wayne Davison
815193e89e Got rid of "set -x" (runtests.sh has a way to set this, if desired). 2005-02-20 17:24:15 +00:00
Wayne Davison
4fd4b3d667 Dropped a useless "const" from the definition of poptStrerror. 2005-02-20 17:21:13 +00:00
Wayne Davison
1526b8b17d Mark a couple unused variables. 2005-02-20 17:20:14 +00:00
Wayne Davison
732537212b Cast char* to uchar* when dereferencing characters for isdigit()
and isprint().
2005-02-20 17:07:31 +00:00
Wayne Davison
4adbb5f246 Have rule_strcmp() accept and return a uchar*. 2005-02-20 17:04:53 +00:00
Wayne Davison
30fa772457 A few improvements to the "test" commands to neaten them up and
to try to fix another problem under solaris.
2005-02-20 17:01:32 +00:00
Wayne Davison
ee03617b3d Cast a uchar* arg to char* for write_buf(). 2005-02-20 16:56:30 +00:00
Wayne Davison
19cb6106d2 Improved the testuser-setting code to try to get it to work
under solaris.
2005-02-20 16:27:10 +00:00
Wayne Davison
cd6bececc1 If --delay-updates is specified with --remove-sent-files, delay
the MSG_SUCCESS messages until we actually move the files into
place at the end.
2005-02-20 02:54:30 +00:00
Wayne Davison
88b93c6159 Corrected "log format" info and added info on --remove-sent-files. 2005-02-20 02:45:10 +00:00
Wayne Davison
b62fd39392 A small twiddle. 2005-02-20 01:14:27 +00:00
Wayne Davison
95306d9d50 - For every file that we send off to the receiver, mark it with
FLAG_SENT.
- Added successful_send(), which is called when MSG_SUCCESS was
  received from the receiver/generator side.  This function
  validates the message, and removes the indicated file/symlink
  (assuming that remove_sent_files was actually set).
2005-02-20 01:04:54 +00:00
Wayne Davison
3e870a6444 If --remove-sent-files was specified and we successfully updated a
file, send MSG_SUCCESS to the sender (through the generator).
2005-02-20 01:04:51 +00:00
Wayne Davison
bf26aa2219 - If --remove-sent-files was specified, abort if we're pulling from
a read-only module.
- If need_messages_from_generator is set, make sure that the
  connection between the generator to the sender has multiplexed
  I/O enabled.
2005-02-20 01:04:49 +00:00
Wayne Davison
9981c27ef1 Handle the new MSG_SUCCESS message for both the generator and the
sender.
2005-02-20 01:04:46 +00:00
Wayne Davison
fe96018750 If we update the contents of a symlink and --remove-sent-files
is enabled, tell the sender about it via MSG_SUCCESS.
2005-02-20 01:04:43 +00:00
Wayne Davison
07c6ae7de8 - Added --remove-sent-files option.
- If a server is refusing "delete" and we're the sender, also refuse
  the --remove-sent-files option.
2005-02-20 01:04:40 +00:00
Wayne Davison
e163683020 Document how refusing "delete" affects --remove-sent-files. 2005-02-20 01:04:37 +00:00
Wayne Davison
961103049b Document --remove-sent-files. 2005-02-20 01:04:34 +00:00
Wayne Davison
0254bd46ec Test --remove-sent-files. 2005-02-20 01:04:27 +00:00
Wayne Davison
8b806ed347 Disallow --remove-sent-files with a read-only server. 2005-02-20 01:04:12 +00:00
Wayne Davison
8e3ead09a3 Got rid of maybe_DEL_TERSE. 2005-02-20 00:47:15 +00:00
Wayne Davison
8715db2cab Tweaked some externs. 2005-02-20 00:16:23 +00:00
Wayne Davison
50839b4bb0 Tweaked some externs. 2005-02-19 23:42:09 +00:00
Wayne Davison
e1f40891c7 - Needed to use a name buffer in delete_missing() to avoid having
a recursive delete reuse our buffer from f_name().
- Moved the backup-handling into delete_file() in rsync.c.
- Moved the --max-delete counting into delete_file() in rsync.c.
2005-02-19 23:41:52 +00:00
Wayne Davison
042f470ef9 Made delete_file() backup files it is removing if --backup was specified. 2005-02-19 23:39:47 +00:00
Wayne Davison
40cc28516d Moved deletion_count here so that we honor --max-delete in
delete_file().
2005-02-19 23:24:41 +00:00
Wayne Davison
8174bc3506 If the server refuses a directory, don't allow any files to be
sent to the server inside that directory.
2005-02-19 23:01:52 +00:00
Wayne Davison
9118a09c77 Changed a couple log_recv() calls back to log_send(). 2005-02-19 22:57:08 +00:00
Wayne Davison
8324bd5c21 When logging PERMS_REPORT messages, send them with the FCLIENT code
if the daemon has "%i" in its log message (because it already got a
detailed log message from the generator).
2005-02-19 22:16:53 +00:00
Wayne Davison
7f37167da5 - Always send the itemized-info bytes on to the receiver. This
not only ensures that batch files are created consistently for
  push and pull, but allows a daemon to log itemized changes.
- Improved the logging of itemized changes for the daemon.
- Make sure we debug-log our presence in send_files().
2005-02-19 22:16:50 +00:00
Wayne Davison
227a9c41c1 - Improved the logging of itemized changes for the daemon.
- Make sure we debug-log our presence in recv_files().
2005-02-19 22:16:47 +00:00
Wayne Davison
6c3862fae3 Make use of new variables (log_format_has_i, log_format_has_o_or_i,
and daemon_log_format_has_i) and the new FCLIENT logging code to
output stats in the best way possible for both the client and the
daemon.
2005-02-19 22:16:45 +00:00
Wayne Davison
1eec003a80 The FCLIENT log code aviods putting the message into the daemon's
log file and instead sends a FINFO message to the client.  This is
used when the daemon wants to log a better message locally than it
is sending to the client.  Improved log_delete() to make use of this
idiom if it needs to log a separate delete message for the daemon
and the client.
2005-02-19 22:16:41 +00:00
Wayne Davison
684d7582b6 - Added log_format_has_i.
- Fixed a problem withe option-refusing code when it refuses the
  daemon options.
- Don't sent --itemize-changes (-i) to the server -- send an
  improved --log-format value instead.
2005-02-19 22:16:39 +00:00
Wayne Davison
f39b2060fe We now set daemon_log_format_has_i and daemon_log_format_has_o_or_i
instead of itemize_daemon_changes.
2005-02-19 22:16:35 +00:00
Wayne Davison
4f2ba7e056 No more need to clear itemize_changes based on protocol_version. 2005-02-19 22:16:33 +00:00
Wayne Davison
1dcf3b4345 Changed some of the values of the MSG_* defines. 2005-02-19 22:16:31 +00:00
Wayne Davison
aa57d14ae7 We now use a regular expression to parse the (restored to its previous
version) default logfile format.  Added parsing for a version of the
default logfile format where %o has been replaced with %i.
2005-02-19 19:36:54 +00:00
Wayne Davison
3c54d8a3ad Decided to leave the "log format" default the same as in
earlier versions.
2005-02-19 17:38:51 +00:00
Wayne Davison
c0814b813f If the "log format" has a %i in it, set itemize_daemon_changes. 2005-02-19 17:37:40 +00:00
Wayne Davison
088aff1a48 - Don't log a delete message to the daemon log in dry-run mode.
- The daemon's wrote/read log message now uses the terms
  sent/received.
2005-02-19 17:23:08 +00:00
Wayne Davison
d6707171e6 Decide whether to log a delete message via the default format by
checking the new log_format_has_o_or_i variable, not itemize_changes.
2005-02-19 03:54:13 +00:00
Wayne Davison
5c5e159892 - Set new variable, log_format_has_o_or_i.
- Make sure that -i can't be set w/o an actual %i in the log_format.
- Only need to pass -i to server if we're the sender.
- Only need to pass some --log-format information to the server in
  certain circumstances.
2005-02-19 03:54:11 +00:00
Wayne Davison
6d7b3d52dc Rules read in from per-dir merge files need to have non-applicable
rules filtered out before the rule gets stored (not in a post-
filtering pass like the rules that are read-in prior to the run).
2005-02-19 03:12:21 +00:00
Wayne Davison
591b908fbf Mention the change in the default "log format" daemon-config setting. 2005-02-19 03:03:13 +00:00
Wayne Davison
742be97ce4 Log items that are unchanged if verbose > 1. 2005-02-19 02:39:33 +00:00
Wayne Davison
1f30a674cd Notify the remote side about -i (if either specified or inferred from
the user's --log-format string) and, if we're not verbose but we're
logging messages, let the server know that --log-format was specified.
2005-02-19 02:39:30 +00:00
Wayne Davison
19bc826d8b - Tweaked the letters output by "%i", including adding support for
logging a deleted item and an identical item.
- Added log_delete(), a routine that either logs the fact that a
  deletion happened, or sends a MSG_DELETED message to the client
  side (or both if we're a daemon server receiver).
2005-02-19 02:39:26 +00:00
Wayne Davison
c786a7aec5 - Changed the calling args to delete_file() to take an st_mode instead
of a DEL_DIR flag.
- Call log_delete() instead of outputting "deleting ..." messages..
- Log deletions if either verbose or log-format is specified.
2005-02-19 02:39:23 +00:00
Wayne Davison
8a8356b7db - Send the itemized data for every file, changed or not, if verbose > 1.
- Don't call set_perms() with PERMS_REPORT if we're itemizing changes.
- Don't call delete_file() with DEL_TERSE if we're itemizing changes.
- Call delete_file() with its new arg.
2005-02-19 02:39:21 +00:00
Wayne Davison
0d67e00af8 - Allow send_msg() to be called by the delete code in flist.c and
have it figure out if it should send the message to our sibling
  or the other side.
- Handle the new MSG_DELETED message in both the generator and the
  sender.  This message is used to let the client side log each
  deletion when the server side is the receiver.
2005-02-19 02:39:18 +00:00
Wayne Davison
7448177753 - Call log_delete() instead of outputting a "deleting ..." message.
- Call delete_file() with its new arg.
2005-02-19 02:39:15 +00:00
Wayne Davison
90d151f423 If the protocol is less than 29, make sure itemize_changes is off. 2005-02-19 02:39:11 +00:00
Wayne Davison
9f7c5dabf8 - Got rid of DEL_DIR define.
- Added define for ITEM_DELETED.
2005-02-19 02:39:09 +00:00
Wayne Davison
a85a151430 - Mention that "%o" can now have the value "del."
- Updated the description of "%i" to reflect the latest functioning.
2005-02-19 02:39:06 +00:00
Wayne Davison
5dd97ab999 Fixed an inaccuracy in the --archive description. 2005-02-19 02:39:03 +00:00
Wayne Davison
8daa9925cc More improvements. 2005-02-18 21:24:00 +00:00
Wayne Davison
e844be4e7b - Use read_short() and write_short().
- If the user does not want itemized changes, don't log the name
  for attribute changes.
2005-02-18 20:17:24 +00:00
Wayne Davison
88b218fa5c - Tweaked code in itemize() a bit.
- Use the new write_short() function.
- Mention the delete() when an item replaces an item of a different type.
- Make sure that this replacing of a non-same item is marked as a new
  transfer in the itemized output.
2005-02-18 20:17:20 +00:00
Wayne Davison
e66d70e34c The '%n' escape needs to append a trailing slash onto a directory name. 2005-02-18 20:17:17 +00:00
Wayne Davison
9361f83933 Added read_short() and write_short(). 2005-02-18 20:17:15 +00:00
Wayne Davison
3b2bebbf90 Improved the "log format" section some more. 2005-02-18 20:17:12 +00:00
Wayne Davison
4f90eb433a Improved --verbose, --itemize-changes, and --log-format. 2005-02-18 20:17:09 +00:00
Wayne Davison
b485e0c16c Fixed/improved the comment before safe_name(). 2005-02-18 20:17:05 +00:00
Wayne Davison
bc1fac9648 Handle uchar and short as a function return type. 2005-02-18 20:16:59 +00:00
Wayne Davison
c78779cce3 - Fixed a few bugs and compile warnings.
- Use the long-option parser for better option handling.
- Output a usage message if the options are wrong.
- Improved the option-variable names.
- Parse the new default daemon log-file format.
- Handle filenames that have spaces in them.
2005-02-18 17:58:03 +00:00
Wayne Davison
702cd15cb0 For the server, don't ever intuit verbosity higher than what
the client asked for.
2005-02-18 17:36:12 +00:00
Wayne Davison
1da05366ad The daemon loop needs to call log_open() because it called log_close(). 2005-02-18 17:34:09 +00:00
Wayne Davison
2267efeac5 Made log_open() non-static and moved log_close() next to it. 2005-02-18 17:33:43 +00:00
Wayne Davison
15954da08f Updated the default "log format" string and the output of "%i". 2005-02-17 09:19:07 +00:00
Wayne Davison
b2dc7bad39 Changed the default log format. 2005-02-17 09:16:51 +00:00
Wayne Davison
d4e0196346 Use '.' for unchanged attributes in the %i output. 2005-02-17 09:16:23 +00:00
Wayne Davison
2fc50f5a98 More improvements for the description of the %i output. 2005-02-16 20:12:20 +00:00
Wayne Davison
bd5b85dbc7 Mention the new flag-word for protocol 29. 2005-02-16 17:08:04 +00:00
Wayne Davison
8a8324657e - The itemized flags are now 2 bytes instead of 1.
- Always send/receive the itemized flags for protocols >= 29.
- The output of the verbose log-the-transfer messages is always handled
  via log_send() (when we're the client).
2005-02-16 17:02:16 +00:00
Wayne Davison
4bb0af79b7 - The itemized flags are now 2 bytes instead of 1.
- Always send/receive the itemized flags for protocols >= 29.
- The output of the verbose log-the-transfer messages is always handled
  via log_recv() (when we're the client).
2005-02-16 17:02:13 +00:00
Wayne Davison
e3bcd89319 - The itemized flags are now 2 bytes instead of 1.
- Always send the itemized flags for protocols >= 29.
- Sent an itemized-flag update for dirs and symlinks for protocols >= 29
  (instead of outputting a message directly).
2005-02-16 17:02:11 +00:00
Wayne Davison
87383697e8 - Auto-set --verbose if --dry-run is specified w/o --log-format.
- When verbose w/o a log_format specified, set it to "%n%L".
- There's no longer a need to send -i to the server.
2005-02-16 17:02:08 +00:00
Wayne Davison
e4b808989e Moved the auto-setting of --verbose when --dry-run is specified into
options.c.
2005-02-16 17:02:05 +00:00
Wayne Davison
59e52bf276 Tweaked ITEM_MISSING_DATA. 2005-02-16 17:02:02 +00:00
Wayne Davison
9b40e44ef4 No need to handle itemize_changes anymore. 2005-02-16 17:01:59 +00:00
Wayne Davison
e92f21d2f7 Tweaked the mention of --itemize-changes. 2005-02-16 08:12:34 +00:00
Wayne Davison
910e89b963 - We now accept an itemized-changes flag-byte over the socket if we're
the local client and --itemized-changes was specified.  If the item
  is not being updated, just call log_recv().
- We reject an attempt to file-update any non-regular file, not just
  dirs.
- Avoid the verbose "log the transfer" output if --log-format was
  specified and log_before_transfer is in effect.
- Call log_recv() with its new iflags arg.
2005-02-16 08:10:45 +00:00
Wayne Davison
8a9cfb2459 - We now accept an itemized-changes flag byte over the socket if we're
in --itemized-changes mode.  If the item is not being updated,
  either pass it along to the receiver (if we're the server) or just
  call log_send().
- We reject an attempt to file-update any non-regular file, not just
  dirs.
- Avoid the verbose "log the transfer" output if --log-format was
  specified and log_before_transfer is in effect.
- Call log_send() with its new iflags arg.
2005-02-16 08:10:41 +00:00
Wayne Davison
41961db0bd Ensure that -i is set consistent with the batch's data. 2005-02-16 08:10:38 +00:00
Wayne Davison
e76518843d - If log_before_transfer is possible, don't force --verbose on for
--progress.
- If --log-format contains %i, set --itemize-changes (-i).
- Always send -i to the remote rsync if it was specified/implied.
2005-02-16 08:10:31 +00:00
Wayne Davison
ef74f5d626 - Improved log_formatted() to handle long filenames better.
- Added %i, for the list of itemized changes, %n for the normal
  filename (might be shorter than %f), and %L for a " -> symlink"
  string IIF the item is a symlink (else "").
- The log_{send,recv}() functions now take an "iflags" arg.
2005-02-16 08:10:28 +00:00
Wayne Davison
c557eb8cec Changed showchg() into itemize(), which now ships off a flag byte of
what changed over to the sender instead of outputting a string itself.
This does mean that we now ship off indexes of non-file items that got
updated, but the sender will know what to do with it.
2005-02-16 08:10:25 +00:00
Wayne Davison
0cc279e0d3 - Added the new ITEM_* flags for the itemized-changes flag passing.
- Also added defines for FLAG_SENT and MSG_SUCCESS.
2005-02-16 08:10:22 +00:00
Wayne Davison
0cfdf22655 Documented that -i now sets a default --log-format string. 2005-02-16 08:10:19 +00:00
Wayne Davison
527a010f10 Documented the new log-format escapes: %n, %L, and %i. 2005-02-16 08:10:13 +00:00
Wayne Davison
c8ca974634 Some tweaks to how --itemize-changes works. 2005-02-16 01:13:03 +00:00
Wayne Davison
3296f91bb0 Check for refusal of --delete-before when it is inferred. 2005-02-15 21:15:58 +00:00
Wayne Davison
e2124620eb Moved two paragraphs. 2005-02-15 20:42:36 +00:00
Wayne Davison
69864a5ccf Made showchg() use safe_fname(). 2005-02-15 20:41:37 +00:00
Wayne Davison
5b4e1f318d - Mention the addition of --itemize-changes.
- Mention the setting of read_only when a daemon is read-only.
2005-02-15 19:47:57 +00:00
Wayne Davison
b78296cb0b Decided on a better option name --itemize-changes (-i). 2005-02-15 07:41:13 +00:00
Wayne Davison
06a1dbad61 Implemented the --what-has-changed functionality. 2005-02-15 07:20:14 +00:00
Wayne Davison
93c31c1a6d Don't force -v with -n if -w was specified. 2005-02-15 07:20:11 +00:00
Wayne Davison
a8ed495833 If -w and -v are both on, don't output the "log the transfer"
verbose message.
2005-02-15 07:20:04 +00:00
Wayne Davison
4a14ed068c Added --what-has-changed (-w), which summaries the changes
being made to the files.
2005-02-15 07:20:01 +00:00
Wayne Davison
dc0f24976d Document --what-has-changed (-w). 2005-02-15 07:19:58 +00:00
Wayne Davison
1e7098b5e3 Fixed a typo. 2005-02-15 03:38:04 +00:00
Wayne Davison
2f24fb18c4 Make sure that there are no directory-time differences between the
dirs that might trip up the check of the merged copy.
2005-02-15 02:01:02 +00:00
Wayne Davison
96a8ca6d98 Had a report that the __attribute__ code needs to check for
__APPLE__ being defined, not APPLE.
2005-02-14 22:49:51 +00:00
Wayne Davison
37a5644576 One arg to matched() is supposed to be an int32. 2005-02-14 22:48:28 +00:00
Wayne Davison
a1cbe76e2c Changed one size_t var into an int32. 2005-02-14 22:47:42 +00:00
Wayne Davison
98bf61c80e Improved description of --whole-file option. 2005-02-14 19:09:30 +00:00
Wayne Davison
01f439ec6e Fixed a mismatch in the compressed-data handling between how the
sending side and the receiving side handled implicit (unsent) data.
2005-02-14 08:28:00 +00:00
Wayne Davison
acc461c7da Changed various token variables from "int"s to "int32"s. 2005-02-14 08:19:32 +00:00
Wayne Davison
1585958497 The count of chunks should really be an int32, not a size_t,
because that's the maximum size we can transmit over the wire.
2005-02-14 08:13:47 +00:00
Wayne Davison
7cacd47edd Changed the size_t variables into int32 variables. 2005-02-14 08:12:22 +00:00
Wayne Davison
e461b9bed4 Don't let --fuzzy be used with a protocol_version < 29. 2005-02-14 02:47:44 +00:00
Wayne Davison
3723c04850 Mention --fuzzy. 2005-02-14 02:41:35 +00:00
Wayne Davison
73273075c8 Added code to read a fuzzy-basis name from the generator. 2005-02-14 02:41:30 +00:00
Wayne Davison
8e85be0a16 Added handling for fuzzy-basis scanning. When a fuzzy filename is
chosen, the name is sent down the name-pipe to the receiver.
2005-02-14 02:41:27 +00:00
Wayne Davison
37802f40dc - If send_file_name() gets f set to -2, it skips the local filter rules.
- Added get_dirlist(), which returns a file_list structure for the
  desired directory, optionally with local filter rules disabled.
2005-02-14 02:41:23 +00:00
Wayne Davison
06b96ffa86 Set need_name_pipe if --fuzzy was specified. 2005-02-14 02:41:18 +00:00
Wayne Davison
c4ed1487f9 Added parsing for the --fuzzy (-y) option. 2005-02-14 02:41:15 +00:00
Wayne Davison
e64ae6d766 Added find_filename_suffix() and fuzzy_distance(). 2005-02-14 02:41:10 +00:00
Wayne Davison
5b4837552b Document the --fuzzy (-y) option. 2005-02-14 02:41:05 +00:00
Wayne Davison
d2004814f0 Changed #if to use "defined". 2005-02-14 02:34:01 +00:00
Wayne Davison
bf0c5bec45 If f_name_cmp() discovers that two directory strings compare to an
equal value without being equal pointers, substitute one of the
pointers for the other in the file list.  This optimizes future name
comparisons.  Note also that this optimization won't be triggered
very often (because rsync tends to send the names grouped by dir-
name at transmission time), but it's nice to be able to assume that
all files in the same dir have identical dir-name pointers after the
qsort is finished.
2005-02-14 01:29:17 +00:00
Wayne Davison
0dd046d36f Don't check defined-ness of SIZEOF_OFF64_T. 2005-02-14 00:58:10 +00:00
Wayne Davison
4f5b0756df John E. Malmberg convinced me to standardize on #ifs for defined
values instead of non-zero.
2005-02-14 00:53:43 +00:00
Wayne Davison
fe1c19dcdf In clean_flist(), if a duplicate is found for a dir and a non-dir,
always dump the non-dir (because the dir might have contents in
the list).
2005-02-13 22:48:38 +00:00
Wayne Davison
24b2096e86 The dir vs non-dir test now assumes the dir wins. 2005-02-13 22:48:35 +00:00
Wayne Davison
86e97e178d Mention the new sorting method for protocol 29. 2005-02-13 22:37:29 +00:00
Wayne Davison
905d906d69 Added a test for the merging of a dir and a non-dir with the same name. 2005-02-13 22:01:15 +00:00
Wayne Davison
abce74bb93 Added some missing commas in some option summary lines. 2005-02-13 21:50:55 +00:00
Wayne Davison
f5db099330 - Made receive_file_entry() return the file_struct pointer instead
of storing it into the files[] array.
- Made flist_find() return "no match" if the found item differs in
  its directory-ness from the search item.
- Changed f_name_cmp() to sort sub-directories after non-directories
  for each directory's contents.  This makes things like the upcoming
  --fuzzy patch easier to get right.
- One complicating factor is that clean_flist() needed some extra
  code to ensure that a directory doesn't duplicate a non-directory
  of the same name.
- Make sure that the "strip_root" code in clean_flist() (for relative
  paths) strips off all leading slashes.
2005-02-13 21:15:47 +00:00
Wayne Davison
122d1771db Improved the call to f_name_cmp(). 2005-02-13 20:06:18 +00:00
Wayne Davison
8824e2cee4 Changed the prefix on the fnc_state enums. 2005-02-13 10:23:56 +00:00
Wayne Davison
8a6f3fead8 Improved the summary for the -F option. 2005-02-13 05:45:42 +00:00
Wayne Davison
9c71f56a25 Improved the help text for -F. 2005-02-13 05:44:29 +00:00
Wayne Davison
f924946eba Improved the description of the --compress (-z) option. 2005-02-12 22:22:14 +00:00
Wayne Davison
32a5edf43f Improved the documentation of the --compress (-z) option. 2005-02-12 22:21:45 +00:00
Wayne Davison
9a338344da Forgot to make sure that the dir-times on the chkdir got synced
in the newest test case.
2005-02-12 21:22:21 +00:00
Wayne Davison
df337831dc When --dry-run is set, note when a directory is missing and avoid
trying to stat() any items inside that dir's hierarchy.  This fixes
a bug where a symlink to a dir getting replaced by a dir with
identical contents to the dir at the other end of the symlink would
not report the updated files in the new hierarchy. (See bug #1673)
2005-02-12 21:18:58 +00:00
Wayne Davison
bb558f6791 Some more improvements to exercise rule-restricted merge files
(i.e. exclude patterns only) and side-restricted filter rules.
2005-02-12 20:45:39 +00:00
Wayne Davison
22558cdd7e Improved checkit() and rsync_ls_lR() to work with filenames that
might have spaces.
2005-02-12 20:25:12 +00:00
Wayne Davison
28c54e81c1 Mention the protocol change for --delete-excluded. 2005-02-12 19:52:40 +00:00
Wayne Davison
0dfffb88e1 Document the new filter rule flags for sender-/receiver-specific
rules.
2005-02-12 19:52:34 +00:00
Wayne Davison
ed243f8c29 - Added modifiers for the include/exclude rules that makes them
apply to the indicated (sender/receiver) side.
- Added the hide/show and protect/risk filter rules as an alternate
  way to specify sender-/receiver-specific include/exclude rules.
- send_rules() now allows f_out to be -1 to indicate that the list
  should be scanned but not sent.
- send_rules() now filters the list to remove any items that don't
  apply to the current side (after sending the item to the other
  side when f_out != -1).
- {send,recv}_filter_list() now transfer the list, even when the
  receiver is the server and --delete-excluded was specified (the
  exchanged list is appropriately filtered, of course).
- recv_filter_list() uses send_rules() to trim non-applicable rules
  when we're a local-server (because we got our filter list without
  send/recv calls when fork() duplicated it).
2005-02-12 19:52:26 +00:00
Wayne Davison
a427e8938a - Define MATCHFLG_SENDER_SIDE and MATCHFLG_RECEIVER_SIDE.
- Updated MATCHFLGS_FROM_CONTAINER.
2005-02-12 19:52:22 +00:00
Wayne Davison
cc25d29132 We don't need to avoid the local filter list in send_file_name()
when --delete-excluded is set because our list has been trimmed to
only include rules that apply in the current mode.
2005-02-12 19:52:18 +00:00
Wayne Davison
134f43385b - Since send_file_list() is no longer called with f == -1, got rid
of all the conditional code to support that.
- Improved the comment before send_directory() to indicate that it
  gets called with f == -1 from delete_in_dir().
2005-02-12 18:40:15 +00:00
Wayne Davison
a5a264842e Don't use underscores in the example filter rules. 2005-02-11 23:16:41 +00:00
Wayne Davison
eed47b6b9c Made "i" a size_t in receive_sums(). 2005-02-11 20:46:55 +00:00
Wayne Davison
3841a04e88 A minor tweak for the dry_run logic. 2005-02-11 20:26:08 +00:00
Wayne Davison
9eef8f0b73 Improved the "refuse options" section, including an update
to the section that talked about --del being a popt alias
(which is no longer true).
2005-02-11 10:52:50 +00:00
Wayne Davison
c258230722 - Several improvements in describing how options imply other options.
- Improved --partial-dir.
2005-02-11 10:51:25 +00:00
Wayne Davison
345e0988cb Changed rule_match() to rule_strcmp(). Likewise for the
define RULE_MATCH() being changed into RULE_STRCMP().
2005-02-11 10:47:43 +00:00
Wayne Davison
3671987f4d - Added some new refused_* variables that note if certain options
have been refused on the server daemon.  This allows us to reject
  implied options (e.g. if --partial is refused and -P specified).
- Changed the handling of the --delete refusals from the old idiom
  of upgrading "delete" to "delete*" into the new idiom of checking
  if refused_delete is set when we determine --delete was implied.
- Changed the --del option from a popt alias into a normal option.
- Mark all the daemon options as refused when a daemon is parsing
  the over-the-socket options.
- Created a new function, create_refuse_error(), which is now called
  from all the spots that check for refused options.
- Don't call clean_fname() on an empty string -- either reject it
  or handle it without erroneously expanding the string.
- If --delay-updates was specified without a --partial-dir option,
  don't send the default "--partial-dir=.~tmp~" option if the server
  is the receiver -- just let it default.
2005-02-11 10:42:55 +00:00
Wayne Davison
5aa7b20a3e Have partial_dir_fname() also check if the dir is excluded
by the server, not just the partial file.
2005-02-11 09:58:31 +00:00
Wayne Davison
68795c640b If a --delay-update can't use the partial-dir (e.g. if a server
daemon excludes the dir or file), update the file without delay.
2005-02-11 09:56:28 +00:00
Wayne Davison
4f1f94d1de Improved the --modify-window description. 2005-02-09 17:08:23 +00:00
Wayne Davison
0f7e31f7d7 Improved several items and added a new section describing what is
different for protocol version 29.
2005-02-09 04:45:36 +00:00
Wayne Davison
2f3cad893b - Decided that flist_find() should be public, not static.
- Modified f_name_cmp() so that, beginning with protocol 29,
  it will guarantee that a directory name will sort one slot
  before its contents (prior versions could sort other items
  in between in rare instances).
2005-02-09 02:36:17 +00:00
Wayne Davison
e79666267d Also test the new long-named filter rules. 2005-02-08 19:30:07 +00:00
Wayne Davison
d91de04671 Mention the new long-name filter rules. 2005-02-08 19:06:30 +00:00
Wayne Davison
64b761c19a Allow a ',' to prefix the MODIFIERS for a single-letter filter rule. 2005-02-08 18:47:25 +00:00
Wayne Davison
a1ac8edd66 - Added long-name filter rules.
- Only parse the "!" token when MATCHFLG_NO_PREFIXES is set if
  MATCHFLG_CVS_IGNORE is also set.
2005-02-08 18:33:16 +00:00
Wayne Davison
1dca857b5b Fixed a typo. 2005-02-07 20:46:42 +00:00
Wayne Davison
f8cd88dbd1 - Added more calls to safe_fname().
- Improved safe_fname() so that it changes all non-printable chars
  into '?'s, and accomodates more simultaneous (and longer) names.
2005-02-07 20:41:43 +00:00
Wayne Davison
71903f601a Added missing calls to safe_fname() and full_fname(). 2005-02-07 20:40:18 +00:00
Wayne Davison
719bc858b5 Made NS define make use of safe_fname(). 2005-02-07 20:39:13 +00:00
Wayne Davison
a6126d678b Added missing call to safe_fname(). 2005-02-07 20:38:56 +00:00
Wayne Davison
4875d6b64d Adding more calls to safe_fname(). 2005-02-07 20:36:43 +00:00
Wayne Davison
54b4059856 Needed to call safe_fname() when listing the remote names. 2005-02-07 19:40:31 +00:00
Wayne Davison
38059f8e8e One more tweak. 2005-02-06 07:24:42 +00:00
Wayne Davison
bb5f4e7285 A few tweaks to the FILTER RULES section, including a mention of
using the +/- modifiers on merge-file rules.
2005-02-06 07:16:19 +00:00
Wayne Davison
448797a1e6 Fixed an off-by-one error in the prefix-length checking in
get_rule_prefix().
2005-02-05 06:53:20 +00:00
Wayne Davison
a261103ce0 Improved the name of a variable. 2005-02-05 05:30:06 +00:00
Wayne Davison
7b82b5adb3 Mention a couple more changes. 2005-02-05 01:38:19 +00:00
Wayne Davison
397a344364 Added the "C" modifier to the itemized list of +/- modifiers. 2005-02-05 00:03:46 +00:00
Wayne Davison
bafa48759f Mention the new --filter=-C syntax that lets you position the default
CVS rules within your other filter rules.
2005-02-04 23:57:26 +00:00
Wayne Davison
46db185081 - Moved get_cvs_excludes() up above its only use and made it static.
- Changed get_cvs_excludes() to make an mflags arg.
2005-02-04 22:32:17 +00:00
Wayne Davison
1412da7c32 If we're a "local server" (i.e. we just forked a server for a
local transfer), don't duplicate all the filter rules that we
already know about in the forked process.
2005-02-04 21:54:02 +00:00
Wayne Davison
d09e800a0e Fixed the way get_rule_prefix() turns the MATCHFLG_WORD_SPLIT flag
back into a modifier character.
2005-02-04 21:16:39 +00:00
Wayne Davison
53b417e414 - Added MATCHFLG_CVS_IGNORE.
- Made the match_flags var a uint32.
2005-02-04 21:13:12 +00:00
Wayne Davison
57dee64e82 - Moved the cvs_exclude checks into send_filter_list() and
recv_filter_list().  Because of this, we never skip these
  calls anymore, though read-batch processing indicates that
  the list should not really be sent by setting f_out to -1.
- Moved the definintion of the "local_server" variable here
  from options.c.
2005-02-04 21:13:09 +00:00
Wayne Davison
fdc795015f - Changed filter_rule() to add_rule().
- Improved the debug info coming from add_rule().
- Changed add_filter() to parse_rule() and add_filter_file()
  to parse_filter_file().
- Changed get_filter_tok() to parse_rule_tok().
- Made the mflags a uint32.
- Added an extra arg to get_rule_prefix() to indicate if we're
  building the options for transmission or other purposes.
- The 'C' modifier can now be applied to a '-' rule, so it now
  sets a new flag: MATCHFLG_CVS_IGNORE.
- The send_filter_list() and recv_filter_list() functions now handle
  all the logic needed to do the right thing for -C (this used to be
  in main.c).
2005-02-04 21:13:06 +00:00
Wayne Davison
3a5e9224d0 - Changed add_filter() to parse_rule() and add_filter_file()
to parse_filter_file().
- Moved the definintion of the "local_server" variable into main.c.
2005-02-04 21:13:03 +00:00
Wayne Davison
ebfd1a1cf7 Changed add_filter() to parse_rule() and add_filter_file()
to parse_filter_file().
2005-02-04 21:13:00 +00:00
Wayne Davison
dd667c2301 Call get_rule_prefix() with its new arg. 2005-02-04 21:12:56 +00:00
Wayne Davison
d727f0ff48 Fixed the MODIFIERS_MERGE_FILE define. 2005-02-04 00:48:18 +00:00
Wayne Davison
eb9b2e53c8 Changed delete_missing() to not limit the use of DEL_FORCE_RECURSE
to just --delete-during now that the other delete routines are using
delete_in_dir().
2005-02-03 19:19:39 +00:00
Wayne Davison
b6f06b8e8b Added an mflags arg to get_filter_tok(), add_filter_file(), and
add_filter().  This made for less flag conversion between various
MATCHFLG_* and XFLG_* values.  It also made it easy to fix a bug
in the handling of no-prefix per-directory include/exclude files.
We also use the new XFLG_OLD_PREFIXES and MATCHFLGS_FROM_CONTAINER
defines.
2005-02-03 19:00:20 +00:00
Wayne Davison
0a68f869d7 Call add_filter() and add_filter_file() with their new flag args. 2005-02-03 19:00:17 +00:00
Wayne Davison
3b2461cf2e - Got rid of a bunch of XFLG_* options.
- Added XFLG_OLD_PREFIXES and MATCHFLGS_FROM_CONTAINER defines.
2005-02-03 19:00:13 +00:00
Wayne Davison
346402ddbf Use the new negated exclude to filter out all non-dirs in a few
of the rsync commands.
2005-02-03 03:45:24 +00:00
Wayne Davison
44d60d5f83 Document the new "!" modifier for include/exclude filter rules (to
negate the match).
2005-02-03 03:37:02 +00:00
Wayne Davison
f2ae9e8583 Implemented a "!" modifier for filter rules that lets a rule trigger
on a non-matching pattern.
2005-02-03 03:36:58 +00:00
Wayne Davison
7c8e23bd9f Added MATCHFLG_NEGATE. 2005-02-03 03:36:55 +00:00
Wayne Davison
0752721dc3 Mention the latest delete optimization. 2005-02-03 02:01:22 +00:00
Wayne Davison
68a94ac30f Changed delete_files() to use the delete_in_dir() function, which
saves a ton of memory for a large set of files.
2005-02-03 02:01:20 +00:00
Wayne Davison
ee3751c8d7 - We now separate the user-specified top-dir flag (via the restored
FLAG_TOP_DIR) from the del-in-this-directory flag (FLAG_DEL_HERE).
  This was needed to properly handle -x in delete_in_dir().
- The delete_in_dir() function takes a slightly changed set of args.
- Always set the FLAG_DEL_HERE flags, not just for --delete-during.
2005-02-03 02:01:17 +00:00
Wayne Davison
ec33e0e6bd - Changed {XMIT,FLAG}_DEL_START back to {XMIT,FLAG}_TOP_DIR.
- Define FLAG_DEL_HERE.
2005-02-03 02:01:14 +00:00
Wayne Davison
31937d363b Call delete_in_dir() with its new args. 2005-02-03 02:01:11 +00:00
Wayne Davison
8982a89b24 In hlink_compare(), call f_name_cmp() directly instead of using
file_compare().
2005-02-03 01:19:03 +00:00
Wayne Davison
0492fdfb2e - Improved some comments.
- Changed the index passed to recv_generator() from "i" to "ndx".
- Call delete_in_dir() with its new args.
- During the redo phase, clear a bunch of options that might interfere
  with the generator deciding it needs to redo the file (for instance,
  --update-only could have interfered if --partial was specified).
2005-02-03 01:19:01 +00:00
Wayne Davison
14698a3a1a - Moved an optimization from file_compare() into f_name_cmp() (the one
that avoids doing a string-compare on two identical char pointers),
  making it just a wrapper for f_name_cmp().  Also made file_compare()
  static because everyone now calls f_name_cmp() directly.
- Improved the flist summary that is output at high verbosity.
- Improved delete_in_dir() to better handle the push/pop semantics
  based on the depth value that is now passed in as an arg (so that
  we don't have to parse it out of the paths each time).
2005-02-03 01:18:58 +00:00
Wayne Davison
8c2ffaf095 - If recv_files() is sent the index of a directory, complain about it
and die.
- Moved a few code snippets in recv_files() into better locations.
2005-02-03 00:19:40 +00:00
Wayne Davison
afd72c78bd If the generator sends us the index of a directory, generate an
error and die.
2005-02-02 17:15:22 +00:00
Wayne Davison
6bf822649b - Fixed a problem with the setting of the --recurse option from the
batch file.
- Save the state of the --dirs option in the batch flags in a way
  that is compatible with older protocol versions.
2005-02-02 09:40:45 +00:00
Wayne Davison
67dde16163 In read_sum_head: output the who_am_i() info in our error messages. 2005-02-01 16:42:01 +00:00
Wayne Davison
f1d5ba4005 Set am_sender to -1 until the end of the option parsing. This
lets who_am_i() output better values for the command-line
--filter/--include/--exclude options.
2005-02-01 09:46:42 +00:00
Wayne Davison
794b0a037f Changed who_am_i() to output "server" or "client" when am_sender
is negative.  This will only occur during the startup phase
before we know if we're the sender or not (e.g. when parsing
client-side --filter/--exclude/--include options).
2005-02-01 09:45:09 +00:00
Wayne Davison
c32edbe02e Make sure the %f expansion handles the new dir.root properly. 2005-02-01 09:23:59 +00:00
Wayne Davison
f3c3ed44e6 - Made flist_find() and receive_file_entry() static functions.
- Changed receive_file_entry() args.
- We now store the directory depth into file->dir.depth when
  receiving the file list.  This will be used to aid in the
  traversal of the file list on the receiving side for things
  such as the future --fuzzy option and better --delete-during
  processing.
- Fixed a bug when -R was used with "." as a source directory:
  subdirectories were not being promoted to FLAG_DEL_START when
  --delete-during was specified.
- Refer to the old basedir variable as dir.root.
- Got rid of the first-push code -- I decided that it wasn't
  the right thing to do for per-dir merge-file processing.
- Improved the flist_find() function to make it a little more
  optimal.  The new code no longer needs the inline function
  flist_up().
- In clean_flist() we now set two new values in the flist struct:
  "low" and "high".  These are used by the new flist_find().
- Tweaked the output_flist() function to output each entry's
  flags and to output the directory-depth on the receiving side
  in place of the directory-root (which is still output on the
  sending side).
2005-02-01 09:21:32 +00:00
Wayne Davison
f805730493 - Put "basedir" into a union "dir" and named it "root". The other
member of the union is "depth".
- Added members "low" and "high" to the file list structure (which
  are set when the list is cleaned).
- Got rid of the flist_up() inline function.
2005-02-01 09:21:30 +00:00
Wayne Davison
2b1366635d Refer to the old basedir variable as dir.root. 2005-02-01 09:21:28 +00:00
Wayne Davison
42f23f479d Fixed a typo in a variable name. 2005-02-01 08:12:00 +00:00
Wayne Davison
62bf783f06 Changed the "s" modifier to "w" for word-splitting tokens from a
merge filter file.  Also sprinkled some bf(...) macros into that
section.
2005-01-31 23:57:35 +00:00
Wayne Davison
0b2901b72d Changed the "s" modifier to "w" for a word-splitting merge file. 2005-01-31 23:51:54 +00:00
Wayne Davison
faa82484a5 - Mark references to command-line switches with the bf(...) macro.
- Changed some verb(...) macros to use other yodl idioms because
  yodl inserts way too much vertical whitespace surrounding the
  item.
- Some items weren't indenting enough in the manpage, though they
  were indenting fine in the HTML version, so used some creative
  idioms to get things to render well in both.
- Got rid of some empty lines in lists.
- Made several quote(...) items also tt(...).
2005-01-31 23:41:08 +00:00
Wayne Davison
4ccfd96cfe Tweaked one or more warning messages. 2005-01-31 19:13:19 +00:00
Wayne Davison
408aa7b24c Improved the exclude tests to make sure that the filter files
are interacting with --delete-during correctly.
2005-01-31 18:09:23 +00:00
Wayne Davison
776b9d1c00 Added "need_first_push" logic to delete_in_dir(). 2005-01-30 20:24:11 +00:00
Wayne Davison
c93fad5ee0 The --delete-during processing only happens during the first phase
(not the redo phase).  We also call delete_in_dir(NULL, NULL) to
make sure that all the local filter files get popped.
2005-01-30 10:06:18 +00:00
Wayne Davison
19b2a5d9fd delete_in_dir() now mananges the push/pop levels of nested
directories properly.
2005-01-30 10:01:21 +00:00
Wayne Davison
f1773e09ab - Now delete_in_dir() calls send_directory(), not send_file_name().
- Moved the local-list push/pop code out of send_directory() so that
  the callers (send_file_name() and delete_in_dir()) can call the
  push/pop functions themselves.  This is in preparation for
  delete_in_dir() getting fully correct push/pop semantics (for
  its --delete-during handling of per-dir filter files).
2005-01-30 09:12:55 +00:00
Wayne Davison
462c51d9a1 - Restored the io_error test to delete_files().
- Sanity check the dir_list value from send_file_list().
2005-01-30 07:35:13 +00:00
Wayne Davison
2430e98412 - Made delete_files() call send_file_list() and delete_missing()
instead of delete_in_dir().
- Tweaked check in front of delete_files() call.
2005-01-29 22:35:53 +00:00
Wayne Davison
78fc60cd29 If --recurse wasn't specified, turn off all the --delete* options. 2005-01-29 22:35:50 +00:00
Wayne Davison
864146de58 Tweaked check in front of delete_files() call. 2005-01-29 22:35:47 +00:00
Wayne Davison
45478cc79b - Improved the handling of -x with -K.
- Changed delete_in_dir() to only be used by the --delete-during
  option.
- Added delete_missing() that is used by both delete_files() and
  delete_in_dir().
- delete_files() still uses send_file_list(), but delete_in_dir()
  now uses send_file_name().
2005-01-29 22:35:44 +00:00
Wayne Davison
5454d22ad8 The --dirs was sending -k instead of -d. 2005-01-29 21:25:44 +00:00
Wayne Davison
dc1488ae47 - Document the new "/" modifier for -/+.
- "=" is no longer a valid separator for a filter rule.
2005-01-29 20:48:27 +00:00
Wayne Davison
0121a8ecad Renamed XFLG_ABS_PATH XFLG_ANCHORED2ABS. 2005-01-29 20:48:23 +00:00
Wayne Davison
7bc90b3066 Moved the module_id define into clientserver.c. 2005-01-29 20:48:20 +00:00
Wayne Davison
bf39270e0c - Renamed make_filter() to filter_rule().
- Added the "/" modifier to the -/+ filter rules to allow the
  rule to specify an absolute path (sets MATCHFLG_ABS_PATH).
- Added the passing of the xflgags to filter_rule() and key off
  XFLG_ANCHORED2ABS to prepend the current dirbuf value (was
  keing off MATCHFLG_ABS_PATH).
- We no longer allow a '=' to separate the filter rule from its
  arg (just a single space or an underscore).
- For triple verbose levels, mention when we look for a filter
  file even if we don't find it (used to only mention the file
  when it was found).
- A chrooted daemon process now includes /.cvsignore (inside the
  chrooted hierarchy) instead of $HOME/.cvsignore.
2005-01-29 20:48:17 +00:00
Wayne Davison
211bc43b6e - Moved the module_id definition from options.c to here.
- Use the new XFLG_ANCHORED2ABS name for the old XFLG_ABS_PATH
  define.
2005-01-29 20:48:14 +00:00
Wayne Davison
91c5833bd0 Change one call to add_cvs_excludes() to add_filter() to just add
the per-dir .cvsignore rule for protocols < 29.
2005-01-29 20:29:06 +00:00
Wayne Davison
8311f1c11e A minor change to the HAVE_GETPGRP code. 2005-01-28 23:00:58 +00:00
Wayne Davison
ae2836325f Fixed some typos. 2005-01-28 22:01:02 +00:00
Wayne Davison
a897af2cde Mention a few more things. 2005-01-28 21:48:32 +00:00
Wayne Davison
cc80022e84 Pass an unsigned character to isdigit(). 2005-01-28 21:32:20 +00:00
Wayne Davison
5a016db9b6 Don't allow the user to specify a filter file that is excluded
by a daemon's config options.
2005-01-28 21:28:08 +00:00
Wayne Davison
92e1aeede7 Got rid of an unreachable free() call. 2005-01-28 21:07:05 +00:00
Wayne Davison
f846a9bfe9 Cast each value referenced from the struct mallinfo to a long
in order to print it.
2005-01-28 21:05:50 +00:00
Wayne Davison
3db859e8b5 Don't set unsigned del_heir_name_len to -1 -- it's only used
if in_del_hier is non-zero, so it doesn't need to take on an
invalid value.
2005-01-28 21:03:50 +00:00
Wayne Davison
0eeb1cf83a Case uchar pointer to a char pointer when calling strlen(). 2005-01-28 21:02:15 +00:00
Wayne Davison
5f238db203 - Use "uchar" instead of "unsigned char".
- Tweaked an initializer to try to avoid a compiler warning.
2005-01-28 21:01:21 +00:00
Wayne Davison
422696201a Call the right stat function based on USE_STAT64_FUNCS. 2005-01-28 20:43:09 +00:00
Wayne Davison
58fef0ac38 Changed direct call to fstat() into a call to do_fstat(). 2005-01-28 20:41:36 +00:00
Wayne Davison
25e1181466 Use new USE_STAT64_FUNCS define. 2005-01-28 20:33:55 +00:00
Wayne Davison
5b5f7e3b59 - Use off_t if SIZEOF_OFF_T is 8.
- Define USE_STAT64_FUNCS if we defined STRUCT_STAT as
  "struct stat64".
2005-01-28 20:32:47 +00:00
Wayne Davison
dc3afaf6aa Changed "char" to "uchar" in delayed_bits's new_array() call. 2005-01-28 20:24:23 +00:00
Wayne Davison
1164f67827 Make use of new HAVE_STRUCT_STAT64 define. 2005-01-28 20:15:08 +00:00
Wayne Davison
c83a2c8ec5 Added a check for "struct stat64". 2005-01-28 20:15:06 +00:00
Wayne Davison
43d0f38b24 Do a better job defining an int32. Also define SIZEOF_INT32
instead of the (unused) LARGE_INT32 variable.
2005-01-28 19:03:16 +00:00
Wayne Davison
e95538ca2c - Changed the main core of system include files to use the same "#if"
idioms that configure uses.
- Use "#if" (not "#ifdef") for configure-defined macros.
- Use "#if !" (not "#ifndef") for configure-defined macros.
2005-01-28 18:50:54 +00:00
Wayne Davison
25ff04417e Use "#if" (not "#ifdef") for configure-defined macros. 2005-01-28 18:50:49 +00:00
Wayne Davison
63ecee4d1a Made log_open() static and made it die with an error if the
log-file can't be opened.
2005-01-28 17:42:21 +00:00
Wayne Davison
4c8f6b6a06 No need to call log_open() in start_accept_loop() because
rsync_module() calls log_init() before it gives up its privileges.
2005-01-28 17:33:57 +00:00
Wayne Davison
2161111900 Document the "max verbosity" setting. 2005-01-28 17:11:48 +00:00
Wayne Davison
24b0922b0e Document the --verbose (-v) option for the daemon. 2005-01-28 17:10:58 +00:00
Wayne Davison
186387301f - Moved read_only variable here from options.c
- Set read_only to 1 if the module is read-only.
- Make sure that the verbose level is 0 before we parse the client's
  options.
2005-01-28 17:10:16 +00:00
Wayne Davison
1bd9db74ba - Added --verbose option parsing to the daemon options.
- Moved read_only into clientserver.c.
2005-01-28 17:07:54 +00:00
Wayne Davison
df6933406f Got rid of unused mmap section. 2005-01-28 17:06:41 +00:00
Wayne Davison
d679c8390a Changed HAVE_OFF64_T to SIZEOF_OFF64_T. 2005-01-28 16:27:02 +00:00
Wayne Davison
d4daa7b68c Changed HAVE_OFF64_T to SIZEOF_OFF64_T. 2005-01-28 16:21:37 +00:00
Wayne Davison
44d98d6166 Improved the option summaries. 2005-01-28 09:55:36 +00:00
Wayne Davison
b3708acf27 Improved the option-descriptions in the --help text. 2005-01-28 09:55:18 +00:00
Wayne Davison
2c0fa6c5df More --delete-before improvements. 2005-01-28 08:01:33 +00:00
Wayne Davison
57f74bd1c2 One minor tweak to the --delete-before option-passing code. 2005-01-28 07:50:00 +00:00
Wayne Davison
598c409e63 Document --delete-before. 2005-01-28 07:39:59 +00:00
Wayne Davison
c6eb7fad68 Added back support for the --delete-before option so that future
verions of rsync can more easily change the default that --delete
implies and still support explicit --delete-before functionality
when interacting with older versions.
2005-01-28 07:39:09 +00:00
Wayne Davison
c561edaa72 Added a sanity check for the SIZEOF_INT64 define. 2005-01-28 06:51:44 +00:00
Wayne Davison
031fa9ad4d Use the new SIZEOF_INT64 define instead of INT64_IS_OFF_T. 2005-01-28 06:46:33 +00:00
Wayne Davison
d622d4bf30 - Switched the int64 code over to using the improved SIZEOF_*
macros.
- Define SIZEOF_INT64 to a value that is useable at compile time.
- Got rid of INT64_IS_OFF_T.
2005-01-28 06:45:16 +00:00
Wayne Davison
e32db5c9aa Switched the checks for "long long" and "off64_t" to use the
AC_CHECK_SIZEOF() macro since it now fully supports cross-
compiling.
2005-01-28 06:43:48 +00:00
Wayne Davison
4a6c209a13 Use SIGNED_CHAR_OK instead of HAVE_UNSIGNED_CHAR. 2005-01-28 02:01:18 +00:00
Wayne Davison
0d2aa5d9d7 - Made some of the tests work better when cross-compiling.
- Added descriptions for all config.h variables that had none.
- Changed HAVE_UNSIGNED_CHAR to SIGNED_CHAR_OK.
- Got rid of (the unused) HAVE_SHORT_INO_T.
- Changed version to 2.6.4cvs (long overdue).
2005-01-28 02:00:40 +00:00
Wayne Davison
e30b1fb8fd Added a few more details of changes since 2.6.3. 2005-01-28 01:56:50 +00:00
Wayne Davison
da1b6eeaf2 Mention the latest changes plus a few missed items. 2005-01-28 00:01:54 +00:00
Wayne Davison
01b835c237 Docment the new --delay-updates option. 2005-01-27 22:47:23 +00:00
Wayne Davison
48e1c8c69d Implement the new --delay-updates option. 2005-01-27 22:46:36 +00:00
Wayne Davison
f06e708282 Added the new --delay-updates option. 2005-01-27 22:46:14 +00:00
Wayne Davison
f0f7e760ae - Output the new flist time stats (when available).
- For protocol 29 and above, send the flist time stats to the
  client side (as needed).
2005-01-27 22:23:30 +00:00
Wayne Davison
31b4d25d10 Set the new stats.flist_buildtime and stats.flist_xfertime values. 2005-01-27 22:21:45 +00:00
Wayne Davison
d41988232e - Added a caveat to the definition of the int64 type.
- Added two time values to the stats struct.
2005-01-27 21:55:11 +00:00
Wayne Davison
880570f228 Added a missing newline to an error message. 2005-01-27 21:45:32 +00:00
Wayne Davison
72a90c750a Bumped the copyright year to 2005. 2005-01-27 21:42:56 +00:00
Wayne Davison
e1988bc744 Added .rsync-filter. 2005-01-25 18:16:34 +00:00
Wayne Davison
d6a3e37b83 If rsync is put in the background, output fewer progress-report
lines.
2005-01-25 17:16:13 +00:00
Wayne Davison
8261047b1e - Use the "--filter=._-" option instead of --exclude-from=- if the
protocol being saved is >= 29.
- Call the new get_rule_prefix() function to figure out the right
  rule prefix.
- Strip out the --filter and -f options from the cached command-line.
2005-01-25 12:13:53 +00:00
Wayne Davison
417b59997f - Moved the code that turns rule flags into chars into a new
function called get_rule_prefix().
- Don't pass the per-dir .cvsignore rule from -C for protocols < 29.
2005-01-25 12:10:31 +00:00
Wayne Davison
4366d2c428 In delete_files(), handle new DEL_NO_RECURSE flag (and use
renamed DEL_FORCE_RECURSE flag.
2005-01-25 12:07:13 +00:00
Wayne Davison
217cc3b045 - The call to delete_file() needs DEL_NO_RECURSE when handling
delete_before or delete_after or --dry-run will report too
  many deletions.
- Changed DEL_RECURSE to DEL_FORCE_RECURSE.
2005-01-25 12:05:20 +00:00
Wayne Davison
757e0a5445 Added DEL_NO_RECURSE and changed DEL_RECURSE to DEL_FORCE_RECURSE. 2005-01-25 12:02:08 +00:00
Wayne Davison
ddf6410130 Needed to call add_cvs_excludes() from one more code path. 2005-01-25 11:55:03 +00:00
Wayne Davison
7842418b7b Renamed several exclude-related functions/variables using new
filter terminology.
2005-01-25 10:39:14 +00:00
Wayne Davison
9624b86426 Mention the latest new options. 2005-01-25 04:00:31 +00:00
Wayne Davison
201a2fe5ff Added testing for --filter and merge-file features. 2005-01-25 03:18:29 +00:00
Wayne Davison
ed032a88b8 Mention that --del is a popt alias for --delete-during, so there's
no need to refuse "del" by name -- just refusing "delete-during" or
"delete*" is sufficient.
2005-01-25 03:09:06 +00:00
Wayne Davison
ae76a74043 Document the latest --delete options, including --delete-during. 2005-01-25 03:09:02 +00:00
Wayne Davison
3359acb8cb - Changed --delete to go back to defaulting to the delete-before
functionality.
- Got rid of --delete-before.
- Added --delete-during.
- Added a popt alias for --delete-during:  --del.
- Fixed a bug in the generation of the proper --delete options
  for the server.
- Generate an error if the user tries to specify both --delete-during
  and --delete-after.
2005-01-25 03:08:58 +00:00
Wayne Davison
a2b371cd52 Don't try to allocate zero bytes in push_local_excludes(). 2005-01-25 02:30:59 +00:00
Wayne Davison
dd69b3976a Document the new "filter" parameter. 2005-01-25 00:53:07 +00:00
Wayne Davison
16e5de84da Document --filter (-f) and -F, with lots of changes to the
include/exclude sections, including a little restructuring.
2005-01-25 00:53:03 +00:00
Wayne Davison
46fa602530 Some changes to support the new --filter option:
- Changed XFLG_WORDS_ONLY to XFLG_NO_PREFIXES.
- Added XFLG_DEF_EXCLUDE and XFLG_ABS_PATH.
- Added some new MATCHFLG_* values for the new merge-file support.
- Put the "slash_cnt" var (in the exclude_struct) into a union with
  the new megelist pointer.
2005-01-25 00:52:59 +00:00
Wayne Davison
aa4d3b4cc0 - Added parsing for --filter (-f) and -F.
- Changed the include/exclude calls to work with the new XFLG_* values.
2005-01-25 00:52:56 +00:00
Wayne Davison
73ed23495e Added the "filter" parameter. 2005-01-25 00:52:53 +00:00
Wayne Davison
c7d970f782 The calls into the exclude system changed a little for the new --filter
option:
- The special handling for cvs_exclude went away.
- Call push_local_excludes() and pop_local_excludes() instead of fiddling
  with the (no longer present) local_exclude_list var.
2005-01-25 00:52:50 +00:00
Wayne Davison
6dfd07d025 Implemented the core of the merge-file and per-dir merge-file support
for the --filter option.  Some noteworthy changes:
- Added push_local_excludes() and pop_local_excludes() to implement
  the changes needed as we go from directory to directory (this takes
  the place of the old local_exclude_list var that only handled the
  .cvsignore files).  These per-dir excludes are linked into the same
  exclude list as the global excludes.
- The exclude list is transferred as filter rules to an rsync that
  talks protocol 29 or above.  It limits itself to just include/exclude
  rules for older rsyncs.
2005-01-25 00:52:47 +00:00
Wayne Davison
e7bf7c0161 Some exclude changes for the new --filter option, including:
- Added module_dirlen var.
- Call set_excludes_dir() instead of setting exclude_path_prefix.
- Use the newest XFLG_* options.
2005-01-25 00:52:44 +00:00
Wayne Davison
f5a7b9e716 Improved the explanation for --omit-dir-times. 2005-01-25 00:47:35 +00:00
Wayne Davison
b951e023ec Moved the code that reads the extra byte for a modern inplace
transfer up nearer the code that reads the index.
2005-01-24 17:19:04 +00:00
Wayne Davison
3ea9bbd632 Optimized away the post-transfer directory loop in certain
circumstances.
2005-01-24 06:19:58 +00:00
Wayne Davison
aaca3daa27 Document --delete-before and --delete's new "during" behavior. 2005-01-24 01:41:57 +00:00
Wayne Davison
a51b316824 Added the delete-during handling (also selected with --delete) and
added --delete-before for the old delete logic.
2005-01-24 01:41:54 +00:00
Wayne Davison
928a00c474 Moved a call to add_cvs_exclude() from the delete code to one code-
path in this file.  This avoids a potential duplication of the
cvs-excludes that would occur in the old logic.
2005-01-24 01:41:51 +00:00
Wayne Davison
fa13f396d5 Added code to implement the delete-during handling. 2005-01-24 01:41:48 +00:00
Wayne Davison
3ab56a20ee Moved some of the delete code into flist.c since the generator now
calls it for the delete-during handling.
2005-01-24 01:41:45 +00:00
Wayne Davison
649f874292 Moved some of the delete code from receiver.c to here and implemented
the handling for delete_during (which is called from the generator).
2005-01-24 01:41:42 +00:00
Wayne Davison
90fdd89a0b Mention the --omit-dir-times option. 2005-01-24 00:56:37 +00:00
Wayne Davison
54e66f1d59 Document --omit-dir-times. 2005-01-24 00:51:38 +00:00
Wayne Davison
82471e68a8 Honor the new omit_dir_times var. 2005-01-24 00:51:34 +00:00
Wayne Davison
20fb7b9175 Added --omit-dir-times (-O). 2005-01-24 00:51:32 +00:00
Wayne Davison
859fdaad45 Mentioned the --dirs and --list-only options. 2005-01-24 00:34:53 +00:00
Wayne Davison
09ed309996 - Changed --keep-dirs (-k) into --dirs (-d).
- Document --list-only.
2005-01-24 00:17:42 +00:00
Wayne Davison
65e4cda059 - Changed --keep-dirs (-k) into --dirs (-d).
- Renamed keep_dirs to xfer_dirs.
- Mention --list-only in the --help.
2005-01-24 00:17:39 +00:00
Wayne Davison
7e037c4226 Renamed keep_dirs, "xfer_dirs". 2005-01-24 00:17:36 +00:00
Wayne Davison
f636c38440 Document the new --keep-dirs option. 2005-01-23 16:49:09 +00:00
Wayne Davison
b98f040ef2 Go back to requiring -r for deletes to happen. 2005-01-23 07:27:01 +00:00
Wayne Davison
e57211c544 When an option defined with POPT_ARG_VAL is being refused, we must
change it to POPT_ARG_NONE or it won't be refused.
2005-01-23 01:25:36 +00:00
Wayne Davison
48a1ff0d45 - Use the new delete_before var.
- Check the "keep_dirs" var instead of "recurse" to decide if
  delete is appropriate.
2005-01-22 22:48:40 +00:00
Wayne Davison
032dcf74b0 Check the "keep_dirs" var instead of "recurse" to decide if
delete-after is appropriate.
2005-01-22 22:48:37 +00:00
Wayne Davison
51d4839861 - We now set a delete_before variable for the --delete option.
- Reordered some of the options in the --help list.
- Made the popt-handling of the delete options simpler.
- Parse the new --keep-dirs option.
- Parse the new --list-only option.
- Set recurse to -1 (infinite) for the -r and -a options.
- Set keep_dirs for --list-only.
2005-01-22 22:48:34 +00:00
Wayne Davison
9f125ea7c1 - Implemented a new handling of the recurse variable: if it is
< 0, it specifies infinite recursion, otherwise it contains a
  count of how many levels of recursion we will allow.
- If the user is processing/listing a non-recursive directory/
  arg, send the contents.
2005-01-22 22:48:31 +00:00
Wayne Davison
9bcb25958d - Mustn't override a user-specified list_only value.
- Moved the computing of the options for the server down until
  after we've figured out the protocol_version for the transfer.
- If we're talking to a protocol-29 server in list-only mode,
  force the new --list-only mode (which avoids the -r with
  --exclude="/*/*" kluge).
- Output the options we sent to the daemon if verbose > 1.
2005-01-22 22:48:27 +00:00
Wayne Davison
866925bfb7 Changed the order of a few of the options in the options summary. 2005-01-22 20:32:03 +00:00
Wayne Davison
f8b3c05311 Mustn't override a user-specified list_only value. 2005-01-22 20:28:17 +00:00
Wayne Davison
353f272434 Changed a comment. 2005-01-22 20:27:22 +00:00
Wayne Davison
3d54c6ec46 Moved the /proc/mounts literal string nearer to the top. 2005-01-22 08:11:43 +00:00
Wayne Davison
71e27c463d - Changed XMIT_TOP_DIR to XMIT_DEL_START.
- Changed FLAG_TOP_DIR to FLAG_DEL_START.
2005-01-21 00:34:37 +00:00
Wayne Davison
8c48382049 Don't mention when the file-list is first allocated, just when it
expands.
2005-01-20 23:57:35 +00:00
Wayne Davison
11781089d1 In delete_file(): got rid of DEL_NO_RECURSE code and added
DEL_RECURSE code.  Improved the verbose output of a recursively
deleted directory when --dry-run is specified.
2005-01-20 23:51:57 +00:00
Wayne Davison
d97fd43a72 Decided that delete_in_dir()'s call to delete_file() would be
better using DEL_RECURSE.
2005-01-20 23:51:55 +00:00
Wayne Davison
f5ea4b3b39 Changed DEL_NO_RECURSE to DEL_RECURSE. 2005-01-20 23:51:52 +00:00
Wayne Davison
f227ffe4b9 Moved the dry_run check in set_perms() so that it only triggers if
we don't have a stat-buffer (and returns 1, not 0).
2005-01-20 23:01:34 +00:00
Wayne Davison
027428eb1d Got rid of the erroneous --dry-run short-circuit in the directory
handling.
2005-01-20 22:59:54 +00:00
Wayne Davison
15778afbdc In set_modtime(), the verbose message should be output even if
--dry-run was specified.
2005-01-20 22:58:30 +00:00
Wayne Davison
d06f63287e - Got rid of the uint64 typedef.
- Changed the dev/inode vars to use int64.
2005-01-20 22:43:32 +00:00
Wayne Davison
1490812ab2 Switched uint64 vars over to int64. 2005-01-20 22:42:47 +00:00
Wayne Davison
707415d4fc Use int64 instead of uint64. 2005-01-20 22:37:38 +00:00
Wayne Davison
9cea6ef1b6 Improved a confusing sentence in the description of subcomponent
include/exclude matching.
2005-01-20 19:31:42 +00:00
Wayne Davison
48ea74bf01 When outputting the file list created for the delete pass, identify
it as such.
2005-01-20 00:53:15 +00:00
Wayne Davison
026deaf759 Added an example of running mnt-excl remotely via ssh for a pull. 2005-01-19 21:07:09 +00:00
Wayne Davison
4c59971194 A perl script that outputs excludes for all mount points that affect
the supplied source dir (or all mount points if the arg is omitted).
The excludes are appropriately anchored relative to the supplied dir,
and honor rsync's trailing-slash idiom.
2005-01-19 21:00:26 +00:00
Wayne Davison
fd8571c2c9 Mention a change in the verbose output when deleting directories. 2005-01-19 20:32:25 +00:00
Wayne Davison
dd096ae080 - Updated delete_file() to take a flag arg that makes it more
flexible.  Optimized away a stat() call since the caller knows
  if the item to delete is a directory or not.
- Tweaked delete_file()'s "deleting ..." messages to include a
  trailing slash when we're deleting a directory.
- No need for conditional code around do_lstat() anymore.
2005-01-19 20:11:03 +00:00
Wayne Davison
eb1accaa91 Define the new DEL_* flags. 2005-01-19 20:11:00 +00:00
Wayne Davison
7e38410e47 - Moved write_sum_head() to io.c.
- Use the new delete_file() calling syntax.
2005-01-19 20:10:57 +00:00
Wayne Davison
d336388403 Got rid of delete_one() since we can (and do) use the updated
delete_file() call now.
2005-01-19 20:10:53 +00:00
Wayne Davison
c207d7ec62 Moved write_sum_head() here from generator.c. 2005-01-19 20:10:50 +00:00
Wayne Davison
018b28328c No need for conditional code around do_lstat() anymore. 2005-01-19 19:30:29 +00:00
Wayne Davison
0957a7463e When SUPPORT_LINKS is not defined, we now go ahead and provide
the do_lstat() function and just have it call do_stat().
2005-01-19 19:29:20 +00:00
Wayne Davison
c72f5bd9c4 A slight simplification to the no-implied-dirs change. 2005-01-19 00:34:13 +00:00
Wayne Davison
0f57446da7 Use the new "keep_dirs" var instead of separately checking the
"recurse" and "files_from" vars.  This also simplifies the case
where the code wants to send the implied dirs without recursing.
2005-01-19 00:24:35 +00:00
Wayne Davison
3a90ea0acd - Added new int, keep_dirs, which is set if either recurse or
files_from was specified.
- Pass the the sender the --no-implied-dirs option if --relative
  was specified (or implied) and the sender is not the client.
2005-01-19 00:23:32 +00:00
Paul Green
58af2f958c Fix typo in handling of lchown when the host operating system does
not implement it.  It should get mapped to chown.
2005-01-18 21:19:42 +00:00
Wayne Davison
a8fd4161bb Mention the latest changes. 2005-01-17 23:55:15 +00:00
Wayne Davison
53f8519a38 For --inplace over protocol-version 29 or greater, read the
type the type of basis file the generator is using from the
socket and set the new updating_basis_file var.
2005-01-17 23:11:26 +00:00
Wayne Davison
eb162f3b0a Mention the change in restrictions for --inplace. Also talk about
how --backup makes an --inplace transfer more optimal.
2005-01-17 23:11:22 +00:00
Wayne Davison
4ce838e1f1 We don't need to complain about --inplace being combined with one
of the --FOO-dest options anymore.
2005-01-17 23:11:18 +00:00
Wayne Davison
a36ffd3910 Changed the checks for --inplace to use the new updating_basis_file
variable.
2005-01-17 23:11:13 +00:00
Wayne Davison
17b5b32f75 For --inplace over protocol-version 29 or greater, tell the
sender what kind of a basis file we've selected.
2005-01-17 23:11:05 +00:00
Wayne Davison
9b919d590a - Moved read_sum_head() to io.c (because the generator uses it too).
- Tweaked the read_size var (formerly map_size) that gets passed to
  map_file().
2005-01-17 22:51:29 +00:00
Wayne Davison
80264051d8 Tweaked the read_size var (formerly map_size) that gets passed to
map_file().
2005-01-17 22:51:27 +00:00
Wayne Davison
188fed9570 Moved read_sum_head() here from sender.c (because the generator uses it
too) and improved it with better error checking.
2005-01-17 22:51:24 +00:00
Wayne Davison
eae7165c79 Make sure that we don't compute a block size larger than MAX_BLOCK_SIZE. 2005-01-17 22:51:21 +00:00
Wayne Davison
54281fe733 - Changed the map_size parameter to map_file() to be an int32 named
"read_size".
- Changed some int vars in map_ptr() needed to be int32 vars.
- All callers expect map_ptr() to return back the full "len" bytes,
  so we never shorten this value, even near EOF--the read will
  just get zero-padded, as needed.
- Die with an error if someone calls map_ptr() with a len < 0, or
  if read_size is computed as a value < 0.
2005-01-17 22:51:17 +00:00
Wayne Davison
2b2ea368aa - Incremented the PROTOCOL_VERSION to 29.
- Added define for MAX_BLOCK_SIZE.
- Reorder the variables in the structure defs to sort by size.
- Some vars in map_struct needed to be int32 instead of int.
2005-01-17 22:51:15 +00:00
Wayne Davison
67a28eb256 Got rid of an unneeded assert(). 2005-01-17 22:25:53 +00:00
Wayne Davison
f5d96a6f80 Added a commented-out RSYNC initialization that uses valgrind. 2005-01-17 22:24:08 +00:00
Wayne Davison
44ac015598 Put double-quotes around the --rsync-path arg. 2005-01-17 22:23:09 +00:00
Wayne Davison
89a9c0545e Collapsed two sed invocations into one. 2005-01-17 06:00:44 +00:00
Wayne Davison
3b26bba0c4 Fixed an off-by-one comparison against MAX_BASIS_DIRS. 2005-01-15 21:23:04 +00:00
Wayne Davison
2be2fb3ed3 Use the new FNAMECMP_BASIS_DIR_HIGH to improve a compare-dest check. 2005-01-15 21:17:39 +00:00
Wayne Davison
e341588a8a Define FNAMECMP_BASIS_DIR_LOW and FNAMECMP_BASIS_DIR_HIGH instead of
FNAMECMP_BASIS_DIR.
2005-01-15 21:17:36 +00:00
Wayne Davison
c56595d749 Make sure that the generator sent us a valid index into basis_dir[]. 2005-01-15 21:14:27 +00:00
Wayne Davison
ce0b384fa6 Made basis_dir_cnt non-static. 2005-01-15 21:12:58 +00:00
Wayne Davison
dfd7d541b0 Made compare_dest non-static. 2005-01-15 20:54:25 +00:00
Wayne Davison
ded4daf049 Some inplace-checking code should have been inside the #ifdef that
handles the case where --inplace cannot be supported.
2005-01-15 20:22:54 +00:00
Wayne Davison
361428213b Simplified the logic in allow_access() and tweaked some whitespace. 2005-01-15 20:06:48 +00:00
Wayne Davison
12a79db2f6 Simplified one "if" that checks if one of the --FOO-dest options
was specified.
2005-01-15 04:40:06 +00:00
Wayne Davison
e8b155a3be Improved the docs on --delete and --delete-after. 2005-01-14 19:49:35 +00:00
Wayne Davison
716b46c550 - We now remove the DEST~old~ dir instead of renaming it to DEST~new~.
- Improved the usage message and added an introductory comment.
2005-01-14 19:23:20 +00:00
Wayne Davison
9d954dca8c Make sure that the presence of a partial-dir file is noted, even
if --whole-file is in effect.  Also needed to force statret to 0
when using a partial-dir file.
2005-01-14 18:20:46 +00:00
Wayne Davison
7162c65df7 We also need the "name pipe" from the generator to the receiver
when --partial-dir was specified.
2005-01-14 18:18:31 +00:00
Wayne Davison
bd9fca4708 For the "unexpected tag" or "multiplexing overflow" messages, we
now output who_am_i() so we know who had the problem.
2005-01-14 18:17:32 +00:00
Wayne Davison
14d496cc8b Aid forward-compatibility in the include/exclude syntax by putting
a "- " in front of any name that starts with a '+' or a '-' and would
otherwise be unprefixed (the old code only did this if the '+' or '-'
was followed by a space).
2005-01-13 22:01:56 +00:00
Wayne Davison
106a8ad918 - Allow multiple source paths to be specified (and checked).
- Allow spaces and a few other extra chars in file names.
- For safety, disallow any option that takes an arg.  This should
  be improved in the future because it blocks options such as
  --block-size=N, but without this rule the user could specify
  something like --files-from=FILE or --backup-dir=DIR and have
  it affect files outside the desired SUBDIR restriction.
- Switched to SSH_CONNECTION from the deprecated SSH_CLIENT.
- Strip "::ffff:" from the start of an IP from SSH_CONNECTION.
2005-01-12 19:20:07 +00:00
Wayne Davison
44a82a175d This is Joe Smith's rrsync (restricted rsync) perl script. 2005-01-12 18:48:26 +00:00
Wayne Davison
99248631aa A simple Makefile. 2005-01-11 18:37:37 +00:00
Wayne Davison
2836ee9b02 A debug program to help diagnose data-transfer corruption problems. 2005-01-11 18:36:31 +00:00
Wayne Davison
d82773ffe9 Fixed the file_checksum1() function that is compiled only when
TEST_MDFOUR is defined:  it did not have the fix that the main
rsync code got back in protocol 27 to properly handle files
that are a multiple of 64-bytes long.
2005-01-10 20:52:08 +00:00
Wayne Davison
ec626b3f0e Two more fixes. 2005-01-10 10:08:59 +00:00
Wayne Davison
997d9ea67f Added a "overwriting_basis" arg to finish_transfer(). 2005-01-10 10:03:12 +00:00
Wayne Davison
aec6b9f86f - Call finish_transfer() with its new arg. This ensures that we only
create a backup file if we're about to overwrite the basis file.
- Only clear make_backups for the redo phase if partial_dir isn't set.
2005-01-10 10:03:10 +00:00
Wayne Davison
d45898df80 Call finish_transfer() with its new arg. 2005-01-10 10:03:06 +00:00
Wayne Davison
b0da4b23a0 Moved the reading of the final MSG_DONE message here from main.c
(this message comes from the receiver).  This ensures that any
redo-pass files and delete-after processing are known to be done
prior to the start of our hard-link and dir-time-munging loops.
2005-01-10 00:31:55 +00:00
Wayne Davison
bf18b7ca67 Moved the reading of the final MSG_DONE message from here to
generator.c (the message comes from the receiver).  This ensures
that any redo-pass files and delete-after processing are known to be
done prior to the start of the hard-link and dir-time-munging loops.
2005-01-10 00:31:55 +00:00
Wayne Davison
cc17fbfe7d Mention new atomic-rsync script. 2005-01-06 17:15:36 +00:00
Wayne Davison
fa170b2e5a A perl script to effect an atomic transfer of a set of files. 2005-01-06 17:13:31 +00:00
Wayne Davison
c61ba345f2 Decided that a cross-compling configure should default the
chown-follows-symlinks check to "yes".
2005-01-03 23:01:19 +00:00
Wayne Davison
ae09fb1f91 Improved the last addition. 2005-01-03 22:49:14 +00:00
Wayne Davison
70a2c84cd2 If lchown() is not available, we only skip the call to chown() for a
symlink if it will try to follow the symlink (as a normal OS should).
2005-01-03 22:47:55 +00:00
Wayne Davison
21524e3083 - Added a test to see if chown() follows symlinks.
- Check for getpgrp() and tcgetpgrp().
2005-01-03 22:42:55 +00:00
Wayne Davison
fbe2aba2e7 Mention lchown() fix. 2005-01-03 21:07:02 +00:00
Wayne Davison
a41a1e8718 If there is no lchown(), don't try to set the user & group of a symlink. 2005-01-03 21:05:39 +00:00
Wayne Davison
051547603a Moved kluged (conditional) define of lchown from rsync.h to syscall.c. 2005-01-03 21:03:33 +00:00
Wayne Davison
80a25bb880 Backed out changes to send_deflated_token() that surrounded the
call to deflate(..., Z_INSERT_ONLY) -- the underlying bug was
caused by the zlib code not handling Z_INSERT_ONLY in the case
where the server has disabled compression.
2005-01-02 09:08:59 +00:00
Wayne Davison
0301b334c7 Fixed Z_INSERT_ONLY support in deflate_stored(). 2005-01-02 09:03:44 +00:00
Wayne Davison
1492b4b2b2 The deflate_stored() function needed to support Z_INSERT_ONLY. 2005-01-02 08:49:47 +00:00
Wayne Davison
5b7bcac260 In send_deflated_token(), the section that handles "token != -2"
now breaks up the calls to deflate() into CHUNK_SIZE chunks, just
like the other sections of the code.
2005-01-02 00:55:55 +00:00
Wayne Davison
7fcbf9e43e - Use an int32 for the each block-size variable.
- Fixed a problem in send_deflated_token() where the data we are
  compressing might not finish processing in one call.
2005-01-01 21:08:20 +00:00
Wayne Davison
6c495e0da4 - Use an int32 for the each block-size variable.
- Fixed a potential overflow in the map_size calculation.
2005-01-01 21:08:17 +00:00
Wayne Davison
a06b419d42 Use an int32 for the each block-size variable. 2005-01-01 21:08:14 +00:00
Wayne Davison
a255c592e8 - Use an int32 for the each block-size variable.
- Improved the layout and error-checking of the code that
  calculates the block-size and the number of checksum bits.
2005-01-01 21:08:11 +00:00
Wayne Davison
7aac6604c4 - Use an int32 for the each block-size variable.
- Renamed the local block_size arg to blk_size (to avoid
  confusion with the global block_size variable).
2005-01-01 21:08:07 +00:00
Wayne Davison
deb5bf1dff - Use an int32 for each checksum length variable.
- Simplified some of the code, removing a useless memcpy().
2005-01-01 21:08:05 +00:00
Wayne Davison
3dfe6e97a7 Since lp_bind_address() can't return NULL, we need to check if it is
an empty string and ignore it when it is.
2004-12-31 09:41:04 +00:00
Wayne Davison
43bab4035b A minor improvement to the just-committed code. 2004-12-31 00:41:32 +00:00
Wayne Davison
ef0c03ff70 The code that tries to read an error from the socket in an abnormal-
exit situation was properly forcing the io_timeout value down to 30
seconds, but failing to set the select_timeout value.
2004-12-31 00:39:59 +00:00
Wayne Davison
ad54dcc827 Set select_timeout if the per-module timeout value was lower than
the default select_timeout value.
2004-12-31 00:35:03 +00:00
Wayne Davison
c0ab28d1d9 If we send --files-from to the remote server and relative-paths
are not enabled, we need to also send --no-relative.
2004-12-22 09:10:08 +00:00
Wayne Davison
5b2f48da27 Mention latest fix. 2004-12-16 22:48:31 +00:00
Wayne Davison
132fcf36b2 The "ignore nonreadable" daemon parameter no longer affects
symlinks that are being copied, even if they point nowhere.
2004-12-16 22:47:36 +00:00
Wayne Davison
4571df58c6 Got rid of the rare failure caused by a directory-time mismatch. 2004-12-14 19:41:19 +00:00
Wayne Davison
f6b384d41f Don't call do_lstat() unless SUPPORT_LINKS is defined. 2004-12-13 17:22:32 +00:00
Wayne Davison
c259892c3a Document the client version of the --port option. 2004-12-08 17:30:40 +00:00
Wayne Davison
b471329591 Allow --port to be used in client mode (as well as daemon mode). 2004-12-08 17:29:54 +00:00
Wayne Davison
3add5835db If rsync_port is 0, set it to RSYNC_PORT. 2004-12-08 17:11:15 +00:00
Wayne Davison
cf510ad2c5 Switching to a better rsync_port fix. 2004-12-08 17:09:59 +00:00
Wayne Davison
696a8d6191 Document the new "address" global option. 2004-12-06 22:45:10 +00:00
Wayne Davison
01f8a1155f Made --port and --address point the user at the relevant global
options in the rsyncd.conf manpage.
2004-12-06 22:45:07 +00:00
Wayne Davison
986aaaaa4b Check the global option "address" if the user didn't specify
an --address option when starting the daemon.
2004-12-06 22:45:03 +00:00
Wayne Davison
c96ee2310d Added support for the "address" option. 2004-12-06 22:45:00 +00:00
Wayne Davison
76cb2a3a4f Set default port value for a :: file-spec without a port number. 2004-12-06 17:57:06 +00:00
Wayne Davison
9bef934c76 Improved the examples for the --relative option. 2004-12-03 01:31:24 +00:00
Wayne Davison
85f14172dc Check the return value of flush_write_file() and report an error
if it reports failure.
2004-12-02 17:16:19 +00:00
Wayne Davison
4539c0d79f Improved the description of the --update option. 2004-11-30 20:43:06 +00:00
Wayne Davison
c3131af90a Improved some of the descriptions. 2004-11-30 06:07:50 +00:00
Wayne Davison
c2c14fa26e Removed some redundant words in a sentence. 2004-11-29 17:09:31 +00:00
Wayne Davison
e49f61f5fc Make some of the --*-dest comments clearer and more complete. 2004-11-27 22:09:33 +00:00
Wayne Davison
22f5bd5e35 Improved some of the items. 2004-11-27 21:55:05 +00:00
Wayne Davison
7a1b73b983 Mentioned the latest enhancements. 2004-11-27 18:26:30 +00:00
Wayne Davison
0c56b1add7 Allow "port" to be specified in the rsyncd.conf file. 2004-11-27 18:24:12 +00:00
Wayne Davison
1e60969646 Added tests for multiple --compare-dest options and --copy-dest. 2004-11-27 17:59:48 +00:00
Wayne Davison
ee29752217 Added support for multiple --*-dest options. 2004-11-27 17:56:58 +00:00
Wayne Davison
e012f858d6 - Added parsing for --copy-dest.
- Added support for multiple --*-dest options.
2004-11-27 17:52:51 +00:00
Wayne Davison
c3fad2e227 The compare_dest variable changed. 2004-11-27 17:52:49 +00:00
Wayne Davison
b7e8628c4b - Added support for --copy-dest, which behaves like --link-dest,
but it copies the identical files instead of hard-linking them.
- Added support for multiple --*-dest options.
2004-11-27 17:52:47 +00:00
Wayne Davison
e4977b0b9f - Define MAX_BASIS_DIRS.
- Renamed FNAMECMP_CMPDEST to FNAMECMP_BASIS_DIR.
2004-11-27 17:52:45 +00:00
Wayne Davison
b127c1dc58 Document --copy-dest and the support for multiple --*-dest options. 2004-11-27 17:52:42 +00:00
Wayne Davison
07bff66fb5 Fixed a socket-data conflict when verbosity is >= 2 and the
files-from list is coming from a remote receiver.
2004-11-20 17:10:54 +00:00
Wayne Davison
4a888ae6d4 Mention latest fix. 2004-11-20 07:23:20 +00:00
Wayne Davison
a0a33ee506 Call set_msg_fd_in() during the early phase of being a client sender
so that we monitor the socket for any messages that it might send to
us (and thus avoid a potential hang when verbosity is high).
2004-11-20 07:08:44 +00:00
Wayne Davison
98f8c9a5e5 Some minor improvements to read_msg_fd() made it safe to use both
set_msg_fd_in() and read_msg_fd() during the early phase of being
a client sender (up through the sending of the file list).  This
makes sure that the sender monitors the socket from the receiver
for any messages that it might send to us, and thus avoids a hang
when verbosity is high.
2004-11-20 07:07:37 +00:00
Wayne Davison
1f69bec480 Mention that the --bwlimit may now be combined with --daemon. 2004-11-17 19:41:09 +00:00
Wayne Davison
8f1b4f3642 - Mention the latest enhancements.
- Aged the 2.6.3 news into OLDNEWS.
2004-11-17 19:35:11 +00:00
Wayne Davison
ca39ebf9fb Aged the 2.6.3 release news. 2004-11-17 19:34:31 +00:00
Wayne Davison
9fb0844100 - Added the --bwlimit option to the options that are handled in
combination with --daemon.  This value is both a default bwlimit
  value and a maximum limit if the client asks for something larger.
- Enabled popt support for option aliases.
2004-11-17 19:29:20 +00:00
Wayne Davison
bdf278f7a5 Separate the daemon options from the normal client options. 2004-11-17 19:11:53 +00:00
Wayne Davison
c8f2f8572f Tweaked the error code for a pipe() failure. 2004-11-13 22:32:34 +00:00
Wayne Davison
5d54f33962 Mentioned the new fork() check. 2004-11-13 21:50:56 +00:00
Wayne Davison
ba449e444b Die with an appropriate error if do_fork() fails. 2004-11-13 21:49:26 +00:00
Wayne Davison
87ba7282f6 Mention the new --max-size option. 2004-11-11 01:45:31 +00:00
Wayne Davison
7d1bfaf7be Obey the max_size setting. 2004-11-11 01:45:28 +00:00
Wayne Davison
7d5acf1d44 Added the --max-size option. 2004-11-11 01:45:25 +00:00
Wayne Davison
3610c4583a Document --max-size. 2004-11-11 01:45:22 +00:00
Wayne Davison
41cfde6be3 Checking in the g2r-basis-filename patch that ensures that the receiver
uses the same basis file that the generator used (avoiding a duplicate
check that could cause a hang if a compare-dest file was a named pipe).
2004-11-03 20:30:31 +00:00
Wayne Davison
34bde8d54a Always include lib/snprintf.o when we include lib/compat.o. 2004-11-02 16:47:15 +00:00
Wayne Davison
1ed55e3e3e Mention latest fix. 2004-10-27 06:35:50 +00:00
Wayne Davison
f80a8520e8 Don't ever call make_backup() if we're removing a destination directory
(just remove it).
2004-10-27 06:34:13 +00:00
Wayne Davison
740bab942d Mention the latest bug-fix. 2004-10-18 20:44:09 +00:00
Wayne Davison
08b1b4860f Fixed an off-by-one error in the handling of --max-delete=N. 2004-10-18 20:41:57 +00:00
Wayne Davison
18ea5dc0d7 Mention new option parsing. 2004-10-14 17:11:28 +00:00
Wayne Davison
3ac7f5d4c1 Separate the daemon options so that the user can't mix client options
with daemon options and visa versa.
2004-10-14 17:08:15 +00:00
Wayne Davison
ad71500818 It seems that some popt releases don't define POPT_TABLEEND, so don't
use it.
2004-10-14 09:11:12 +00:00
Wayne Davison
b2ad840a6b Decided we don't need the build_gen target after all. 2004-10-12 20:08:51 +00:00
Wayne Davison
8db7cc2cff - Got rid of some awkward spacing in the long_options table.
- Use the POPT_TABLEEND macro to end the long_options table.
- Improved the count_args() function to accept a NULL pointer.
- Simplified the code that sets *argc using count_args().
2004-10-11 10:43:25 +00:00
Wayne Davison
ac1541f4b7 Mention the latest changes. 2004-10-10 20:33:07 +00:00
Wayne Davison
09e2bbce8a Call flush_write_file() in _exit_cleanup() if we are keeping a
partially-received file.
2004-10-10 20:31:54 +00:00
Wayne Davison
73496a36a1 Handle systems where the makedev() macro is named mkdev(). 2004-10-08 21:27:22 +00:00
Wayne Davison
8303cc1021 A new target, build_gen, works like gen w/o man-page generation. 2004-10-08 19:52:38 +00:00
Wayne Davison
ab759cd27b Improved an error message by using rsyserr(). 2004-10-07 17:02:39 +00:00
Wayne Davison
64444de582 Mention in -a's usage message that -H isn't implied. 2004-10-07 17:00:36 +00:00
Wayne Davison
e425fbe85d Re-enable the "!" token-handling in a .cvsignore file. 2004-10-06 00:10:08 +00:00
Wayne Davison
4f4b2f0927 The device-handling code is no longer omitted based on HAVE_MKNOD
(this is because do_mknod() might be using a different function
to handle fifos and sockets without the help of mknod().
2004-10-01 06:58:23 +00:00
Wayne Davison
da6eb9d123 Improved do_mknod() so that it handles creating a fifo file
and a socket file when mknod() itself does not.
2004-10-01 06:56:14 +00:00
Wayne Davison
1b15e07e99 Make sure that all programs that use syscall.o also include
lib/compat.o so that we can use strlcpy().
2004-10-01 06:53:26 +00:00
Wayne Davison
e49d720081 - Check if struct sockaddr_un has a sun_len member.
- Check if mknod() can make a fifo file.
- Check if mknod() can make a socket file.
2004-10-01 06:51:34 +00:00
Wayne Davison
3267d6a9ce Some systems need do_mkstemp() to use setmode() to set O_BINARY. 2004-10-01 02:34:22 +00:00
Wayne Davison
3ba2c330e1 Check for the setmode() function. 2004-10-01 02:31:10 +00:00
Wayne Davison
618c8a73db Preparing for release of 2.6.3 2004-09-30 16:36:42 +00:00
Wayne Davison
aa0ea373cd Mention the enhancement that was made (quite a while ago) to the
daemon's wildcard-expansion limit (formerly 1000 items, now memory
limited).
2004-09-30 10:46:43 +00:00
Wayne Davison
6c3fda83ba Refined the text of a few of the news items. 2004-09-30 09:58:39 +00:00
Wayne Davison
a3571c6cce - Mention the fix for lost output with 2>&1.
- Prepare the file for the 2.6.3 final release.
2004-09-30 09:37:38 +00:00
Wayne Davison
6fcedb7dbe Mention the (anticipated) 2.6.3 release date. 2004-09-30 09:36:29 +00:00
Wayne Davison
18882701d2 Set our stderr output to blocking I/O to avoid any loss of output. 2004-09-29 17:58:07 +00:00
Wayne Davison
30c041f9ad Changed the errors concerning the secrets file to output with FLOG
instead of FERROR.
2004-09-24 17:04:05 +00:00
Wayne Davison
be7cf82299 - Make sure that match_address() always restores the "tok" string,
even on error.
- Turned the various FERROR messages into (the more proper) FLOG.
2004-09-24 16:50:07 +00:00
Wayne Davison
fde045cd77 Turned the various FERROR messages into (the more proper) FLOG. 2004-09-24 16:39:41 +00:00
Wayne Davison
183150b741 Added some more --inplace info (i.e. it implies --partial and conflicts
with 3 basis-file-affecting options).
2004-09-23 21:15:04 +00:00
Wayne Davison
a2570930e8 Made the refused-option message clearer, like Paul suggested. 2004-09-23 17:39:05 +00:00
Wayne Davison
fdb6716c0f Create a FIFO using mkfifo. 2004-09-23 16:34:43 +00:00
Wayne Davison
a20a88d235 Assume that gettimeofday() takes two arguments when cross-compiling. 2004-09-23 16:00:44 +00:00
Wayne Davison
48d3ff94c9 Only output major/minor info for a character/block device, not for
a FIFO or a socket.
2004-09-23 05:33:48 +00:00
Wayne Davison
a33857da09 Mention that --partial-dir now sets an exclude that helps to avoid
losing the partial data when deleting, and avoid copying any partial
data from the sender.
2004-09-22 04:14:43 +00:00
Wayne Davison
13791b1eeb If the partial-dir value is relative, add a directory-exclude for it
to the end of the user's exclude list.
2004-09-22 04:12:13 +00:00
Wayne Davison
9a5e37fca8 In get_exclude_tok(), if XFLG_DIRECTORY was passed in the xflags,
set MATCHFLG_DIRECTORY in the mflags we return.
2004-09-22 04:11:15 +00:00
Wayne Davison
3e976df0fb Added XFLG_DIRECTORY define. 2004-09-22 04:10:10 +00:00
Wayne Davison
42afed9c1a Preparing for release of 2.6.3pre2 2004-09-21 16:10:35 +00:00
Wayne Davison
37c36e2692 Mention the daemon-socket-connection change. 2004-09-21 15:47:20 +00:00
Wayne Davison
7fbc7031f4 Mentioned a couple more changes. 2004-09-21 15:31:33 +00:00
Wayne Davison
9f004a9ea9 The delete_one() function no longer needs to handle the case where
it thinks it is removing a directory and it is really removing a
symlink.
2004-09-21 09:24:06 +00:00
Wayne Davison
23f4587f2b - Turned readlink_stat() into a static function.
- Made readlink_stat() no longer honor keep_dirlinks.
- The make_file() function now checks keep_dirlinks late in the
  function so that it only transforms a symlink to a local dir
  into a directory if the receiver also has a directory by that
  name.  This makes the use of --delete with --keep-dirlinks
  work much better.
2004-09-21 09:24:02 +00:00
Wayne Davison
4d8f5b0ae7 - Fixed a problem with the $bakdir value.
- Made the files have better contents to copy.
- Also test --backup without --backup-dir.
2004-09-20 19:50:04 +00:00
Wayne Davison
89389a29ef Output a backup message when verbose > 1 and we did a copy prior
to an --inplace update.
2004-09-20 19:47:59 +00:00
Wayne Davison
29fe3961ab Output the same backup-message prefix when verbose > 1 regardless of
the setting of --backup-dir.
2004-09-20 19:46:45 +00:00
Wayne Davison
4e8a085ac9 Use $diffopt instead of -u. 2004-09-20 05:17:57 +00:00
Wayne Davison
fb22c2774d Got rid of a superfluous static buffer. 2004-09-20 05:01:38 +00:00
Wayne Davison
7d059d4c37 A simple test of the backup functionality. 2004-09-20 04:59:01 +00:00
Wayne Davison
9715c5899a Improved a comment. 2004-09-20 04:17:42 +00:00
Wayne Davison
cc07f21211 Mention the new RSYNC_PARTIAL_DIR environment variable. 2004-09-18 17:37:54 +00:00
Wayne Davison
b4d1e854ef Document the new RSYNC_PARTIAL_DIR environment variable. 2004-09-18 17:35:20 +00:00
Wayne Davison
075aa18fd4 Look for the RSYNC_PARTIAL_DIR environment variable when --partial
was specified (and --partial-dir was not).
2004-09-18 17:34:56 +00:00
Wayne Davison
e0204f5621 Mention that older rsync versions had a problem with --link-dest and
how to work around it.
2004-09-18 01:49:19 +00:00
Wayne Davison
a9ac4411e5 Mention the latest changes. 2004-09-17 16:53:51 +00:00
Wayne Davison
50b31539c2 - Added the ability to parse a literal IPv6 address in an "rsync:" URL
(e.g. rsync://[2001:638:500:101::21]:873/module/dir).
- Improved a couple --files-from error messages.
2004-09-17 16:50:53 +00:00
Wayne Davison
56194bcd95 When outputting the flist info (in a debug-level of verbosity) we
now mention the UID of the file when we are the sender (as well as
when we are root).
2004-09-17 16:39:34 +00:00
Wayne Davison
eb8ffa9040 Actually, since the close calls shouldn't fail (now that listener
is properly set to -1 on close), we don't really need to play the
save-errno game after all.
2004-09-16 17:22:31 +00:00
Wayne Davison
a7a1cc2c75 Make sure that /etc and /bin actually are readable before we try
to list them.
2004-09-16 17:16:36 +00:00
Wayne Davison
ab217f7ffa - Set "listener" to -1 after we close it so that the error-handler
doesn't try to re-close it.
- Set blocking I/O before the second (final) connect() call.
2004-09-16 17:09:46 +00:00
Wayne Davison
a20c9893e4 Don't try to optimize-away the sending of the --delete option if
--delete-after was specified (since we don't know what the protocol
version will be yet).
2004-09-08 07:33:06 +00:00
Wayne Davison
3bb400ca14 If --backup was used with --inplace, we don't limit the basis-file
matches (as we normally would) because the receiver is using the
backup-file as the basis-file.
2004-09-07 21:45:19 +00:00
Wayne Davison
cd6aa5b5c0 When --backup is used with --inplace, we make a copy of the destination
file into its backup spot while generating the checksums.
2004-09-07 21:44:02 +00:00
Wayne Davison
dc55d7bdab If we're making backups with --inplace, use the backup file as the
basis file while still updating the real destination file inplace.
2004-09-07 21:34:26 +00:00
Wayne Davison
8b115ac8dc Turn off make_backups during the redo phase, just like the receiver. 2004-09-07 21:32:36 +00:00
Wayne Davison
c94e4afbfa Moved the code that determines the backup filename into a new function
named get_backup_name().
2004-09-07 21:29:26 +00:00
Wayne Davison
6566d205e2 Made full_write() non-static. 2004-09-07 21:26:26 +00:00
Wayne Davison
e484f0cc04 W mustn't backup an inplace file in finish_transfer(). 2004-09-07 20:37:36 +00:00
Wayne Davison
bd397b8cba Reject the use of --compare-dest or --link-dest with --inplace
(it will take extra code to suppor this).
2004-09-07 20:36:36 +00:00
Wayne Davison
f8c8ef9eac When we say we're skipping a non-regular file, actually skip it. 2004-09-07 19:49:09 +00:00
Wayne Davison
72c19bb3de A minor optimization to the partial-dir code. 2004-09-07 17:03:51 +00:00
Wayne Davison
89f7eff382 Fix the case where a partial-dir file exists but the destination
file does not.
2004-09-07 16:50:07 +00:00
Wayne Davison
b90a6d9ff6 Mention that --whole-file interferes with the reuse of a --partial-dir
file.
2004-09-07 16:49:10 +00:00
Wayne Davison
584ba4ebae Fixed a typo Paul pointed out. 2004-09-05 21:30:00 +00:00
Wayne Davison
ba3db4795e Allow the use of the --exclude*/--include* options to a server
process again, but make sure that the user didn't specify a
server-excluded file for one of the --*-from options.
2004-08-26 17:39:48 +00:00
Wayne Davison
59d73bf3d2 Some fixes & clarifications for the BATCH MODE section. 2004-08-18 07:50:36 +00:00
Wayne Davison
919ca3a3cc Few few more minor improvements to the existing change items. 2004-08-18 07:49:03 +00:00
Wayne Davison
5886edfac2 Corrected/enhanced a comment. 2004-08-18 07:00:17 +00:00
Wayne Davison
d414962af4 One more NEWS tweak. 2004-08-12 21:02:13 +00:00
Wayne Davison
8fb7db245a Mention the security fix. 2004-08-12 20:58:33 +00:00
Wayne Davison
6f0fc27e33 Got rid of one item. 2004-08-12 20:48:05 +00:00
Wayne Davison
9c54ad58f8 Preparing for release of 2.6.3pre1 2004-08-12 20:06:57 +00:00
Wayne Davison
f55c2dfc03 One last minor tweak to clean_fname(). 2004-08-12 20:04:47 +00:00
Wayne Davison
675ef1aa3a Tweaked the USAGE section a tad and added an ADVANCED USAGE section
that discusses how to request multiple names from a remote rsync.
2004-08-12 19:31:23 +00:00
Wayne Davison
ef57235623 Improved the build rule for getfsdev and added getfsdev.o to the
files we cleanup.
2004-08-12 18:59:03 +00:00
Wayne Davison
d66d07e883 If system won't let us set chmod bits, fall back to testing without
them set.
2004-08-12 18:51:35 +00:00
Wayne Davison
b92693daba - Made clean_flist()'s collapsing of ".." dirs optional by adding
a "BOOL collapse_dot_dot" arg.
- Improved some comments.
2004-08-12 18:20:14 +00:00
Wayne Davison
58b1999e08 Call clean_flist() with its new "collapse_dot_dot" arg. 2004-08-12 18:20:07 +00:00
Wayne Davison
8e5f029e02 One (hopefully) last change to the sanitize_path() code. 2004-08-12 10:13:45 +00:00
Wayne Davison
2d41264e9e Simplified sanitize_path() logic a little. 2004-08-12 09:32:16 +00:00
Wayne Davison
82c6be7edf More improvements and a couple missing items. 2004-08-12 01:27:26 +00:00
Wayne Davison
0219d4dfba Improved a comment. 2004-08-12 00:58:01 +00:00
Wayne Davison
391516da51 Got rid of a comment that became inapplicable. 2004-08-12 00:52:58 +00:00
Wayne Davison
1d6b8f9ad2 - Call sanitize_path() with updated args.
- Added count_dir_elements() function.
- Changed the args for sanitize_path() so that the caller can request
  the value for the rootdir and so that the caller tells us the current
  subdir depth instead of sending us a string that we have to figure it
  out from.
- Make sure that sanitize_path() doesn't mis-parse multiple adjacent
  slashes.
2004-08-11 23:41:06 +00:00
Wayne Davison
10796f4b6e Call sanitize_path() with updated args. 2004-08-11 23:41:03 +00:00
Wayne Davison
33ffd7c37d - Set the var lastdir_depth when setting lastdir.
- Call sanitize_path() with updated args.
2004-08-11 23:41:00 +00:00
Wayne Davison
21d1e929a0 Ignore new getfsdev executable. 2004-08-11 17:33:52 +00:00
Wayne Davison
d0bc3520de Make the text of the --times (-t) option more correct on what
happens if it is omitted.
2004-08-11 17:24:37 +00:00
Wayne Davison
9f18657889 A minor improvement in check_one_exclude(). 2004-08-10 18:15:33 +00:00
Wayne Davison
c16d69b292 Mention the early-chmod change. 2004-08-09 20:58:26 +00:00
Wayne Davison
ebeacb36fb Set each file's permissions and modtime before it gets renamed. 2004-08-09 20:57:10 +00:00
Wayne Davison
6558854dbe Do some simple tests with various read-only and set[ug]id files. 2004-08-09 20:52:35 +00:00
Wayne Davison
7d9d5d9478 Added a rule for building getfsdev and for requiring it to run "test". 2004-08-09 20:51:44 +00:00
Wayne Davison
630f548ff4 Made robust_rename() return a 1 if it had to copy the file. 2004-08-09 20:48:38 +00:00
Wayne Davison
100b62bb69 Output a device string for each file given on the command-line. 2004-08-09 20:46:54 +00:00
Wayne Davison
e012b94f21 Fixed a bug in clean_fname() that could sometimes leave a "dir/.."
sequence uncollapsed.
2004-08-07 20:56:41 +00:00
Wayne Davison
3104620cf0 Made clean_fname() return the length of the string. 2004-08-06 22:36:55 +00:00
Wayne Davison
ebdd24d6d0 An improved clean_fname() routine that is more efficient and will also
collapse ".." dirs that aren't at the start of the path.  Care was taken
to ensure that the cleaning of a name that goes over the socket is done
in the same way as the old code (because both sides call clean_fname()
on those file-list names).  This ensures compatibility with older rsync
versions.
2004-08-06 21:24:14 +00:00
Wayne Davison
7cd72c79ec Set "eob" correctly in add_exclude_file(). 2004-08-05 22:58:17 +00:00
Wayne Davison
84a6379565 Merged alloc_sanitize_path() into sanitize_path(), adding an extra arg
that indicates the destination dir for the resulting path (if the dest
is NULL, a buffer will be allocated) and having it return a value.
2004-08-05 21:57:11 +00:00
Wayne Davison
0a5f12720e Use the new sanitize_path() calling syntax. 2004-08-05 21:57:09 +00:00
Wayne Davison
73f7af0e88 If dry_run is > 1 then the destination directory was missing, so we
set stat_errno to ENOENT and statret to -1 without calling stat().
2004-08-05 18:18:36 +00:00
Wayne Davison
e5a96f0f54 In get_local_name(), if we would have created the destination dir but
were prevented by dry_run being set, increment dry_run so that the
generator knows that all the files are missing.
2004-08-05 18:17:44 +00:00
Wayne Davison
d73e7f6edd In set_refuse_options(): make sure we scan the whole list of options
and avoid complaining about a wild-card spec that actually matches
one or more options.
2004-08-04 21:20:34 +00:00
Wayne Davison
61542c41de Decided that we don't need to limit the block size after all now
that the map_file() code handles large block sizes better.
2004-08-03 15:41:16 +00:00
Wayne Davison
bd1a581bee Use MAX_MAP_SIZE in the args to map_file(). 2004-08-03 15:37:54 +00:00
Wayne Davison
6e8a1782ab - Changed the calling syntax for map_file() so that it takes both
a (possibly approximate) window size and an optional block size
  (which is used to round-up the window size if it is non-zero).
- Don't set window_start behind the supplied offset in map_ptr().
2004-08-03 08:05:29 +00:00
Wayne Davison
96d910c770 Call map_file() with its new args, including a suggested window
size.
2004-08-03 08:05:27 +00:00
Wayne Davison
7560c17adc We call map_ptr() with a data range than includes any unmatched data
(which we might need to reference again) in addition to the current
rolling-checksum block (this prevents the unmatched data from being
lost when we slide the buffer and read more data).
2004-08-03 08:05:23 +00:00
Wayne Davison
9cd339eb39 - Changed the description for --block-size in the --help text.
- Use the new MAX_BLOCK_SIZE to limit the block_size value.
2004-08-03 08:05:20 +00:00
Wayne Davison
f310029387 - Added define for MAX_BLOCK_SIZE.
- Increased the MAX_MAP_SIZE.
2004-08-03 08:05:17 +00:00
Wayne Davison
3ed8eb3f9c Updated the description of the --block-size option. 2004-08-03 07:58:48 +00:00
Wayne Davison
007351494d Mention the open64()/mkstemp64() configure change. 2004-08-02 22:06:17 +00:00
Wayne Davison
6dcb93208d Don't use mkstemp() if the OS has open64() but not mkstemp64(). 2004-08-02 21:56:07 +00:00
Wayne Davison
84e1a698bf Test for functions open64() and mkstemp64(). 2004-08-02 21:54:49 +00:00
Wayne Davison
0d7638eafd Got rid of trailing whitespace. 2004-08-02 16:49:20 +00:00
Wayne Davison
86e2f445f7 Mention the "refuse options" change. 2004-08-02 07:41:04 +00:00
Wayne Davison
093e816c37 Allow better wildcard matching against the short-option letters in
the "refuse options" handling.
2004-08-02 07:40:34 +00:00
Wayne Davison
1cb0a3edc6 Document the improved "refuse options" syntax. 2004-08-02 05:01:36 +00:00
Wayne Davison
06a5054273 - Extended the "refuse options" daemon setting to allow wildcards
and to allow single-letter option names.
- No need to send the various --delete* options or the --force option
  from the receiver to the sender.
2004-08-02 05:00:30 +00:00
Wayne Davison
acd0299243 Got rid of unused externs. 2004-08-02 04:50:33 +00:00
Wayne Davison
dca68b0aad - Changed "read so far" to "received so far".
- Output the who_am_i() information in the socket read/write errors to
  make it a little clearer who is complaining about what (for those
  familiar with rsync, at least -- e.g. it will help when users report
  errors).
2004-08-02 02:43:54 +00:00
Wayne Davison
c3ea09906d - Changed all the errors in parse_arguments() to use the err_buf so
that a client talking to a daemon server actually gets the error.
- If a daemon has a list of exclusions, apply that list to various
  options to ensure that an excluded file can't be affected.
- Fixed an arg-checking problem when --files-from got passed to a
  daemon.
2004-07-31 20:09:54 +00:00
Wayne Davison
bf4679e8a0 If we need to return an error during the startup phase and the other
side is expecting us to send them a files-from list, send the list
terminator before sending the error.
2004-07-31 19:55:42 +00:00
Wayne Davison
c4054610c8 Don't allow a --partial-dir setting to overwrite a server-excluded
file (affects a daemon receiver only).
2004-07-31 18:13:20 +00:00
Wayne Davison
f6c0d3d70b - Document the change to --copy-links.
- Improved the "OUTPUT CHANGES" section.
2004-07-31 16:20:28 +00:00
Wayne Davison
ef855d198e Document the old side-effect to --copy-links and that it no longer
happens in a modern rsync w/o --keep-dirlinks.
2004-07-31 16:19:14 +00:00
Wayne Davison
81b07870c8 One call to link_stat() (in set_perms()) needed to honor the setting
of keep_dirlinks if the current item is a directory.
2004-07-31 16:15:41 +00:00
Wayne Davison
bb6721dce6 Reset copy_links in the receiver. 2004-07-31 16:14:27 +00:00
Wayne Davison
446a2987cd Prominently mention the changes to the text that gets output. 2004-07-31 03:33:05 +00:00
Wayne Davison
4de2a17409 Changed "wrote"/"written" to "sent" and "read" to "received" in
the text that is output.
2004-07-31 03:32:42 +00:00
Wayne Davison
99d24f77ed - Mention the "list = no" change in error handling.
- Improved a few of the NEWS items.
2004-07-30 22:46:07 +00:00
Wayne Davison
c0422cea9f If someone is denied access to a "list = no" module, lie and tell them
that the module is "Unknown" (so the user can't probe to find unlisted
modules).
2004-07-30 20:07:52 +00:00
Wayne Davison
8b6ad0193d Don't ignore case in lp_number() because the rest of the daemon code
can't handle the case where the module name doesn't exactly match the
string the user provided.
2004-07-30 20:05:37 +00:00
Wayne Davison
33eff8bfd6 If we reject a name due to a server-exclude, someone is trying to hack
rsync (because the generator would not have included this file).  Respond
with an exit.
2004-07-30 07:02:37 +00:00
Wayne Davison
65af3dab03 Document the latest changes. 2004-07-29 18:08:16 +00:00
Wayne Davison
065a605270 Got rid of bogus compare_dest scan in skip_file() -- it must checksum
the same file that we used for the stat() (in the parent routine).
2004-07-29 16:45:48 +00:00
Wayne Davison
a7260c4037 Added the new --partial-dir option. 2004-07-29 16:06:38 +00:00
Wayne Davison
44cad59f2b Document the new --partial-dir option. 2004-07-29 16:06:34 +00:00
Wayne Davison
c52461f911 Check the error return of flush_write_file(). 2004-07-29 07:37:27 +00:00
Wayne Davison
7f459268d9 Added close_multiplexing_in() and renamed io_multiplexing_close()
to close_multiplexing_out().
2004-07-29 07:24:45 +00:00
Wayne Davison
9eeb3b9c88 Call the new close_multiplexing_in() function in the generator. 2004-07-29 07:24:00 +00:00
Wayne Davison
d1b31da71e If we fail writing to the socket and we're receiving error messages
from the other side via a multiplexed input, read the socket to see
if we get some errors that would explain why they went away.
2004-07-29 07:09:46 +00:00
Wayne Davison
89e540e638 One more inplace code tweak. 2004-07-29 06:59:30 +00:00
Wayne Davison
fab65a5bc2 Some minor fixes and improvements for the inplace code. 2004-07-29 06:40:26 +00:00
Wayne Davison
e7d13fe532 - Explicitly save the stat()'s errno so that we can be sure we're
testing the right thing lower down (and so that future code doesn't
  always have to remember to save it off and restore it).
- Improved a chunk of link_dest code.
- Handle the removal of a non-regular file without so much duplicated
  code.
2004-07-28 10:04:06 +00:00
Wayne Davison
ecc81fce17 Use the new safe_fname() function. 2004-07-26 16:36:59 +00:00
Wayne Davison
b4afd23c30 Allow safe_fname() to tweak up to two name at a time. 2004-07-26 16:34:36 +00:00
Wayne Davison
af1a3f9b6e Use safe_fname() in full_fname(). 2004-07-26 15:59:51 +00:00
Wayne Davison
820b6c9aa0 Added safe_fname() that converts any newlines in a name into '?'s. 2004-07-26 15:52:25 +00:00
Wayne Davison
3cb22c204c Made a comment better. 2004-07-26 05:38:02 +00:00
Wayne Davison
7432ccf4ed Some batch-mode changes. 2004-07-24 16:51:58 +00:00
Wayne Davison
6a48e792c1 Made the new option-twiddling message only output when verbose. 2004-07-24 16:51:16 +00:00
Wayne Davison
9459290ae7 Call read_stream_flags() as soon as we open the batch file for
reading.
2004-07-24 16:40:41 +00:00
Wayne Davison
741d654495 Call write_stream_flags() from start_write_batch(). 2004-07-24 16:39:53 +00:00
Wayne Davison
d3e182af09 Added write_stream_flags() to write the state of certain flags into
the batchfile and read_stream_flags() to read and twiddle the same
flags.  This ensures that the batchfile reading doesn't get confused
about what data to expect from the socket.
2004-07-24 16:38:49 +00:00
Wayne Davison
d9b4d267c7 Tweaked a compound line. 2004-07-23 16:59:38 +00:00
Wayne Davison
58c5c24555 Added a comment. 2004-07-23 16:59:22 +00:00
Wayne Davison
341c9a137f Some basic batch-mode tests. 2004-07-23 02:13:34 +00:00
Wayne Davison
871446fc98 Chris added a missing "not" to a comment. 2004-07-23 01:40:22 +00:00
Wayne Davison
0abda1b176 Fixed the opening comments. 2004-07-23 01:39:19 +00:00
Wayne Davison
394bcdb5e3 If we sucessfully renamed a file that has multiple links to it, unlink()
it to ensure that rename() didn't lie to us (which it does if you try to
rename() a file over another link to the same file).
2004-07-22 22:52:39 +00:00
Wayne Davison
28deecca55 Changed NO_INT64 to INT64_IS_OFF_T because off_t might actually be
64 bits.  The code now only complains if int64 is really too short.
2004-07-22 19:28:45 +00:00
Wayne Davison
4db88e5b8f Some --help text fixes. 2004-07-22 15:43:28 +00:00
Wayne Davison
75b243a51d Some more --inplace improvements. 2004-07-22 15:41:09 +00:00
Wayne Davison
9bccfc429c Should always call finish_transfer() for inplace handling, just like
for keep_partial handling.
2004-07-22 15:31:06 +00:00
Wayne Davison
077e59b769 The inplace handling in finish_transfer() now passes PERMS_SKIP_MTIME
to set_perms() if ok_to_set_time wasn't specified.
2004-07-22 15:30:04 +00:00
Wayne Davison
007e3c0e9a Need to output the "failed verification" error before sending the
MSG_REDO so that the output comes out in the right order.
2004-07-22 08:16:35 +00:00
Wayne Davison
e2bc412669 Added a warning message when a file fails to verify, letting the user
know if we retained it or discarded it.  Especially useful for batch-
reading mode where the old code could look like it did the update when
it really silently failed.
2004-07-22 04:15:18 +00:00
Wayne Davison
e344209582 Added even more double-quoting. 2004-07-22 03:23:04 +00:00
Wayne Davison
e76ca1458c No need to check both delete_after and delete_mode since the former
implies the latter.
2004-07-22 02:52:57 +00:00
Wayne Davison
16cc9ca2c9 In read_batch mode, we read ints from the new batch_gen_fd pipe and
only process the updates from the batch file when the generator has
indicated that it is ready (which ensures that all the necessary
dirs have been created).
2004-07-21 23:59:37 +00:00
Wayne Davison
8c90957ff5 Got rid of read_batch special case. 2004-07-21 23:59:33 +00:00
Wayne Davison
c0d8e84c9d Setup for read_batch mode a little differently:
- Avoid calling local_child().
- Create a pipe that lets the generator send us index values.
- Set batch_gen_fd for the receiver to read the pipe.
2004-07-21 23:59:31 +00:00
Wayne Davison
b0ad542928 Added batch_gen_fd. 2004-07-21 23:59:28 +00:00
Wayne Davison
727b35f665 In read_batch mode, we now let the code write out the index value
to the f_out pipe before we return from recv_generator().  This gives
the receiver something to sync with so that it doesn't rush ahead of
us (which could be bad if we didn't have a chance to create the
destination dirs yet).
2004-07-21 23:59:25 +00:00
Wayne Davison
aa4343211f Don't write out the protocol_version number in read_batch mode. 2004-07-21 23:59:22 +00:00
Wayne Davison
3611989355 Complain if the user combines --read-batch with --files-from. 2004-07-21 22:50:11 +00:00
Wayne Davison
3381b77d71 Improved the test a little. 2004-07-21 21:06:13 +00:00
Wayne Davison
dce70db374 Adding a test for the --compare-dest option. 2004-07-21 20:58:32 +00:00
Wayne Davison
2adbcdc7ea A couple am_sender checks (one negated) were not needed. 2004-07-21 20:17:02 +00:00
Wayne Davison
7e5fa372cf Call map_file() with the new block_size arg (had to delay the
call to map_file() until the block size was known).
2004-07-20 21:35:58 +00:00
Wayne Davison
6e45e1dd86 - Call map_file() with the new block_size arg (had to delay the
call to map_file() until the block size was known).
- Got rid of the setting of max_map_size.
2004-07-20 21:35:55 +00:00
Wayne Davison
7f290d5c82 - Added a new block_size arg to map_file(). Use it to set the
new def_window_size member variable.
- Got rid of max_map_size global (we use def_window_size now).
2004-07-20 21:35:52 +00:00
Wayne Davison
b6609cafae - Got rid of cleanup_buf (map-file cleanup is not needed).
- Renamed the cleanup_fd* vars.
2004-07-20 21:35:49 +00:00
Wayne Davison
efa95a1842 Call map_file() with its new block_size arg. 2004-07-20 21:35:46 +00:00
Wayne Davison
51bd4f0f3a Tweaked an error message. 2004-07-20 21:10:20 +00:00
Wayne Davison
562b61695e Added a def_window_size variable to struct map_struct. 2004-07-20 21:08:33 +00:00
Wayne Davison
98f51bfb56 - More batch-file improvements.
- A few spelling fixes.
2004-07-20 18:12:50 +00:00
Wayne Davison
73f0ce69e7 We now append the exclude list as a "here" document to the end of
the BATCH.sh file.
2004-07-20 17:07:55 +00:00
Wayne Davison
cf338ab1be Made write_sbuf() non-static. 2004-07-20 16:57:18 +00:00
Wayne Davison
66a9dc9639 Changed write_batch_argvs_file() to new write_batch_shell_file()
call (with extra arg).
2004-07-19 17:11:41 +00:00
Wayne Davison
8ed9d849dc Added new function discard_receive_data(). 2004-07-19 17:05:01 +00:00
Wayne Davison
5ebab6c10c - Don't allow some crafty user to try to force us to update a
server-excluded file.
- If get_tmpname() fails we need to discard the update using
  receive_data().
2004-07-19 16:37:30 +00:00
Wayne Davison
e7a69008e6 Do a better job of writing out the BATCH.sh file (i.e. quote special
characters and spaces in args, omit all the source args, omit the
include/exclude args if we can).
2004-07-19 08:27:17 +00:00
Wayne Davison
73e015683c Changed batch.rsync_argvs to batch.sh. 2004-07-19 03:59:35 +00:00
Wayne Davison
b462781fd0 Fixed the argv munging to work properly regardless of whether the
user specified a trailing '=VALUE' or put the value in a separate
arg.
2004-07-19 00:53:49 +00:00
Wayne Davison
93095cbe99 A very minor optimization was made to read_sbuf(), read_byte(),
write_sbuf(), and write_byte().
2004-07-17 21:17:34 +00:00
Wayne Davison
399371e7b5 - Improved the warning about --inplace.
- Fixed the sentence describing how to read standard input with
  --read-batch.
2004-07-17 16:44:16 +00:00
Wayne Davison
d7142e2328 Moved the read_batch abort check below the code that handles the
symlinks and devices.
2004-07-17 16:29:10 +00:00
Wayne Davison
1f75bb1066 Revamped some of the io variables and calls to make the various I/O
functions seemlessly work on fds that aren't for the main socket. This
involved changing some fd-variable names (to make them clearer), adding
io_set_sock_fds(), and making input buffering have a better enabled
flag (via an allocated buffer, just like the output buffering).  I also
got rid of the fd arg to some functions where the fd arg could only
specify the input or output fd for the socket (which we already know).
2004-07-17 15:20:00 +00:00
Wayne Davison
088adfacc1 Got rid of the arg to io_start_multiplex_out(). 2004-07-17 15:19:57 +00:00
Wayne Davison
da3478b2a7 - Got rid of the arg to the io_start_multiplex_{in,out}() calls.
- Call io_set_sock_fds().
2004-07-17 15:19:54 +00:00
Wayne Davison
5126ed1ef0 Changed a MIN() to a MAX() when setting max_map_size. 2004-07-17 10:59:14 +00:00
Wayne Davison
61fb21ad28 Mention the new --inplace option. 2004-07-17 00:00:27 +00:00
Wayne Davison
a3221d2ac1 My version of Mark Curtis's --inplace option. 2004-07-16 20:06:24 +00:00
Wayne Davison
2c713fcdfa Added a check for ftruncate. 2004-07-16 20:04:20 +00:00
Wayne Davison
afd8bdb907 Avoid some useless memory copying. 2004-07-16 18:08:52 +00:00
Wayne Davison
efd5ee5786 - Limit the maximum block size we compute for a file.
- Set max_map_size based on the current file's block size (so that
  map_ptr() is more efficient with large blocks).
2004-07-16 18:04:23 +00:00
Wayne Davison
510b4cd4d5 Added a max_map_size variable, initialized to MAX_MAP_SIZE. 2004-07-16 18:02:30 +00:00
Wayne Davison
de584c658c Limit the block-size that the user can specify. 2004-07-16 18:01:30 +00:00
Wayne Davison
6eb770bbcc Improved a sentence about --whole-file. 2004-07-16 17:14:55 +00:00
Wayne Davison
c7e11bfdc0 Make wf_writeBufSize based on a multiple of WRITE_SIZE instead
of the unrelated MAX_MAP_SIZE.
2004-07-16 01:32:02 +00:00
Wayne Davison
94327ff0c2 - Complain and die if --dry-run is used with a batch option.
- Improved the warning if a batch option gets sent to the server.
2004-07-15 19:06:32 +00:00
Wayne Davison
4602eafa87 Changed the batch examples to show how to do a remote read-batch
without first transferring the batch file.
2004-07-15 19:04:54 +00:00
Wayne Davison
bb3edc3b47 Expanded the comment on the new batch code. 2004-07-15 19:03:50 +00:00
Wayne Davison
c769702fe5 Mention that "-" can be used with --read-batch for reading from stdin. 2004-07-15 17:56:11 +00:00
Wayne Davison
dbbab0c4d2 Allow --read-batch=- to indicate stdin. 2004-07-15 17:01:51 +00:00
Wayne Davison
9b3318b0df We no longer refer to a batch "prefix". 2004-07-15 16:27:02 +00:00
Wayne Davison
0fac7fe8b8 Mention new batch-mode changes. 2004-07-15 03:13:09 +00:00
Wayne Davison
b9f592fbf5 My modified version of Chris Shoemaker's improved batch-file handling. 2004-07-15 02:20:08 +00:00
Wayne Davison
c7b1a56b3d Mention recent changes. 2004-07-14 17:11:53 +00:00
Wayne Davison
3896bca4d8 Tweaked some single-line ifs. 2004-07-14 16:41:10 +00:00
Wayne Davison
9774cc3344 The "len" to generate_and_send_sums() is supposed to be an OFF_T. 2004-07-14 16:40:08 +00:00
Wayne Davison
d3979b025d Committed a space-tweak from Chris Shoemaker. 2004-07-14 16:39:08 +00:00
Wayne Davison
01966df4f7 Improved the write_batch_argvs_file() routine so that it doesn't
need the character buffers and so that it properly removes the
hostname from the destination arg.
2004-07-14 07:20:18 +00:00
Wayne Davison
f38bd4a072 Got rid of the disable_deltas_p() function (the whole_file value
is now fully set before the generator forks).
2004-07-13 01:45:51 +00:00
Wayne Davison
b1df18d76f We now conditionally turn on whole_file in do_cmd() right before
calling local_child().
2004-07-13 01:44:03 +00:00
Wayne Davison
7daccb8e72 In generate_files(), changed arg "f" to "f_out", as Chris Shoemaker
suggested.
2004-07-12 20:42:48 +00:00
Wayne Davison
bb91a624f1 Made hard_link_check() compile when SUPPORT_HARD_LINKS isn't enabled. 2004-07-12 07:03:28 +00:00
Wayne Davison
a04d77bcbc Use want_i instead of last_i+1. 2004-07-07 08:38:40 +00:00
Wayne Davison
25bd99451c Make the GID_NONE define a little safer. 2004-07-07 08:25:13 +00:00
Wayne Davison
ed43d0a76d Added some missing $(srcdir) references. 2004-07-04 08:56:31 +00:00
Wayne Davison
066a844c4e Changed a "for" loop into a "do ... while" loop. 2004-07-04 08:07:23 +00:00
Wayne Davison
5e252dea4b Optimized away a loop in hash_search(). 2004-07-02 23:35:30 +00:00
Wayne Davison
d2a918b454 Some formatting tweaks. 2004-07-02 18:23:57 +00:00
Wayne Davison
da38e779ea Moved the verbose message about renaming the finished file down into
finish_transfer() so that it only gets output when we're actually going
to rename the file.
2004-07-02 18:13:53 +00:00
Wayne Davison
8186ae6bc0 Tweaked some formatting. 2004-07-02 18:12:24 +00:00
Wayne Davison
e1f67417d7 Some simple whitespace tweaks. 2004-06-30 07:27:30 +00:00
Wayne Davison
fd322eef82 Made recv_generator static. 2004-06-29 19:19:00 +00:00
Wayne Davison
d3a4375f78 Optimized away a call to cmp_modtime() for a compare-dest file. 2004-06-29 16:22:54 +00:00
Wayne Davison
78112d305b Mention the extended argv-overflow checking. 2004-06-29 15:13:18 +00:00
Wayne Davison
f7c3ee9932 Tweaked an overly-long line. 2004-06-29 15:12:01 +00:00
Wayne Davison
e7a392c77c A few more improvements to the anti-overflow args[] checking. 2004-06-28 17:45:40 +00:00
Wayne Davison
887e553f05 Make sure that do_cmd() doesn't overflow its arg-pointer array
(which was also made larger).
2004-06-28 17:25:14 +00:00
Wayne Davison
beb227ddf1 Got rid of a couple unneeded assignments. 2004-06-24 04:46:02 +00:00
Wayne Davison
84acca07ae Restoring correct skip_file() return semantics. 2004-06-23 21:21:19 +00:00
Wayne Davison
cc1e997dcd Thought skip_file() wasn't returning 1 for "skip" and 0 or "keep"
so I reversed the return.
2004-06-23 16:51:21 +00:00
Wayne Davison
a7026ba90a Fixed a newly-introduced problem in read_timeout() where FD_ZERO(&w_fds)
wasn't always called before w_fds was used.
2004-06-23 01:13:09 +00:00
Wayne Davison
3a69fad0f6 Some trivial format tweaks. 2004-06-20 21:48:06 +00:00
Wayne Davison
40564811ee Mentioned the latest socket change and fixed a few typos. 2004-06-20 20:37:06 +00:00
Wayne Davison
dcd08dc51c Restored the code in the IPV6_V6ONLY section that checks the
return value from setsockopt() with one improvement:  if the
user has used --ipv6 (-6) we don't discard the IPv6 socket.
This should help people using older Linux kernels that don't
implement IPv6 support quite right.
2004-06-20 19:51:19 +00:00
Wayne Davison
fdf57ede8c Tweaked a comment. 2004-06-20 19:47:05 +00:00
Wayne Davison
bd717af8ab Must not call check_timeout() before checking the errno value. 2004-06-19 07:09:57 +00:00
Wayne Davison
c54f5170bf Added some missing changes. 2004-06-19 06:55:58 +00:00
Wayne Davison
eae4e1f9f0 Some minor improved sentences. 2004-06-19 05:52:45 +00:00
Wayne Davison
9c513d678d Tweaked some comments. 2004-06-18 16:55:12 +00:00
Wayne Davison
d16c245fc4 Some helpful comments from Chris Shoemaker. 2004-06-18 16:50:20 +00:00
Wayne Davison
ec8290c897 Fixed some typos in a comment, moved an extern, and made a few
minor format tweaks.
2004-06-18 16:30:24 +00:00
Wayne Davison
b293a7f62c Improved a comment. 2004-06-18 16:29:21 +00:00
Wayne Davison
d67c8bdfc3 Moved the externs to the top and made a few trivial format tweaks. 2004-06-18 16:22:14 +00:00
Wayne Davison
e2ccd3578c Got rid of some trailing whitespace. 2004-06-18 16:00:33 +00:00
Wayne Davison
4e834af140 If --partial was specified, make sure that make_backup is turned
off during the second (retry) phase of the transfer to avoid
making a second backup of a file (which would lose the original).
2004-06-14 15:09:36 +00:00
Wayne Davison
7e5614383d Added a short msleep() after option_error() before we exit. This
ensures that the remote client has time to read our error message
while it is trying to write data to us before it gets a socket
error.
2004-06-13 14:18:48 +00:00
Wayne Davison
eb84a83b47 Changed the new code in delete_one() so that some compilers
don't complain about returning a value from a void function.
2004-06-12 21:30:07 +00:00
Wayne Davison
2c2898a388 Mention the bugfix in option-parsing error-reporting from a daemon. 2004-06-12 18:27:04 +00:00
Wayne Davison
1732b6c037 - Changed some FERROR log calls to FLOG.
- Improved the option-error-reporting to actually get the error back
  to the user (by getting I/O multiplexing started).
2004-06-12 18:22:39 +00:00
Wayne Davison
314f459161 - Made readlink_stat() and link_stat() optionally follow a symlink
to a dir.  This fixes deletions inside "kept" symlinked dirs.
- Call link_stat() with its new arg (for --keep-dirlinks support).
2004-06-11 07:40:57 +00:00
Wayne Davison
83926d3cae Make sure that keep_dirlinks is turned off for the sender. 2004-06-11 07:40:54 +00:00
Wayne Davison
6218c7bf42 - Moved --keep-dirlinks code over to flist.c.
- Call link_stat() with its new arg (for --keep-dirlinks support).
2004-06-11 07:40:51 +00:00
Wayne Davison
566fce3237 Made delete_one() handle a failed rmdir on a symlink when
--keep-dirlinks was specified.
2004-06-11 07:40:48 +00:00
Wayne Davison
373ef16010 Call link_stat() with its new arg (for --keep-dirlinks support). 2004-06-11 07:40:45 +00:00
Wayne Davison
ea76e76104 In set_filesystem(), call do_stat(), not link_stat() to ensure
that we get the directory behind it all.
2004-06-11 05:02:59 +00:00
Wayne Davison
9fd62d1588 The mkdir code should be using do_stat(), not do_lstat() to copy
each existing dir's mode & owner info.
2004-06-10 16:43:52 +00:00
Wayne Davison
b7061c82b4 Allow the argv list the daemon uses for globbing its args to grow. 2004-06-09 21:51:07 +00:00
Wayne Davison
6fb812f747 Removed some excessive parens. 2004-06-09 21:43:28 +00:00
Wayne Davison
40e8d11e64 Mentioned a couple more bugfixes. 2004-06-09 21:42:33 +00:00
Wayne Davison
73042aae5b Restore UNUSED() macro (the prior problems that prompted me to remove
it appear to have been a build-farm bug).
2004-06-09 21:41:21 +00:00
Wayne Davison
e5ce3bcf2c Needed to enclose the new symlink-warning code in an
"#if SUPPORT_LINKS" conditional.
2004-06-09 19:23:56 +00:00
Wayne Davison
c399d22a19 Renamed read_unbuffered() to readfd_unbuffered() so that it matches
writefd_unbuffered().
2004-06-09 03:07:50 +00:00
Wayne Davison
1ea087a794 - Made the maximum-fd computation prior to a select() use the same idiom
in both the read and write code (also use a better variable name).
- Made the bytes-available code at the end of the select() loop use the
  same flow of control in the read and the write code.
2004-06-08 22:18:04 +00:00
Wayne Davison
00bdf89977 Improved a comment in read_msg_fd() and made the byte-reading code
in read_timeout() a little better.
2004-06-08 16:23:54 +00:00
Wayne Davison
0bb4d17634 Improved rwrite() in two ways:
- We no longer assume that the buffer is null terminated (daemon
  mode would ignore the len when logging a message).
- Errors in daemon mode are now sent to both the log and the user.
2004-06-07 22:51:14 +00:00
Wayne Davison
f9c6b3e7d6 Increase the size of the message-receving buffer for error
messages sent from the receiver to the generator.
2004-06-07 22:47:01 +00:00
Wayne Davison
9e5a5ddb4c Changed a few FINFO messages to FLOG. 2004-06-07 22:33:01 +00:00
Wayne Davison
8c0d6a8432 Got rid of some am_daemon games in option_error(). 2004-06-07 22:05:22 +00:00
Wayne Davison
553f93758a Updated some exclude information that has changed. 2004-06-07 21:40:11 +00:00
Wayne Davison
a4a7e64c19 Don't report a "file vanished" error if a symlink points to nowhere
and -L was specified.
2004-06-07 19:59:20 +00:00
Wayne Davison
22832c30a0 Updated a couple things. 2004-06-06 20:41:01 +00:00
Wayne Davison
1a21666286 Tell folks to go to the bug-tracking page to report bugs. 2004-06-06 20:36:56 +00:00
Wayne Davison
4033b80b51 - Got rid of some useless calls to msg_list_push().
- Added a couple checks to ensure that the receiver doesn't mix two
  clashing kinds of writes on the msg_fd_out pipe.
- Made sure that the read code in the receiver flushes the msg_fd_out
  pipe, if needed.
2004-06-06 19:15:58 +00:00
Wayne Davison
99218d821b If the user specifies a small io_timeout value, lower select_timeout. 2004-06-06 19:02:40 +00:00
Wayne Davison
e626b29e10 Make sure our select calls don't sleep for over one minute at a time,
even when io_timeout is a longer value (though the code in options.c
might set it to a shorter value if io_timeout is small).
2004-06-06 19:02:09 +00:00
Wayne Davison
f89b936801 Don't use single-line "if (condition) statement;" idiom. 2004-06-06 18:36:22 +00:00
Wayne Davison
17f59e818d Mention changes to the patches dir. 2004-06-05 21:23:59 +00:00
Wayne Davison
b5bd5542eb Neatened up some of the glob-expand code and made a few other
minor tweaks.
2004-06-05 20:26:56 +00:00
Wayne Davison
2e94e70e2b Some superficial code tweaks. 2004-06-05 19:59:03 +00:00
Wayne Davison
4e1f385711 Mentioned new --keep-dirlinks option. 2004-06-05 16:19:02 +00:00
Wayne Davison
716e73d483 New --keep-dirlinks option. 2004-06-05 16:16:30 +00:00
Wayne Davison
5b36173d11 Mention new SSH_* vars. 2004-06-03 17:20:33 +00:00
Wayne Davison
b2ef4f6134 The daemon-over-ssh code now looks for $SSH_CONNECTION and $SSH2_CLIENT
as well as $SSH_CLIENT to figure out the remote IP address.
2004-06-03 17:20:21 +00:00
Wayne Davison
c7be6dec11 - Added older news from NEWS file.
- Added missing releases from the Partial Protocol History section.
2004-06-01 21:27:52 +00:00
Wayne Davison
bd1574b208 Moved older news to OLDNEWS. 2004-06-01 21:27:12 +00:00
Wayne Davison
f376e67420 Got rid of an unneeded character pointer in send_file_entry(). 2004-05-29 21:21:17 +00:00
Wayne Davison
ef0bc0abff Mention the --bwlimit change. 2004-05-28 19:42:06 +00:00
Wayne Davison
71e586304b Improvements to make --bwlimit work better. 2004-05-27 22:09:31 +00:00
Wayne Davison
3c74c3a358 Set a new variable, bwlimit_writemax, based on the value of the bwlimit
option.
2004-05-27 21:51:53 +00:00
Wayne Davison
edad5898f2 Got rid of a superfluous call to gettimeofday(). 2004-05-24 22:59:16 +00:00
Wayne Davison
fa0c1939ed The various include/exclude options are not used on the server side,
so if someone is trying something funny, just quit.
2004-05-24 18:38:05 +00:00
Wayne Davison
9a5ade185c Made full_fname()'s char-pointer arg const. 2004-05-24 08:10:22 +00:00
Wayne Davison
f1dd0f27cb - Properly quote the $excl references.
- Moved the creation of our .cvsignore exclude file.
2004-05-24 00:16:07 +00:00
Wayne Davison
f9e5a0cde2 Improved the depth calculation in sanitize_path() so that it properly
handles a trailing slash, a leading slash, and an empty string.
2004-05-23 23:46:56 +00:00
Wayne Davison
ead751c62b Moved a couple lines. 2004-05-22 19:29:53 +00:00
Wayne Davison
0058c58edd A few minor improvements to the existing items. 2004-05-22 19:24:24 +00:00
Wayne Davison
221ddb9456 Fixed a typo in the sending of the --checksum-seed option to the server. 2004-05-22 06:09:22 +00:00
Wayne Davison
65e2487096 Fixed the comment for get_exclude_tok(). 2004-05-22 05:32:20 +00:00
Wayne Davison
0501f36390 Tweaked the alloc/realloc code in flist_expand(). 2004-05-21 23:22:14 +00:00
Wayne Davison
96981b9cff Tell rsync to preserve permissions. 2004-05-21 10:06:09 +00:00
Wayne Davison
f51e87f5ad Another new option. 2004-05-21 10:00:21 +00:00
Wayne Davison
cb213f1c1b Got rid of a compiler warning (which was only output by certain
compilers).
2004-05-21 09:59:49 +00:00
Wayne Davison
c8d895de26 Added the --checksum-seed option. 2004-05-21 09:44:32 +00:00
Wayne Davison
e51094b721 - Improved option_error() to make sure that the user sees the error in
daemon mode.
- Got rid of some repetitious outputting of the same error-message.
2004-05-21 09:41:38 +00:00
Wayne Davison
b03bded70b Document a couple more changes. 2004-05-21 09:29:17 +00:00
Wayne Davison
ee1df1ccae If --backup was specified without a --backup-dir, don't preserve the
directory timestamps.
2004-05-21 08:43:03 +00:00
Wayne Davison
bc6ebcd248 Moved a few externs. 2004-05-21 08:40:25 +00:00
Wayne Davison
ba582f753a Changed sum_init() to take a seed value as an arg instead of always
using checksum_init.  This fixes an authentication problem in server
mode (as pointed out by Craig Barratt).
2004-05-21 08:27:04 +00:00
Wayne Davison
cbd85b472e - Mention the change to the daemon-mode's exclude handling.
- Mention the new "write only" daemon-config option.
- Fixed another entry to refer to the right files.
2004-05-19 22:20:56 +00:00
Wayne Davison
7a92ded39a Added the "write only" option to the daemon config file. 2004-05-19 22:19:19 +00:00
Wayne Davison
831f05df51 A few minor text improvements. 2004-05-18 09:54:52 +00:00
Wayne Davison
0d94a6a66c Added a little more quoting. 2004-05-18 09:47:42 +00:00
Wayne Davison
3e35c34b6b Output a message when we skip a server-excluded file. 2004-05-18 08:50:17 +00:00
Wayne Davison
03a9ca0a97 Document the latest changes. 2004-05-18 01:13:14 +00:00
Wayne Davison
6f481bb0e0 - Use fromdir, todir, and tmpdir instead of FROM, TO, and TMP.
- Added chkdir.
- Quote the dir expansions to avoid problems with spaces.
- Added "exclude = foobar.baz" the the rsync.conf file we create.
2004-05-18 00:41:55 +00:00
Wayne Davison
f98cc5685d Test that a config-file-specified exclude works right. 2004-05-18 00:41:51 +00:00
Wayne Davison
9135621ff9 Quote the dir expansions to avoid problems with spaces. 2004-05-18 00:41:49 +00:00
Wayne Davison
8624daa7f8 - Use fromdir and todir instead of FROM and TO.
- Quote the dir expansions to avoid problems with spaces.
2004-05-18 00:41:46 +00:00
Wayne Davison
3051c46dc3 - Use $suitedir to find rsync.fns.
- Use tmpdir instead of TMP.
2004-05-18 00:41:43 +00:00
Wayne Davison
e920830ec5 Use $suitedir to find rsync.fns. 2004-05-18 00:41:40 +00:00
Wayne Davison
7892e5ac77 - Use $suitedir to find rsync.fns.
- The values of fromdir, todir, and chkdir are already set.
2004-05-18 00:41:38 +00:00
Wayne Davison
b0e9bafc78 - Use $suitedir to find rsync.fns.
- The values of fromdir and todir are already set.
2004-05-18 00:41:35 +00:00
Wayne Davison
44aa070770 Removing obsoleted test.sh file (we used the runtests.sh framework for
some time now).
2004-05-18 00:32:36 +00:00
Wayne Davison
97f9dcae6a If the server has excluded a file, we now exclude it from being
uploaded as well as downloaded.
2004-05-18 00:14:10 +00:00
Wayne Davison
8cbf495a57 Renamed free_exclude_list() to clear_exclude_list(). 2004-05-16 23:54:12 +00:00
Wayne Davison
c1b29492c5 Moved the setting of ret->match_flags up a little in make_exclude(). 2004-05-16 14:08:34 +00:00
Wayne Davison
669a31924e - Save some memory in each exclude_struct item by dumping the "include"
and "directory" ints and using bits in the match_flags value instead.
- Added defines for the new match-flag values, including a new one that
  lets get_exclude_tok() properly return an indication that it parsed
  the list-clearing token.
2004-05-16 07:28:24 +00:00
Wayne Davison
5e972dcf34 - Switched the "include" and "directory" ints into bits in match_flags.
- Made some length vars unsigned.
2004-05-16 07:28:21 +00:00
Wayne Davison
8fcdc444df - Improved rsyserr() to prefix RSYNC_NAME (as the TODO requested),
to construct the string in a better manner, and to have a buffer
  big enough to hold a full MAXPATHLEN filename plus some error
  text.
- Fixed some comments referring to vsprintf() returning -1 -- our
  configuration process now ensures that we replace such a function
  with our own lib version.
2004-05-15 19:31:16 +00:00
Wayne Davison
619d21ffc9 - Complain about an exclude that was too long and then dump it
(used to be silently truncated).
- Include extra space in our exclude-reading buffers so that we
  can fit a 2-char prefix and a trailing slash and still handle
  a MAXPATHLEN name.
2004-05-15 19:31:13 +00:00
Wayne Davison
d62bcc17f3 Changed rprintf() calls that included strerror() to use rsyserr(). 2004-05-15 19:31:10 +00:00
Wayne Davison
982e05bbd5 Changed rprintf() calls that included strerror() to use rsyserr(). 2004-05-15 19:31:10 +00:00
Wayne Davison
a3c8b36863 Added rsyserr(). 2004-05-15 19:31:05 +00:00
Wayne Davison
630e3c408b Whitespace tweaks. 2004-05-15 19:09:42 +00:00
Wayne Davison
1082b52bd4 Changing if (!write_batch) in front of send_exclude_list() to
if (!read_batch) -- fixes hang.
2004-05-15 18:51:21 +00:00
Wayne Davison
914f3066bb Added a "gen" rule to remake various generated files: configure,
config.h.in, proto.h, rsync.1, and rsyncd.conf.5 .
2004-05-15 00:48:11 +00:00
Wayne Davison
de91e75724 In the debug output, distinguish between a user-requested clearing
of the exclude list and the popping of the local exclude list that
occurs when we finish each subdir.
2004-05-14 21:23:41 +00:00
Wayne Davison
384431886a Changed PERMS_SKIP_TIME to PERMS_SKIP_MTIME. 2004-05-13 18:51:22 +00:00
Wayne Davison
82b302d928 Got rid of some useless externs. 2004-05-13 18:41:17 +00:00
Wayne Davison
4ecc9e6b64 The finish_transfer() call takes an arg that specifies if we should set the
modtime or not on the finished file.  It calls set_perms(), which now takes a
flag arg that allows us to specify if we want to skip the modtime modification.
2004-05-13 07:08:25 +00:00
Wayne Davison
55e50d890b If the file did not transfer correctly, only save it if --partial was
specified.  We also skip the setting of the modtime too on a partial
copy (that way the partial file won't be confused with an up-to-date
copy of the original).
2004-05-13 07:08:22 +00:00
Wayne Davison
6e86c951d7 Call finish_transfer() with its new arg. Also put the externs
at the top and got rid of some trailing whitespace.
2004-05-13 07:08:18 +00:00
Wayne Davison
c41b52c487 Use the new PERMS_REPORT flag when calling set_perms(). 2004-05-13 06:55:01 +00:00
Wayne Davison
5c6fc4a6a3 Added PERMS_REPORT and PERMS_SKIP_TIME. 2004-05-13 06:53:23 +00:00
Wayne Davison
edecdad54d If we got a read-error on a file, make sure that the whole-file
checksum we send to the receiver is wrong (so they won't save
the bogus file).
2004-05-13 06:46:20 +00:00
Wayne Davison
5291364f1d Don't force the modtime on our backup dirs -- the dirs in the
backup hierarchy should have their own timestamps.
2004-05-13 06:34:03 +00:00
Wayne Davison
41cc97ae64 In send_files(), changed the name of the map_struct variable from
"buf" to "mbuf" (so that it wouldn't be so similar to the "buff"
variable nor use a name that is more typically a char* buffer).
2004-05-11 19:53:16 +00:00
Wayne Davison
bf2b7ddfc5 Use memset() to initialize a new map_struct. 2004-05-11 19:46:56 +00:00
Wayne Davison
eb0cbdaa90 Got rid of an unused extern. 2004-05-11 17:25:16 +00:00
Wayne Davison
0d0142e812 Got rid of unused externs. 2004-05-11 17:25:01 +00:00
Wayne Davison
a43e21e05c Let's just remove all the UNUSED() macros for now. 2004-05-08 22:49:58 +00:00
Wayne Davison
4135d091a6 Changed the non-globbing version of glob_expand_one() so that it
checks the maxargs argument instead of leaving it unused.
2004-05-08 20:03:39 +00:00
Wayne Davison
534407b1f4 One more attempt to get HP-UX's cc to build popt successfully. 2004-05-08 19:50:22 +00:00
Wayne Davison
18cc8c7ef1 Improved a comment and got rid of some trailing whitespace. 2004-05-08 19:37:28 +00:00
Wayne Davison
58c9b4b7f6 Tweaked the sizeof syntax and some multi-statement lines. 2004-05-08 19:26:53 +00:00
Wayne Davison
cde719f49f Changed the order of the msgcode enum so that new items now get added
at the start (which avoids the need for trailing-comma changes on old
entries when new ones are added).
2004-05-08 18:48:09 +00:00
Wayne Davison
38cab94d9a - Improved the get_secret()'s function comments, made it accept a line
that doesn't end with a newline, and optimized it a bit.
- Improved getpassf() to work if the line does not end with a newline.
2004-05-08 18:18:42 +00:00
Wayne Davison
6ed6d7f5a8 Improved the function comments for read_line() and slightly tweaked
its code.  Also changed "IO" to "I/O" in various comments.
2004-05-08 18:03:43 +00:00
Wayne Davison
e40a46de71 Document the -4, -6, --ipv4, --ipv6 options. 2004-05-07 00:18:37 +00:00
Wayne Davison
c5bf99a1c2 Correct a typo. 2004-05-06 21:29:36 +00:00
Wayne Davison
2c7d63c765 - Updated the comments for open_socket_in().
- Changed open_socket_in() to return an array of ints with a trailing -1
  value to indicate the end of the list.
- Use the out_of_memory() routine to complain about no memory.
- Undid the recent IPV6_V6ONLY change, as I think it would prevent the
  use of IPv6 sockets on some older systems.
- If we get an EADDRINUSE error and this is not the first socket in the
  list, suggest that the user try --ipv4 or --ipv6.
- When forking, the child now closes all the open bound sockets, not just
  one of them (I'm not talking about the fd from accept(), obviously).
2004-05-06 21:26:46 +00:00
Wayne Davison
3dd22903ac Introduced long-option names for -4 and -6. 2004-05-06 21:08:01 +00:00
Wayne Davison
d8d36af452 If we need to set IPV6_V6ONLY but setsockopt() fails, close the
socket and skip it.
2004-05-05 22:17:48 +00:00
Wayne Davison
e610e50f9c Added missing extern for read_batch. 2004-05-05 17:15:03 +00:00
Wayne Davison
935c64173f Don't force the whole-file option when using read-batch. 2004-05-05 16:23:49 +00:00
Wayne Davison
377dbd2075 Calls to make_bak_dir() should only happen when we fail to create a
file/dir/etc. with errno == ENOENT.
2004-05-04 03:10:45 +00:00
Wayne Davison
93272700d2 A slight refinement to my last patch. 2004-05-03 01:24:10 +00:00
Wayne Davison
d508258ad8 Fixed crash bug that can affect --delete in certain circumstances. 2004-05-03 01:18:07 +00:00
Wayne Davison
f57b2e6150 Got rid of a TODO comment that was fixed long ago. 2004-05-02 17:04:14 +00:00
Wayne Davison
af45f9e27e Renamed variable STRIP to INSTALL_STRIP to avoid an accidental match
with an environment variable in OpenBSD.
2004-05-02 16:52:52 +00:00
Wayne Davison
4c4d61b046 Got rid of trailing comma in an enum. 2004-05-02 16:34:33 +00:00
Wayne Davison
7561c3e132 Moved some news items under new headings. 2004-04-30 21:10:58 +00:00
Wayne Davison
1514ad2a80 Changed the order that ssh and rsh are mentioned. 2004-04-30 20:39:29 +00:00
92 changed files with 11796 additions and 5962 deletions

View File

@@ -21,3 +21,5 @@ tls
trimslash
t_unsafe
wildtest
getfsdev
.rsync-filter

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.

View File

@@ -41,14 +41,14 @@ popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
TLS_OBJ = tls.o syscall.o lib/permstring.o
TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o
# Programs we must have to run the test cases
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) \
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
# Objects for CHECK_PROGS to clean
CHECK_OBJS=getgroups.o t_stub.o t_unsafe.o trimslash.o wildtest.o
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
@@ -58,18 +58,16 @@ CHECK_OBJS=getgroups.o t_stub.o t_unsafe.o trimslash.o wildtest.o
all: rsync$(EXEEXT)
man: rsync.1 rsyncd.conf.5
install: all
-mkdir -p ${DESTDIR}${bindir}
${INSTALLCMD} ${STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
-mkdir -p ${DESTDIR}${mandir}/man1
-mkdir -p ${DESTDIR}${mandir}/man5
${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1
${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5
install-strip:
$(MAKE) STRIP='-s' install
$(MAKE) INSTALL_STRIP='-s' install
rsync$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
@@ -82,7 +80,10 @@ tls$(EXEEXT): $(TLS_OBJ)
getgroups$(EXEEXT): getgroups.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getgroups.o $(LIBS)
TRIMSLASH_OBJ = trimslash.o syscall.o
getfsdev$(EXEEXT): getfsdev.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
@@ -90,17 +91,15 @@ T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
# I don't like these rules because CVS can skew the timestamps and
# produce spurious warnings, and also make "make install" fail if the
# source directory can no longer be found. Since we don't rebuild
# automatically they're kind of lame anyhow.
gen: $(srcdir)/configure $(srcdir)/config.h.in proto man
#Makefile: Makefile.in configure config.status
# echo "WARNING: You need to run ./config.status --recheck"
man: $(srcdir)/rsync.1 $(srcdir)/rsyncd.conf.5
# don't actually run autoconf, just issue a warning
#configure: configure.in
# echo "WARNING: you need to rerun autoconf"
$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4
cd $(srcdir); autoconf
$(srcdir)/config.h.in: $(srcdir)/configure.in $(srcdir)/aclocal.m4
cd $(srcdir); autoheader
$(srcdir)/rsync.1: $(srcdir)/rsync.yo
yodl2man -o $(srcdir)/rsync.1 $(srcdir)/rsync.yo
@@ -109,7 +108,12 @@ $(srcdir)/rsyncd.conf.5: $(srcdir)/rsyncd.conf.yo
yodl2man -o $(srcdir)/rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
proto:
cat $(srcdir)/*.c $(srcdir)/lib/compat.c | awk -f $(srcdir)/mkproto.awk > $(srcdir)/proto.h
cat $(srcdir)/*.c $(srcdir)/lib/compat.c | awk -f $(srcdir)/mkproto.awk >$(srcdir)/proto.h.new
if diff $(srcdir)/proto.h $(srcdir)/proto.h.new >/dev/null; then \
rm $(srcdir)/proto.h.new; \
else \
mv $(srcdir)/proto.h.new $(srcdir)/proto.h; \
fi
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS)
@@ -146,9 +150,6 @@ test: check
# There seems to be no standard way to specify some variables as
# exported from a Makefile apart from listing them like this.
# TODO: Tests that depend on built test aide programs like tls need to
# know where the build directory is.
# This depends on building rsync; if we need any helper programs it
# should depend on them too.

319
NEWS
View File

@@ -1,229 +1,164 @@
NEWS for rsync 2.6.2 (30 Apr 2004)
Protocol: 28 (unchanged)
Changes since 2.6.1:
NEWS for rsync 2.6.5 (UNRELEASED)
Protocol: 29 (unchanged)
Changes since 2.6.4:
OUTPUT CHANGES:
- 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.
- 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.
BUG FIXES:
- Fixed a major bug in the sorting of the filenames when --relative
is used for some sources (just sources such as "/" and "/*" were
affected). This fix ensures that we ask for the right file-list
item when requesting changes from the sender.
- 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.
- Rsync now checks the return value of the close() function to
better report disk-full problems on an NFS file system.
- Fixed a bug in the transfer of a single file when -H is specified
that might have caused an infinite loop or perhaps a crash.
- Restored the old daemon-server behavior of logging error messages
rather than returning them to the user. (A better long-term fix
will be sought in the future.)
- Fixed a case where the generator might try to tweak the write
permissions of a read-only directory in list-only mode.
- An obscure uninitialized-variable bug was fixed in the uid/gid
code. (This bug probably had no ill effects.)
- 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.
- Got rid of the configure check for sys/sysctl.h (it wasn't used
and was causing a problem on some systems). Also improved the
broken-largefile-locking test to try to avoid failure due to an
NFS build-dir.
- Fixed the accidental disabling of --backup during the --delete-after
processing.
- Fixed a compile problem on systems that don't define
AI_NUMERICHOST.
- Restored the ability to use the --address option in client mode (in
addition to its use in daemon mode).
- Fixed a compile problem in the popt source for compilers that
don't support __attribute__.
- 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.
INTERNAL:
- When --existing skips a directory with extra verbosity, refer to it
as a "directory", not a "file".
- Improved the testsuite's "merge" test to work on OSF1.
- 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.
- Two new diffs were added to the patches dir.
- Fixed a bug where hard-linking a group of files might fail if the
generator hasn't created a needed destination directory yet.
NEWS for rsync 2.6.1 (26 Apr 2004)
Protocol: 28 (changed)
Changes since 2.6.0:
- 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.
SECURITY FIXES:
- 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.
- Paths sent to an rsync daemon are more thoroughly sanitized when
chroot is not used. If you're running a non-read-only rsync
daemon with chroot disabled, *please upgrade*, ESPECIALLY if the
user privs you run rsync under is anything above "nobody".
- Fixed a compatibility problem when using --cvs-ignore (-C) and
sending files to an older rsync without using --delete.
- Make sure that a "- !" or "+ !" include/exclude pattern does not
trigger the list-clearing action that is reserved for "!".
- Avoid a timeout in the generator when the sender/receiver aren't
handling the generator's checksum output quickly enough.
- Fixed the ommission of some directories in the delete processing when
--relative (-R) was combined with a source path that had a trailing
slash.
- Make sure that --max-size doesn't affect a device or a symlink.
- 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.)
- If a source filename ends with "..", treat it as if "../" had been
specified (so that we don't copy files to the parent dir of the
destination).
- 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.
- If --stats is specified with --delete-after, ensure that all the
"deleting" messages are output before the statistics.
- Improved one "if" in the deletion code that was only checking errno
for ENOTEMPTY when it should have also been checking for EEXIST.
ENHANCEMENTS:
- Lower memory use, more optimal transfer of data over the socket,
and lower CPU usage (see the INTERNAL section for details).
- 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).
- The RSYNC_PROXY environment variable can now contain a
"USER:PASS@" prefix before the "HOST:PORT" information.
(Bardur Arantsson)
- 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.
- The --progress output now mentions how far along in the transfer
we are, including both a count of files transferred and a
percentage of the total file-count that we've processed. It also
shows better current-rate-of-transfer and remaining-transfer-time
values.
- Improved the keep-alive code to handle a long silence between the
sender and the receiver that can occur when processing the checksum
data for a large file.
- The configure script now accepts --with-rsyncd-conf=PATH to
override the default value of the /etc/rsyncd.conf file.
- 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 a couple extra diffs in the "patches" dir, removed the ones
that got applied, and rebuilt the rest.
- 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).
- Documentation changes now attempt to describe some often mis-
understood features more clearly.
- 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 failure (since a
daemon is not usually run with the --no-detach option that was
necessary to see the error on stderr).
BUG FIXES:
- The man pages now consistently refer to an rsync daemon as a "daemon"
to distinguish it from a server in a non-daemon transfer.
- When -x (--one-file-system) is combined with -L (--copy-links) or
--copy-unsafe-links, no symlinked files are skipped, even if the
referent file is on a different filesystem.
- The --link-dest code now works properly for a non-root user when
(1) the UIDs of the source and destination differ and -o was
specified, or (2) when the group of the source can't be used on
the destination and -g was specified.
- Fixed a bug in the handling of -H (hard-links) that might cause
the expanded PATH/NAME value of the current item to get
overwritten (due to an expanded-name caching bug).
- We now reset the "new data has been sent" flag at the start of
each file we send. This makes sure that an interrupted transfer
with the --partial option set doesn't keep a shorter temp file
than the current basis file when no new data has been transfered
over the wire for that file.
- Fixed a byte-order problem in --batch-mode on big-endian machines.
(Jay Fenlason)
- Fixed configure bug when running "./configure --disable-ipv6".
- Fixed "make test" bug when build dir is not the source dir.
- When using --cvs-exclude, the exclude items we get from a
per-directory's .cvsignore file once again only affect that one
directory (not all following directories too). The items are also
now properly word-split and parsed without any +/- prefix parsing.
- When specifying the USER@HOST: prefix for a file, the USER part
can now contain an '@', if needed (i.e. the last '@' is used to
find the HOST, not the first).
- Fixed some bugs in the handling of group IDs for non-root users:
(1) It properly handles a group that the sender didn't have a name
for (it would previously skip changing the group on any files in
that group). (2) If --numeric-ids is used, rsync no longer
attempts to set groups that the user doesn't have the permission
to set.
- Fixed the "refuse options" setting in the rsyncd.conf file.
- Improved the -x (--one-file-system) flag's handling of any mount-
point directories we encounter. It is both more optimal (in that
it no longer does a useless scan of the contents of the mount-
point dirs) and also fixes a bug where a remapped mount of the
original filesystem could get discovered in a subdir we should be
ignoring.
- Rsync no longer discards a double-slash at the start of a filename
when trying to open the file. It also no longer constructs names
that start with a double slash (unless the user supplied them).
- Path-specifying options to a daemon should now work the same with
or without chroot turned on. Previously, such a option (such as
--link-dest) would get its absolute path munged into a relative
one if chroot was not on, making that setting fairly useless.
Rsync now transforms the path into one that is based on the
module's base dir when chroot is not enabled.
- Fixed compilation problem on Tru64 Unix (having to do with
sockaddr.sa_len and sockaddr.sin_len).
- Fixed a compatibility problem interacting with older rsync
versions that might send us an empty --suffix value without
telling us that --backup-dir was specified.
- The "hosts allow" option for a daemon-over-remote-shell process
now has improved support for IPv6 addresses and a fix for systems
that have a length field in their socket structs.
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
- 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:
- Most of the I/O is now buffered, which results in a pretty large
speedup when running under MS Windows. (Craig Barratt)
- Rsync now calls setlocale(LC_CTYPE, "") to enable isprint() to better
discern which filename characters need to be escaped in messages.
- Optimizations to the name-handling/comparing code have made some
significant reductions in user-CPU time for large file sets.
- Improved the naming of the log-file open/reopen/close functions.
- Some cleanup of the variable types make the code more consistent.
- Removed some protocol compatibility code that was only needed to help
someone running a pre-release of 2.6.4.
- Reduced memory requirements of hard link preservation.
(J.W. Schultz)
BUILD CHANGES:
- Implemented a new algorithm for hard-link handling that speeds up
the code significantly. (J.W. Schultz and Wayne Davison)
- Fixed a bug in the SUPPORT{,_HARD}_LINKS defines which prevented
rsync from being built without symlink or hard-link support.
- The --hard-link option now uses the first existing file in the
group of linked files as the basis for the transfer. This
prevents the sub-optimal transfer of a file's data when a new
hardlink is added on the sending side and it sorts alphabetically
earlier in the list than the files that are already present on the
receiving side.
- You can use --disable-locale to turn off any use of setlocale().
- Dropped support for protocol versions less than 20 (2.3.0 released
15 Mar 1999) and activated warnings for protocols less than 25
(2.5.0 released 23 Aug 2001). (Wayne Davison and J.W. Schultz,
severally)
- Configure now disables the use of mkstemp() under HP-UX (since they
refuse to fix its broken handling of large files).
- More optimal data transmission for --hard-links (protocol 28).
- 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.
- More optimal data transmission for --checksum (protocol 28).
- Some minor enhancements to the test scripts.
- Less memory is used when --checksum is specified.
- Less memory is used in the file list (a per-file savings).
- The generator is now better about not modifying the file list
during the transfer in order to avoid a copy-on-write memory
bifurcation (on systems where fork() uses shared memory).
Previously, rsync's shared memory would slowly become unshared,
resulting in real memory usage nearly doubling on the receiving
side by the end of the transfer. Now, as long as permissions
are being preserved, the shared memory should remain that way
for the entire transfer.
- Changed hardlink info and file_struct + strings to use allocation
pools. This reduces memory use for large file-sets and permits
freeing memory to the OS. (J.W. Schultz)
- The 2 pipes used between the receiver and generator processes
(which are forked on the same machine) were reduced to 1 pipe and
the protocol improved so that (1) it is now impossible to have the
"redo" pipe fill up and hang rsync, and (2) trailing messages from
the receiver don't get lost on their way through the generator
over to the sender (which mainly affected hard-link messages and
verbose --stats output).
- Improved the internal uid/gid code to be more portable and a
little more optimized.
- The device numbers sent when using --devices are now sent as
separate major/minor values with 32-bit accuracy (protocol 28).
Previously, the copied devices were sent as a single 32-bit
number. This will make inter-operation of 64-bit binaries more
compatible with their 32-bit brethren (with both ends of the
connection are using protocol 28). Note that optimizations in the
binary protocol for sending the device numbers often results in
fewer bytes being used than before, even though more precision is
now available.
- Some cleanup of the exclude/include structures and its code made
things clearer (internally), simpler, and more efficient.
- The reading & writing of the file-list in batch-mode is now
handled by the same code that sends & receives the list over the
wire. This makes it much easier to maintain. (Note that the
batch code is still considered to be experimental.)
- Added a few new diffs to the patches dir, including a patch that
enables the optional copying of extended attributes.

888
OLDNEWS
View File

@@ -1,3 +1,884 @@
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:
SECURITY FIXES:
- A bug in the sanitize_path routine (which affects a non-chrooted
rsync daemon) could allow a user to craft a pathname that would get
transformed into an absolute path for certain options (but not for
file-transfer names). If you're running an rsync daemon with chroot
disabled, *please upgrade*, ESPECIALLY if the user privs you run
rsync under is anything above "nobody".
OUTPUT CHANGES (ATTN: those using a script to parse the verbose output):
- Please note that the 2-line footer (output when verbose) now uses the
term "sent" instead of "wrote" and "received" instead of "read". If
you are not parsing the numeric values out of this footer, a script
would be better off using the empty line prior to the footer as the
indicator that the verbose output is over.
- The output from the --stats option was similarly affected to change
"written" to "sent" and "read" to "received".
- Rsync ensures that a filename that contains a newline gets mentioned
with each newline transformed into a question mark (which prevents a
filename from causing an empty line to be output).
- The "backed up ..." message that is output when at least 2 --verbose
options are specified is now the same both with and without the
--backup-dir option.
BUG FIXES:
- Fixed a crash bug that might appear when --delete was used and
multiple source directories were specified.
- Fixed a 32-bit truncation of the file length when generating the
checksums.
- The --backup code no longer attempts to create some directories
over and over again (generating warnings along the way).
- Fixed a bug in the reading of the secrets file (by the daemon) and
the password file (by the client): the files no longer need to be
terminated by a newline for their content to be read in.
- If a file has a read error on the sending side or the reconstructed
data doesn't match the expected checksum (perhaps due to the basis
file changing during the transfer), the receiver will no longer
retain the resulting file unless the --partial option was specified.
(Note: for the read-error detection to work, neither side can be
older than 2.6.3 -- older receivers will always retain the file, and
older senders don't tell the receiver that the file had a read
error.)
- If a file gets resent in a single transfer and the --backup option
is enabled, rsync no longer performs a duplicate backup (it used to
overwrite the original file in the backup area).
- Files specified in the daemon's "exclude" or "exclude from" config
items are now excluded from being uploaded (assuming that the module
allows uploading at all) in addition to the old download exclusion.
- Got rid of a potential hang in the receiver when near the end of a
phase.
- When using --backup without a --backup-dir, rsync no longer preserves
the modify time on directories. This avoids confusing NFS.
- When --copy-links (-L) is specified, we now output a separate error
for a symlink that has no referent instead of claiming that a file
"vanished".
- The --copy-links (-L) option no longer has the side-effect of telling
the receiving side to follow symlinks. See the --keep-dirlinks
option (mentioned below) for a way to specify that behavior.
- Error messages from the daemon server's option-parsing (such as
refused options) are now successfully transferred back to the client
(the server used to fail to send the message because the socket
wasn't in the right state for the message to get through).
- Most transfer errors that occur during a daemon transfer are now
returned to the user in addition to being logged (some messages are
intended to be daemon-only and are not affected by this).
- Fixed a bug in the daemon authentication code when using one of the
batch-processing options.
- We try to work around some buggy IPv6 implementations that fail to
implement IPV6_V6ONLY. This should fix the "address in use" error
that some daemons get when running on an OS with a buggy IPv6
implementation. Also, if the new code gets this error, we might
suggest that the user specify --ipv4 or --ipv6 (if we think it will
help).
- When the remote rsync dies, make a better effort to recover any error
messages it may have sent before dying (the local rsync used to just
die with a socket-write error).
- When using --delete and a --backup-dir that contains files that are
hard-linked to their destination equivalents, rsync now makes sure
that removed files really get removed (avoids a really weird rename()
behavior).
- Avoid a bogus run-time complaint about a lack of 64-bit integers when
the int64 type is defined as an off_t and it actually has 64-bits.
- Added a configure check for open64() without mkstemp64() so that we
can avoid using mkstemp() when such a combination is encountered.
This bypasses a problem writing out large temp files on OSes such as
AIX and HP-UX.
- Fixed an age-old crash problem with --read-batch on a local copy
(rsync was improperly assuming --whole-file for the local copy).
- When --dry-run (-n) is used and the destination directory does not
exist, rsync now produces a correct report of files that would be
sent instead of dying with a chdir() error.
- Fixed a bug that could cause a slow-to-connect rsync daemon to die
with an error instead of waiting for the connection to finish.
- Fixed an ssh interaction that could cause output to be lost when the
user chose to combine the output of rsync's stdout and stderr (e.g.
using the "2>&1").
ENHANCEMENTS:
- Added the --partial-dir=DIR option that lets you specify where to
(temporarily) put a partially transferred file (instead of over-
writing the destination file). E.g. --partial-dir=.rsync-partial
Also added support for the RSYNC_PARTIAL_DIR environment variable
that, when found, transforms a regular --partial option (such as
the convenient -P option) into one that also specifies a directory.
- Added --keep-dirlinks (-K), which allows you to symlink a directory
onto another partition on the receiving side and have rsync treat it
as matching a normal directory from the sender.
- Added the --inplace option that tells rsync to write each destination
file without using a temporary file. The matching of existing data
in the destination file can be severely limited by this, but there
are also cases where this is more efficient (such as appending data).
Use only when needed (see the man page for more details).
- Added the "write only" option for the daemon's config file.
- Added long-option names for -4 and -6 (namely --ipv4 and --ipv6)
and documented all these options in the man page.
- Improved the handling of the --bwlimit option so that it's less
bursty, more accurate, and works properly over a larger range of
values.
- The rsync daemon-over-ssh code now looks for SSH_CONNECTION and
SSH2_CLIENT in addition to SSH_CLIENT to figure out the IP address.
- Added the --checksum-seed=N option for advanced users.
- Batch writing/reading has a brand-new implementation that is simpler,
fixes a few weird problems with the old code (such as no longer
sprinkling the batch files into different dirs or even onto different
systems), and is much less intrusive into the code (making it easier
to maintain for the future). The new code generates just one data
file instead of three, which makes it possible to read the batch on
stdin via a remote shell. Also, the old requirement of forcing the
same fixed checksum-seed for all batch processing has been removed.
- If an rsync daemon has a module set with "list = no" (which hides its
presence in the list of available modules), a user that fails to
authenticate gets the same "unknown module" error that they would get
if the module were actually unknown (while still logging the real
error to the daemon's log file). This prevents fishing for module
names.
- The daemon's "refuse options" config item now allows you to match
option names using wildcards and/or the single-letter option names.
- Each transferred file now gets its permissions and modified-time
updated before the temp-file gets moved into place. Previously, the
finished file would have a very brief window where its permissions
disallowed all group and world access.
- Added the ability to parse a literal IPv6 address in an "rsync:" URL
(e.g. rsync://[2001:638:500:101::21]:873/module/dir).
- The daemon's wildcard expanding code can now handle more than 1000
filenames (it's now limited by memory instead of having a hard-wired
limit).
INTERNAL:
- Some cleanup in the exclude code has saved some per-exclude memory
and made the code easier to maintain.
- Improved the argv-overflow checking for a remote command that has a
lot of args.
- Use rsyserr() in the various places that were still calling rprintf()
with strerror() as an arg.
- If an rsync daemon is listening on multiple sockets (to handle both
IPv4 and IPv6 to a single port), we now close all the unneeded file
handles after we accept a connection (we used to close just one of
them).
- Optimized the handling of larger block sizes (rsync used to slow to a
crawl if the block size got too large).
- Optimized away a loop in hash_search().
- Some improvements to the sanitize_path() and clean_fname() functions
makes them more efficient and produce better results (while still
being compatible with the file-name cleaning that gets done on both
sides when sending the file-list).
- Got rid of alloc_sanitize_path() after adding a destination-buffer
arg to sanitize_path() made it possible to put all the former's
functionality into the latter.
- The file-list that is output when at least 4 verbose options are
specified reports the uid value on the sender even when rsync is
not running as root (since we might be sending to a root receiver).
BUILD CHANGES:
- Added a "gen" target to rebuild most of the generated files,
including configure, config.h.in, the man pages, and proto.h.
- If "make proto" doesn't find some changes in the prototypes, the
proto.h file is left untouched (its time-stamp used to always be
updated).
- The variable $STRIP (that is optionally set by the install-strip
target's rule) was changed to $INSTALL_STRIP because some systems
have $STRIP already set in the environment.
- Fixed a build problem when SUPPORT_HARD_LINKS isn't defined.
- When cross-compiling, the gettimeofday() function is now assumed to
be a modern version that takes two-args (since we can't test it).
DEVELOPER RELATED:
- The scripts in the testsuite dir were cleaned up a bit and a few
new tests added.
- Some new diffs were added to the patches dir, and some accepted
ones were removed.
NEWS for rsync 2.6.2 (30 Apr 2004)
Protocol: 28 (unchanged)
Changes since 2.6.1:
BUG FIXES:
- Fixed a major bug in the sorting of the filenames when --relative
is used for some sources (just sources such as "/" and "/*" were
affected). This fix ensures that we ask for the right file-list
item when requesting changes from the sender.
- Rsync now checks the return value of the close() function to
better report disk-full problems on an NFS file system.
- Restored the old daemon-server behavior of logging error messages
rather than returning them to the user. (A better long-term fix
will be sought in the future.)
- An obscure uninitialized-variable bug was fixed in the uid/gid
code. (This bug probably had no ill effects.)
BUILD CHANGES:
- Got rid of the configure check for sys/sysctl.h (it wasn't used
and was causing a problem on some systems). Also improved the
broken-largefile-locking test to try to avoid failure due to an
NFS build-dir.
- Fixed a compile problem on systems that don't define
AI_NUMERICHOST.
- Fixed a compile problem in the popt source for compilers that
don't support __attribute__.
DEVELOPER RELATED:
- Improved the testsuite's "merge" test to work on OSF1.
- Two new diffs were added to the patches dir.
NEWS for rsync 2.6.1 (26 Apr 2004)
Protocol: 28 (changed)
Changes since 2.6.0:
SECURITY FIXES:
- Paths sent to an rsync daemon are more thoroughly sanitized when
chroot is not used. If you're running a non-read-only rsync
daemon with chroot disabled, *please upgrade*, ESPECIALLY if the
user privs you run rsync under is anything above "nobody".
ENHANCEMENTS:
- Lower memory use, more optimal transfer of data over the socket,
and lower CPU usage (see the INTERNAL section for details).
- The RSYNC_PROXY environment variable can now contain a
"USER:PASS@" prefix before the "HOST:PORT" information.
(Bardur Arantsson)
- The --progress output now mentions how far along in the transfer
we are, including both a count of files transferred and a
percentage of the total file-count that we've processed. It also
shows better current-rate-of-transfer and remaining-transfer-time
values.
- Documentation changes now attempt to describe some often mis-
understood features more clearly.
BUG FIXES:
- When -x (--one-file-system) is combined with -L (--copy-links) or
--copy-unsafe-links, no symlinked files are skipped, even if the
referent file is on a different filesystem.
- The --link-dest code now works properly for a non-root user when
(1) the UIDs of the source and destination differ and -o was
specified, or (2) when the group of the source can't be used on
the destination and -g was specified.
- Fixed a bug in the handling of -H (hard-links) that might cause
the expanded PATH/NAME value of the current item to get
overwritten (due to an expanded-name caching bug).
- We now reset the "new data has been sent" flag at the start of
each file we send. This makes sure that an interrupted transfer
with the --partial option set doesn't keep a shorter temp file
than the current basis file when no new data has been transfered
over the wire for that file.
- Fixed a byte-order problem in --batch-mode on big-endian machines.
(Jay Fenlason)
- When using --cvs-exclude, the exclude items we get from a
per-directory's .cvsignore file once again only affect that one
directory (not all following directories too). The items are also
now properly word-split and parsed without any +/- prefix parsing.
- When specifying the USER@HOST: prefix for a file, the USER part
can now contain an '@', if needed (i.e. the last '@' is used to
find the HOST, not the first).
- Fixed some bugs in the handling of group IDs for non-root users:
(1) It properly handles a group that the sender didn't have a name
for (it would previously skip changing the group on any files in
that group). (2) If --numeric-ids is used, rsync no longer
attempts to set groups that the user doesn't have the permission
to set.
- Fixed the "refuse options" setting in the rsyncd.conf file.
- Improved the -x (--one-file-system) flag's handling of any mount-
point directories we encounter. It is both more optimal (in that
it no longer does a useless scan of the contents of the mount-
point dirs) and also fixes a bug where a remapped mount of the
original filesystem could get discovered in a subdir we should be
ignoring.
- Rsync no longer discards a double-slash at the start of a filename
when trying to open the file. It also no longer constructs names
that start with a double slash (unless the user supplied them).
- Path-specifying options to a daemon should now work the same with
or without chroot turned on. Previously, such a option (such as
--link-dest) would get its absolute path munged into a relative
one if chroot was not on, making that setting fairly useless.
Rsync now transforms the path into one that is based on the
module's base dir when chroot is not enabled.
- Fixed a compatibility problem interacting with older rsync
versions that might send us an empty --suffix value without
telling us that --backup-dir was specified.
- The "hosts allow" option for a daemon-over-remote-shell process
now has improved support for IPv6 addresses and a fix for systems
that have a length field in their socket structs.
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
INTERNAL:
- Most of the I/O is now buffered, which results in a pretty large
speedup when running under MS Windows. (Craig Barratt)
- Optimizations to the name-handling/comparing code have made some
significant reductions in user-CPU time for large file sets.
- Some cleanup of the variable types make the code more consistent.
- Reduced memory requirements of hard link preservation.
(J.W. Schultz)
- Implemented a new algorithm for hard-link handling that speeds up
the code significantly. (J.W. Schultz and Wayne Davison)
- The --hard-link option now uses the first existing file in the
group of linked files as the basis for the transfer. This
prevents the sub-optimal transfer of a file's data when a new
hardlink is added on the sending side and it sorts alphabetically
earlier in the list than the files that are already present on the
receiving side.
- Dropped support for protocol versions less than 20 (2.3.0 released
15 Mar 1999) and activated warnings for protocols less than 25
(2.5.0 released 23 Aug 2001). (Wayne Davison and J.W. Schultz,
severally)
- More optimal data transmission for --hard-links (protocol 28).
- More optimal data transmission for --checksum (protocol 28).
- Less memory is used when --checksum is specified.
- Less memory is used in the file list (a per-file savings).
- The generator is now better about not modifying the file list
during the transfer in order to avoid a copy-on-write memory
bifurcation (on systems where fork() uses shared memory).
Previously, rsync's shared memory would slowly become unshared,
resulting in real memory usage nearly doubling on the receiving
side by the end of the transfer. Now, as long as permissions
are being preserved, the shared memory should remain that way
for the entire transfer.
- Changed hardlink info and file_struct + strings to use allocation
pools. This reduces memory use for large file-sets and permits
freeing memory to the OS. (J.W. Schultz)
- The 2 pipes used between the receiver and generator processes
(which are forked on the same machine) were reduced to 1 pipe and
the protocol improved so that (1) it is now impossible to have the
"redo" pipe fill up and hang rsync, and (2) trailing messages from
the receiver don't get lost on their way through the generator
over to the sender (which mainly affected hard-link messages and
verbose --stats output).
- Improved the internal uid/gid code to be more portable and a
little more optimized.
- The device numbers sent when using --devices are now sent as
separate major/minor values with 32-bit accuracy (protocol 28).
Previously, the copied devices were sent as a single 32-bit
number. This will make inter-operation of 64-bit binaries more
compatible with their 32-bit brethren (with both ends of the
connection are using protocol 28). Note that optimizations in the
binary protocol for sending the device numbers often results in
fewer bytes being used than before, even though more precision is
now available.
- Some cleanup of the exclude/include structures and its code made
things clearer (internally), simpler, and more efficient.
- The reading & writing of the file-list in batch-mode is now
handled by the same code that sends & receives the list over the
wire. This makes it much easier to maintain. (Note that the
batch code is still considered to be experimental.)
BUILD CHANGES:
- The configure script now accepts --with-rsyncd-conf=PATH to
override the default value of the /etc/rsyncd.conf file.
- Fixed configure bug when running "./configure --disable-ipv6".
- Fixed compilation problem on Tru64 Unix (having to do with
sockaddr.sa_len and sockaddr.sin_len).
DEVELOPER RELATED:
- Fixed "make test" bug when build dir is not the source dir.
- Added a couple extra diffs in the "patches" dir, removed the ones
that got applied, and rebuilt the rest.
NEWS for rsync 2.6.0 (1 Jan 2004)
Protocol: 27 (changed)
Changes since 2.5.7:
@@ -552,7 +1433,12 @@ Changes since 2.4.6:
build farm.
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT PROTOCOL
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? May 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
26 Apr 2004 2.6.1 08 Jan 2004 28
01 Jan 2004 2.6.0 10 Apr 2003 27 (MAX=40)
04 Dec 2003 2.5.7 26
26 Jan 2003 2.5.6 26

17
README
View File

@@ -1,7 +1,7 @@
WHAT IS RSYNC?
--------------
rsync is a replacement for rcp that has many more features.
rsync is a replacement for scp/rcp that has many more features.
rsync uses the "rsync algorithm" which provides a very fast method for
bringing remote files into sync. It does this by sending just the
@@ -29,9 +29,9 @@ and see the manual for more information.
SETUP
-----
Rsync normally uses rsh or ssh for communication. It does not need to
Rsync normally uses ssh or rsh for communication. It does not need to
be setuid and requires no special privileges for installation. You
must, however, have a working rsh or ssh system. Using ssh is
must, however, have a working ssh or rsh system. Using ssh is
recommended for its security features.
Alternatively, rsync can run in `daemon' mode, listening on a socket.
@@ -77,7 +77,7 @@ BUG REPORTS
If you have web access then please look at
http://rsync.samba.org
http://rsync.samba.org/
That page contains links to the current bug list, and information on
how to report a bug well. You might also like to try searching the
@@ -86,9 +86,11 @@ mailing list archives at
http://mail-archive.com/rsync@lists.samba.org/
Please send bug reports to
To send a bug report, follow the instructions on the bug-tracking
page of the web site.
rsync@lists.samba.org
If you don't have web access, email your bug report to
rsync@lists.samba.org.
CVS TREE
@@ -103,8 +105,7 @@ recent version of cvs then use the following commands:
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co rsync
Look at the cvs documentation, or http://samba.org/cvs.html, for more
details.
Look at the cvs documentation for more details.
COPYRIGHT

240
TODO
View File

@@ -1,15 +1,9 @@
-*- indented-text -*-
BUGS ---------------------------------------------------------------
Fix progress indicator to not corrupt log
lchmod question
Do not rely on having a group called "nobody"
Incorrect timestamps (Debian #100295)
Win32
FEATURES ------------------------------------------------------------
server-imposed bandwidth limits
rsyncd over ssh
Use chroot only if supported
Allow supplementary groups in rsyncd.conf 2002/04/09
Handling IPv6 on old machines
@@ -21,28 +15,22 @@ SOCKS 2002/01/23
FAT support
Allow forcing arbitrary permissions 2002/03/12
--diff david.e.sewell 2002/03/15
Add daemon --no-detach and --no-fork options
Add daemon --no-fork option
Create more granular verbosity jw 2003/05/15
DOCUMENTATION --------------------------------------------------------
Update README
Keep list of open issues and todos on the web site
Update web site from CVS
Perhaps redo manual as SGML
LOGGING --------------------------------------------------------------
Make dry run list all updates 2002/04/03
Memory accounting
Improve error messages
Better statistics: Rasmus 2002/03/08
Perhaps flush stdout like syslog
Log deamon sessions that just list modules
Log child death on signal
Keep stderr and stdout properly separated (Debian #23626)
Log errors with function that reports process of origin
verbose output David Stein 2001/12/20
Add reason for transfer to file logging
debugging of daemon 2002/04/08
internationalization
DEVELOPMENT --------------------------------------------------------
@@ -50,9 +38,6 @@ Handling duplicate names
Use generic zlib 2002/02/25
TDB: 2002/03/12
Splint 2002/03/12
Memory debugger
Create release script
Add machines to build farm
PERFORMANCE ----------------------------------------------------------
File list structure in memory
@@ -83,37 +68,6 @@ reverse rsync over HTTP Range
BUGS ---------------------------------------------------------------
Fix progress indicator to not corrupt log
Progress indicator can produce corrupt output when transferring directories:
main/binary-arm/
main/binary-arm/admin/
main/binary-arm/base/
main/binary-arm/comm/8.56kB/s 0:00:52
main/binary-arm/devel/
main/binary-arm/doc/
main/binary-arm/editors/
main/binary-arm/electronics/s 0:00:53
main/binary-arm/games/
main/binary-arm/graphics/
main/binary-arm/hamradio/
main/binary-arm/interpreters/
main/binary-arm/libs/6.61kB/s 0:00:54
main/binary-arm/mail/
main/binary-arm/math/
main/binary-arm/misc/
-- --
lchmod question
I don't think we handle this properly on systems that don't have the
call. Are there any such?
-- --
Do not rely on having a group called "nobody"
@@ -123,40 +77,8 @@ Do not rely on having a group called "nobody"
-- --
Incorrect timestamps (Debian #100295)
A bit hard to believe, but apparently it happens.
-- --
Win32
Don't detach, because this messes up --srvany.
http://sources.redhat.com/ml/cygwin/2001-08/msg00234.html
-- --
FEATURES ------------------------------------------------------------
server-imposed bandwidth limits
-- --
rsyncd over ssh
There are already some patches to do this.
BitKeeper uses a server whose login shell is set to bkd. That's
probably a reasonable approach.
-- --
Use chroot only if supported
@@ -224,14 +146,6 @@ Other IPv6 stuff:
multiple passive addresses. This might be a bit harder, because we
may need to select on all of them. Hm.
Define a syntax for IPv6 literal addresses. Since they include
colons, they tend to break most naming systems, including ours.
Based on the HTTP IPv6 syntax, I think we should use
rsync://[::1]/foo/bar [::1]::bar
which should just take a small change to the parser code.
-- --
@@ -240,6 +154,7 @@ Add ACL support 2001/12/02
Transfer ACLs. Need to think of a standard representation.
Probably better not to even try to convert between NT and POSIX.
Possibly can share some code with Samba.
NOTE: there is a patch that implements this in the "patches" subdir.
-- --
@@ -308,6 +223,8 @@ Allow forcing arbitrary permissions 2002/03/12
(Debian #23628)
NOTE: there is a patch that implements this in the "patches" subdir.
-- --
@@ -326,7 +243,7 @@ Allow forcing arbitrary permissions 2002/03/12
-- --
Add daemon --no-detach and --no-fork options
Add daemon --no-fork option
Very useful for debugging. Also good when running under a
daemon-monitoring process that tries to restart the service when the
@@ -352,21 +269,12 @@ Create more granular verbosity jw 2003/05/15
DOCUMENTATION --------------------------------------------------------
Update README
-- --
Keep list of open issues and todos on the web site
-- --
Update web site from CVS
-- --
Perhaps redo manual as SGML
The man page is getting rather large, and there is more information
@@ -382,17 +290,6 @@ Perhaps redo manual as SGML
LOGGING --------------------------------------------------------------
Make dry run list all updates 2002/04/03
--dry-run is too dry
Mark Santcroos points out that -n fails to list files which have
only metadata changes, though it probably should.
There may be a Debian bug about this as well.
-- --
Memory accounting
@@ -474,11 +371,6 @@ Log child death on signal
-- --
Keep stderr and stdout properly separated (Debian #23626)
-- --
Log errors with function that reports process of origin
Use a separate function for reporting errors; prefix it with
@@ -490,29 +382,12 @@ Log errors with function that reports process of origin
verbose output David Stein 2001/12/20
Indicate whether files are new, updated, or deleted
At end of transfer, show how many files were or were not transferred
correctly.
-- --
Add reason for transfer to file logging
Explain *why* every file is transferred or not (e.g. "local mtime
123123 newer than 1283198")
-- --
debugging of daemon 2002/04/08
Add an rsyncd.conf parameter to turn on debugging on the server.
-- --
internationalization
Change to using gettext(). Probably need to ship this for platforms
@@ -530,46 +405,16 @@ DEVELOPMENT --------------------------------------------------------
Handling duplicate names
We need to be careful of duplicate names getting into the file list.
See clean_flist(). This could happen if multiple arguments include
the same file. Bad.
I think duplicates are only a problem if they're both flowing
through the pipeline at the same time. For example we might have
updated the first occurrence after reading the checksums for the
second. So possibly we just need to make sure that we don't have
both in the pipeline at the same time.
Possibly if we did one directory at a time that would be sufficient.
Alternatively we could pre-process the arguments to make sure no
duplicates will ever be inserted. There could be some bad cases
when we're collapsing symlinks.
We could have a hash table.
The root of the problem is that we do not want more than one file
list entry referring to the same file. At first glance there are
several ways this could happen: symlinks, hardlinks, and repeated
names on the command line.
If names are repeated on the command line, they may be present in
different forms, perhaps by traversing directory paths in different
ways, traversing paths including symlinks. Also we need to allow
for expansion of globs by rsync.
At the moment, clean_flist() requires having the entire file list in
memory. Duplicate names are detected just by a string comparison.
We don't need to worry about hard links causing duplicates because
files are never updated in place. Similarly for symlinks.
I think even if we're using a different symlink mode we don't need
to worry.
Unless we're really clever this will introduce a protocol
incompatibility, so we need to be able to accept the old format as
well.
Some folks would like rsync to be deterministic in how it handles
duplicate names that come from mering multiple source directories
into a single destination directory; e.g. the last name wins. We
could do this by switching our sort algorithm to one that will
guarantee that the names won't be reordered. Alternately, we could
assign an ever-increasing number to each item as we insert it into
the list and then make sure that we leave the largest number when
cleaning the file list (see clean_flist()). Another solution would
be to add a hash table, and thus never put any duplicate names into
the file list (and bump the protocol to handle this).
-- --
@@ -625,45 +470,6 @@ Splint 2002/03/12
-- --
Memory debugger
jra recommends Valgrind:
http://devel-home.kde.org/~sewardj/
-- --
Create release script
Script would:
Update spec files
Build tar file; upload
Send announcement to mailing list and c.o.l.a.
Make freshmeat announcement
Update web site
-- --
Add machines to build farm
Cygwin (on different versions of Win32?)
HP-UX variants (via HP?)
SCO
-- --
PERFORMANCE ----------------------------------------------------------
File list structure in memory
@@ -698,14 +504,10 @@ Allow skipping MD4 file_sum 2002/04/08
calculating MD4 checksums uses 90% of CPU and is unlikely to be
useful.
Indeed for transfers over zlib or ssh we can also rely on the
transport to have quite strong protection against corruption.
Perhaps we should have an option to disable this,
analogous to --whole-file, although it would default to
disabled. The file checksum takes up a definite space in
the protocol -- we can either set it to 0, or perhaps just
leave it out.
We should not allow it to be disabled separately from -W, though
as it is the only thing that lets us know when the rsync algorithm
got out of sync and messed the file up (i.e. if the basis file
changed between checksum generation and reception).
-- --
@@ -848,5 +650,9 @@ reverse rsync over HTTP Range
Goswin Brederlow suggested this on Debian; I think tridge and I
talked about it previous in relation to rproxy.
Addendum: It looks like someone is working on a version of this:
http://zsync.moria.org.uk/
-- --

View File

@@ -26,7 +26,8 @@
static int match_hostname(char *host, char *tok)
{
if (!host || !*host) return 0;
if (!host || !*host)
return 0;
return wildmatch(tok, host);
}
@@ -34,16 +35,16 @@ static int match_binary(char *b1, char *b2, char *mask, int addrlen)
{
int i;
for (i=0; i<addrlen; i++) {
if ((b1[i]^b2[i])&mask[i]) {
for (i = 0; i < addrlen; i++) {
if ((b1[i] ^ b2[i]) & mask[i])
return 0;
}
}
return 1;
}
static void make_mask(char *mask, int plen, int addrlen) {
static void make_mask(char *mask, int plen, int addrlen)
{
int w, b;
w = plen >> 3;
@@ -75,22 +76,26 @@ static int match_address(char *addr, char *tok)
char *a = NULL, *t = NULL;
unsigned int len;
if (!addr || !*addr) return 0;
if (!addr || !*addr)
return 0;
p = strchr(tok,'/');
if (p) {
*p = '\0';
len = p - tok;
}
else
} else
len = strlen(tok);
/* Fail quietly if tok is a hostname (not an address) */
if (strspn(tok, ".0123456789") != len
#ifdef INET6
&& !strchr(tok, ':')
&& strchr(tok, ':') == NULL
#endif
) return 0;
) {
if (p)
*p = '/';
return 0;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
@@ -99,17 +104,18 @@ static int match_address(char *addr, char *tok)
hints.ai_flags = AI_NUMERICHOST;
#endif
gai = getaddrinfo(addr, NULL, &hints, &resa);
if (gai) return 0;
if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
if (p)
*p = '/';
return 0;
}
gai = getaddrinfo(tok, NULL, &hints, &rest);
if (p)
*p++ = '/';
if (gai) {
rprintf(FERROR,
"error matching address %s: %s\n",
tok,
gai_strerror(gai));
if (gai != 0) {
rprintf(FLOG, "error matching address %s: %s\n",
tok, gai_strerror(gai));
freeaddrinfo(resa);
return 0;
}
@@ -152,7 +158,7 @@ static int match_address(char *addr, char *tok)
}
#endif
default:
rprintf(FERROR,"unknown family %u\n", rest->ai_family);
rprintf(FLOG, "unknown family %u\n", rest->ai_family);
ret = 0;
goto out;
}
@@ -169,14 +175,14 @@ static int match_address(char *addr, char *tok)
#ifdef HAVE_STRTOL
bits = strtol(p, &ep, 10);
if (!*p || *ep) {
rprintf(FERROR,"malformed mask in %s\n", tok);
rprintf(FLOG, "malformed mask in %s\n", tok);
ret = 0;
goto out;
}
#else
for (pp = (unsigned char *)p; *pp; pp++) {
if (!isascii(*pp) || !isdigit(*pp)) {
rprintf(FERROR,"malformed mask in %s\n", tok);
rprintf(FLOG, "malformed mask in %s\n", tok);
ret = 0;
goto out;
}
@@ -188,7 +194,7 @@ static int match_address(char *addr, char *tok)
goto out;
}
if (bits < 0 || bits > (addrlen << 3)) {
rprintf(FERROR,"malformed mask in %s\n", tok);
rprintf(FLOG, "malformed mask in %s\n", tok);
ret = 0;
goto out;
}
@@ -213,12 +219,14 @@ static int access_match(char *list, char *addr, char *host)
char *tok;
char *list2 = strdup(list);
if (!list2) out_of_memory("access_match");
if (!list2)
out_of_memory("access_match");
strlower(list2);
if (host) strlower(host);
if (host)
strlower(host);
for (tok=strtok(list2," ,\t"); tok; tok=strtok(NULL," ,\t")) {
for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
if (match_hostname(host, tok) || match_address(addr, tok)) {
free(list2);
return 1;
@@ -231,29 +239,25 @@ static int access_match(char *list, char *addr, char *host)
int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
{
/* if theres no deny list and no allow list then allow access */
if ((!deny_list || !*deny_list) && (!allow_list || !*allow_list))
return 1;
if (allow_list && !*allow_list)
allow_list = NULL;
if (deny_list && !*deny_list)
deny_list = NULL;
/* if there is an allow list but no deny list then allow only hosts
on the allow list */
if (!deny_list || !*deny_list)
return(access_match(allow_list, addr, host));
/* If we match an allow-list item, we always allow access. */
if (allow_list) {
if (access_match(allow_list, addr, host))
return 1;
/* For an allow-list w/o a deny-list, disallow non-matches. */
if (!deny_list)
return 0;
}
/* if theres a deny list but no allow list then allow
all hosts not on the deny list */
if (!allow_list || !*allow_list)
return(!access_match(deny_list,addr,host));
/* if there are both type of list then allow all hosts on the
allow list */
if (access_match(allow_list,addr,host))
return 1;
/* if there are both type of list and it's not on the allow then
allow it if its not on the deny */
if (access_match(deny_list,addr,host))
/* If we match a deny-list item (and got past any allow-list
* items), we always disallow access. */
if (deny_list && access_match(deny_list, addr, host))
return 0;
/* Allow all other access. */
return 1;
}

View File

@@ -1,17 +1,17 @@
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2000 by Andrew Tridgell
Copyright (C) 1998-2000 by Andrew Tridgell
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -20,6 +20,9 @@
/* support rsync authentication */
#include "rsync.h"
extern char *password_file;
extern int am_root;
/***************************************************************************
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
@@ -48,13 +51,14 @@ 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));
memset(input, 0, sizeof input);
strlcpy((char *)input, addr, 17);
sys_gettimeofday(&tv);
@@ -62,217 +66,234 @@ static void gen_challenge(char *addr, char *challenge)
SIVAL(input, 20, tv.tv_usec);
SIVAL(input, 24, getpid());
sum_init();
sum_update(input, sizeof(input));
sum_end(challenge);
sum_init(0);
sum_update(input, sizeof input);
sum_end(md4_out);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge);
}
/* return the secret for a user from the sercret file. maximum length
is len. null terminate it */
/* Return the secret for a user from the secret file, null terminated.
* Maximum length is len (not counting the null). */
static int get_secret(int module, char *user, char *secret, int len)
{
char *fname = lp_secrets_file(module);
int fd, found=0;
char line[MAXPATHLEN];
char *p, *pass=NULL;
STRUCT_STAT st;
int ok = 1;
extern int am_root;
int fd, ok = 1;
char ch, *p;
if (!fname || !*fname) return 0;
if (!fname || !*fname)
return 0;
fd = open(fname,O_RDONLY);
if (fd == -1) return 0;
if ((fd = open(fname, O_RDONLY)) < 0)
return 0;
if (do_stat(fname, &st) == -1) {
rsyserr(FERROR, errno, "stat(%s)", fname);
rsyserr(FLOG, errno, "stat(%s)", safe_fname(fname));
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
rprintf(FERROR,"secrets file must not be other-accessible (see strict modes option)\n");
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
ok = 0;
} else if (am_root && (st.st_uid != 0)) {
rprintf(FERROR,"secrets file must be owned by root when running as root (see strict modes)\n");
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
ok = 0;
}
}
if (!ok) {
rprintf(FERROR,"continuing without secrets file\n");
rprintf(FLOG, "continuing without secrets file\n");
close(fd);
return 0;
}
while (!found) {
int i = 0;
memset(line, 0, sizeof line);
while ((size_t) i < (sizeof(line)-1)) {
if (read(fd, &line[i], 1) != 1) {
memset(line, 0, sizeof(line));
close(fd);
return 0;
}
if (line[i] == '\r') continue;
if (line[i] == '\n') break;
i++;
}
line[i] = 0;
if (line[0] == '#') continue;
p = strchr(line,':');
if (!p) continue;
*p = 0;
if (strcmp(user, line)) continue;
pass = p+1;
found = 1;
if (*user == '#') {
/* Reject attempt to match a comment. */
close(fd);
return 0;
}
close(fd);
if (!found) return 0;
/* Try to find a line that starts with the user name and a ':'. */
p = user;
while (1) {
if (read(fd, &ch, 1) != 1) {
close(fd);
return 0;
}
if (ch == '\n')
p = user;
else if (p) {
if (*p == ch)
p++;
else if (!*p && ch == ':')
break;
else
p = NULL;
}
}
/* Slurp the secret into the "secret" buffer. */
p = secret;
while (len > 0) {
if (read(fd, p, 1) != 1 || *p == '\n')
break;
if (*p == '\r')
continue;
p++;
len--;
}
*p = '\0';
close(fd);
strlcpy(secret, pass, len);
return 1;
}
static char *getpassf(char *filename)
{
char buffer[100];
int fd=0;
STRUCT_STAT st;
int ok = 1;
extern int am_root;
char *envpw=getenv("RSYNC_PASSWORD");
char buffer[512], *p;
int fd, n, ok = 1;
char *envpw = getenv("RSYNC_PASSWORD");
if (!filename) return NULL;
if (!filename)
return NULL;
if ( (fd=open(filename,O_RDONLY)) == -1) {
rsyserr(FERROR, errno, "could not open password file \"%s\"",filename);
if (envpw) rprintf(FERROR,"falling back to RSYNC_PASSWORD environment variable.\n");
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FERROR, errno, "could not open password file \"%s\"",
safe_fname(filename));
if (envpw)
rprintf(FERROR, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
if (do_stat(filename, &st) == -1) {
rsyserr(FERROR, errno, "stat(%s)", filename);
rsyserr(FERROR, errno, "stat(%s)", safe_fname(filename));
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FERROR,"password file must not be other-accessible\n");
ok = 0;
} else if (am_root && (st.st_uid != 0)) {
} else if (am_root && st.st_uid != 0) {
rprintf(FERROR,"password file must be owned by root when running as root\n");
ok = 0;
}
if (!ok) {
rprintf(FERROR,"continuing without password file\n");
if (envpw) rprintf(FERROR,"using RSYNC_PASSWORD environment variable.\n");
if (envpw)
rprintf(FERROR, "using RSYNC_PASSWORD environment variable.\n");
close(fd);
return NULL;
}
if (envpw) rprintf(FERROR,"RSYNC_PASSWORD environment variable ignored\n");
if (envpw)
rprintf(FERROR, "RSYNC_PASSWORD environment variable ignored\n");
buffer[sizeof(buffer)-1]='\0';
if (read(fd,buffer,sizeof(buffer)-1) > 0)
{
char *p = strtok(buffer,"\n\r");
close(fd);
if (p) p = strdup(p);
return p;
}
n = read(fd, buffer, sizeof buffer - 1);
close(fd);
if (n > 0) {
buffer[n] = '\0';
if ((p = strtok(buffer, "\n\r")) != NULL)
return strdup(p);
}
return NULL;
}
/* generate 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();
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);
}
/* possible negotiate authentication with the client. Use "leader" to
start off the auth if necessary
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)
/* Possibly negotiate authentication with the client. Use "leader" to
* start off the auth if necessary.
*
* Return NULL if authentication failed. Return "" if anonymous access.
* Otherwise return username.
*/
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) return "";
if (!users || !*users)
return "";
gen_challenge(addr, challenge);
base64_encode(challenge, 16, b64_challenge);
io_printf(f_out, "%s%s\n", leader, b64_challenge);
io_printf(f_out, "%s%s\n", leader, 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)) break;
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));
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 (strcmp(pass, pass2) == 0)
return user;
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;
}
return NULL;
generate_hash(secret, challenge, pass2);
memset(secret, 0, sizeof secret);
if (strcmp(pass, pass2) != 0) {
rprintf(FLOG, "auth failed on module %s from %s (%s): "
"password mismatch\n",
lp_name(module), host, addr);
return NULL;
}
return strdup(line);
}
void auth_client(int fd, char *user, char *challenge)
{
char *pass;
char pass2[30];
extern char *password_file;
char pass2[MD4_SUM_LENGTH*2];
if (!user || !*user)
user = "nobody";
if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
if (!(pass = getpassf(password_file))
&& !(pass = getenv("RSYNC_PASSWORD"))) {
/* XXX: cyeoh says that getpass is deprecated, because
* it may return a truncated password on some systems,
* and it is not in the LSB.
@@ -285,12 +306,9 @@ void auth_client(int fd, char *user, char *challenge)
pass = getpass("Password: ");
}
if (!pass || !*pass) {
if (!pass)
pass = "";
}
generate_hash(pass, challenge, pass2);
io_printf(fd, "%s %s\n", user, pass2);
}

158
backup.c
View File

@@ -33,27 +33,59 @@ extern int preserve_devices;
extern int preserve_links;
extern int preserve_hard_links;
extern int orig_umask;
extern int safe_symlinks;
/* make a complete pathname for backup file */
char *get_backup_name(char *fname)
{
if (backup_dir) {
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
fname, backup_suffix, NULL) < backup_dir_remainder)
return backup_dir_buf;
} else {
if (stringjoin(backup_dir_buf, MAXPATHLEN,
fname, backup_suffix, NULL) < MAXPATHLEN)
return backup_dir_buf;
}
rprintf(FERROR, "backup filename too long\n");
return NULL;
}
/* simple backup creates a backup with a suffix in the same directory */
static int make_simple_backup(char *fname)
{
char fnamebak[MAXPATHLEN];
int rename_errno;
char *fnamebak = get_backup_name(fname);
if (stringjoin(fnamebak, sizeof fnamebak, fname, backup_suffix, NULL)
>= sizeof fnamebak) {
rprintf(FERROR, "backup filename too long\n");
if (!fnamebak)
return 0;
while (1) {
if (do_rename(fname, fnamebak) == 0) {
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
safe_fname(fname),
safe_fname(fnamebak));
}
break;
}
/* cygwin (at least version b19) reports EINVAL */
if (errno == ENOENT || errno == EINVAL)
break;
rename_errno = errno;
if (errno == EISDIR && do_rmdir(fnamebak) == 0)
continue;
if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
continue;
rsyserr(FERROR, rename_errno, "rename %s to backup %s",
safe_fname(fname), safe_fname(fnamebak));
errno = rename_errno;
return 0;
}
if (do_rename(fname, fnamebak) != 0) {
/* cygwin (at least version b19) reports EINVAL */
if (errno != ENOENT && errno != EINVAL) {
rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
return 0;
}
} else if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n", fname, fnamebak);
}
return 1;
}
@@ -83,9 +115,9 @@ static int make_bak_dir(char *fullpath)
if (do_mkdir(fullpath, 0777 & ~orig_umask) == 0)
break;
if (errno != ENOENT) {
rprintf(FERROR,
"make_bak_dir mkdir %s failed: %s\n",
full_fname(fullpath), strerror(errno));
rsyserr(FERROR, errno,
"make_bak_dir mkdir %s failed",
full_fname(fullpath));
goto failure;
}
}
@@ -96,12 +128,11 @@ static int make_bak_dir(char *fullpath)
if (p >= rel) {
/* Try to transfer the directory settings of the
* actual dir that the files are coming from. */
if (do_lstat(rel, &st) != 0) {
rprintf(FERROR,
"make_bak_dir stat %s failed: %s\n",
full_fname(rel), strerror(errno));
if (do_stat(rel, &st) < 0) {
rsyserr(FERROR, errno,
"make_bak_dir stat %s failed",
full_fname(rel));
} else {
set_modtime(fullpath, st.st_mtime);
do_lchown(fullpath, st.st_uid, st.st_gid);
do_chmod(fullpath, st.st_mode);
}
@@ -111,9 +142,8 @@ static int make_bak_dir(char *fullpath)
if (p == end)
break;
if (do_mkdir(fullpath, 0777 & ~orig_umask) < 0) {
rprintf(FERROR,
"make_bak_dir mkdir %s failed: %s\n",
full_fname(fullpath), strerror(errno));
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
full_fname(fullpath));
goto failure;
}
}
@@ -143,53 +173,48 @@ static int keep_backup(char *fname)
{
STRUCT_STAT st;
struct file_struct *file;
char *buf;
int kept = 0;
int ret_code;
/* return if no file to keep */
#if SUPPORT_LINKS
if (do_lstat(fname, &st)) return 1;
#else
if (do_stat(fname, &st)) return 1;
#endif
if (do_lstat(fname, &st) < 0)
return 1;
file = make_file(fname, NULL, NO_EXCLUDES);
if (!(file = make_file(fname, NULL, NO_FILTERS)))
return 1; /* the file could have disappeared */
/* the file could have disappeared */
if (!file) return 1;
/* make a complete pathname for backup file */
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
fname, backup_suffix, NULL) >= backup_dir_remainder) {
rprintf(FERROR, "keep_backup filename too long\n");
if (!(buf = get_backup_name(fname)))
return 0;
}
#ifdef HAVE_MKNOD
/* Check to see if this is a device file, or link */
if (IS_DEVICE(file->mode)) {
if (am_root && preserve_devices) {
make_bak_dir(backup_dir_buf);
if (do_mknod(backup_dir_buf, file->mode, file->u.rdev) != 0) {
rprintf(FERROR, "mknod %s failed: %s\n",
full_fname(backup_dir_buf), strerror(errno));
if (do_mknod(buf, file->mode, file->u.rdev) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mknod(buf, file->mode, file->u.rdev) < 0)) {
rsyserr(FERROR, errno, "mknod %s failed",
full_fname(buf));
} else if (verbose > 2) {
rprintf(FINFO,
"make_backup: DEVICE %s successful.\n",
fname);
safe_fname(fname));
}
}
kept = 1;
do_unlink(fname);
}
#endif
if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */
make_bak_dir(backup_dir_buf);
do_mkdir(backup_dir_buf, file->mode);
ret_code = do_rmdir(fname);
if (do_mkdir(buf, file->mode) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mkdir(buf, file->mode) < 0)) {
rsyserr(FINFO, errno, "mkdir %s failed",
full_fname(buf));
}
ret_code = do_rmdir(fname);
if (verbose > 2) {
rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
full_fname(fname), ret_code);
@@ -197,20 +222,20 @@ static int keep_backup(char *fname)
kept = 1;
}
#if SUPPORT_LINKS
#ifdef SUPPORT_LINKS
if (!kept && preserve_links && S_ISLNK(file->mode)) {
extern int safe_symlinks;
if (safe_symlinks && unsafe_symlink(file->u.link, backup_dir_buf)) {
if (safe_symlinks && unsafe_symlink(file->u.link, buf)) {
if (verbose) {
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
full_fname(backup_dir_buf), file->u.link);
full_fname(buf), file->u.link);
}
kept = 1;
}
make_bak_dir(backup_dir_buf);
if (do_symlink(file->u.link, backup_dir_buf) != 0) {
rprintf(FERROR, "link %s -> %s : %s\n",
full_fname(backup_dir_buf), file->u.link, strerror(errno));
if (do_symlink(file->u.link, buf) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_symlink(file->u.link, buf) < 0)) {
rsyserr(FERROR, errno, "link %s -> \"%s\"",
full_fname(buf), safe_fname(file->u.link));
}
do_unlink(fname);
kept = 1;
@@ -219,21 +244,28 @@ static int keep_backup(char *fname)
if (!kept && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
fname);
safe_fname(fname));
return 1;
}
/* move to keep tree if a file */
if (!kept) {
if (robust_move(fname, backup_dir_buf) != 0) {
rprintf(FERROR, "keep_backup failed: %s -> \"%s\": %s\n",
full_fname(fname), backup_dir_buf, strerror(errno));
if (robust_move(fname, buf) != 0) {
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
full_fname(fname), safe_fname(buf));
} else if (st.st_nlink > 1) {
/* If someone has hard-linked the file into the backup
* dir, rename() might return success but do nothing! */
robust_unlink(fname); /* Just in case... */
}
}
set_perms(backup_dir_buf, file, NULL, 0);
set_perms(buf, file, NULL, 0);
free(file);
if (verbose > 1)
rprintf(FINFO, "keep_backup %s -> %s\n", fname, backup_dir_buf);
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
safe_fname(fname), safe_fname(buf));
}
return 1;
}

496
batch.c
View File

@@ -8,329 +8,195 @@
#include "rsync.h"
#include <time.h>
extern char *batch_prefix;
extern int csum_length;
extern int am_sender;
extern int eol_nulls;
extern int recurse;
extern int xfer_dirs;
extern int preserve_links;
extern int preserve_hard_links;
extern int preserve_devices;
extern int preserve_uid;
extern int preserve_gid;
extern int always_checksum;
extern int do_compression;
extern int protocol_version;
extern struct stats stats;
extern char *batch_name;
struct file_list *batch_flist;
extern struct filter_list_struct filter_list;
static char rsync_flist_file[] = ".rsync_flist";
static char rsync_csums_file[] = ".rsync_csums";
static char rsync_delta_file[] = ".rsync_delta";
static char rsync_argvs_file[] = ".rsync_argvs";
static int *flag_ptr[] = {
&recurse, /* 0 */
&preserve_uid, /* 1 */
&preserve_gid, /* 2 */
&preserve_links, /* 3 */
&preserve_devices, /* 4 */
&preserve_hard_links, /* 5 */
&always_checksum, /* 6 */
&xfer_dirs, /* 7 (protocol 29) */
&do_compression, /* 8 (protocol 29) */
NULL
};
static int f_csums = -1;
static int f_delta = -1;
static char *flag_name[] = {
"--recurse (-r)",
"--owner (-o)",
"--group (-g)",
"--links (-l)",
"--devices (-D)",
"--hard-links (-H)",
"--checksum (-c)",
"--dirs (-d)",
"--compress (-z)",
NULL
};
void write_batch_flist_info(int flist_count, struct file_struct **files)
void write_stream_flags(int fd)
{
char filename[MAXPATHLEN];
int i, f, save_pv;
int64 save_written;
int i, flags;
stringjoin(filename, sizeof filename,
batch_prefix, rsync_flist_file, NULL);
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (f < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
exit_cleanup(1);
/* Start the batch file with a bitmap of data-stream-affecting
* flags. */
if (protocol_version < 29)
flag_ptr[7] = NULL;
for (i = 0, flags = 0; flag_ptr[i]; i++) {
if (*flag_ptr[i])
flags |= 1 << i;
}
save_written = stats.total_written;
save_pv = protocol_version;
protocol_version = PROTOCOL_VERSION;
write_int(f, protocol_version);
write_int(f, flist_count);
for (i = 0; i < flist_count; i++) {
send_file_entry(files[i], f,
files[i]->flags & FLAG_TOP_DIR ? XMIT_TOP_DIR : 0);
}
send_file_entry(NULL, f, 0);
protocol_version = save_pv;
stats.total_written = save_written;
close(f);
write_int(fd, flags);
}
void write_batch_argvs_file(int argc, char *argv[])
void read_stream_flags(int fd)
{
int f;
int i;
char buff[256]; /* XXX */
char buff2[MAXPATHLEN + 6];
char filename[MAXPATHLEN];
int i, flags;
if (protocol_version < 29)
flag_ptr[7] = NULL;
for (i = 0, flags = read_int(fd); flag_ptr[i]; i++) {
int set = flags & (1 << i) ? 1 : 0;
if (*flag_ptr[i] != set) {
if (verbose) {
rprintf(FINFO,
"%sing the %s option to match the batchfile.\n",
set ? "Sett" : "Clear", flag_name[i]);
}
*flag_ptr[i] = set;
}
}
if (protocol_version < 29) {
if (recurse)
xfer_dirs |= 1;
else if (xfer_dirs < 2)
xfer_dirs = 0;
}
}
static void write_arg(int fd, char *arg)
{
char *x, *s;
if (*arg == '-' && (x = strchr(arg, '=')) != NULL) {
write(fd, arg, x - arg + 1);
arg += x - arg + 1;
}
if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) {
write(fd, "'", 1);
for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) {
write(fd, s, x - s + 1);
write(fd, "'", 1);
}
write(fd, s, strlen(s));
write(fd, "'", 1);
return;
}
write(fd, arg, strlen(arg));
}
static void write_filter_rules(int fd)
{
struct filter_struct *ent;
write_sbuf(fd, " <<'#E#'\n");
for (ent = filter_list.head; ent; ent = ent->next) {
unsigned int plen;
char *p = get_rule_prefix(ent->match_flags, "- ", 0, &plen);
write_buf(fd, p, plen);
write_sbuf(fd, ent->pattern);
if (ent->match_flags & MATCHFLG_DIRECTORY)
write_byte(fd, '/');
write_byte(fd, eol_nulls ? 0 : '\n');
}
if (eol_nulls)
write_sbuf(fd, ";\n");
write_sbuf(fd, "#E#");
}
/* This routine tries to write out an equivalent --read-batch command
* given the user's --write-batch args. However, it doesn't really
* understand most of the options, so it uses some overly simple
* heuristics to munge the command line into something that will
* (hopefully) work. */
void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
{
int fd, i, len;
char *p, filename[MAXPATHLEN];
stringjoin(filename, sizeof filename,
batch_prefix, rsync_argvs_file, NULL);
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IEXEC);
if (f < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
batch_name, ".sh", NULL);
fd = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IEXEC);
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
safe_fname(filename));
exit_cleanup(1);
}
buff[0] = '\0';
/* Write argvs info to batch file */
for (i = 0; i < argc; ++i) {
if (i == argc - 2) /* Skip source directory on cmdline */
/* Write argvs info to BATCH.sh file */
write_arg(fd, argv[0]);
if (filter_list.head) {
if (protocol_version >= 29)
write_sbuf(fd, " --filter=._-");
else
write_sbuf(fd, " --exclude-from=-");
}
for (i = 1; i < argc - file_arg_cnt; i++) {
p = argv[i];
if (strncmp(p, "--files-from", 12) == 0
|| strncmp(p, "--filter", 8) == 0
|| strncmp(p, "--include", 9) == 0
|| strncmp(p, "--exclude", 9) == 0) {
if (strchr(p, '=') == NULL)
i++;
continue;
/*
* FIXME:
* I think directly manipulating argv[] is probably bogus
*/
if (!strncmp(argv[i], "--write-batch",
strlen("--write-batch"))) {
/* Safer to change it here than script */
/*
* Change to --read-batch=prefix
* to get ready for remote
*/
strlcat(buff, "--read-batch=", sizeof buff);
strlcat(buff, batch_prefix, sizeof buff);
}
if (strcmp(p, "-f") == 0) {
i++;
continue;
}
write(fd, " ", 1);
if (strncmp(p, "--write-batch", len = 13) == 0
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
write(fd, "--read-batch", 12);
if (p[len] == '=') {
write(fd, "=", 1);
write_arg(fd, p + len + 1);
}
} else
if (i == argc - 1) {
snprintf(buff2, sizeof buff2, "${1:-%s}", argv[i]);
strlcat(buff, buff2, sizeof buff);
}
else {
strlcat(buff, argv[i], sizeof buff);
}
if (i < (argc - 1)) {
strlcat(buff, " ", sizeof buff);
}
write_arg(fd, p);
}
strlcat(buff, "\n", sizeof buff);
if (!write(f, buff, strlen(buff))) {
rprintf(FERROR, "Batch file %s write error: %s\n",
filename, strerror(errno));
close(f);
if (!(p = check_for_hostspec(argv[argc - 1], &p, &i)))
p = argv[argc - 1];
write(fd, " ${1:-", 6);
write_arg(fd, p);
write_byte(fd, '}');
if (filter_list.head)
write_filter_rules(fd);
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
rsyserr(FERROR, errno, "Batch file %s write error",
safe_fname(filename));
exit_cleanup(1);
}
close(f);
}
struct file_list *create_flist_from_batch(void)
{
char filename[MAXPATHLEN];
unsigned short flags;
int i, f, save_pv;
int64 save_read;
stringjoin(filename, sizeof filename,
batch_prefix, rsync_flist_file, NULL);
f = do_open(filename, O_RDONLY, 0);
if (f < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
exit_cleanup(1);
}
batch_flist = flist_new(WITH_HLINK, "create_flist_from_batch");
save_read = stats.total_read;
save_pv = protocol_version;
protocol_version = read_int(f);
batch_flist->count = read_int(f);
flist_expand(batch_flist);
for (i = 0; (flags = read_byte(f)) != 0; i++) {
if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS))
flags |= read_byte(f) << 8;
receive_file_entry(&batch_flist->files[i], flags, batch_flist, f);
}
receive_file_entry(NULL, 0, NULL, 0); /* Signal that we're done. */
protocol_version = save_pv;
stats.total_read = save_read;
return batch_flist;
}
void write_batch_csums_file(void *buff, int bytes_to_write)
{
if (write(f_csums, buff, bytes_to_write) < 0) {
rprintf(FERROR, "Batch file write error: %s\n",
strerror(errno));
close(f_csums);
exit_cleanup(1);
}
}
void close_batch_csums_file(void)
{
close(f_csums);
f_csums = -1;
}
/**
* Write csum info to batch file
*
* @todo This will break if s->count is ever larger than maxint. The
* batch code should probably be changed to consistently use the
* variable-length integer routines, which is probably a compatible
* change.
**/
void write_batch_csum_info(int *flist_entry, struct sum_struct *s)
{
size_t i;
int int_count;
char filename[MAXPATHLEN];
if (f_csums < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_csums_file, NULL);
f_csums = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR);
if (f_csums < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(f_csums);
exit_cleanup(1);
}
}
write_batch_csums_file(flist_entry, sizeof (int));
int_count = s ? (int) s->count : 0;
write_batch_csums_file(&int_count, sizeof int_count);
if (s) {
for (i = 0; i < s->count; i++) {
write_batch_csums_file(&s->sums[i].sum1,
sizeof (uint32));
write_batch_csums_file(s->sums[i].sum2, csum_length);
}
}
}
int read_batch_csums_file(char *buff, int len)
{
int bytes_read;
if ((bytes_read = read(f_csums, buff, len)) < 0) {
rprintf(FERROR, "Batch file read error: %s\n", strerror(errno));
close(f_csums);
exit_cleanup(1);
}
return bytes_read;
}
void read_batch_csum_info(int flist_entry, struct sum_struct *s,
int *checksums_match)
{
int i;
int file_flist_entry;
int file_chunk_ct;
uint32 file_sum1;
char file_sum2[SUM_LENGTH];
char filename[MAXPATHLEN];
if (f_csums < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_csums_file, NULL);
f_csums = do_open(filename, O_RDONLY, 0);
if (f_csums < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(f_csums);
exit_cleanup(1);
}
}
read_batch_csums_file((char *) &file_flist_entry, sizeof (int));
if (file_flist_entry != flist_entry) {
rprintf(FINFO, "file_flist_entry (%d) != flist_entry (%d)\n",
file_flist_entry, flist_entry);
close(f_csums);
exit_cleanup(1);
} else {
read_batch_csums_file((char *) &file_chunk_ct, sizeof (int));
*checksums_match = 1;
for (i = 0; i < file_chunk_ct; i++) {
read_batch_csums_file((char *) &file_sum1,
sizeof (uint32));
read_batch_csums_file(file_sum2, csum_length);
if ((s->sums[i].sum1 != file_sum1)
|| memcmp(s->sums[i].sum2, file_sum2, csum_length))
*checksums_match = 0;
} /* end for */
}
}
void write_batch_delta_file(char *buff, int bytes_to_write)
{
char filename[MAXPATHLEN];
if (f_delta < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_delta_file, NULL);
f_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR);
if (f_delta < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
exit_cleanup(1);
}
}
if (write(f_delta, buff, bytes_to_write) < 0) {
rprintf(FERROR, "Batch file %s write error: %s\n",
filename, strerror(errno));
close(f_delta);
exit_cleanup(1);
}
}
void close_batch_delta_file(void)
{
close(f_delta);
f_delta = -1;
}
int read_batch_delta_file(char *buff, int len)
{
int bytes_read;
char filename[MAXPATHLEN];
if (f_delta < 0) {
stringjoin(filename, sizeof filename,
batch_prefix, rsync_delta_file, NULL);
f_delta = do_open(filename, O_RDONLY, 0);
if (f_delta < 0) {
rprintf(FERROR, "Batch file %s open error: %s\n",
filename, strerror(errno));
close(f_delta);
exit_cleanup(1);
}
}
bytes_read = read(f_delta, buff, len);
if (bytes_read < 0) {
rprintf(FERROR, "Batch file %s read error: %s\n",
filename, strerror(errno));
close(f_delta);
exit_cleanup(1);
}
return bytes_read;
}
void show_flist(int index, struct file_struct **fptr)
@@ -345,25 +211,25 @@ void show_flist(int index, struct file_struct **fptr)
rprintf(FINFO, "flist->length=%.0f\n",
(double) fptr[i]->length);
rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
rprintf(FINFO, "flist->basename=%s\n", fptr[i]->basename);
if (fptr[i]->dirname)
rprintf(FINFO, "flist->basename=%s\n",
safe_fname(fptr[i]->basename));
if (fptr[i]->dirname) {
rprintf(FINFO, "flist->dirname=%s\n",
fptr[i]->dirname);
if (fptr[i]->basedir)
rprintf(FINFO, "flist->basedir=%s\n",
fptr[i]->basedir);
safe_fname(fptr[i]->dirname));
}
if (am_sender && fptr[i]->dir.root) {
rprintf(FINFO, "flist->dir.root=%s\n",
safe_fname(fptr[i]->dir.root));
}
}
}
/* for debugging */
void show_argvs(int argc, char *argv[])
{
/* for debugging * */
int i;
rprintf(FINFO, "BATCH.C:show_argvs,argc=%d\n", argc);
for (i = 0; i < argc; i++) {
/* if (argv[i]) */
rprintf(FINFO, "i=%d,argv[i]=%s\n", i, argv[i]);
}
rprintf(FINFO, "BATCH.C:show_argvs,argc=%d\n", argc);
for (i = 0; i < argc; i++)
rprintf(FINFO, "i=%d,argv[i]=%s\n", i, safe_fname(argv[i]));
}

View File

@@ -1,17 +1,17 @@
/*
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -30,17 +30,17 @@ extern int protocol_version;
a simple 32 bit checksum that can be upadted from either end
(inspired by Mark Adler's Adler-32 checksum)
*/
uint32 get_checksum1(char *buf1,int len)
uint32 get_checksum1(char *buf1, int32 len)
{
int i;
int32 i;
uint32 s1, s2;
schar *buf = (schar *)buf1;
s1 = s2 = 0;
for (i = 0; i < (len-4); i+=4) {
s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3] +
10*CHAR_OFFSET;
s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
s1 += (buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3] + 4*CHAR_OFFSET);
}
for (; i < len; i++) {
s1 += (buf[i]+CHAR_OFFSET); s2 += s1;
@@ -49,28 +49,30 @@ uint32 get_checksum1(char *buf1,int len)
}
void get_checksum2(char *buf,int len,char *sum)
void get_checksum2(char *buf, int32 len, char *sum)
{
int i;
int32 i;
static char *buf1;
static int len1;
static int32 len1;
struct mdfour m;
if (len > len1) {
if (buf1) free(buf1);
if (buf1)
free(buf1);
buf1 = new_array(char, len+4);
len1 = len;
if (!buf1) out_of_memory("get_checksum2");
if (!buf1)
out_of_memory("get_checksum2");
}
mdfour_begin(&m);
memcpy(buf1,buf,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
}
@@ -83,7 +85,7 @@ void get_checksum2(char *buf,int len,char *sum)
if (len - i > 0 || protocol_version >= 27) {
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
}
mdfour_result(&m, (uchar *)sum);
}
@@ -94,35 +96,29 @@ void file_checksum(char *fname,char *sum,OFF_T size)
struct map_struct *buf;
int fd;
OFF_T len = size;
char tmpchunk[CSUM_CHUNK];
struct mdfour m;
memset(sum,0,MD4_SUM_LENGTH);
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1) return;
buf = map_file(fd,size);
if (fd == -1)
return;
buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
mdfour_begin(&m);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
mdfour_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
CSUM_CHUNK);
}
/*
* Prior to version 27 an incorrect MD4 checksum was computed
/* Prior to version 27 an incorrect MD4 checksum was computed
* by failing to call mdfour_tail() for block sizes that
* are multiples of 64. This is fixed by calling mdfour_update()
* even when there are no more bytes.
*/
if (len - i > 0) {
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
}
if (len - i > 0 || protocol_version >= 27) {
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
}
* even when there are no more bytes. */
if (len - i > 0 || protocol_version >= 27)
mdfour_update(&m, (uchar *)map_ptr(buf, i, len-i), len-i);
mdfour_result(&m, (uchar *)sum);
@@ -131,17 +127,17 @@ void file_checksum(char *fname,char *sum,OFF_T size)
}
static int sumresidue;
static int32 sumresidue;
static char sumrbuf[CSUM_CHUNK];
static struct mdfour md;
void sum_init(void)
void sum_init(int seed)
{
char s[4];
mdfour_begin(&md);
sumresidue=0;
SIVAL(s,0,checksum_seed);
sum_update(s,4);
sumresidue = 0;
SIVAL(s, 0, seed);
sum_update(s, 4);
}
/**
@@ -152,41 +148,37 @@ void sum_init(void)
* @todo Perhaps get rid of md and just pass in the address each time.
* Very slightly clearer and slower.
**/
void sum_update(char *p, int len)
void sum_update(char *p, int32 len)
{
int i;
if (len + sumresidue < CSUM_CHUNK) {
memcpy(sumrbuf+sumresidue, p, len);
memcpy(sumrbuf + sumresidue, p, len);
sumresidue += len;
return;
}
if (sumresidue) {
i = MIN(CSUM_CHUNK-sumresidue,len);
memcpy(sumrbuf+sumresidue,p,i);
mdfour_update(&md, (uchar *)sumrbuf, (i+sumresidue));
int32 i = CSUM_CHUNK - sumresidue;
memcpy(sumrbuf + sumresidue, p, i);
mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
len -= i;
p += i;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(sumrbuf,p+i,CSUM_CHUNK);
mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
while (len >= CSUM_CHUNK) {
mdfour_update(&md, (uchar *)p, CSUM_CHUNK);
len -= CSUM_CHUNK;
p += CSUM_CHUNK;
}
if (len - i > 0) {
sumresidue = len-i;
memcpy(sumrbuf,p+i,sumresidue);
} else {
sumresidue = 0;
}
sumresidue = len;
if (sumresidue)
memcpy(sumrbuf, p, sumresidue);
}
void sum_end(char *sum)
{
if (sumresidue || protocol_version >= 27) {
if (sumresidue || protocol_version >= 27)
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
}
mdfour_result(&md, (uchar *)sum);
}

View File

@@ -1,19 +1,19 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -21,6 +21,11 @@
#include "rsync.h"
extern int io_error;
extern int keep_partial;
extern int log_got_error;
extern char *partial_dir;
/**
* Close all open sockets and files, allowing a (somewhat) graceful
* shutdown() of socket connections. This eliminates the abortive
@@ -32,15 +37,13 @@ void close_all(void)
int max_fd;
int fd;
int ret;
struct stat st;
STRUCT_STAT st;
max_fd = sysconf(_SC_OPEN_MAX) - 1;
for (fd = max_fd; fd >= 0; fd--) {
ret = fstat(fd,&st);
if (fstat(fd,&st) == 0) {
if (is_a_socket(fd)) {
if ((ret = do_fstat(fd, &st)) == 0) {
if (is_a_socket(fd))
ret = shutdown(fd, 2);
}
ret = close(fd);
}
}
@@ -65,15 +68,13 @@ void close_all(void)
* --partial is selected. We need to ensure that the partial file is
* kept if any real data has been transferred.
**/
int cleanup_got_literal=0;
int cleanup_got_literal = 0;
static char *cleanup_fname;
static char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd1, cleanup_fd2;
static struct map_struct *cleanup_buf;
static int cleanup_fd_r, cleanup_fd_w;
static pid_t cleanup_pid = 0;
extern int io_error;
pid_t cleanup_child_pid = -1;
@@ -85,8 +86,6 @@ pid_t cleanup_child_pid = -1;
void _exit_cleanup(int code, const char *file, int line)
{
int ocode = code;
extern int keep_partial;
extern int log_got_error;
static int inside_cleanup = 0;
if (inside_cleanup > 10) {
@@ -98,51 +97,60 @@ void _exit_cleanup(int code, const char *file, int line)
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
if (verbose > 3)
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, file, line);
if (verbose > 3) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, safe_fname(file), line);
}
if (cleanup_child_pid != -1) {
int status;
if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code) code = status;
if (status > code)
code = status;
}
}
if (cleanup_got_literal && cleanup_fname && keep_partial) {
if (cleanup_got_literal && cleanup_fname && keep_partial
&& handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_buf) unmap_file(cleanup_buf);
if (cleanup_fd1 != -1) close(cleanup_fd1);
if (cleanup_fd2 != -1) close(cleanup_fd2);
finish_transfer(cleanup_new_fname, fname, cleanup_file);
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
}
finish_transfer(cleanup_new_fname, fname, cleanup_file, 0,
!partial_dir);
}
io_flush(FULL_FLUSH);
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code) {
if (code)
kill_all(SIGUSR1);
}
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf) {
if (pidf && *pidf)
unlink(lp_pid_file());
}
}
if (code == 0) {
if ((io_error & ~IOERR_VANISHED) || log_got_error)
code = RERR_PARTIAL;
else if (io_error)
if (io_error & IOERR_DEL_LIMIT)
code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
code = RERR_PARTIAL;
}
if (code) log_exit(code, file, line);
if (code)
log_exit(code, file, line);
if (verbose > 2)
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
ocode, file, line, code);
if (verbose > 2) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
ocode, safe_fname(file), line, code);
}
close_all();
exit(code);
@@ -156,14 +164,13 @@ void cleanup_disable(void)
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
struct map_struct *buf, int fd1, int fd2)
int fd_r, int fd_w)
{
cleanup_fname = fnametmp;
cleanup_new_fname = fname;
cleanup_file = file;
cleanup_buf = buf;
cleanup_fd1 = fd1;
cleanup_fd2 = fd2;
cleanup_fd_r = fd_r;
cleanup_fd_w = fd_w;
}
void cleanup_set_pid(pid_t pid)

View File

@@ -43,12 +43,11 @@ extern int am_server;
**/
char *client_addr(int fd)
{
struct sockaddr_storage ss;
socklen_t length = sizeof ss;
char *ssh_client, *p;
int len;
static char addr_buf[100];
static int initialised;
struct sockaddr_storage ss;
socklen_t length = sizeof ss;
char *ssh_info, *p;
if (initialised)
return addr_buf;
@@ -57,14 +56,13 @@ char *client_addr(int fd)
if (am_server) { /* daemon over --rsh mode */
strcpy(addr_buf, "0.0.0.0");
if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
/* truncate SSH_CLIENT to just IP address */
if ((p = strchr(ssh_client, ' ')) != NULL) {
len = MIN((unsigned int) (p - ssh_client),
sizeof addr_buf - 1);
strncpy(addr_buf, ssh_client, len);
*(addr_buf + len) = '\0';
}
if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
|| (ssh_info = getenv("SSH_CLIENT")) != NULL
|| (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
strlcpy(addr_buf, ssh_info, sizeof addr_buf);
/* Truncate the value to just the IP address. */
if ((p = strchr(addr_buf, ' ')) != NULL)
*p = '\0';
}
} else {
client_sockaddr(fd, &ss, &length);
@@ -124,7 +122,7 @@ char *client_name(int fd)
hint.ai_socktype = SOCK_STREAM;
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
rprintf(FLOG, "malformed address %s: %s\n",
addr, gai_strerror(err));
return name_buf;
}
@@ -147,8 +145,8 @@ char *client_name(int fd)
client_sockaddr(fd, &ss, &ss_len);
}
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
port_buf, sizeof port_buf))
if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
port_buf, sizeof port_buf) == 0)
check_name(fd, &ss, name_buf);
return name_buf;
@@ -170,8 +168,7 @@ void client_sockaddr(int fd,
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
/* FIXME: Can we really not continue? */
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
fd, strerror(errno));
rsyserr(FLOG, errno, "getpeername on fd%d failed", fd);
exit_cleanup(RERR_SOCKETIO);
}
@@ -192,7 +189,7 @@ void client_sockaddr(int fd,
memset(sin, 0, sizeof *sin);
sin->sin_family = AF_INET;
*ss_len = sizeof (struct sockaddr_in);
#if HAVE_SOCKADDR_IN_LEN
#ifdef HAVE_SOCKADDR_IN_LEN
sin->sin_len = *ss_len;
#endif
sin->sin_port = sin6.sin6_port;
@@ -226,9 +223,8 @@ int lookup_name(int fd, const struct sockaddr_storage *ss,
NI_NAMEREQD | NI_NUMERICSERV);
if (name_err != 0) {
strcpy(name_buf, default_name);
rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
client_addr(fd),
gai_strerror(name_err));
rprintf(FLOG, "name lookup failed for %s: %s\n",
client_addr(fd), gai_strerror(name_err));
return name_err;
}
@@ -249,8 +245,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
const char fn[] = "compare_addrinfo_sockaddr";
if (ai->ai_family != ss_family) {
rprintf(FERROR,
"%s: response family %d != %d\n",
rprintf(FLOG, "%s: response family %d != %d\n",
fn, ai->ai_family, ss_family);
return 1;
}
@@ -274,8 +269,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
rprintf(FERROR,
"%s: too short sockaddr_in6; length=%d\n",
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
fn, ai->ai_addrlen);
return 1;
}
@@ -321,8 +315,7 @@ int check_name(int fd,
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(name_buf, NULL, &hints, &res0);
if (error) {
rprintf(FERROR,
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
rprintf(FLOG, "forward name lookup for %s failed: %s\n",
name_buf, gai_strerror(error));
strcpy(name_buf, default_name);
return error;
@@ -339,23 +332,17 @@ int check_name(int fd,
if (!res0) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FERROR, RSYNC_NAME
": no known address for \"%s\": "
"spoofed address?\n",
name_buf);
rprintf(FLOG, "no known address for \"%s\": "
"spoofed address?\n", name_buf);
strcpy(name_buf, default_name);
} else if (res == NULL) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FERROR, RSYNC_NAME
": %s is not a known address for \"%s\": "
"spoofed address?\n",
client_addr(fd),
name_buf);
rprintf(FLOG, "%s is not a known address for \"%s\": "
"spoofed address?\n", client_addr(fd), name_buf);
strcpy(name_buf, default_name);
}
freeaddrinfo(res0);
return 0;
}

View File

@@ -27,17 +27,15 @@
#include "rsync.h"
extern int verbose;
extern int list_only;
extern int am_sender;
extern int am_server;
extern int am_daemon;
extern int am_root;
extern int module_id;
extern int read_only;
extern int verbose;
extern int rsync_port;
extern int kludge_around_eof;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int list_only;
extern int sanitize_paths;
extern int filesfrom_fd;
extern int remote_protocol;
@@ -47,11 +45,18 @@ extern int orig_umask;
extern int no_detach;
extern int default_af_hint;
extern char *bind_address;
extern struct exclude_list_struct server_exclude_list;
extern char *exclude_path_prefix;
extern struct filter_list_struct server_filter_list;
extern char *config_file;
extern char *files_from;
char *auth_user;
int read_only = 0;
int daemon_log_format_has_i = 0;
int daemon_log_format_has_o_or_i = 0;
int module_id = -1;
/* Length of lp_path() string when in daemon mode & not chrooted, else 0. */
unsigned int module_dirlen = 0;
/**
* Run a client connected to an rsyncd. The alternative to this
@@ -70,21 +75,21 @@ char *auth_user;
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
int fd, ret;
char *p, *user=NULL;
char *p, *user = NULL;
/* this is redundant with code in start_inband_exchange(), but
* this short-circuits a problem before we open a socket, and
* the extra check won't hurt */
/* This is redundant with code in start_inband_exchange(), but this
* short-circuits a problem in the client before we open a socket,
* and the extra check won't hurt. */
if (*path == '/') {
rprintf(FERROR,"ERROR: The remote path must start with a module name not a /\n");
rprintf(FERROR,
"ERROR: The remote path must start with a module name not a /\n");
return -1;
}
p = strchr(host, '@');
if (p) {
if ((p = strrchr(host, '@')) != NULL) {
user = host;
host = p+1;
*p = 0;
*p = '\0';
}
fd = open_socket_out_wrapped(host, rsync_port, bind_address,
@@ -94,10 +99,11 @@ 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, int argc)
int start_inband_exchange(char *user, char *path, int f_in, int f_out,
int argc)
{
int i;
char *sargs[MAX_ARGS];
@@ -106,15 +112,37 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
char *p;
if (argc == 0 && !am_sender)
list_only = 1;
list_only |= 1;
if (*path == '/') {
rprintf(FERROR, "ERROR: The remote path must start with a module name\n");
rprintf(FERROR,
"ERROR: The remote path must start with a module name\n");
return -1;
}
if (!user) user = getenv("USER");
if (!user) user = getenv("LOGNAME");
if (!user)
user = getenv("USER");
if (!user)
user = getenv("LOGNAME");
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
if (!read_line(f_in, line, sizeof line - 1)) {
rprintf(FERROR, "rsync: did not see server greeting\n");
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
/* note that read_line strips of \n or \r */
rprintf(FERROR, "rsync: server sent \"%s\" rather than greeting\n",
line);
return -1;
}
if (protocol_version > remote_protocol)
protocol_version = remote_protocol;
if (list_only && protocol_version >= 29)
list_only |= 2;
/* set daemon_over_rsh to false since we need to build the
* true set of args passed through the rsh/ssh connection;
@@ -129,21 +157,8 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
sargs[sargc] = NULL;
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
if (!read_line(f_in, line, sizeof(line)-1)) {
rprintf(FERROR, "rsync: did not see server greeting\n");
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
/* note that read_line strips of \n or \r */
rprintf(FERROR, "rsync: server sent \"%s\" rather than greeting\n",
line);
return -1;
}
if (protocol_version > remote_protocol)
protocol_version = remote_protocol;
if (verbose > 1)
print_child_argv(sargs);
p = strchr(path,'/');
if (p) *p = 0;
@@ -152,10 +167,10 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
/* Old servers may just drop the connection here,
rather than sending a proper EXIT command. Yuck. */
kludge_around_eof = list_only && (protocol_version < 25);
kluge_around_eof = list_only && protocol_version < 25 ? 1 : 0;
while (1) {
if (!read_line(f_in, line, sizeof(line)-1)) {
if (!read_line(f_in, line, sizeof line - 1)) {
rprintf(FERROR, "rsync: didn't get server startup line\n");
return -1;
}
@@ -165,7 +180,8 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
continue;
}
if (strcmp(line,"@RSYNCD: OK") == 0) break;
if (strcmp(line,"@RSYNCD: OK") == 0)
break;
if (strcmp(line,"@RSYNCD: EXIT") == 0) {
/* This is sent by recent versions of the
@@ -176,15 +192,15 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
}
if (strncmp(line, "@ERROR", 6) == 0) {
rprintf(FERROR,"%s\n", line);
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);
}
kludge_around_eof = False;
kluge_around_eof = 0;
for (i = 0; i < sargc; i++) {
io_printf(f_out, "%s\n", sargs[i]);
@@ -193,7 +209,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
if (protocol_version < 23) {
if (protocol_version == 22 || !am_sender)
io_start_multiplex_in(f_in);
io_start_multiplex_in();
}
return 0;
@@ -203,8 +219,9 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
static int rsync_module(int f_in, int f_out, int i)
{
int argc=0;
char *argv[MAX_ARGS];
int argc = 0;
int maxargs;
char **argv;
char **argp;
char line[MAXPATHLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
@@ -214,57 +231,69 @@ static int rsync_module(int f_in, int f_out, int i)
char *host = client_name(f_in);
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int start_glob=0;
int start_glob = 0;
int ret;
char *request=NULL;
char *request = NULL;
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
io_printf(f_out, "@ERROR: access denied to %s from %s (%s)\n",
name, host, addr);
if (!lp_list(i))
io_printf(f_out, "@ERROR: Unknown module '%s'\n", name);
else {
io_printf(f_out,
"@ERROR: access denied to %s from %s (%s)\n",
name, host, addr);
}
return -1;
}
if (am_daemon && am_server) {
rprintf(FINFO, "rsync allowed access on module %s from %s (%s)\n",
rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
name, host, addr);
}
if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
if (errno) {
rprintf(FERROR,"failed to open lock file %s : %s\n",
lp_lock_file(i), strerror(errno));
io_printf(f_out, "@ERROR: failed to open lock file %s : %s\n",
lp_lock_file(i), strerror(errno));
rsyserr(FLOG, errno, "failed to open lock file %s",
safe_fname(lp_lock_file(i)));
io_printf(f_out, "@ERROR: failed to open lock file\n");
} else {
rprintf(FERROR,"max connections (%d) reached\n",
rprintf(FLOG, "max connections (%d) reached\n",
lp_max_connections(i));
io_printf(f_out, "@ERROR: max connections (%d) reached - try again later\n",
io_printf(f_out, "@ERROR: max connections (%d) reached -- try again later\n",
lp_max_connections(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(FERROR,"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;
}
module_id = i;
if (lp_read_only(i))
read_only = 1;
if (lp_transfer_logging(i)) {
if (log_format_has(lp_log_format(i), 'i'))
daemon_log_format_has_i = 1;
if (daemon_log_format_has_i
|| log_format_has(lp_log_format(i), 'o'))
daemon_log_format_has_o_or_i = 1;
}
am_root = (MY_UID() == 0);
if (am_root) {
p = lp_uid(i);
if (!name_to_uid(p, &uid)) {
if (!isdigit(* (unsigned char *) p)) {
rprintf(FERROR,"Invalid uid %s\n", p);
if (!isdigit(*(unsigned char *)p)) {
rprintf(FLOG, "Invalid uid %s\n", p);
io_printf(f_out, "@ERROR: invalid uid %s\n", p);
return -1;
}
@@ -273,8 +302,8 @@ static int rsync_module(int f_in, int f_out, int i)
p = lp_gid(i);
if (!name_to_gid(p, &gid)) {
if (!isdigit(* (unsigned char *) p)) {
rprintf(FERROR,"Invalid gid %s\n", p);
if (!isdigit(*(unsigned char *)p)) {
rprintf(FLOG, "Invalid gid %s\n", p);
io_printf(f_out, "@ERROR: invalid gid %s\n", p);
return -1;
}
@@ -289,26 +318,32 @@ 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. */
exclude_path_prefix = use_chroot? "" : lp_path(i);
if (*exclude_path_prefix == '/' && !exclude_path_prefix[1])
exclude_path_prefix = "";
if (use_chroot || (module_dirlen = strlen(lp_path(i))) == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
set_filter_dir(lp_path(i), module_dirlen);
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ANCHORED2ABS);
p = lp_include_from(i);
add_exclude_file(&server_exclude_list, p,
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
add_exclude(&server_exclude_list, p,
XFLG_WORD_SPLIT | XFLG_DEF_INCLUDE);
parse_rule(&server_filter_list, p,
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
add_exclude_file(&server_exclude_list, p,
XFLG_FATAL_ERRORS);
parse_filter_file(&server_filter_list, p, 0,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
add_exclude(&server_exclude_list, p, XFLG_WORD_SPLIT);
exclude_path_prefix = NULL;
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);
log_init();
@@ -326,20 +361,23 @@ static int rsync_module(int f_in, int f_out, int i)
* in which case we fail.
*/
if (chroot(lp_path(i))) {
rsyserr(FERROR, errno, "chroot %s failed", lp_path(i));
rsyserr(FLOG, errno, "chroot %s failed",
safe_fname(lp_path(i)));
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/")) {
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
rsyserr(FLOG, errno, "chdir %s failed\n",
safe_fname(lp_path(i)));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i))) {
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
rsyserr(FLOG, errno, "chdir %s failed\n",
safe_fname(lp_path(i)));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
@@ -358,7 +396,7 @@ static int rsync_module(int f_in, int f_out, int i)
* all their supplementary groups. */
if (setgid(gid)) {
rsyserr(FERROR, errno, "setgid %d failed", (int) gid);
rsyserr(FLOG, errno, "setgid %d failed", (int)gid);
io_printf(f_out, "@ERROR: setgid failed\n");
return -1;
}
@@ -366,14 +404,14 @@ static int rsync_module(int f_in, int f_out, int i)
/* Get rid of any supplementary groups this process
* might have inheristed. */
if (setgroups(1, &gid)) {
rsyserr(FERROR, errno, "setgroups failed");
rsyserr(FLOG, errno, "setgroups failed");
io_printf(f_out, "@ERROR: setgroups failed\n");
return -1;
}
#endif
if (setuid(uid)) {
rsyserr(FERROR, errno, "setuid %d failed", (int) uid);
rsyserr(FLOG, errno, "setuid %d failed", (int)uid);
io_printf(f_out, "@ERROR: setuid failed\n");
return -1;
}
@@ -383,41 +421,42 @@ static int rsync_module(int f_in, int f_out, int i)
io_printf(f_out, "@RSYNCD: OK\n");
maxargs = MAX_ARGS;
if (!(argv = new_array(char *, maxargs)))
out_of_memory("rsync_module");
argv[argc++] = "rsyncd";
while (1) {
if (!read_line(f_in, line, sizeof(line)-1)) {
if (!read_line(f_in, line, sizeof line - 1))
return -1;
}
if (!*line) break;
if (!*line)
break;
p = line;
argv[argc] = strdup(p);
if (!argv[argc]) {
return -1;
if (argc == maxargs) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("rsync_module");
}
if (!(argv[argc] = strdup(p)))
out_of_memory("rsync_module");
if (start_glob) {
if (start_glob == 1) {
request = strdup(p);
start_glob++;
}
glob_expand(name, argv, &argc, MAX_ARGS);
} else {
glob_expand(name, &argv, &argc, &maxargs);
} else
argc++;
}
if (strcmp(line,".") == 0) {
if (strcmp(line, ".") == 0)
start_glob = 1;
}
if (argc == MAX_ARGS) {
return -1;
}
}
verbose = 0; /* future verbosity is controlled by client options */
argp = argv;
ret = parse_arguments(&argc, (const char ***) &argp, 0);
@@ -426,12 +465,12 @@ static int rsync_module(int f_in, int f_out, int i)
if (request) {
if (*auth_user) {
rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n",
am_sender?"on":"to",
rprintf(FLOG, "rsync %s %s from %s@%s (%s)\n",
am_sender ? "on" : "to",
request, auth_user, host, addr);
} else {
rprintf(FINFO,"rsync %s %s from %s (%s)\n",
am_sender?"on":"to",
rprintf(FLOG, "rsync %s %s from %s (%s)\n",
am_sender ? "on" : "to",
request, host, addr);
}
free(request);
@@ -443,27 +482,43 @@ static int rsync_module(int f_in, int f_out, int i)
verbose = lp_max_verbosity();
#endif
if (protocol_version < 23) {
if (protocol_version == 22 || am_sender)
io_start_multiplex_out(f_out);
if (protocol_version < 23
&& (protocol_version == 22 || am_sender))
io_start_multiplex_out();
else if (!ret) {
/* We have to get I/O multiplexing started so that we can
* get the error back to the client. This means getting
* the protocol setup finished first in later versions. */
setup_protocol(f_out, f_in);
if (!am_sender) {
/* Since we failed in our option parsing, we may not
* have finished parsing that the client sent us a
* --files-from option, so look for it manually.
* Without this, the socket would be in the wrong
* state for the upcoming error message. */
if (!files_from) {
int i;
for (i = 0; i < argc; i++) {
if (strncmp(argv[i], "--files-from", 12) == 0) {
files_from = "";
break;
}
}
}
if (files_from)
write_byte(f_out, 0);
}
io_start_multiplex_out();
}
/* For later protocol versions, we don't start multiplexing
* until we've configured nonblocking in start_server. That
* means we're in a sticky situation now: there's no way to
* convey errors to the client. */
/* FIXME: Hold off on reporting option processing errors until
* we've set up nonblocking and multiplexed IO and can get the
* message back to them. */
if (!ret) {
option_error();
msleep(400);
exit_cleanup(RERR_UNSUPPORTED);
}
if (lp_timeout(i)) {
io_timeout = lp_timeout(i);
}
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
set_io_timeout(lp_timeout(i));
start_server(f_in, f_out, argc, argp);
@@ -477,9 +532,10 @@ static void send_listing(int fd)
int n = lp_numservices();
int i;
for (i=0;i<n;i++)
for (i = 0; i < n; i++) {
if (lp_list(i))
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
}
if (protocol_version >= 25)
io_printf(fd,"@RSYNCD: EXIT\n");
@@ -492,11 +548,12 @@ int start_daemon(int f_in, int f_out)
{
char line[200];
char *motd;
int i = -1;
int i;
if (!lp_load(config_file, 0)) {
io_set_sock_fds(f_in, f_out);
if (!lp_load(config_file, 0))
exit_cleanup(RERR_SYNTAX);
}
log_init();
@@ -512,19 +569,19 @@ int start_daemon(int f_in, int f_out)
if (motd && *motd) {
FILE *f = fopen(motd,"r");
while (f && !feof(f)) {
int len = fread(line, 1, sizeof(line)-1, f);
int len = fread(line, 1, sizeof line - 1, f);
if (len > 0) {
line[len] = 0;
io_printf(f_out, "%s", line);
}
}
if (f) fclose(f);
if (f)
fclose(f);
io_printf(f_out, "\n");
}
if (!read_line(f_in, line, sizeof(line)-1)) {
if (!read_line(f_in, line, sizeof line - 1))
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
io_printf(f_out, "@ERROR: protocol startup error\n");
@@ -533,28 +590,28 @@ int start_daemon(int f_in, int f_out)
if (protocol_version > remote_protocol)
protocol_version = remote_protocol;
while (i == -1) {
line[0] = 0;
if (!read_line(f_in, line, sizeof(line)-1)) {
return -1;
}
line[0] = 0;
if (!read_line(f_in, line, sizeof line - 1))
return -1;
if (!*line || strcmp(line,"#list")==0) {
send_listing(f_out);
return -1;
}
if (!*line || strcmp(line, "#list") == 0) {
send_listing(f_out);
return -1;
}
if (*line == '#') {
/* it's some sort of command that I don't understand */
io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
return -1;
}
if (*line == '#') {
/* it's some sort of command that I don't understand */
io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
return -1;
}
i = lp_number(line);
if (i == -1) {
io_printf(f_out, "@ERROR: Unknown module '%s'\n", line);
return -1;
}
if ((i = lp_number(line)) < 0) {
char *addr = client_addr(f_in);
char *host = client_name(f_in);
rprintf(FLOG, "unknown module '%s' tried from %s (%s)\n",
line, host, addr);
io_printf(f_out, "@ERROR: Unknown module '%s'\n", line);
return -1;
}
return rsync_module(f_in, f_out, i);
@@ -571,7 +628,7 @@ int daemon_main(void)
/* we are running via inetd - close off stdout and
* stderr so that library functions (and getopt) don't
* try to use them. Redirect them to /dev/null */
for (i=1;i<3;i++) {
for (i = 1; i < 3; i++) {
close(i);
open("/dev/null", O_RDWR);
}
@@ -582,13 +639,17 @@ int daemon_main(void)
if (!no_detach)
become_daemon();
if (!lp_load(config_file, 1)) {
if (!lp_load(config_file, 1))
exit_cleanup(RERR_SYNTAX);
}
if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
rsync_port = RSYNC_PORT;
if (bind_address == NULL && *lp_bind_address())
bind_address = lp_bind_address();
log_init();
rprintf(FINFO, "rsyncd version %s starting, listening on port %d\n",
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
RSYNC_VERSION, rsync_port);
/* TODO: If listening on a particular address, then show that
* address too. In fact, why not just do inet_ntop on the
@@ -602,7 +663,8 @@ int daemon_main(void)
if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
0666 & ~orig_umask)) == -1) {
cleanup_set_pid(0);
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
rsyserr(FLOG, errno, "failed to create pid file %s",
safe_fname(pid_file));
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);

View File

@@ -27,36 +27,31 @@
int remote_protocol = 0;
extern int am_server;
extern int preserve_links;
extern int preserve_perms;
extern int preserve_devices;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_times;
extern int always_checksum;
extern int checksum_seed;
extern int protocol_version;
extern int verbose;
extern int am_server;
extern int am_sender;
extern int inplace;
extern int fuzzy_basis;
extern int read_batch;
extern int write_batch;
extern int checksum_seed;
extern int basis_dir_cnt;
extern int protocol_version;
extern char *dest_option;
void setup_protocol(int f_out,int f_in)
{
if (remote_protocol == 0) {
if (am_server) {
remote_protocol = read_int(f_in);
if (!read_batch)
write_int(f_out, protocol_version);
} else {
write_int(f_out, protocol_version);
remote_protocol = read_int(f_in);
}
remote_protocol = read_int(f_in);
if (protocol_version > remote_protocol)
protocol_version = remote_protocol;
}
if (read_batch && remote_protocol > protocol_version) {
rprintf(FERROR, "The protocol version in the batch file is too new (%d > %d).\n",
remote_protocol, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (verbose > 3) {
rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
@@ -64,7 +59,7 @@ void setup_protocol(int f_out,int f_in)
}
if (remote_protocol < MIN_PROTOCOL_VERSION
|| remote_protocol > MAX_PROTOCOL_VERSION) {
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
rprintf(FERROR,"protocol version mismatch -- is your shell clean?\n");
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
exit_cleanup(RERR_PROTOCOL);
}
@@ -83,6 +78,27 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
if (fuzzy_basis && protocol_version < 29) {
rprintf(FERROR,
"--fuzzy requires protocol 29 or higher (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt && inplace && protocol_version < 29) {
rprintf(FERROR,
"%s with --inplace requires protocol 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt > 1 && protocol_version < 29) {
rprintf(FERROR,
"Multiple %s options requires protocol 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (am_server) {
if (!checksum_seed)
checksum_seed = time(NULL);

View File

@@ -3,9 +3,9 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT()
AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.52)
AC_PREREQ(2.59)
RSYNC_VERSION=2.6.2
RSYNC_VERSION=2.6.5pre2
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -57,7 +57,7 @@ fi
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],
AC_HELP_STRING([--enable-profile],
[turn on CPU profiling (default no)],
[], []))
if test x"$enable_profile" = xyes
@@ -68,7 +68,7 @@ fi
# Specifically, this turns on panic_action handling.
AC_ARG_ENABLE(maintainer-mode,
AC_HELP_STRING([--enable-maintainer-mode],
AC_HELP_STRING([--enable-maintainer-mode],
[turn on extra debug features],
[], []))
if test x"$enable_maintainer_mode" = xyes
@@ -82,7 +82,7 @@ fi
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
# If GCC, turn on warnings.
if test "x$GCC" = "xyes"
if test x"$GCC" = x"yes"
then
CFLAGS="$CFLAGS -Wall -W"
fi
@@ -181,6 +181,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])
@@ -275,7 +286,7 @@ AC_MSG_CHECKING([whether to call shutdown on all sockets])
case $host_os in
*cygwin* ) AC_MSG_RESULT(yes)
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
[Define if sockets need to be shutdown])
[Define to 1 if sockets need to be shutdown])
;;
* ) AC_MSG_RESULT(no);;
esac
@@ -287,15 +298,19 @@ 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
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(off_t)
AC_CHECK_SIZEOF(off64_t)
AC_C_INLINE
AC_C_LONG_DOUBLE
AC_TYPE_SIGNAL
AC_TYPE_UID_T
@@ -306,14 +321,13 @@ AC_TYPE_PID_T
AC_TYPE_GETGROUPS
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_TYPE([ino_t], [unsigned])
TYPE_SOCKLEN_T
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
rsync_cv_errno=yes,rsync_cv_have_errno_decl=no)])
if test x"$rsync_cv_errno" = x"yes"; then
AC_DEFINE(HAVE_ERRNO_DECL, 1, [ ])
AC_DEFINE(HAVE_ERRNO_DECL, 1, [Define to 1 if errno is declared in errno.h])
fi
# The following test taken from the cvs sources
@@ -348,7 +362,7 @@ if test x"$ac_cv_func_connect" = x"no"; then
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
AC_DEFINE(HAVE_CONNECT, 1, [ ])
AC_DEFINE(HAVE_CONNECT, 1, [Define to 1 if you have the "connect" function])
fi
fi
@@ -383,7 +397,7 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_GETADDRINFO, 1,
[Define if you have the `getaddrinfo' function.])],
[Define to 1 if you have the "getaddrinfo" function.])],
[AC_MSG_RESULT([no])
AC_LIBOBJ(lib/getaddrinfo)])])
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
@@ -409,13 +423,22 @@ AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
#include <netinet/in.h>
])
AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
[ AC_DEFINE(HAVE_SOCKADDR_UN_LEN, 1, [Do we have sockaddr_un.sun_len?]) ],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct sockaddr_storage)
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>],
[struct sockaddr_storage x;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
[Define if you have strct sockaddr_storage.] ),
[Define to 1 if you have struct sockaddr_storage.] ),
AC_MSG_RESULT(no))
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
@@ -427,6 +450,27 @@ AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct stat64)
AC_TRY_COMPILE([#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#if STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# if HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
],[struct stat64 st;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STRUCT_STAT64,1,[Define to 1 if you have struct stat64.]),
AC_MSG_RESULT(no))
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
#
AC_CHECK_FUNCS(strcasecmp)
@@ -442,9 +486,35 @@ dnl AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
fchmod fstat strchr readlink link utime utimes strftime mtrace \
memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid)
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 \
setlocale setmode open64 lseek64 mkstemp64 va_copy __va_copy)
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
fi
# Determine whether chown follows symlinks (it should).
AC_CACHE_CHECK([whether chown() dereferences symlinks],rsync_cv_chown_follows_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
main() {
char const *dangling_symlink = "conftest.dangle";
unlink(dangling_symlink);
if (symlink("conftest.no-such", dangling_symlink) < 0) abort();
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(0);
exit(1);
}],
rsync_cv_chown_follows_symlink=yes,rsync_cv_chown_follows_symlink=no,rsync_cv_chown_follows_symlink=yes)])
if test $rsync_cv_chown_follows_symlink = no; then
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
fi
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
@@ -457,7 +527,7 @@ main() {
}],
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
AC_DEFINE(HAVE_SOCKETPAIR, 1, [ ])
AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function])
fi
if test x"$with_included_popt" != x"yes"
@@ -481,39 +551,11 @@ else
AC_MSG_RESULT(no)
fi
AC_CACHE_CHECK([for long long],rsync_cv_HAVE_LONGLONG,[
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
rsync_cv_HAVE_LONGLONG=yes,rsync_cv_HAVE_LONGLONG=no,rsync_cv_HAVE_LONGLONG=cross)])
if test x"$rsync_cv_HAVE_LONGLONG" = x"yes"; then
AC_DEFINE(HAVE_LONGLONG, 1, [ ])
fi
AC_CACHE_CHECK([for off64_t],rsync_cv_HAVE_OFF64_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/stat.h>
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }],
rsync_cv_HAVE_OFF64_T=yes,rsync_cv_HAVE_OFF64_T=no,rsync_cv_HAVE_OFF64_T=cross)])
if test x"$rsync_cv_HAVE_OFF64_T" = x"yes"; then
AC_DEFINE(HAVE_OFF64_T, 1, [ ])
fi
AC_CACHE_CHECK([for short ino_t],rsync_cv_HAVE_SHORT_INO_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
rsync_cv_HAVE_SHORT_INO_T=yes,rsync_cv_HAVE_SHORT_INO_T=no,rsync_cv_HAVE_SHORT_INO_T=cross)])
if test x"$rsync_cv_HAVE_SHORT_INO_T" = x"yes"; then
AC_DEFINE(HAVE_SHORT_INO_T, 1, [ ])
fi
AC_CACHE_CHECK([for unsigned char],rsync_cv_HAVE_UNSIGNED_CHAR,[
AC_TRY_RUN([#include <stdio.h>
main() { char c; c=250; exit((c > 0)?0:1); }],
rsync_cv_HAVE_UNSIGNED_CHAR=yes,rsync_cv_HAVE_UNSIGNED_CHAR=no,rsync_cv_HAVE_UNSIGNED_CHAR=cross)])
if test x"$rsync_cv_HAVE_UNSIGNED_CHAR" = x"yes"; then
AC_DEFINE(HAVE_UNSIGNED_CHAR, 1, [ ])
AC_CACHE_CHECK([for unsigned char],rsync_cv_SIGNED_CHAR_OK,[
AC_TRY_COMPILE([],[signed char *s = ""],
rsync_cv_SIGNED_CHAR_OK=yes,rsync_cv_SIGNED_CHAR_OK=no)])
if test x"$rsync_cv_SIGNED_CHAR_OK" = x"yes"; then
AC_DEFINE(SIGNED_CHAR_OK, 1, [Define to 1 if "signed char" is a valid type])
fi
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
@@ -524,26 +566,25 @@ if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) exit(0); exit(1);} ],
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [ ])
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [Define to 1 if readdir() is broken])
fi
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no,rsync_cv_HAVE_UTIMBUF=cross)])
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF, 1, [ ])
AC_DEFINE(HAVE_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
AC_TRY_RUN([
#include <sys/time.h>
#include <unistd.h>
main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}],
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no,rsync_cv_HAVE_GETTIMEOFDAY_TZ=cross)])
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [ ])
AC_TRY_COMPILE([#include <sys/time.h>
#include <unistd.h>],
[struct timeval tv; exit(gettimeofday(&tv, NULL));],
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no)])
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" != x"no"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [Define to 1 if gettimeofday() takes a time-zone arg])
fi
AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
@@ -568,7 +609,7 @@ main() { foo("hello"); }
],
rsync_cv_HAVE_C99_VSNPRINTF=yes,rsync_cv_HAVE_C99_VSNPRINTF=no,rsync_cv_HAVE_C99_VSNPRINTF=cross)])
if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [ ])
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [Define to 1 if vsprintf has a C99-compatible return value])
fi
@@ -591,7 +632,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, [ ])
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
@@ -607,7 +658,7 @@ if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
exit(0);}],
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA, 1, [ ])
AC_DEFINE(REPLACE_INET_NTOA, 1, [Define to 1 if inet_ntoa() needs to be replaced])
fi
@@ -621,7 +672,35 @@ main() { struct in_addr ip;
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
AC_DEFINE(REPLACE_INET_ATON, 1, [ ])
AC_DEFINE(REPLACE_INET_ATON, 1, [Define to 1 if inet_aton() needs to be replaced])
fi
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
main() { int rc, ec; char *fn = "fifo-test";
unlink(fn); rc = mknod(fn,S_IFIFO,0600); ec = errno; unlink(fn);
if (rc) {printf("%d %d\n",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_FIFOS=yes,rsync_cv_MKNOD_CREATES_FIFOS=no,rsync_cv_MKNOD_CREATES_FIFOS=cross)])
if test x"$rsync_cv_MKNOD_CREATES_FIFOS" = x"yes"; then
AC_DEFINE(MKNOD_CREATES_FIFOS, 1, [Define to 1 if mknod() can create FIFOs.])
fi
AC_CACHE_CHECK([if mknod creates sockets],rsync_cv_MKNOD_CREATES_SOCKETS,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
main() { int rc, ec; char *fn = "sock-test";
unlink(fn); rc = mknod(fn,S_IFSOCK,0600); ec = errno; unlink(fn);
if (rc) {printf("%d %d\n",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_SOCKETS=yes,rsync_cv_MKNOD_CREATES_SOCKETS=no,rsync_cv_MKNOD_CREATES_SOCKETS=cross)])
if test x"$rsync_cv_MKNOD_CREATES_SOCKETS" = x"yes"; then
AC_DEFINE(MKNOD_CREATES_SOCKETS, 1, [Define to 1 if mknod() can create sockets.])
fi
#

View File

@@ -40,6 +40,7 @@
#define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_PARTIAL 23 /* partial transfer */
#define RERR_VANISHED 24 /* file(s) vanished on sender side */
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */

1252
exclude.c
View File

File diff suppressed because it is too large Load Diff

104
fileio.c
View File

@@ -22,9 +22,10 @@
*/
#include "rsync.h"
extern int sparse_files;
static char last_byte;
static int last_sparse;
extern int sparse_files;
int sparse_end(int f)
{
@@ -91,6 +92,7 @@ int flush_write_file(int f)
return ret;
}
/*
* write_file does not allow incomplete writes. It loops internally
* until len bytes are written or errno is set.
@@ -106,9 +108,9 @@ int write_file(int f,char *buf,size_t len)
r1 = write_sparse(f, buf, len1);
} else {
if (!wf_writeBuf) {
wf_writeBufSize = MAX_MAP_SIZE;
wf_writeBufSize = WRITE_SIZE * 8;
wf_writeBufCnt = 0;
wf_writeBuf = new_array(char, MAX_MAP_SIZE);
wf_writeBuf = new_array(char, wf_writeBufSize);
if (!wf_writeBuf)
out_of_memory("write_file");
}
@@ -125,7 +127,8 @@ int write_file(int f,char *buf,size_t len)
}
}
if (r1 <= 0) {
if (ret > 0) return ret;
if (ret > 0)
return ret;
return r1;
}
len -= r1;
@@ -136,76 +139,67 @@ int write_file(int f,char *buf,size_t len)
}
/* this provides functionality somewhat similar to mmap() but using
read(). It gives sliding window access to a file. mmap() is not
used because of the possibility of another program (such as a
mailer) truncating the file thus giving us a SIGBUS */
struct map_struct *map_file(int fd,OFF_T len)
/* This provides functionality somewhat similar to mmap() but using read().
* It gives sliding window access to a file. mmap() is not used because of
* the possibility of another program (such as a mailer) truncating the
* file thus giving us a SIGBUS. */
struct map_struct *map_file(int fd, OFF_T len, int32 read_size,
int32 blk_size)
{
struct map_struct *map;
map = new(struct map_struct);
if (!map) out_of_memory("map_file");
if (!(map = new(struct map_struct)))
out_of_memory("map_file");
if (blk_size && (read_size % blk_size))
read_size += blk_size - (read_size % blk_size);
memset(map, 0, sizeof map[0]);
map->fd = fd;
map->file_size = len;
map->p = NULL;
map->p_size = 0;
map->p_offset = 0;
map->p_fd_offset = 0;
map->p_len = 0;
map->status = 0;
map->def_window_size = read_size;
return map;
}
/* slide the read window in the file */
char *map_ptr(struct map_struct *map,OFF_T offset,int len)
char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
{
int nread;
int32 nread;
OFF_T window_start, read_start;
int window_size, read_size, read_offset;
int32 window_size, read_size, read_offset;
if (len == 0) {
if (len == 0)
return NULL;
}
/* can't go beyond the end of file */
if (len > (map->file_size - offset)) {
len = map->file_size - offset;
if (len < 0) {
rprintf(FERROR, "invalid len passed to map_ptr: %ld\n",
(long)len);
exit_cleanup(RERR_FILEIO);
}
/* in most cases the region will already be available */
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->p + (offset - map->p_offset));
}
if (offset >= map->p_offset && offset+len <= map->p_offset+map->p_len)
return map->p + (offset - map->p_offset);
/* nope, we are going to have to do a read. Work out our desired window */
if (offset > 2*CHUNK_SIZE) {
window_start = offset - 2*CHUNK_SIZE;
window_start &= ~((OFF_T)(CHUNK_SIZE-1)); /* assumes power of 2 */
} else {
window_start = 0;
}
window_size = MAX_MAP_SIZE;
if (window_start + window_size > map->file_size) {
window_start = offset;
window_size = map->def_window_size;
if (window_start + window_size > map->file_size)
window_size = map->file_size - window_start;
}
if (offset + len > window_start + window_size) {
window_size = (offset+len) - window_start;
}
if (len > window_size)
window_size = len;
/* make sure we have allocated enough memory for the window */
if (window_size > map->p_size) {
map->p = realloc_array(map->p, char, window_size);
if (!map->p) out_of_memory("map_ptr");
if (!map->p)
out_of_memory("map_ptr");
map->p_size = window_size;
}
/* now try to avoid re-reading any bytes by reusing any bytes from the previous
buffer. */
/* Now try to avoid re-reading any bytes by reusing any bytes
* from the previous buffer. */
if (window_start >= map->p_offset &&
window_start < map->p_offset + map->p_len &&
window_start + window_size >= map->p_offset + map->p_len) {
@@ -220,11 +214,16 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
}
if (read_size <= 0) {
rprintf(FINFO,"Warning: unexpected read size of %d in map_ptr\n", read_size);
rprintf(FERROR, "invalid read_size of %ld in map_ptr\n",
(long)read_size);
exit_cleanup(RERR_FILEIO);
} else {
if (map->p_fd_offset != read_start) {
if (do_lseek(map->fd,read_start,SEEK_SET) != read_start) {
rprintf(FERROR,"lseek failed in map_ptr\n");
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
if (ret != read_start) {
rsyserr(FERROR, errno,
"lseek returned %.0f, not %.0f",
(double)ret, (double)read_start);
exit_cleanup(RERR_FILEIO);
}
map->p_fd_offset = read_start;
@@ -246,7 +245,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
map->p_offset = window_start;
map->p_len = window_size;
return map->p + (offset - map->p_offset);
return map->p;
}
@@ -259,9 +258,8 @@ int unmap_file(struct map_struct *map)
map->p = NULL;
}
ret = map->status;
memset(map, 0, sizeof(*map));
memset(map, 0, sizeof map[0]);
free(map);
return ret;
}

937
flist.c
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

23
getfsdev.c Normal file
View File

@@ -0,0 +1,23 @@
#include "rsync.h"
int main(int argc, char *argv[])
{
STRUCT_STAT st;
int ret;
while (--argc > 0) {
#ifdef USE_STAT64_FUNCS
ret = stat64(*++argv, &st);
#else
ret = stat(*++argv, &st);
#endif
if (ret < 0) {
fprintf(stderr, "Unable to stat `%s'\n", *argv);
exit(1);
}
printf("%ld/%ld\n", (long)major(st.st_dev),
(long)minor(st.st_dev));
}
return 0;
}

242
hlink.c
View File

@@ -23,12 +23,21 @@
extern int dry_run;
extern int verbose;
extern int make_backups;
extern struct file_list *the_file_list;
#if SUPPORT_HARD_LINKS
static int hlink_compare(struct file_struct **file1, struct file_struct **file2)
#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)
static int hlink_compare(int *int1, int *int2)
{
struct file_struct *f1 = *file1;
struct file_struct *f2 = *file2;
struct file_struct *f1 = FPTR(*int1);
struct file_struct *f2 = FPTR(*int2);
if (f1->F_DEV != f2->F_DEV)
return (int) (f1->F_DEV > f2->F_DEV ? 1 : -1);
@@ -36,54 +45,51 @@ static int hlink_compare(struct file_struct **file1, struct file_struct **file2)
if (f1->F_INODE != f2->F_INODE)
return (int) (f1->F_INODE > f2->F_INODE ? 1 : -1);
return file_compare(file1, file2);
return f_name_cmp(f1, f2);
}
static struct file_struct **hlink_list;
static int *hlink_list;
static int hlink_count;
#define LINKED(p1,p2) ((p1)->F_DEV == (p2)->F_DEV \
&& (p1)->F_INODE == (p2)->F_INODE)
/* Analyze the data in the hlink_list[], remove items that aren't multiply
* linked, and replace the dev+inode data with the hlindex+next linked list. */
static void link_idev_data(struct file_list *flist)
static void link_idev_data(void)
{
struct file_struct *head;
int from, to, start;
int cur, from, to, start;
alloc_pool_t hlink_pool;
alloc_pool_t idev_pool = flist->hlink_pool;
alloc_pool_t idev_pool = the_file_list->hlink_pool;
hlink_pool = pool_create(128 * 1024, sizeof (struct hlink),
out_of_memory, POOL_INTERN);
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, hlink_list[from]->link_u.idev);
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");
hlink_list[from]->F_HLINDEX = to;
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, hlink_list[from]->link_u.idev);
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");
hlink_list[from]->F_HLINDEX = to;
hlink_list[from]->F_NEXT = head;
hlink_list[from]->flags |= FLAG_HLINK_EOL;
FPTR(head)->flags |= FLAG_HLINK_TOL;
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, head->link_u.idev);
head->link_u.idev = NULL;
}
} else
FPTR(cur)->link_u.links = NULL;
}
if (!to) {
@@ -93,33 +99,30 @@ static void link_idev_data(struct file_list *flist)
hlink_pool = NULL;
} else {
hlink_count = to;
if (!(hlink_list = realloc_array(hlink_list,
struct file_struct *, hlink_count)))
hlink_list = realloc_array(hlink_list, int, hlink_count);
if (!hlink_list)
out_of_memory("init_hard_links");
}
flist->hlink_pool = hlink_pool;
the_file_list->hlink_pool = hlink_pool;
pool_destroy(idev_pool);
}
#endif
void init_hard_links(struct file_list *flist)
void init_hard_links(void)
{
#if SUPPORT_HARD_LINKS
#ifdef SUPPORT_HARD_LINKS
int i;
if (flist->count < 2)
return;
if (hlink_list)
free(hlink_list);
if (!(hlink_list = new_array(struct file_struct *, flist->count)))
if (!(hlink_list = new_array(int, the_file_list->count)))
out_of_memory("init_hard_links");
hlink_count = 0;
for (i = 0; i < flist->count; i++) {
if (flist->files[i]->link_u.idev)
hlink_list[hlink_count++] = flist->files[i];
for (i = 0; i < the_file_list->count; i++) {
if (FPTR(i)->link_u.idev)
hlink_list[hlink_count++] = i;
}
qsort(hlink_list, hlink_count,
@@ -129,83 +132,136 @@ void init_hard_links(struct file_list *flist)
free(hlink_list);
hlink_list = NULL;
} else
link_idev_data(flist);
link_idev_data();
#endif
}
int hard_link_check(struct file_struct *file, 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 (!hlink_list || !file->link_u.links)
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
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] != file) {
if (verbose > 1) {
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",
f_name(file));
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
return 0;
}
#if SUPPORT_HARD_LINKS
static void hard_link_one(char *hlink1, char *hlink2)
#ifdef SUPPORT_HARD_LINKS
int hard_link_one(struct file_struct *file, int ndx, char *fname,
int statret, STRUCT_STAT *st, char *toname, int terse,
int itemizing, enum logcode code)
{
if (do_link(hlink1, hlink2)) {
if (verbose) {
rprintf(FINFO, "link %s => %s failed: %s\n",
hlink2, hlink1, strerror(errno));
}
if (do_link(toname, fname)) {
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;
}
else if (verbose)
rprintf(FINFO, "%s => %s\n", hlink2, hlink1);
if (itemizing) {
itemize(file, ndx, statret, st,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
terse ? "" : toname);
}
if (code && verbose && !terse) {
rprintf(code, "%s => %s\n",
safe_fname(fname), safe_fname(toname));
}
return 0;
}
#endif
/**
* Create any hard links in the global hlink_list. They were put
* there by running init_hard_links on the filelist.
**/
void do_hard_links(void)
void hard_link_cluster(struct file_struct *file, int master, int itemizing,
enum logcode code)
{
#if SUPPORT_HARD_LINKS
struct file_struct *file, *first;
#ifdef SUPPORT_HARD_LINKS
char hlink1[MAXPATHLEN];
char *hlink2;
STRUCT_STAT st1, st2;
int i;
int statret, ndx = master;
if (!hlink_list)
file->F_HLINDEX = FINISHED_LINK;
if (link_stat(f_name_to(file, hlink1), &st1, 0) < 0)
return;
for (i = 0; i < hlink_count; i++) {
first = file = hlink_list[i];
if (link_stat(f_name_to(first, hlink1), &st1) != 0)
continue;
while ((file = file->F_NEXT) != first) {
hlink2 = f_name(file);
if (link_stat(hlink2, &st2) == 0) {
if (st2.st_dev == st1.st_dev
&& st2.st_ino == st1.st_ino)
continue;
if (make_backups) {
if (!make_backup(hlink2))
continue;
} else if (robust_unlink(hlink2)) {
if (verbose > 0) {
rprintf(FINFO,
"unlink %s failed: %s\n",
full_fname(hlink2),
strerror(errno));
}
continue;
}
}
hard_link_one(hlink1, hlink2);
if (!(file->flags & FLAG_HLINK_TOL)) {
while (!(file->flags & FLAG_HLINK_EOL)) {
ndx = file->F_NEXT;
file = FPTR(ndx);
}
}
do {
ndx = file->F_NEXT;
file = FPTR(ndx);
if (file->F_HLINDEX != SKIPPED_LINK)
continue;
hlink2 = f_name(file);
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
}

919
io.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -155,7 +155,7 @@
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#if WORDS_BIGENDIAN
#ifdef WORDS_BIGENDIAN
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
@@ -196,7 +196,7 @@
/* some systems don't take the 2nd argument */
int sys_gettimeofday(struct timeval *tv)
{
#if HAVE_GETTIMEOFDAY_TZ
#ifdef HAVE_GETTIMEOFDAY_TZ
return gettimeofday(tv, NULL);
#else
return gettimeofday(tv);

View File

@@ -206,9 +206,11 @@ void mdfour(unsigned char *out, unsigned char *in, int n)
}
#ifdef TEST_MDFOUR
int protocol_version = 28;
static void file_checksum1(char *fname)
{
int fd, i;
int fd, i, was_multiple_of_64 = 1;
struct mdfour md;
unsigned char buf[64*1024], sum[16];
@@ -222,9 +224,13 @@ static void file_checksum1(char *fname)
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
if (n <= 0)
break;
was_multiple_of_64 = !(n % 64);
mdfour_update(&md, buf, n);
}
if (was_multiple_of_64 && protocol_version >= 27)
mdfour_update(&md, buf, 0);
close(fd);

View File

@@ -17,10 +17,10 @@ struct alloc_pool
/* statistical data */
unsigned long e_created; /* extents created */
unsigned long e_freed; /* extents detroyed */
uint64 n_allocated; /* calls to alloc */
uint64 n_freed; /* calls to free */
uint64 b_allocated; /* cum. bytes allocated */
uint64 b_freed; /* cum. bytes freed */
int64 n_allocated; /* calls to alloc */
int64 n_freed; /* calls to free */
int64 b_allocated; /* cum. bytes allocated */
int64 b_freed; /* cum. bytes freed */
};
struct pool_extent
@@ -34,7 +34,7 @@ struct pool_extent
struct align_test {
void *foo;
uint64 bar;
int64 bar;
};
#define MINALIGN offsetof(struct align_test, bar)

View File

@@ -1,3 +1,7 @@
/*
* NOTE: If you change this file, please merge it into rsync, samba, etc.
*/
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
@@ -53,14 +57,57 @@
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
* Paul Green (paulg@samba.org) April 9, 2003
* fixed handling of %f when converting fractions with leading zeros.
* (e.g., 0.025).
* date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
* actually print args for %g and %e
*
* date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
* Since includes.h isn't included here, VA_COPY has to be defined here. I don't
* see any include file that is guaranteed to be here, so I'm defining it
* locally. Fixes AIX and Solaris builds.
*
* date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
* put the ifdef for HAVE_VA_COPY in one place rather than in lots of
* functions
*
* date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
* Fix usage of va_list passed as an arg. Use __va_copy before using it
* when it exists.
*
* date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
* Fix incorrect zpadlen handling in fmtfp.
* Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
* few mods to make it easier to compile the tests.
* addedd the "Ollie" test to the floating point ones.
*
* Martin Pool (mbp@samba.org) April 2003
* Remove NO_CONFIG_H so that the test case can be built within a source
* tree with less trouble.
* Remove unnecessary SAFE_FREE() definition.
*
* Martin Pool (mbp@samba.org) May 2003
* Put in a prototype for dummy_snprintf() to quiet compiler warnings.
*
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
* if the C library has some snprintf functions already.
**************************************************************/
#ifndef NO_CONFIG_H /* for some tests */
#ifndef NO_CONFIG_H
#include "config.h"
#endif
#else
#define NULL 0
#endif
#ifdef TEST_SNPRINTF /* need math library headers for testing */
/* In test mode, we pretend that this system doesn't have any snprintf
* functions, regardless of what config.h says. */
# undef HAVE_SNPRINTF
# undef HAVE_VSNPRINTF
# undef HAVE_C99_VSNPRINTF
# undef HAVE_ASPRINTF
# undef HAVE_VASPRINTF
# include <math.h>
#endif /* TEST_SNPRINTF */
#ifdef HAVE_STRING_H
#include <string.h>
@@ -82,8 +129,9 @@
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
#include <stdio.h>
/* make the compiler happy with an empty file */
void dummy_snprintf(void);
void dummy_snprintf(void) {}
#else
#endif /* HAVE_SNPRINTF, etc */
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
@@ -91,21 +139,22 @@
#define LDOUBLE double
#endif
#ifdef HAVE_LONG_LONG
#if SIZEOF_LONG_LONG
#define LLONG long long
#else
#define LLONG long
#endif
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
#ifndef VA_COPY
#ifdef HAVE_VA_COPY
#define VA_COPY(dest, src) va_copy(dest, src)
#else
#ifdef HAVE___VA_COPY
#define VA_COPY(dest, src) __va_copy(dest, src)
#else
#define VA_COPY(dest, src) (dest) = (src)
#endif
#endif
/*
* dopr(): poor man's version of doprintf
@@ -141,7 +190,20 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args)
/* yes this really must be a ||. Don't muck with this (tridge) */
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args_in);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
{
char ch;
LLONG value;
@@ -153,6 +215,9 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
int flags;
int cflags;
size_t currlen;
va_list args;
VA_COPY(args, args_in);
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
@@ -322,6 +387,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'G':
flags |= DP_F_UP;
@@ -330,12 +396,14 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'c':
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
if (!strvalue) strvalue = "(NULL)";
if (max == -1) {
max = strlen(strvalue);
}
@@ -564,28 +632,26 @@ static double my_modf(double x0, double *iptr)
for (i=0;i<100;i++) {
l = (long)x;
if (l <= (x+1) && l >= (x-1)) break;
if (l <= (x+1) && l >= (x-1)) {
if (i != 0) {
double i2;
double ret;
ret = my_modf(x0-l*f, &i2);
(*iptr) = l*f + i2;
return ret;
}
(*iptr) = l;
return x - (*iptr);
}
x *= 0.1;
f *= 10.0;
}
if (i == 100) {
/* yikes! the number is beyond what we can handle. What do we do? */
(*iptr) = 0;
return 0;
}
if (i != 0) {
double i2;
double ret;
ret = my_modf(x0-l*f, &i2);
(*iptr) = l*f + i2;
return ret;
}
(*iptr) = l;
return x - (*iptr);
/* yikes! the number is beyond what we can handle. What do we do? */
(*iptr) = 0;
return 0;
}
@@ -601,7 +667,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
int index;
int idx;
double intpart;
double fracpart;
double temp;
@@ -658,14 +724,13 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
/* Convert integer part */
do {
temp = intpart;
my_modf(intpart*0.1, &intpart);
temp = temp*0.1;
index = (int) ((temp -intpart +0.05)* 10.0);
/* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, index); */
temp = intpart*0.1;
my_modf(temp, &intpart);
idx = (int) ((temp -intpart +0.05)* 10.0);
/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[index];
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while (intpart && (iplace < 311));
if (iplace == 311) iplace--;
iconvert[iplace] = 0;
@@ -674,14 +739,13 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
if (fracpart)
{
do {
temp = fracpart;
my_modf(fracpart*0.1, &fracpart);
temp = temp*0.1;
index = (int) ((temp -fracpart +0.05)* 10.0);
/* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
temp = fracpart*0.1;
my_modf(temp, &fracpart);
idx = (int) ((temp -fracpart +0.05)* 10.0);
/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[index];
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while(fracpart && (fplace < 311));
if (fplace == 311) fplace--;
}
@@ -729,14 +793,14 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
dopr_outch (buffer, currlen, maxlen, '.');
while (zpadlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
while (fplace > 0)
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
}
while (padlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
@@ -751,17 +815,21 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
(*currlen)++;
}
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
#define vsnprintf rsync_vsnprintf
int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
int rsync_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
#define vsnprintf rsync_vsnprintf
#endif
/* yes this really must be a ||. Don't muck with this (tridge)
*
* The logic for these two is that we need our own definition if the
* OS *either* has no definition of *sprintf, or if it does have one
* that doesn't work properly according to the autoconf test.
*/
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
#define snprintf rsync_snprintf
int snprintf(char *str,size_t count,const char *fmt,...)
int rsync_snprintf(char *str,size_t count,const char *fmt,...)
{
size_t ret;
va_list ap;
@@ -771,6 +839,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
va_end(ap);
return ret;
}
#define snprintf rsync_snprintf
#endif
#endif
@@ -779,13 +848,19 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
int vasprintf(char **ptr, const char *format, va_list ap)
{
int ret;
va_list ap2;
VA_COPY(ap2, ap);
ret = vsnprintf(NULL, 0, format, ap);
ret = vsnprintf(NULL, 0, format, ap2);
if (ret <= 0) return ret;
(*ptr) = (char *)malloc(ret+1);
if (!*ptr) return -1;
ret = vsnprintf(*ptr, ret+1, format, ap);
VA_COPY(ap2, ap);
ret = vsnprintf(*ptr, ret+1, format, ap2);
return ret;
}
@@ -798,6 +873,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
va_list ap;
int ret;
*ptr = NULL;
va_start(ap, format);
ret = vasprintf(ptr, format, ap);
va_end(ap);
@@ -832,8 +908,9 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
"-16.16f",
NULL
};
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 0};
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 5.030201, 0.00205,
/* END LIST */ 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
@@ -928,8 +1005,10 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
{
double v0 = 0.12345678901234567890123456789012345678901;
for (x=0; x<100; x++) {
snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
sprintf(buf2, "%1.1f", v0*pow(10, x));
double p = pow(10, x);
double r = v0*p;
snprintf(buf1, sizeof(buf1), "%1.1f", r);
sprintf(buf2, "%1.1f", r);
if (strcmp(buf1, buf2)) {
printf("we seem to support %d digits\n", x-1);
break;
@@ -939,4 +1018,4 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
return 0;
}
#endif /* SNPRINTF_TEST */
#endif /* TEST_SNPRINTF */

View File

@@ -57,10 +57,10 @@
int wildmatch_iteration_count;
#endif
static int domatch(const unsigned char *p, const unsigned char *text)
static int domatch(const uchar *p, const uchar *text)
{
int matched, special;
unsigned char ch, prev;
uchar ch, prev;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count++;
@@ -141,9 +141,9 @@ static int domatch(const unsigned char *p, const unsigned char *text)
ch = 0; /* This makes "prev" get set to 0. */
}
else if (ch == '[' && p[1] == ':') {
const unsigned char *s = p += 2;
const uchar *s;
int i;
while ((ch = *p) && ch != ']') p++;
for (s = p += 2; (ch = *p) && ch != ']'; p++) {}
if (!ch)
return ABORT_ALL;
i = p - s - 1;
@@ -225,5 +225,5 @@ int wildmatch(const char *p, const char *t)
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
return domatch((const unsigned char*)p, (const unsigned char*)t) == TRUE;
return domatch((const uchar*)p, (const uchar*)t) == TRUE;
}

View File

@@ -102,8 +102,10 @@ typedef struct
char *log_file;
char *pid_file;
char *socket_options;
char *bind_address;
int syslog_facility;
int max_verbosity;
int rsync_port;
} global;
static global Globals;
@@ -119,6 +121,7 @@ typedef struct
char *comment;
char *lock_file;
BOOL read_only;
BOOL write_only;
BOOL list;
BOOL use_chroot;
BOOL transfer_logging;
@@ -130,6 +133,7 @@ typedef struct
char *auth_users;
char *secrets_file;
BOOL strict_modes;
char *filter;
char *exclude;
char *exclude_from;
char *include;
@@ -151,6 +155,7 @@ static service sDefault =
NULL, /* comment */
DEFAULT_LOCK_FILE, /* lock file */
True, /* read only */
False, /* write only */
True, /* list */
True, /* use chroot */
False, /* transfer logging */
@@ -171,6 +176,7 @@ static service sDefault =
NULL, /* auth users */
NULL, /* secrets file */
True, /* strict modes */
NULL, /* filter */
NULL, /* exclude */
NULL, /* exclude from */
NULL, /* include */
@@ -269,6 +275,8 @@ static struct parm_struct parm_table[] =
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
{"max verbosity", P_INTEGER, P_GLOBAL, &Globals.max_verbosity, NULL, 0},
{"port", P_INTEGER, P_GLOBAL, &Globals.rsync_port, NULL, 0},
{"address", P_STRING, P_GLOBAL, &Globals.bind_address, NULL, 0},
{"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
{"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
@@ -277,6 +285,7 @@ static struct parm_struct parm_table[] =
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
{"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL, 0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable, NULL, 0},
@@ -287,6 +296,7 @@ static struct parm_struct parm_table[] =
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes,NULL, 0},
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL, 0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL, 0},
@@ -350,12 +360,15 @@ FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
FN_GLOBAL_INTEGER(lp_max_verbosity, &Globals.max_verbosity)
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
FN_LOCAL_STRING(lp_name, name)
FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_STRING(lp_lock_file, lock_file)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_write_only, write_only)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
@@ -368,6 +381,7 @@ FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
FN_LOCAL_STRING(lp_filter, filter)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
FN_LOCAL_STRING(lp_include, include)
@@ -807,7 +821,7 @@ int lp_number(char *name)
int iService;
for (iService = iNumServices - 1; iService >= 0; iService--)
if (strequal(lp_name(iService), name))
if (strcmp(lp_name(iService), name) == 0)
break;
return (iService);

494
log.c
View File

@@ -27,21 +27,29 @@
*/
#include "rsync.h"
extern int verbose;
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;
extern int protocol_version;
extern int preserve_times;
extern int log_format_has_o_or_i;
extern int daemon_log_format_has_o_or_i;
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;
int log_got_error=0;
int log_got_error = 0;
struct {
int code;
@@ -61,12 +69,13 @@ struct {
{ RERR_WAITCHILD , "some error returned by waitpid()" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files could not be transferred" },
{ RERR_VANISHED , "some files vanished before they could be transfered" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
{ RERR_TIMEOUT , "timeout in data send/receive" },
{ RERR_CMD_FAILED , "remote shell failed" },
{ RERR_CMD_KILLED , "remote shell killed" },
{ RERR_CMD_RUN, "remote command could not be run" },
{ RERR_CMD_NOTFOUND, "remote command not found" },
{ RERR_CMD_RUN , "remote command could not be run" },
{ RERR_CMD_NOTFOUND,"remote command not found" },
{ RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" },
{ 0, NULL }
};
@@ -88,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);
@@ -99,29 +108,14 @@ static void logit(int priority, char *buf)
}
}
void log_init(void)
static void syslog_init()
{
static int been_here = 0;
int options = LOG_PID;
time_t t;
if (log_initialised) return;
log_initialised = 1;
/* this looks pointless, but it is needed in order for the
* C library on some systems to fetch the timezone info
* before the chroot */
t = time(NULL);
localtime(&t);
/* optionally use a log file instead of syslog */
logfname = lp_log_file();
if (logfname) {
if (*logfname) {
log_open();
return;
}
logfname = NULL;
}
if (been_here)
return;
been_here = 1;
#ifdef LOG_NDELAY
options |= LOG_NDELAY;
@@ -134,33 +128,70 @@ void log_init(void)
#endif
#ifndef LOG_NDELAY
logit(LOG_INFO,"rsyncd started\n");
logit(LOG_INFO, "rsyncd started\n");
#endif
}
void log_open(void)
static void logfile_open(void)
{
if (logfname && !logfile) {
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
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_close(void)
void log_init(void)
{
time_t t;
if (log_initialised)
return;
log_initialised = 1;
/* this looks pointless, but it is needed in order for the
* C library on some systems to fetch the timezone info
* before the chroot */
t = time(NULL);
localtime(&t);
/* optionally use a log file instead of syslog */
logfname = lp_log_file();
if (logfname && *logfname)
logfile_open();
else
syslog_init();
}
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)
{
FILE *f=NULL;
FILE *f = NULL;
/* recursion can happen with certain fatal conditions */
if (quiet && code == FINFO)
@@ -171,45 +202,41 @@ void rwrite(enum logcode code, char *buf, int len)
buf[len] = 0;
if (code == FLOG) {
if (am_daemon) logit(LOG_INFO, buf);
if (am_server && msg_fd_out >= 0) {
/* Pass the message to our sibling. */
send_msg((enum msgcode)code, buf, len);
return;
}
if (code == FCLIENT)
code = FINFO;
else if (am_daemon) {
static int in_block;
char msg[2048];
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
if (in_block)
return;
in_block = 1;
if (!log_initialised)
log_init();
strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
logit(priority, msg);
in_block = 0;
if (code == FLOG || !am_server)
return;
} else if (code == FLOG)
return;
if (am_server) {
/* Pass it to non-server side, perhaps through our sibling. */
if (msg_fd_out >= 0) {
send_msg((enum msgcode)code, buf, len);
/* Pass the message to the non-server side. */
if (io_multiplex_write((enum msgcode)code, buf, len))
return;
if (am_daemon) {
/* TODO: can we send the error to the user somehow? */
return;
}
if (!am_daemon
&& io_multiplex_write((enum msgcode)code, buf, len))
return;
}
/* otherwise, if in daemon mode and either we are not a server
* (that is, we are not running --daemon over a remote shell) or
* the log has already been initialised, log the message on this
* side because we don't want the client to see most errors for
* security reasons. We do want early messages when running daemon
* mode over a remote shell to go to the remote side; those will
* fall through to the next case.
* Note that this is only for the time before multiplexing is enabled.
*/
if (am_daemon && (!am_server || log_initialised)) {
static int depth;
int priority = LOG_INFO;
if (code == FERROR) priority = LOG_WARNING;
if (depth) return;
depth++;
log_init();
logit(priority, buf);
depth--;
return;
}
if (code == FERROR) {
@@ -217,55 +244,53 @@ void rwrite(enum logcode code, char *buf, int len)
f = stderr;
}
if (code == FINFO) {
if (am_server)
f = stderr;
else
f = stdout;
}
if (code == FINFO)
f = am_server ? stderr : stdout;
if (!f) exit_cleanup(RERR_MESSAGEIO);
if (!f)
exit_cleanup(RERR_MESSAGEIO);
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
if (fwrite(buf, len, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
if (buf[len-1] == '\r' || buf[len-1] == '\n')
fflush(f);
}
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
char buf[MAXPATHLEN+512];
size_t len;
va_start(ap, format);
/* Note: might return -1 */
len = vsnprintf(buf, sizeof(buf), format, ap);
len = vsnprintf(buf, sizeof buf, format, ap);
va_end(ap);
/* Deal with buffer overruns. Instead of panicking, just
* truncate the resulting string. Note that some vsnprintf()s
* return -1 on truncation, e.g., glibc 2.0.6 and earlier. */
if ((size_t) len > sizeof(buf)-1 || len < 0) {
* truncate the resulting string. (Note that configure ensures
* that we have a vsnprintf() that doesn't ever return -1.) */
if (len > sizeof buf - 1) {
const char ellipsis[] = "[...]";
/* Reset length, and zero-terminate the end of our buffer */
len = sizeof(buf)-1;
len = sizeof buf - 1;
buf[len] = '\0';
/* Copy the ellipsis to the end of the string, but give
* us one extra character:
*
* v--- null byte at buf[sizeof(buf)-1]
* v--- null byte at buf[sizeof buf - 1]
* abcdefghij0
* -> abcd[...]00 <-- now two null bytes at end
*
* If the input format string has a trailing newline,
* we copy it into that extra null; if it doesn't, well,
* all we lose is one byte. */
strncpy(buf+len-sizeof(ellipsis), ellipsis, sizeof(ellipsis));
strncpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
if (format[strlen(format)-1] == '\n') {
buf[len-1] = '\n';
}
@@ -286,33 +311,23 @@ void rprintf(enum logcode code, const char *format, ...)
void rsyserr(enum logcode code, int errcode, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
size_t sys_len;
char *sysmsg;
char buf[MAXPATHLEN+512];
size_t len;
strcpy(buf, RSYNC_NAME ": ");
len = (sizeof RSYNC_NAME ": ") - 1;
va_start(ap, format);
/* Note: might return <0 */
len = vsnprintf(buf, sizeof(buf), format, ap);
len += vsnprintf(buf + len, sizeof buf - len, format, ap);
va_end(ap);
/* TODO: Put in RSYNC_NAME at the start. */
if ((size_t) len > sizeof(buf)-1)
if (len < sizeof buf) {
len += snprintf(buf + len, sizeof buf - len,
": %s (%d)\n", strerror(errcode), errcode);
}
if (len >= sizeof buf)
exit_cleanup(RERR_MESSAGEIO);
sysmsg = strerror(errcode);
sys_len = strlen(sysmsg);
if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
exit_cleanup(RERR_MESSAGEIO);
strcpy(buf + len, ": ");
len += 2;
strcpy(buf + len, sysmsg);
len += sys_len;
strcpy(buf + len, "\n");
len++;
rwrite(code, buf, len);
}
@@ -321,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;
}
@@ -349,49 +364,96 @@ void rflush(enum logcode code)
/* a generic logging routine for send/recv, with parameter
* substitiution */
static void log_formatted(enum logcode code,
char *format, char *op, struct file_struct *file,
struct stats *initial_stats)
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[1024];
char buf2[1024];
char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
char *p, *s, *n;
size_t l;
size_t len, total;
int64 b;
/* 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.
* Just to make sure we don't clobber that nul and therefore
* accidentally keep going, we zero the buffer now. */
memset(buf, 0, sizeof buf);
strlcpy(buf, format, sizeof(buf));
for (s = &buf[0]; s && (p = strchr(s,'%')); ) {
n = NULL;
s = p + 1;
*fmt = '%';
switch (p[1]) {
/* We expand % codes one by one in place in buf. We don't
* 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);
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) {
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,
file->basedir ? file->basedir : "",
f_name(file));
clean_fname(buf2);
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 = safe_fname(f_name(file));
if (S_ISDIR(file->mode)) {
/* The buffer from safe_fname() has more
* room than MAXPATHLEN, so this is safe. */
strcat(n, "/");
}
break;
case 'L':
if (hlink && *hlink) {
n = safe_fname(hlink);
strcpy(buf2, " => ");
} else if (S_ISLNK(file->mode) && file->u.link) {
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;
if (*n == '/') n++;
break;
case 'm': n = lp_name(module_id); break;
case 't': n = timestring(time(NULL)); break;
@@ -405,7 +467,8 @@ static void log_formatted(enum logcode code,
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':
@@ -416,62 +479,165 @@ static void log_formatted(enum logcode code,
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':
if (iflags & ITEM_DELETED) {
n = "*deleting";
break;
}
n = buf2 + MAXPATHLEN - 32;
n[0] = iflags & ITEM_LOCAL_CHANGE
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
: !(iflags & ITEM_TRANSFER) ? '.'
: !local_server && *op == 's' ? '<' : '>';
n[1] = S_ISDIR(file->mode) ? 'd'
: IS_DEVICE(file->mode) ? 'D'
: S_ISLNK(file->mode) ? 'L' : 'f';
n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || IS_DEVICE(file->mode)
|| S_ISLNK(file->mode) ? 'T' : 't';
n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
n[8] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
n[9] = '\0';
if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
char ch = iflags & ITEM_IS_NEW ? '+' : '?';
int i;
for (i = 2; n[i]; i++)
n[i] = ch;
} else if (!(iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE))) {
int i;
for (i = 2; n[i]; i++) {
if (n[i] != '.')
break;
}
if (!n[i]) {
for (i = 2; n[i]; i++)
n[i] = ' ';
}
}
break;
}
/* n is the string to be inserted in place of this %
* code; l is its length not including the trailing
* NUL */
/* "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);
l = strlen(n);
/* Subtract the length of the escape from the string's size. */
total -= p - s + 1;
if (l + ((int)(s - &buf[0])) >= sizeof(buf)) {
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
if (len + total >= (size_t)sizeof buf) {
rprintf(FERROR,
"buffer overflow expanding %%%c -- exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
}
/* Shuffle the rest of the string along to make space for n */
if (l != 2) {
memmove(s+(l-1), s+1, strlen(s+1)+1);
}
if (len != (size_t)(p - s + 1))
memmove(s + len, p + 1, total - (s - buf) + 1);
total += len;
/* Copy in n but NOT its nul, because the format sting
* probably continues after this. */
memcpy(p, n, l);
/* Insert the contents of string "n", but NOT its null. */
if (len)
memcpy(s, n, len);
/* Skip over inserted string; continue looking */
s = p+l;
p = s + len;
}
rprintf(code,"%s\n", buf);
rwrite(code, buf, total);
}
/* log the outgoing transfer of a file */
void log_send(struct file_struct *file, struct stats *initial_stats)
/* 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)
{
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, "send", file, initial_stats);
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 incoming transfer of a file */
void log_recv(struct file_struct *file, struct stats *initial_stats)
/* log the transfer of a file */
void log_item(struct file_struct *file, struct stats *initial_stats,
int iflags, char *hlink)
{
char *s_or_r = am_sender ? "send" : "recv";
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "recv", file, initial_stats);
log_formatted(FLOG, lp_log_format(module_id), s_or_r,
file, initial_stats, iflags, hlink);
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, "recv", file, initial_stats);
log_formatted(FINFO, log_format, s_or_r,
file, initial_stats, iflags, hlink);
}
}
void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
char *buf)
{
int see_item = itemizing && (iflags || verbose > 1);
if (am_server) {
if (am_daemon && !dry_run && see_item)
log_item(file, &stats, iflags, buf);
} else if (see_item || iflags & ITEM_LOCAL_CHANGE || *buf
|| (S_ISDIR(file->mode) && iflags & SIGNIFICANT_ITEM_FLAGS))
log_item(file, &stats, iflags, buf);
}
void log_delete(char *fname, int mode)
{
static struct file_struct file;
int len = strlen(fname);
char *fmt;
file.mode = mode;
file.basename = fname;
if (!verbose && !log_format)
;
else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
if (S_ISDIR(mode))
len++; /* directories include trailing null */
send_msg(MSG_DELETED, fname, len);
} else {
fmt = log_format_has_o_or_i ? log_format : "deleting %n";
log_formatted(FCLIENT, fmt, "del.", &file, &stats,
ITEM_DELETED, NULL);
}
if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
return;
fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
}
/*
@@ -483,7 +649,7 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
void log_exit(int code, const char *file, int line)
{
if (code == 0) {
rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
rprintf(FLOG,"sent %.0f bytes received %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);

713
main.c
View File

File diff suppressed because it is too large Load Diff

176
match.c
View File

@@ -22,11 +22,14 @@
extern int verbose;
extern int am_server;
extern int do_progress;
extern int checksum_seed;
int updating_basis_file;
typedef unsigned short tag;
#define TABLESIZE (1<<16)
#define NULL_TAG ((size_t)-1)
#define NULL_TAG (-1)
static int false_alarms;
static int tag_hits;
@@ -41,12 +44,12 @@ extern struct stats stats;
struct target {
tag t;
size_t i;
int32 i;
};
static struct target *targets;
static size_t *tag_table;
static int32 *tag_table;
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
@@ -59,10 +62,10 @@ static int compare_targets(struct target *t1,struct target *t2)
static void build_hash_table(struct sum_struct *s)
{
size_t i;
int32 i;
if (!tag_table)
tag_table = new_array(size_t, TABLESIZE);
tag_table = new_array(int32, TABLESIZE);
targets = new_array(struct target, s->count);
if (!tag_table || !targets)
@@ -98,17 +101,20 @@ static OFF_T last_match;
* @param i If >0, the number of a matched token. If 0, indicates we
* have only literal data.
**/
static void matched(int f,struct sum_struct *s,struct map_struct *buf,
OFF_T offset,int i)
static void matched(int f, struct sum_struct *s, struct map_struct *buf,
OFF_T offset, int32 i)
{
OFF_T n = offset - last_match;
OFF_T j;
int32 n = offset - last_match; /* max value: block_size (int32) */
int32 j;
if (verbose > 2 && i >= 0)
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%u n=%.0f\n",
(double)offset,(double)last_match,i,s->sums[i].len,(double)n);
if (verbose > 2 && i >= 0) {
rprintf(FINFO,
"match at %.0f last_match=%.0f j=%d len=%ld n=%ld\n",
(double)offset, (double)last_match, i,
(long)s->sums[i].len, (long)n);
}
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
send_token(f, i, buf, last_match, n, i < 0 ? 0 : s->sums[i].len);
data_transfer += n;
if (i >= 0) {
@@ -117,8 +123,8 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
}
for (j = 0; j < n; j += CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,n-j);
sum_update(map_ptr(buf,last_match+j,n1),n1);
int32 n1 = MIN(CHUNK_SIZE, n - j);
sum_update(map_ptr(buf, last_match + j, n1), n1);
}
@@ -127,35 +133,31 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
else
last_match = offset;
if (buf && do_progress) {
if (buf && do_progress)
show_progress(last_match, buf->file_size);
if (i == -1)
end_progress(buf->file_size);
}
}
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf, OFF_T len)
{
OFF_T offset, end;
unsigned int k;
size_t last_i;
OFF_T offset, end, backup;
int32 k, want_i;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
int more;
schar *map;
/* last_i is used to encourage adjacent matches, allowing the RLL coding of the
output to work more efficiently */
last_i = (size_t)-1;
/* want_i is used to encourage adjacent matches, allowing the RLL
* coding of the output to work more efficiently. */
want_i = 0;
if (verbose > 2) {
rprintf(FINFO,"hash search b=%u len=%.0f\n",
s->blength, (double)len);
rprintf(FINFO, "hash search b=%ld len=%.0f\n",
(long)s->blength, (double)len);
}
k = MIN(len, s->blength);
k = (int32)MIN(len, (OFF_T)s->blength);
map = (schar *)map_ptr(buf, 0, k);
@@ -163,21 +165,21 @@ static void hash_search(int f,struct sum_struct *s,
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
rprintf(FINFO, "sum=%.8x k=%u\n", sum, k);
rprintf(FINFO, "sum=%.8x k=%ld\n", sum, (long)k);
offset = 0;
end = len + 1 - s->sums[s->count-1].len;
if (verbose > 3) {
rprintf(FINFO, "hash search s->blength=%u len=%.0f count=%.0f\n",
s->blength, (double)len, (double)s->count);
rprintf(FINFO, "hash search s->blength=%ld len=%.0f count=%.0f\n",
(long)s->blength, (double)len, (double)s->count);
}
do {
tag t = gettag2(s1,s2);
int done_csum2 = 0;
size_t j = tag_table[t];
int32 j = tag_table[t];
if (verbose > 4)
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
@@ -187,18 +189,23 @@ static void hash_search(int f,struct sum_struct *s,
sum = (s1 & 0xffff) | (s2 << 16);
tag_hits++;
for (; j < s->count && targets[j].t == t; j++) {
unsigned int l;
size_t i = targets[j].i;
do {
int32 l, i = targets[j].i;
if (sum != s->sums[i].sum1)
continue;
/* also make sure the two blocks are the same length */
l = MIN((OFF_T)s->blength, len-offset);
l = (int32)MIN((OFF_T)s->blength, len-offset);
if (l != s->sums[i].len)
continue;
/* in-place: ensure chunk's offset is either >= our
* offset or that the data didn't move. */
if (updating_basis_file && s->sums[i].offset < offset
&& !(s->sums[i].flags & SUMFLG_SAME_OFFSET))
continue;
if (verbose > 3)
rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
(double)offset,(double)j,(double)i,sum);
@@ -214,44 +221,70 @@ static void hash_search(int f,struct sum_struct *s,
continue;
}
/* we've found a match, but now check to see
* if last_i can hint at a better match */
for (j++; j < s->count && targets[j].t == t; j++) {
size_t i2 = targets[j].i;
if (i2 == last_i + 1) {
if (sum != s->sums[i2].sum1)
break;
if (memcmp(sum2,s->sums[i2].sum2,s->s2length) != 0)
break;
/* we've found an adjacent match - the RLL coder
* will be happy */
i = i2;
break;
}
/* When updating in-place, the best possible match is
* one with an identical offset, so we prefer that over
* the following want_i optimization. */
if (updating_basis_file) {
do {
int32 i2 = targets[j].i;
if (s->sums[i2].offset != offset)
continue;
if (i2 != i) {
if (sum != s->sums[i2].sum1)
break;
if (memcmp(sum2, s->sums[i2].sum2,
s->s2length) != 0)
break;
i = i2;
}
/* This chunk was at the same offset on
* both the sender and the receiver. */
s->sums[i].flags |= SUMFLG_SAME_OFFSET;
goto set_want_i;
} while (++j < s->count && targets[j].t == t);
}
last_i = i;
/* we've found a match, but now check to see
* if want_i can hint at a better match. */
if (i != want_i && want_i < s->count
&& (!updating_basis_file || s->sums[want_i].offset >= offset
|| s->sums[want_i].flags & SUMFLG_SAME_OFFSET)
&& sum == s->sums[want_i].sum1
&& memcmp(sum2, s->sums[want_i].sum2, s->s2length) == 0) {
/* we've found an adjacent match - the RLL coder
* will be happy */
i = want_i;
}
set_want_i:
want_i = i + 1;
matched(f,s,buf,offset,i);
offset += s->sums[i].len - 1;
k = MIN(s->blength, len-offset);
k = (int32)MIN((OFF_T)s->blength, len-offset);
map = (schar *)map_ptr(buf, offset, k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
matches++;
break;
}
} while (++j < s->count && targets[j].t == t);
null_tag:
backup = offset - last_match;
/* We sometimes read 1 byte prior to last_match... */
if (backup < 0)
backup = 0;
/* Trim off the first byte from the checksum */
map = (schar *)map_ptr(buf, offset, k+1);
more = offset + k < len;
map = (schar *)map_ptr(buf, offset - backup, k + more + backup)
+ backup;
s1 -= map[0] + CHAR_OFFSET;
s2 -= k * (map[0]+CHAR_OFFSET);
/* Add on the next byte (if there is one) to the checksum */
if (k < (len-offset)) {
s1 += (map[k]+CHAR_OFFSET);
if (more) {
s1 += map[k] + CHAR_OFFSET;
s2 += s1;
} else
--k;
@@ -262,15 +295,12 @@ static void hash_search(int f,struct sum_struct *s,
match. The 3 reads are caused by the
running match, the checksum update and the
literal send. */
if (offset > last_match
&& offset-last_match >= CHUNK_SIZE+s->blength
&& end-offset > CHUNK_SIZE) {
matched(f,s,buf,offset - s->blength, -2);
}
if (backup >= s->blength+CHUNK_SIZE && end-offset > CHUNK_SIZE)
matched(f, s, buf, offset - s->blength, -2);
} while (++offset < end);
matched(f,s,buf,len,-1);
map_ptr(buf,len-1,1);
matched(f, s, buf, len, -1);
map_ptr(buf, len-1, 1);
}
@@ -291,7 +321,6 @@ static void hash_search(int f,struct sum_struct *s,
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
{
char file_sum[MD4_SUM_LENGTH];
extern int write_batch;
last_match = 0;
false_alarms = 0;
@@ -299,9 +328,9 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
matches = 0;
data_transfer = 0;
sum_init();
sum_init(checksum_seed);
if (len > 0 && s->count>0) {
if (len > 0 && s->count > 0) {
build_hash_table(s);
if (verbose > 2)
@@ -314,20 +343,19 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
} else {
OFF_T j;
/* by doing this in pieces we avoid too many seeks */
for (j = 0; j < len-CHUNK_SIZE; j += CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
matched(f,s,buf,j+n1,-2);
}
matched(f,s,buf,len,-1);
for (j = CHUNK_SIZE; j < len; j += CHUNK_SIZE)
matched(f, s, buf, j, -2);
matched(f, s, buf, len, -1);
}
sum_end(file_sum);
/* If we had a read error, send a bad checksum. */
if (buf && buf->status != 0)
file_sum[0]++;
if (verbose > 2)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
if (write_batch)
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
if (targets) {
free(targets);

View File

@@ -58,7 +58,7 @@ BEGIN {
next;
}
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^const/ {
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^uchar|^short|^struct|^BOOL|^void|^time|^const/ {
next;
}

1117
options.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,46 @@
Summary: Program for efficient remote updates of files.
Summary: A program for synchronizing files over a network.
Name: rsync
Version: 2.6.2
Version: 2.6.5pre2
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-%{version}.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz
URL: http://rsync.samba.org/
Prefix: %{_prefix}
BuildRoot: /var/tmp/%{name}-root
License: GPL
%description
rsync is a replacement for rcp that has many more features.
Rsync uses a reliable algorithm to bring remote and host files into
sync very quickly. Rsync is fast because it just sends the differences
in the files over the network instead of sending the complete
files. Rsync is often used as a very powerful mirroring process or
just as a more capable replacement for the rcp command. A technical
report which describes the rsync algorithm is included in this
package.
rsync uses the "rsync algorithm" which provides a very fast method for
bringing remote files into sync. It does this by sending just the
differences in the files across the link, without requiring that both
sets of files are present at one of the ends of the link beforehand.
%prep
%setup -q
A technical report describing the rsync algorithm is included with
this package.
%build
%configure
make
%install
rm -rf $RPM_BUILD_ROOT
%makeinstall
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc COPYING README tech_report.tex
%{_prefix}/bin/rsync
%{_mandir}/man1/rsync.1*
%{_mandir}/man5/rsyncd.conf.5*
%changelog
* Thu Jan 30 2003 Horst von Brand <vonbrand@inf.utfsm.cl>
@@ -64,30 +86,3 @@ to '%build', removed '%prefix'.
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
previous package(s).)
%prep
%setup
%build
./configure --prefix=/usr --mandir=%{_mandir}
make CFLAGS="$RPM_OPT_FLAGS"
strip rsync
%install
mkdir -p $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man{1,5}
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
install -m644 rsync.1 $RPM_BUILD_ROOT/%{_mandir}/man1
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5
%clean
rm -rf $RPM_BUILD_ROOT
%files
%attr(-,root,root) /usr/bin/rsync
%attr(-,root,root) %{_mandir}/man1/rsync.1*
%attr(-,root,root) %{_mandir}/man5/rsyncd.conf.5*
%attr(-,root,root) %doc tech_report.tex
%attr(-,root,root) %doc README
%attr(-,root,root) %doc COPYING
%attr(-,root,root) %doc doc/README-SGML doc/rsync.sgml

View File

@@ -491,8 +491,8 @@ static FILE *OpenConfFile( char *FileName )
OpenedFile = fopen( FileName, "r" );
if( NULL == OpenedFile )
{
rprintf(FERROR,"rsync: unable to open configuration file \"%s\": %s\n",
FileName, strerror(errno));
rsyserr(FERROR, errno, "rsync: unable to open configuration file \"%s\"",
safe_fname(FileName));
}
return( OpenedFile );

64
pipe.c
View File

@@ -1,19 +1,19 @@
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 1996-2000 by Andrew Tridgell
*
* Copyright (C) 1996-2000 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -25,14 +25,13 @@ extern int am_sender;
extern int am_server;
extern int blocking_io;
extern int orig_umask;
extern int read_batch;
extern int filesfrom_fd;
/**
* Create a child connected to use on stdin/stdout.
*
* This is derived from CVS code
*
* This is derived from CVS code
*
* Note that in the child STDIN is set to blocking and STDOUT
* is set to non-blocking. This is necessary as rsh relies on stdin being blocking
* and ssh relies on stdout being non-blocking
@@ -46,20 +45,19 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
pid_t pid;
int to_child_pipe[2];
int from_child_pipe[2];
if (verbose >= 2) {
print_child_argv(command);
}
if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
rprintf(FERROR, "pipe: %s\n", strerror(errno));
rsyserr(FERROR, errno, "pipe");
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid == -1) {
rprintf(FERROR, "fork: %s\n", strerror(errno));
rsyserr(FERROR, errno, "fork");
exit_cleanup(RERR_IPC);
}
@@ -68,8 +66,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
rprintf(FERROR, "Failed to dup/close : %s\n",
strerror(errno));
rsyserr(FERROR, errno, "Failed to dup/close");
exit_cleanup(RERR_IPC);
}
if (to_child_pipe[0] != STDIN_FILENO)
@@ -81,13 +78,13 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
if (blocking_io > 0)
set_blocking(STDOUT_FILENO);
execvp(command[0], command);
rprintf(FERROR, "Failed to exec %s : %s\n",
command[0], strerror(errno));
rsyserr(FERROR, errno, "Failed to exec %s",
safe_fname(command[0]));
exit_cleanup(RERR_IPC);
}
if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
rsyserr(FERROR, errno, "Failed to close");
exit_cleanup(RERR_IPC);
}
@@ -97,7 +94,17 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
return pid;
}
pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
/* This function forks a child which calls child_main(). First,
* however, it has to establish communication paths to and from the
* newborn child. It creates two socket pairs -- one for writing to
* the child (from the parent) and one for reading from the child
* (writing to the parent). Since that's four socket ends, each
* process has to close the two ends it doesn't need. The remaining
* two socket ends are retained for reading and writing. In the
* child, the STDIN and STDOUT file descriptors refer to these
* sockets. In the parent, the function arguments f_in and f_out are
* set to refer to these sockets. */
pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
int (*child_main)(int, char*[]))
{
pid_t pid;
@@ -106,20 +113,19 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
rsyserr(FERROR, errno, "pipe");
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
rsyserr(FERROR, errno, "fork");
exit_cleanup(RERR_IPC);
}
if (pid == 0) {
am_sender = read_batch ? 0 : !am_sender;
am_server = 1;
am_sender = !am_sender;
am_server = 1;
if (!am_sender)
filesfrom_fd = -1;
@@ -128,11 +134,13 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
rsyserr(FERROR, errno, "Failed to dup/close");
exit_cleanup(RERR_IPC);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
if (to_child_pipe[0] != STDIN_FILENO)
close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO)
close(from_child_pipe[1]);
child_main(argc, argv);
}
@@ -141,12 +149,12 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
rsyserr(FERROR, errno, "Failed to close");
exit_cleanup(RERR_IPC);
}
*f_in = from_child_pipe[0];
*f_out = to_child_pipe[1];
return pid;
}

View File

@@ -1128,7 +1128,7 @@ const char * poptBadOption(poptContext con, int flags)
/*@=nullderef@*/
}
const char *const poptStrerror(const int error)
const char * poptStrerror(const int error)
{
switch (error) {
case POPT_ERROR_NOARG:

View File

@@ -373,7 +373,7 @@ int poptParseArgvString(const unsigned char * s,
* @return error string
*/
/*@-redecl@*/
/*@observer@*/ const char *const poptStrerror(const int error)
/*@observer@*/ const char * poptStrerror(const int error)
/*@*/;
/*@=redecl@*/

View File

@@ -63,7 +63,7 @@ struct poptOption poptHelpOptions[] = {
/**
* @param table option(s)
*/
/*@observer@*/ /*@null@*/ static const char *const
/*@observer@*/ /*@null@*/ static const char *
getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
/*@*/
{
@@ -81,7 +81,7 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
* @param opt option(s)
* @param translation_domain translation domain
*/
/*@observer@*/ /*@null@*/ static const char *const
/*@observer@*/ /*@null@*/ static const char *
getArgDescrip(const struct poptOption * opt,
/*@-paramuse@*/ /* FIX: wazzup? */
/*@null@*/ UNUSED(const char * translation_domain))

View File

@@ -26,6 +26,12 @@ extern int am_server;
#define PROGRESS_HISTORY_SECS 5
#ifdef GETPGRP_VOID
#define GETPGRP_ARG
#else
#define GETPGRP_ARG 0
#endif
struct progress_history {
struct timeval time;
OFF_T ofs;
@@ -61,17 +67,18 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
if (is_last) {
/* Compute stats based on the starting info. */
diff = msdiff(&ph_start.time, now);
if (!diff)
if (!ph_start.time.tv_sec
|| !(diff = msdiff(&ph_start.time, now)))
diff = 1;
rate = (double) (ofs - ph_start.ofs) * 1000.0 / diff / 1024.0;
/* Switch to total time taken for our last update. */
remain = (double) diff / 1000.0;
} else {
/* Compute stats based on recent progress. */
diff = msdiff(&ph_list[oldest_hpos].time, now);
rate = diff ? (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
/ diff / 1024.0 : 0;
if (!(diff = msdiff(&ph_list[oldest_hpos].time, now)))
diff = 1;
rate = (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
/ diff / 1024.0;
remain = rate ? (double) (size - ofs) / rate / 1000.0 : 0.0;
}
@@ -115,10 +122,19 @@ void end_progress(OFF_T size)
void show_progress(OFF_T ofs, OFF_T size)
{
struct timeval now;
#if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
static pid_t pgrp = -1;
pid_t tc_pgrp;
#endif
if (am_server)
return;
#if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
if (pgrp == -1)
pgrp = getpgrp(GETPGRP_ARG);
#endif
gettimeofday(&now, NULL);
if (!ph_start.time.tv_sec) {
@@ -150,5 +166,11 @@ void show_progress(OFF_T ofs, OFF_T size)
ph_list[newest_hpos].ofs = ofs;
}
#if defined HAVE_GETPGRP && defined HAVE_TCGETPGRP
tc_pgrp = tcgetpgrp(STDOUT_FILENO);
if (tc_pgrp != pgrp && tc_pgrp != -1)
return;
#endif
rprint_progress(ofs, size, &now, False);
}

View File

@@ -21,110 +21,104 @@
#include "rsync.h"
extern int verbose;
extern int recurse;
extern int delete_mode;
extern int delete_after;
extern int max_delete;
extern int csum_length;
extern struct stats stats;
extern int dry_run;
extern int do_xfers;
extern int am_daemon;
extern int am_server;
extern int do_progress;
extern int log_before_transfer;
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;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int preserve_perms;
extern int cvs_exclude;
extern int io_error;
extern char *tmpdir;
extern char *compare_dest;
extern int basis_dir_cnt;
extern int make_backups;
extern int do_progress;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
extern int cleanup_got_literal;
extern int remove_sent_files;
extern int module_id;
extern int ignore_errors;
extern int orig_umask;
extern int keep_partial;
extern int checksum_seed;
extern int inplace;
extern int delay_updates;
extern struct stats stats;
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;
static void delete_one(char *fn, int is_dir)
#define SLOT_SIZE (16*1024) /* Desired size in bytes */
#define PER_SLOT_BITS (SLOT_SIZE * 8) /* Number of bits per slot */
#define PER_SLOT_INTS (SLOT_SIZE / 4) /* Number of int32s per slot */
static uint32 **delayed_bits = NULL;
static int delayed_slot_cnt = 0;
static int phase = 0;
static void init_delayed_bits(int max_ndx)
{
if (!is_dir) {
if (robust_unlink(fn) != 0) {
rprintf(FERROR, "delete_one: unlink %s failed: %s\n",
full_fname(fn), strerror(errno));
} else if (verbose) {
rprintf(FINFO, "deleting %s\n", fn);
}
} else {
if (do_rmdir(fn) != 0) {
if (errno != ENOTEMPTY && errno != EEXIST) {
rprintf(FERROR, "delete_one: rmdir %s failed: %s\n",
full_fname(fn), strerror(errno));
}
} else if (verbose) {
rprintf(FINFO, "deleting directory %s\n", fn);
}
}
delayed_slot_cnt = (max_ndx + PER_SLOT_BITS - 1) / PER_SLOT_BITS;
if (!(delayed_bits = (uint32**)calloc(delayed_slot_cnt, sizeof (uint32*))))
out_of_memory("set_delayed_bit");
}
static int is_backup_file(char *fn)
static void set_delayed_bit(int ndx)
{
int k = strlen(fn) - backup_suffix_len;
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
}
int slot = ndx / PER_SLOT_BITS;
ndx %= PER_SLOT_BITS;
/* This deletes any files on the receiving side that are not present
* on the sending side. */
void delete_files(struct file_list *flist)
{
struct file_list *local_file_list;
int i, j;
char *argv[1], fbuf[MAXPATHLEN];
static int deletion_count;
if (cvs_exclude)
add_cvs_excludes();
if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
return;
if (!delayed_bits[slot]) {
if (!(delayed_bits[slot] = (uint32*)calloc(PER_SLOT_INTS, 4)))
out_of_memory("set_delayed_bit");
}
for (j = 0; j < flist->count; j++) {
if (!(flist->files[j]->flags & FLAG_TOP_DIR)
|| !S_ISDIR(flist->files[j]->mode))
delayed_bits[slot][ndx/32] |= 1u << (ndx % 32);
}
/* Call this with -1 to start checking from 0. Returns -1 at the end. */
static int next_delayed_bit(int after)
{
uint32 bits, mask;
int i, ndx = after + 1;
int slot = ndx / PER_SLOT_BITS;
ndx %= PER_SLOT_BITS;
mask = (1u << (ndx % 32)) - 1;
for (i = ndx / 32; slot < delayed_slot_cnt; slot++, i = mask = 0) {
if (!delayed_bits[slot])
continue;
argv[0] = f_name_to(flist->files[j], fbuf);
if (!(local_file_list = send_file_list(-1, 1, argv)))
continue;
if (verbose > 1)
rprintf(FINFO, "deleting in %s\n", fbuf);
for (i = local_file_list->count-1; i >= 0; i--) {
if (max_delete && deletion_count > max_delete)
break;
if (!local_file_list->files[i]->basename)
for ( ; i < PER_SLOT_INTS; i++, mask = 0) {
if (!(bits = delayed_bits[slot][i] & ~mask))
continue;
if (flist_find(flist,local_file_list->files[i]) < 0) {
char *f = f_name(local_file_list->files[i]);
if (make_backups && (backup_dir || !is_backup_file(f))) {
(void) make_backup(f);
if (verbose)
rprintf(FINFO, "deleting %s\n", f);
} else {
int mode = local_file_list->files[i]->mode;
delete_one(f, S_ISDIR(mode) != 0);
}
deletion_count++;
/* The xor magic figures out the lowest enabled bit in
* bits, and the switch quickly computes log2(bit). */
switch (bits ^ (bits & (bits-1))) {
#define LOG2(n) case 1u << n: return slot*PER_SLOT_BITS + i*32 + n
LOG2(0); LOG2(1); LOG2(2); LOG2(3);
LOG2(4); LOG2(5); LOG2(6); LOG2(7);
LOG2(8); LOG2(9); LOG2(10); LOG2(11);
LOG2(12); LOG2(13); LOG2(14); LOG2(15);
LOG2(16); LOG2(17); LOG2(18); LOG2(19);
LOG2(20); LOG2(21); LOG2(22); LOG2(23);
LOG2(24); LOG2(25); LOG2(26); LOG2(27);
LOG2(28); LOG2(29); LOG2(30); LOG2(31);
}
return -1; /* impossible... */
}
flist_free(local_file_list);
}
return -1;
}
@@ -177,7 +171,8 @@ static int get_tmpname(char *fnametmp, char *fname)
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
if (maxname < 1) {
rprintf(FERROR, "temporary filename too long: %s\n", fname);
rprintf(FERROR, "temporary filename too long: %s\n",
safe_fname(fname));
fnametmp[0] = '\0';
return 0;
}
@@ -189,22 +184,33 @@ static int get_tmpname(char *fnametmp, char *fname)
}
static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
OFF_T total_size)
static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
char *fname, int fd, OFF_T total_size)
{
int i;
static char file_sum1[MD4_SUM_LENGTH];
static char file_sum2[MD4_SUM_LENGTH];
struct map_struct *mapbuf;
struct sum_struct sum;
unsigned int len;
int32 len;
OFF_T offset = 0;
OFF_T offset2;
char *data;
static char file_sum1[MD4_SUM_LENGTH];
static char file_sum2[MD4_SUM_LENGTH];
char *map=NULL;
int32 i;
char *map = NULL;
read_sum_head(f_in, &sum);
sum_init();
if (fd_r >= 0 && size_r > 0) {
int32 read_size = MAX(sum.blength * 2, 16*1024);
mapbuf = map_file(fd_r, size_r, read_size, sum.blength);
if (verbose > 2) {
rprintf(FINFO, "recv mapped %s of size %.0f\n",
safe_fname(fname_r), (double)size_r);
}
} else
mapbuf = NULL;
sum_init(checksum_seed);
while ((i = recv_token(f_in, &data)) != 0) {
if (do_progress)
@@ -219,160 +225,331 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
stats.literal_data += i;
cleanup_got_literal = 1;
sum_update(data,i);
sum_update(data, i);
if (fd != -1 && write_file(fd,data,i) != i) {
rprintf(FERROR, "write failed on %s: %s\n",
full_fname(fname), strerror(errno));
exit_cleanup(RERR_FILEIO);
}
if (fd != -1 && write_file(fd,data,i) != i)
goto report_write_error;
offset += i;
continue;
}
i = -(i+1);
offset2 = i*(OFF_T)sum.blength;
offset2 = i * (OFF_T)sum.blength;
len = sum.blength;
if (i == (int) sum.count-1 && sum.remainder != 0)
if (i == (int)sum.count-1 && sum.remainder != 0)
len = sum.remainder;
stats.matched_data += len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
i,len,(double)offset2,(double)offset);
if (verbose > 3) {
rprintf(FINFO,
"chunk[%d] of size %ld at %.0f offset=%.0f\n",
i, (long)len, (double)offset2, (double)offset);
}
if (mapbuf) {
map = map_ptr(mapbuf,offset2,len);
see_token(map, len);
sum_update(map,len);
sum_update(map, len);
}
if (fd != -1 && write_file(fd,map,len) != (int) len) {
rprintf(FERROR, "write failed on %s: %s\n",
full_fname(fname), strerror(errno));
exit_cleanup(RERR_FILEIO);
if (inplace) {
if (offset == offset2 && fd != -1) {
if (flush_write_file(fd) < 0)
goto report_write_error;
offset += len;
if (do_lseek(fd, len, SEEK_CUR) != offset) {
rsyserr(FERROR, errno,
"lseek failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
continue;
}
}
if (fd != -1 && map && write_file(fd, map, len) != (int)len)
goto report_write_error;
offset += len;
}
flush_write_file(fd);
if (flush_write_file(fd) < 0)
goto report_write_error;
#ifdef HAVE_FTRUNCATE
if (inplace && fd != -1)
ftruncate(fd, offset);
#endif
if (do_progress)
end_progress(total_size);
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
rprintf(FERROR, "write failed on %s: %s\n",
full_fname(fname), strerror(errno));
report_write_error:
rsyserr(FERROR, errno, "write failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
sum_end(file_sum1);
if (mapbuf)
unmap_file(mapbuf);
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
if (verbose > 2) {
if (verbose > 2)
rprintf(FINFO,"got file_sum\n");
}
if (fd != -1 && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
if (fd != -1 && memcmp(file_sum1, file_sum2, MD4_SUM_LENGTH) != 0)
return 0;
}
return 1;
}
static void discard_receive_data(int f_in, OFF_T length)
{
receive_data(f_in, NULL, -1, 0, NULL, -1, length);
}
static void handle_delayed_updates(struct file_list *flist, char *local_name)
{
char *fname, *partialptr, numbuf[4];
int i;
for (i = -1; (i = next_delayed_bit(i)) >= 0; ) {
struct file_struct *file = flist->files[i];
fname = local_name ? local_name : f_name(file);
if ((partialptr = partial_dir_fname(fname)) != NULL) {
if (make_backups && !make_backup(fname))
continue;
if (verbose > 2) {
rprintf(FINFO, "renaming %s to %s\n",
safe_fname(partialptr),
safe_fname(fname));
}
if (do_rename(partialptr, fname) < 0) {
rsyserr(FERROR, errno,
"rename failed for %s (from %s)",
full_fname(fname),
safe_fname(partialptr));
} else {
if (remove_sent_files
|| (preserve_hard_links
&& file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS,numbuf,4);
}
handle_partial_dir(partialptr,
PDIR_DELETE);
}
}
}
}
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.
*
* Receiver process runs on the same host as the generator process. */
int recv_files(int f_in,struct file_list *flist,char *local_name)
int recv_files(int f_in, struct file_list *flist, char *local_name)
{
int next_gen_i = -1;
int fd1,fd2;
STRUCT_STAT st;
int iflags, xlen;
char *fname, fbuf[MAXPATHLEN];
char template[MAXPATHLEN];
char xname[MAXPATHLEN];
char fnametmp[MAXPATHLEN];
char *fnamecmp;
char *fnamecmp, *partialptr, numbuf[4];
char fnamecmpbuf[MAXPATHLEN];
struct map_struct *mapbuf;
int i;
uchar fnamecmp_type;
struct file_struct *file;
int phase=0;
int recv_ok;
struct stats initial_stats;
int save_make_backups = make_backups;
int itemizing = am_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
int max_phase = protocol_version >= 29 ? 2 : 1;
int i, recv_ok;
if (verbose > 2) {
if (verbose > 2)
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
if (flist->hlink_pool) {
pool_destroy(flist->hlink_pool);
flist->hlink_pool = NULL;
}
if (delay_updates)
init_delayed_bits(flist->count);
while (1) {
cleanup_disable();
i = read_int(f_in);
if (i == -1) {
if (phase == 0) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO,"recv_files phase=%d\n",phase);
send_msg(MSG_DONE, "", 0);
continue;
if (read_batch) {
get_next_gen_i(batch_gen_fd, next_gen_i,
flist->count);
next_gen_i = -1;
}
break;
if (++phase > max_phase)
break;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO, "recv_files phase=%d\n", phase);
if (phase == 2 && delay_updates)
handle_delayed_updates(flist, local_name);
send_msg(MSG_DONE, "", 0);
if (keep_partial && !partial_dir)
make_backups = 0; /* prevents double backup */
continue;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
i, flist->count);
exit_cleanup(RERR_PROTOCOL);
}
iflags = read_item_attrs(f_in, -1, i, &fnamecmp_type,
xname, &xlen);
if (iflags == ITEM_IS_NEW) /* no-op packet */
continue;
file = flist->files[i];
fname = local_name ? local_name : f_name_to(file, fbuf);
if (verbose > 2)
rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
continue;
}
if (phase == 2) {
rprintf(FERROR,
"got transfer request in phase 2 [%s]\n",
who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
stats.current_file_index = i;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
cleanup_got_literal = 0;
if (local_name)
fname = local_name;
else
fname = f_name_to(file, fbuf);
if (server_filter_list.head
&& check_filter(&server_filter_list, fname, 0) < 0) {
rprintf(FERROR, "attempt to hack rsync failed.\n");
exit_cleanup(RERR_PROTOCOL);
}
if (dry_run) {
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname);
}
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) {
next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i);
if (i < next_gen_i) {
rprintf(FINFO, "(Skipping batched update for \"%s\")\n",
safe_fname(fname));
discard_receive_data(f_in, file->length);
continue;
}
next_gen_i = -1;
}
partialptr = partial_dir ? partial_dir_fname(fname) : fname;
if (protocol_version >= 29) {
switch (fnamecmp_type) {
case FNAMECMP_FNAME:
fnamecmp = fname;
break;
case FNAMECMP_PARTIAL_DIR:
fnamecmp = partialptr;
break;
case FNAMECMP_BACKUP:
fnamecmp = get_backup_name(fname);
break;
case FNAMECMP_FUZZY:
if (file->dirname) {
pathjoin(fnamecmpbuf, MAXPATHLEN,
file->dirname, xname);
fnamecmp = fnamecmpbuf;
} else
fnamecmp = xname;
break;
default:
if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
fnamecmp_type);
exit_cleanup(RERR_PROTOCOL);
}
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
basis_dir[fnamecmp_type], fname);
fnamecmp = fnamecmpbuf;
break;
}
if (!fnamecmp || (server_filter_list.head
&& check_filter(&server_filter_list, fname, 0) < 0))
fnamecmp = fname;
} else {
/* Reminder: --inplace && --partial-dir are never
* enabled at the same time. */
if (inplace && make_backups) {
if (!(fnamecmp = get_backup_name(fname)))
fnamecmp = fname;
} else if (partial_dir && partialptr)
fnamecmp = partialptr;
else
fnamecmp = fname;
}
initial_stats = stats;
if (verbose > 2)
rprintf(FINFO,"recv_files(%s)\n",fname);
fnamecmp = fname;
/* open the file */
fd1 = do_open(fnamecmp, O_RDONLY, 0);
if (fd1 == -1 && compare_dest != NULL) {
/* try the file at compare_dest instead */
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
compare_dest, fname);
fnamecmp = fnamecmpbuf;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
if (fd1 == -1 && protocol_version < 29) {
if (fnamecmp != fname) {
fnamecmp = fname;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
}
if (fd1 == -1 && basis_dir[0]) {
/* pre-29 allowed only one alternate basis */
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
basis_dir[0], fname);
fnamecmp = fnamecmpbuf;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
}
}
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rprintf(FERROR, "fstat %s failed: %s\n",
full_fname(fnamecmp), strerror(errno));
receive_data(f_in,NULL,-1,NULL,file->length);
rsyserr(FERROR, errno, "fstat %s failed",
full_fname(fnamecmp));
discard_receive_data(f_in, file->length);
close(fd1);
continue;
}
@@ -385,7 +562,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name)
*/
rprintf(FERROR,"recv_files: %s is a directory\n",
full_fname(fnamecmp));
receive_data(f_in, NULL, -1, NULL, file->length);
discard_receive_data(f_in, file->length);
close(fd1);
continue;
}
@@ -393,7 +570,6 @@ int recv_files(int f_in,struct file_list *flist,char *local_name)
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
close(fd1);
fd1 = -1;
mapbuf = NULL;
}
if (fd1 != -1 && !preserve_perms) {
@@ -403,91 +579,135 @@ int recv_files(int f_in,struct file_list *flist,char *local_name)
file->mode = st.st_mode;
}
if (fd1 != -1 && st.st_size > 0) {
mapbuf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
} else
mapbuf = NULL;
/* We now check to see if we are writing file "inplace" */
if (inplace) {
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0);
if (fd2 == -1) {
rsyserr(FERROR, errno, "open %s failed",
full_fname(fname));
discard_receive_data(f_in, file->length);
if (fd1 != -1)
close(fd1);
continue;
}
} else {
if (!get_tmpname(fnametmp,fname)) {
discard_receive_data(f_in, file->length);
if (fd1 != -1)
close(fd1);
continue;
}
if (!get_tmpname(fnametmp,fname)) {
if (mapbuf) unmap_file(mapbuf);
if (fd1 != -1) close(fd1);
continue;
}
strlcpy(template, fnametmp, sizeof template);
/* we initially set the perms without the
* setuid/setgid bits to ensure that there is no race
* condition. They are then correctly updated after
* the lchown. Thanks to snabb@epipe.fi for pointing
* this out. We also set it initially without group
* access because of a similar race condition. */
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
/* in most cases parent directories will already exist
* because their information should have been previously
* transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp, orig_umask) == 0) {
strlcpy(fnametmp, template, sizeof fnametmp);
/* we initially set the perms without the
* setuid/setgid bits to ensure that there is no race
* condition. They are then correctly updated after
* the lchown. Thanks to snabb@epipe.fi for pointing
* this out. We also set it initially without group
* access because of a similar race condition. */
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR, "mkstemp %s failed: %s\n",
full_fname(fnametmp), strerror(errno));
receive_data(f_in,mapbuf,-1,NULL,file->length);
if (mapbuf) unmap_file(mapbuf);
if (fd1 != -1) close(fd1);
continue;
/* in most cases parent directories will already exist
* because their information should have been previously
* transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT
&& create_directory_path(fnametmp, orig_umask) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rsyserr(FERROR, errno, "mkstemp %s failed",
full_fname(fnametmp));
discard_receive_data(f_in, file->length);
if (fd1 != -1)
close(fd1);
continue;
}
if (partialptr)
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
}
cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname);
}
/* log the transfer */
if (log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FINFO, "%s\n", safe_fname(fname));
/* recv file data */
recv_ok = receive_data(f_in,mapbuf,fd2,fname,file->length);
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
fname, fd2, file->length);
log_recv(file, &initial_stats);
if (!log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
if (mapbuf) unmap_file(mapbuf);
if (fd1 != -1) {
if (fd1 != -1)
close(fd1);
}
if (close(fd2) < 0) {
rprintf(FERROR, "close failed on %s: %s\n",
full_fname(fnametmp), strerror(errno));
rsyserr(FERROR, errno, "close failed on %s",
full_fname(fnametmp));
exit_cleanup(RERR_FILEIO);
}
if (verbose > 2)
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
finish_transfer(fname, fnametmp, file);
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
finish_transfer(fname, fnametmp, file, recv_ok, 1);
if (partialptr != fname && fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, file, recv_ok,
!partial_dir);
if (delay_updates && recv_ok) {
set_delayed_bit(i);
recv_ok = -1;
}
} else {
partialptr = NULL;
do_unlink(fnametmp);
}
cleanup_disable();
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
full_fname(fname));
} else {
char buf[4];
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
SIVAL(buf, 0, i);
send_msg(MSG_REDO, buf, 4);
if (recv_ok > 0) {
if (remove_sent_files
|| (preserve_hard_links && file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS, numbuf, 4);
}
} else if (!recv_ok) {
int msgtype = phase || read_batch ? FERROR : FINFO;
if (msgtype == FERROR || verbose) {
char *errstr, *redostr, *keptstr;
if (!(keep_partial && partialptr) && !inplace)
keptstr = "discarded";
else if (partial_dir)
keptstr = "put into partial-dir";
else
keptstr = "retained";
if (msgtype == FERROR) {
errstr = "ERROR";
redostr = "";
} else {
errstr = "WARNING";
redostr = " (will try again)";
}
rprintf(msgtype,
"%s: %s failed verification -- update %s%s.\n",
errstr, safe_fname(fname),
keptstr, redostr);
}
if (!phase) {
SIVAL(numbuf, 0, i);
send_msg(MSG_REDO, numbuf, 4);
}
}
}
make_backups = save_make_backups;
if (delete_after && recurse && delete_mode && !local_name
&& flist->count > 0)
delete_files(flist);
if (phase == 2 && delay_updates) /* for protocol_version < 29 */
handle_delayed_updates(flist, local_name);
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");

185
rsync.c
View File

@@ -24,15 +24,20 @@
extern int verbose;
extern int dry_run;
extern int daemon_log_format_has_i;
extern int preserve_times;
extern int omit_dir_times;
extern int am_root;
extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_starting_up;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_perms;
extern int inplace;
extern int keep_dirlinks;
extern int make_backups;
extern struct stats stats;
/*
@@ -45,109 +50,32 @@ void free_sums(struct sum_struct *s)
}
/*
* delete a file or directory. If force_delete is set then delete
* recursively
*/
int delete_file(char *fname)
{
DIR *d;
struct dirent *di;
char buf[MAXPATHLEN];
extern int force_delete;
STRUCT_STAT st;
int ret;
extern int recurse;
#if SUPPORT_LINKS
ret = do_lstat(fname, &st);
#else
ret = do_stat(fname, &st);
#endif
if (ret)
return -1;
if (!S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) == 0 || errno == ENOENT)
return 0;
rprintf(FERROR, "delete_file: unlink %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
}
if (do_rmdir(fname) == 0 || errno == ENOENT)
return 0;
if (!force_delete || !recurse
|| (errno != ENOTEMPTY && errno != EEXIST)) {
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
}
/* now we do a recsursive delete on the directory ... */
if (!(d = opendir(fname))) {
rprintf(FERROR, "delete_file: opendir %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
}
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
char *dname = d_name(di);
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
continue;
pathjoin(buf, sizeof buf, fname, dname);
if (verbose > 0)
rprintf(FINFO, "deleting %s\n", buf);
if (delete_file(buf) != 0) {
closedir(d);
return -1;
}
}
if (errno) {
rprintf(FERROR, "delete_file: readdir %s failed: %s\n",
full_fname(fname), strerror(errno));
closedir(d);
return -1;
}
closedir(d);
if (do_rmdir(fname) != 0) {
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
full_fname(fname), strerror(errno));
return -1;
}
return 0;
}
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
int report)
int flags)
{
int updated = 0;
STRUCT_STAT st2;
int change_uid, change_gid;
if (dry_run) return 0;
if (!st) {
if (link_stat(fname,&st2) != 0) {
rprintf(FERROR, "stat %s failed: %s\n",
full_fname(fname), strerror(errno));
if (dry_run)
return 1;
if (link_stat(fname, &st2, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(fname));
return 0;
}
st = &st2;
}
if (preserve_times && !S_ISLNK(st->st_mode) &&
cmp_modtime(st->st_mtime, file->modtime) != 0) {
/* don't complain about not setting times on directories
* because some filesystems can't do it */
if (set_modtime(fname,file->modtime) != 0 &&
!S_ISDIR(st->st_mode)) {
rprintf(FERROR, "failed to set times on %s: %s\n",
full_fname(fname), strerror(errno));
if (!preserve_times || S_ISLNK(st->st_mode)
|| (S_ISDIR(st->st_mode) && omit_dir_times))
flags |= PERMS_SKIP_MTIME;
if (!(flags & PERMS_SKIP_MTIME)
&& cmp_modtime(st->st_mtime, file->modtime) != 0) {
if (set_modtime(fname,file->modtime) != 0) {
rsyserr(FERROR, errno, "failed to set times on %s",
full_fname(fname));
return 0;
}
updated = 1;
@@ -156,17 +84,24 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
change_gid = preserve_gid && file->gid != GID_NONE
&& st->st_gid != file->gid;
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
if (S_ISLNK(st->st_mode))
;
else
#endif
if (change_uid || change_gid) {
if (verbose > 2) {
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %ld to %ld\n",
fname, (long)st->st_uid, (long)file->uid);
"set uid of %s from %ld to %ld\n",
safe_fname(fname),
(long)st->st_uid, (long)file->uid);
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %ld to %ld\n",
fname, (long)st->st_gid, (long)file->gid);
"set gid of %s from %ld to %ld\n",
safe_fname(fname),
(long)st->st_gid, (long)file->gid);
}
}
if (do_lchown(fname,
@@ -174,16 +109,17 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
change_gid ? file->gid : st->st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
* unless have the privilege */
rprintf(FERROR, "%s %s failed: %s\n",
rsyserr(FERROR, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname), strerror(errno));
full_fname(fname));
return 0;
}
/* a lchown had been done - we have to re-stat if the
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
if (st->st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, st);
link_stat(fname, st,
keep_dirlinks && S_ISDIR(st->st_mode));
}
updated = 1;
}
@@ -193,19 +129,21 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
updated = 1;
if (do_chmod(fname,(file->mode & CHMOD_BITS)) != 0) {
rprintf(FERROR, "failed to set permissions on %s: %s\n",
full_fname(fname), strerror(errno));
rsyserr(FERROR, errno, "failed to set permissions on %s",
full_fname(fname));
return 0;
}
}
}
#endif
if (verbose > 1 && report) {
if (verbose > 1 && flags & PERMS_REPORT) {
enum logcode code = daemon_log_format_has_i || dry_run
? FCLIENT : FINFO;
if (updated)
rprintf(FINFO,"%s\n",fname);
rprintf(code, "%s\n", safe_fname(fname));
else
rprintf(FINFO,"%s is uptodate\n",fname);
rprintf(code, "%s is uptodate\n", safe_fname(fname));
}
return updated;
}
@@ -228,26 +166,47 @@ void sig_int(void)
/* finish off a file transfer, renaming the file and setting the permissions
and ownership */
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file,
int ok_to_set_time, int overwriting_basis)
{
int ret;
if (make_backups && !make_backup(fname))
if (inplace) {
if (verbose > 2)
rprintf(FINFO, "finishing %s\n", safe_fname(fname));
goto do_set_perms;
}
if (make_backups && overwriting_basis && !make_backup(fname))
return;
/* Change permissions before putting the file into place. */
set_perms(fnametmp, file, NULL, ok_to_set_time ? 0 : PERMS_SKIP_MTIME);
/* move tmp file over real file */
if (verbose > 2) {
rprintf(FINFO, "renaming %s to %s\n",
safe_fname(fnametmp), safe_fname(fname));
}
ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
if (ret < 0) {
rprintf(FERROR, "%s %s -> \"%s\": %s\n",
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname, strerror(errno));
full_fname(fnametmp), safe_fname(fname));
do_unlink(fnametmp);
} else {
set_perms(fname,file,NULL,0);
return;
}
if (ret == 0) {
/* The file was moved into place (not copied), so it's done. */
return;
}
do_set_perms:
set_perms(fname, file, NULL, ok_to_set_time ? 0 : PERMS_SKIP_MTIME);
}
const char *who_am_i(void)
{
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
if (am_starting_up)
return am_server ? "server" : "client";
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
}

378
rsync.h
View File

@@ -1,18 +1,18 @@
/*
/*
Copyright (C) by Andrew Tridgell 1996, 2000
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -58,11 +58,15 @@
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0)
#define FLAG_HLINK_EOL (1<<1) /* generator only */
#define FLAG_MOUNT_POINT (1<<2) /* sender only */
#define FLAG_HLINK_EOL (1<<1) /* receiver/generator */
#define FLAG_MOUNT_POINT (1<<2) /* sender */
#define FLAG_NO_FUZZY (1<<2) /* generator */
#define FLAG_DEL_HERE (1<<3) /* receiver/generator */
#define FLAG_SENT (1<<3) /* sender */
#define FLAG_HLINK_TOL (1<<4) /* receiver/generator */
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 28
#define PROTOCOL_VERSION 29
/* We refuse to interoperate with versions that are not in this range.
* Note that we assume we'll work with later versions: the onus is on
@@ -92,38 +96,84 @@
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (256*1024)
#define IO_BUFFER_SIZE (4092)
#define MAX_BLOCK_SIZE ((int32)1 << 29)
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
#define IOERR_VANISHED (1<<1)
#define IOERR_DEL_LIMIT (1<<2)
#define MAX_ARGS 1000
#define MAX_BASIS_DIRS 20
#define MAX_SERVER_ARGS (MAX_BASIS_DIRS*2 + 100)
#define MPLEX_BASE 7
#define NO_EXCLUDES 0
#define SERVER_EXCLUDES 1
#define ALL_EXCLUDES 2
#define NO_FILTERS 0
#define SERVER_FILTERS 1
#define ALL_FILTERS 2
#define XFLG_FATAL_ERRORS (1<<0)
#define XFLG_DEF_INCLUDE (1<<1)
#define XFLG_WORDS_ONLY (1<<2)
#define XFLG_WORD_SPLIT (1<<3)
#define XFLG_OLD_PREFIXES (1<<1)
#define XFLG_ANCHORED2ABS (1<<2)
#define PERMS_REPORT (1<<0)
#define PERMS_SKIP_MTIME (1<<1)
#define FULL_FLUSH 1
#define NORMAL_FLUSH 0
#define PDIR_CREATE 1
#define PDIR_DELETE 0
/* Log-message categories. FLOG is only used on the daemon side to
* output messages to the log file. */
enum logcode { FERROR=1, FINFO=2, FLOG=3 };
/* Note: 0x00 - 0x7F are used for basis_dir[] indexes! */
#define FNAMECMP_BASIS_DIR_LOW 0x00 /* Must remain 0! */
#define FNAMECMP_BASIS_DIR_HIGH 0x7F
#define FNAMECMP_FNAME 0x80
#define FNAMECMP_PARTIAL_DIR 0x81
#define FNAMECMP_BACKUP 0x82
#define FNAMECMP_FUZZY 0x83
/* For calling delete_file() */
#define DEL_NO_RECURSE (1<<1)
#define DEL_FORCE_RECURSE (1<<2) /* recurse even w/o --force */
#define DEL_TERSE (1<<3)
/* For use by the itemize_changes code */
#define ITEM_REPORT_CHECKSUM (1<<1)
#define ITEM_REPORT_SIZE (1<<2)
#define ITEM_REPORT_TIME (1<<3)
#define ITEM_REPORT_PERMS (1<<4)
#define ITEM_REPORT_OWNER (1<<5)
#define ITEM_REPORT_GROUP (1<<6)
#define ITEM_REPORT_XATTRS (1<<7)
#define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
#define ITEM_XNAME_FOLLOWS (1<<12)
#define ITEM_IS_NEW (1<<13)
#define ITEM_LOCAL_CHANGE (1<<14)
#define ITEM_TRANSFER (1<<15)
/* These are outside the range of the transmitted flags. */
#define ITEM_NO_DEST_AND_NO_UPDATE (1<<16) /* used by itemize() */
#define ITEM_MISSING_DATA (1<<16) /* used by log_formatted() */
#define ITEM_DELETED (1<<17) /* used by log_formatted() */
#define SIGNIFICANT_ITEM_FLAGS (~(\
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
/* Log-message categories. FLOG and FCLIENT are only used on the daemon
* side for custom logging -- they don't get sent over the socket. */
enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4 };
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, MSG_LOG=FLOG, /* remote logging */
MSG_REDO=4, /* reprocess indicated flist index */
MSG_DONE=5, /* current phase is done */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_FCLIENT=FCLIENT, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
MSG_SUCCESS=100,/* successfully updated indicated flist index */
MSG_DELETED=101,/* successfully deleted a file on receiving side */
MSG_DONE=86 /* current phase is done */
};
#include "errcode.h"
@@ -132,23 +182,39 @@ enum msgcode {
/* The default RSYNC_RSH is always set in config.h. */
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <stddef.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if defined(HAVE_MALLOC_H) && (defined(HAVE_MALLINFO) || !defined(HAVE_STDLIB_H))
#if defined HAVE_MALLOC_H && (defined HAVE_MALLINFO || !defined HAVE_STDLIB_H)
#include <malloc.h>
#endif
@@ -156,10 +222,6 @@ enum msgcode {
#include <sys/socket.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
@@ -179,8 +241,6 @@ enum msgcode {
#endif
#endif
#include <sys/stat.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -231,24 +291,27 @@ enum msgcode {
#include <syslog.h>
#include <sys/file.h>
#if HAVE_DIRENT_H
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#else
# define dirent direct
# if HAVE_SYS_NDIR_H
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#if MAJOR_IN_MKDEV
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#elif MAJOR_IN_SYSMACROS
# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
# define makedev mkdev
# endif
#elif defined MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
@@ -266,61 +329,85 @@ enum msgcode {
#define uchar unsigned char
#endif
#if HAVE_UNSIGNED_CHAR
#ifdef SIGNED_CHAR_OK
#define schar signed char
#else
#define schar char
#endif
/* Find a variable that is either exactly 32-bits or longer.
* If some code depends on 32-bit truncation, it will need to
* take special action in a "#if SIZEOF_INT32 > 4" section. */
#ifndef int32
#if (SIZEOF_INT == 4)
#define int32 int
#elif (SIZEOF_LONG == 4)
#define int32 long
#elif (SIZEOF_SHORT == 4)
#define int32 short
#if SIZEOF_INT == 4
# define int32 int
# define SIZEOF_INT32 4
#elif SIZEOF_LONG == 4
# define int32 long
# define SIZEOF_INT32 4
#elif SIZEOF_SHORT == 4
# define int32 short
# define SIZEOF_INT32 4
#elif SIZEOF_INT > 4
# define int32 int
# define SIZEOF_INT32 SIZEOF_INT
#elif SIZEOF_LONG > 4
# define int32 long
# define SIZEOF_INT32 SIZEOF_LONG
#else
/* I hope this works */
#define int32 int
#define LARGE_INT32
# error Could not find a 32-bit integer variable
#endif
#else
# define SIZEOF_INT32 4
#endif
#ifndef uint32
#define uint32 unsigned int32
#endif
#if HAVE_OFF64_T
#define OFF_T off64_t
#define STRUCT_STAT struct stat64
#else
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
#define OFF_T off_t
#define STRUCT_STAT struct stat
#else
#define OFF_T off64_t
#define STRUCT_STAT struct stat64
#define USE_STAT64_FUNCS 1
#endif
#if HAVE_OFF64_T
#define int64 off64_t
#elif (SIZEOF_LONG == 8)
#define int64 long
#elif (SIZEOF_INT == 8)
#define int64 int
#elif HAVE_LONGLONG
#define int64 long long
/* CAVEAT: on some systems, int64 will really be a 32-bit integer IFF
* that's the maximum size the file system can handle and there is no
* 64-bit type available. The rsync source must therefore take steps
* to ensure that any code that really requires a 64-bit integer has
* it (e.g. the checksum code uses two 32-bit integers for its 64-bit
* counter). */
#if SIZEOF_OFF64_T == 8
# define int64 off64_t
# define SIZEOF_INT64 8
#elif SIZEOF_LONG == 8
# define int64 long
# define SIZEOF_INT64 8
#elif SIZEOF_INT == 8
# define int64 int
# define SIZEOF_INT64 8
#elif SIZEOF_LONG_LONG == 8
# define int64 long long
# define SIZEOF_INT64 8
#elif SIZEOF_OFF_T == 8
# define int64 off_t
# define SIZEOF_INT64 8
#elif SIZEOF_INT > 8
# define int64 int
# define SIZEOF_INT64 SIZEOF_INT
#elif SIZEOF_LONG > 8
# define int64 long
# define SIZEOF_INT64 SIZEOF_LONG
#elif SIZEOF_LONG_LONG > 8
# define int64 long long
# define SIZEOF_INT64 SIZEOF_LONG_LONG
#else
/* As long as it gets... */
#define int64 off_t
#define NO_INT64
#endif
#if (SIZEOF_LONG == 8)
#define uint64 unsigned long
#elif (SIZEOF_INT == 8)
#define uint64 unsigned int
#elif HAVE_LONGLONG
#define uint64 unsigned long long
#else
/* As long as it gets... */
#define uint64 unsigned off_t
# define int64 off_t
# define SIZEOF_INT64 SIZEOF_OFF_T
#endif
/* Starting from protocol version 26, we always use 64-bit
@@ -347,11 +434,11 @@ enum msgcode {
*
* FIXME: I don't think the code in flist.c has ever worked on a system
* where dev_t is a struct.
*/
*/
struct idev {
uint64 inode;
uint64 dev;
int64 inode;
int64 dev;
};
#ifndef MIN
@@ -388,14 +475,14 @@ struct idev {
#define IN_LOOPBACKNET 127
#endif
#define GID_NONE (gid_t) -1
#define GID_NONE ((gid_t)-1)
#define HL_CHECK_MASTER 0
#define HL_SKIP 1
struct hlink {
int next;
int hlindex;
struct file_struct *next;
};
#define F_DEV link_u.idev->dev
@@ -411,9 +498,12 @@ struct file_struct {
char *link; /* Points to symlink string, if a symlink */
} u;
OFF_T length;
char *basename;
char *dirname;
char *basedir;
char *basename; /* The current item's name (AKA filename) */
char *dirname; /* The directory info inside the transfer */
union {
char *root; /* Sender-side dir info outside transfer */
int depth; /* Receiver-side directory depth info */
} dir;
union {
struct idev *idev;
struct hlink *links;
@@ -448,60 +538,81 @@ struct file_struct {
#define WITHOUT_HLINK 0
struct file_list {
int count;
int malloced;
struct file_struct **files;
alloc_pool_t file_pool;
alloc_pool_t hlink_pool;
struct file_struct **files;
int count;
int malloced;
int low, high;
};
#define SUMFLG_SAME_OFFSET (1<<0)
struct sum_buf {
OFF_T offset; /**< offset in file of this chunk */
unsigned int len; /**< length of chunk of file */
int i; /**< index of this chunk */
int32 len; /**< length of chunk of file */
uint32 sum1; /**< simple checksum */
short flags; /**< flag bits */
char sum2[SUM_LENGTH]; /**< checksum */
};
struct sum_struct {
OFF_T flength; /**< total file length */
size_t count; /**< how many chunks */
unsigned int blength; /**< block_length */
unsigned int remainder; /**< flength % block_length */
int s2length; /**< sum2_length */
struct sum_buf *sums; /**< points to info for each chunk */
int32 count; /**< how many chunks */
int32 blength; /**< block_length */
int32 remainder; /**< flength % block_length */
int s2length; /**< sum2_length */
};
struct map_struct {
char *p; /* Window pointer */
int fd; /* File Descriptor */
int p_size; /* Window size at allocation */
int p_len; /* Window size after fill */
/* p_size and p_len could be
* consolodated by using a local
* variable in map_ptr() */
int status; /* first errno from read errors */
OFF_T file_size; /* File size (from stat) */
OFF_T p_offset; /* Window start */
OFF_T p_fd_offset; /* offset of cursor in fd ala lseek */
char *p; /* Window pointer */
int32 p_size; /* Largest window size we allocated */
int32 p_len; /* Latest (rounded) window size */
int32 def_window_size; /* Default window size */
int fd; /* File Descriptor */
int status; /* first errno from read errors */
};
#define MATCHFLG_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
#define MATCHFLG_WILD2 (1<<1) /* pattern has '**' */
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with '**' */
#define MATCHFLG_ABS_PATH (1<<3) /* path-match on absolute path */
struct exclude_struct {
struct exclude_struct *next;
#define MATCHFLG_INCLUDE (1<<4) /* this is an include, not an exclude */
#define MATCHFLG_DIRECTORY (1<<5) /* this matches only directories */
#define MATCHFLG_CLEAR_LIST (1<<6) /* this item is the "!" token */
#define MATCHFLG_WORD_SPLIT (1<<7) /* split rules on whitespace */
#define MATCHFLG_NO_INHERIT (1<<8) /* don't inherit these rules */
#define MATCHFLG_NO_PREFIXES (1<<9) /* parse no prefixes from patterns */
#define MATCHFLG_MERGE_FILE (1<<10)/* specifies a file to merge */
#define MATCHFLG_PERDIR_MERGE (1<<11)/* merge-file is searched per-dir */
#define MATCHFLG_EXCLUDE_SELF (1<<12)/* merge-file name should be excluded */
#define MATCHFLG_FINISH_SETUP (1<<13)/* per-dir merge file needs setup */
#define MATCHFLG_NEGATE (1<<14)/* rule matches when pattern does not */
#define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
#define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
| MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
| MATCHFLG_NEGATE | MATCHFLG_RECEIVER_SIDE)
struct filter_struct {
struct filter_struct *next;
char *pattern;
int match_flags;
int include;
int directory;
int slash_cnt;
uint32 match_flags;
union {
int slash_cnt;
struct filter_list_struct *mergelist;
} u;
};
struct exclude_list_struct {
struct exclude_struct *head;
struct exclude_struct *tail;
struct filter_list_struct {
struct filter_struct *head;
struct filter_struct *tail;
char *debug_type;
};
@@ -512,6 +623,8 @@ struct stats {
int64 total_read;
int64 literal_data;
int64 matched_data;
int64 flist_buildtime;
int64 flist_xfertime;
int flist_size;
int num_files;
int num_transferred_files;
@@ -519,15 +632,6 @@ struct stats {
};
/* we need this function because of the silly way in which duplicate
entries are handled in the file lists - we can't change this
without breaking existing versions */
static inline int flist_up(struct file_list *flist, int i)
{
while (!flist->files[i]->basename) i++;
return i;
}
#include "byteorder.h"
#include "lib/mdfour.h"
#include "lib/wildmatch.h"
@@ -545,18 +649,18 @@ int asprintf(char **ptr, const char *format, ...);
int vasprintf(char **ptr, const char *format, va_list ap);
#endif
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
#if !defined HAVE_VSNPRINTF || !defined HAVE_C99_VSNPRINTF
#define vsnprintf rsync_vsnprintf
int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
#endif
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
#if !defined HAVE_SNPRINTF || !defined HAVE_C99_VSNPRINTF
#define snprintf rsync_snprintf
int snprintf(char *str,size_t count,const char *fmt,...);
#endif
#if !HAVE_STRERROR
#ifndef HAVE_STRERROR
extern char *sys_errlist[];
#define strerror(i) sys_errlist[i]
#endif
@@ -570,14 +674,11 @@ extern char *sys_errlist[];
extern int errno;
#endif
#define SUPPORT_LINKS HAVE_READLINK
#define SUPPORT_HARD_LINKS HAVE_LINK
/* This could be bad on systems which have no lchown and where chown
* follows symbollic links. On such systems it might be better not to
* try to chown symlinks at all. */
#ifndef HAVE_LCHOWN
#define lchown chown
#ifdef HAVE_READLINK
#define SUPPORT_LINKS 1
#endif
#ifdef HAVE_LINK
#define SUPPORT_HARD_LINKS 1
#endif
#define SIGNAL_CAST (RETSIGTYPE (*)())
@@ -663,9 +764,9 @@ extern int errno;
/* work out what fcntl flag to use for non-blocking */
#ifdef O_NONBLOCK
# define NONBLOCK_FLAG O_NONBLOCK
#elif defined(SYSV)
#elif defined SYSV
# define NONBLOCK_FLAG O_NDELAY
#else
#else
# define NONBLOCK_FLAG FNDELAY
#endif
@@ -685,13 +786,13 @@ extern int errno;
#define INITACCESSPERMS 0700
/* handler for null strings in printf format */
#define NS(s) ((s)?(s):"<NULL>")
#define NS(s) ((s)?safe_fname(s):"<NULL>")
#if !defined(__GNUC__) || defined(APPLE)
#if !defined __GNUC__ || defined __APPLE__
/* Apparently the OS X port of gcc gags on __attribute__.
*
* <http://www.opensource.apple.com/bugs/X/gcc/2512150.html> */
#define __attribute__(x)
#define __attribute__(x)
#endif
@@ -749,9 +850,8 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
extern int verbose;
#ifndef HAVE_INET_NTOP
const char *
inet_ntop(int af, const void *src, char *dst, size_t size);
#endif /* !HAVE_INET_NTOP */
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#ifndef HAVE_INET_PTON
int inet_pton(int af, const char *src, void *dst);

2008
rsync.yo
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(30 Apr 2004)()()
manpagename(rsyncd.conf)(configuration file for rsync server)
manpage(rsyncd.conf)(5)(19 May 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.
@@ -19,7 +19,7 @@ The file consists of modules and parameters. A module begins with the
name of the module in square brackets and continues until the next
module begins. Modules contain parameters of the form 'name = value'.
The file is line-based - that is, each newline-terminated line represents
The file is line-based -- that is, each newline-terminated line represents
either a comment, a module name or a parameter.
Only the first equals sign in a parameter is significant. Whitespace before
@@ -41,7 +41,7 @@ in string values.
manpagesection(LAUNCHING THE RSYNC DAEMON)
The rsync daemon is launched by specifying the --daemon option to
The rsync daemon is launched by specifying the bf(--daemon) option to
rsync.
The daemon must run with root privileges if you wish to use chroot, to
@@ -51,24 +51,24 @@ write the appropriate data, log, and lock files.
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 "rsync --daemon" from a suitable startup script.
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
"-e/--rsh" option and server mode with "::" or "rsync://"), the --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:
quote(rsync 873/tcp)
verb( rsync 873/tcp)
and a single line something like this to /etc/inetd.conf:
quote(rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
verb( rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
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,20 +137,20 @@ 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,
of not being able to follow symbolic links outside of the new root path
when reading, and of complicating the preservation of usernames and groups
of not being able to follow symbolic links that are either absolute or outside
of the new root path, and of complicating the preservation of usernames and groups
(see below). When "use chroot" is false, for security reasons,
symlinks may only be relative paths pointing to other files within the root
path, and leading slashes are removed from most absolute paths (options
such as --backup-dir, --compare-dest, etc. interpret an absolute path as
such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
rooted in the module's "path" dir, just as if chroot was specified).
The default for "use chroot" is true.
@@ -149,17 +160,21 @@ getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
process in the chroot namespace will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
able to copy the IDs, just as if the --numeric-ids option had been
able to copy the IDs, just as if the bf(--numeric-ids) option had been
specified.
Note that you are free to setup user/group information in the chroot area
differently from your normal system. For example, you could abbreviate
the list of users and groups. Also, you can protect this information
from being downloaded by adding an exclude rule to the rsync.conf file
(e.g. "exclude = /etc/"). To protect it from being changed by an upload
(if the module is not read only), be sure to set the permissions (or
owner) on the files and/or parent directories so that they cannot be
written by the daemon.
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 daemon is
at least 2.6.3 to effect this. Also note that it is safest to exclude a
directory and all its contents combining the rule "/some/dir/" with the
rule "/some/dir/**" just to be sure that rsync will not allow deeper
access to some of the excluded files inside the directory (rsync tries to
do this automatically, but you might as well specify both to be extra
sure).
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow.
@@ -167,8 +182,13 @@ Any clients connecting when the maximum has been reached will receive a
message telling them to try later. The default is 0 which means no limit.
See also the "lock file" option.
dit(bf(max verbosity)) The "max verbosity" option allows you to control
the maximum amount of verbose information that you'll allow the daemon to
generate (since the information goes into the log file). The default is 1,
which allows the client to request one level of verbosity.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync 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).
@@ -176,9 +196,15 @@ 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 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
listed when the client asks for a listing of available modules. By
setting this to false you can create hidden modules. The default is
@@ -195,48 +221,52 @@ file transfers to and from that module should take place as when the daemon
was run as root. This complements the "uid" option. The default is gid -2,
which is normally the group "nobody".
dit(bf(exclude)) The "exclude" option allows you to specify a space
separated list of patterns to add to the exclude list.
This is only superficially equivalent
to the client specifying these patterns with the --exclude option.
Only one "exclude" option may be specified, but
you can use "-" and "+" before patterns to specify exclude/include.
dit(bf(filter)) The "filter" option allows you to specify a space-separated
list of filter rules that the daemon will not allow to be read or written.
This is only superficially equivalent to the client specifying these
patterns with the bf(--filter) option. Only one "filter" option may be
specified, but it may contain as many rules as you like, including
merge-file rules. Note that per-directory merge-file rules do not provide
as much protection as global rules, but they can be used to make bf(--delete)
work better when a client downloads the daemon's files (if the per-dir
merge files are included in the transfer).
dit(bf(exclude)) The "exclude" option allows you to specify a
space-separated list of patterns that the daemon will not allow to be read
or written. This is only superficially equivalent to the client
specifying these patterns with the bf(--exclude) option. Only one "exclude"
option may be specified, but you can use "-" and "+" before patterns to
specify exclude/include.
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
it doesn't exclude files sent from a client when sending to a server or
files deleted on a client when receiving from a server.
Note that this option is not designed with strong security in
mind, it is quite possible that a client may find a way to bypass this
exclude list. If you want to absolutely ensure that certain files
cannot be accessed then use the uid/gid options in combination with
file permissions.
the daemon: that is, it excludes files received by a client when receiving
from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a daemon.
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 --exclude-from option with an equivalent file.
to the client specifying the bf(--exclude-from) option with an equivalent file.
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 --include option because it applies only on the server.
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)) The "include" option allows you to specify a
space-separated list of patterns which rsync should not exclude. This is
only superficially equivalent to the client specifying these patterns with
the bf(--include) option because it applies only on the daemon. This is
useful as it allows you to build up quite complex exclude/include rules.
Only one "include" option may be specified, but you can use "+" and "-"
before patterns to switch include/exclude. See the "exclude" option
above.
dit(bf(include 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
--include-from option with a equivalent file.
bf(--include-from) option with a equivalent file.
See the "exclude" option above.
dit(bf(auth users)) The "auth users" option specifies a comma and
space separated list of usernames that will be allowed to connect to
space-separated list of usernames that will be allowed to connect to
this module. The usernames do not need to exist on the local
system. The usernames may also contain shell wildcard characters. If
"auth users" is set then the client will be challenged to supply a
@@ -246,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
@@ -279,34 +309,32 @@ connection is rejected.
Each pattern can be in one of five forms:
itemize(
quote(itemize(
it() a dotted decimal IPv4 address of the form a.b.c.d, or an IPv6 address
of the form a:b:c::d:e:f. In this case the incoming machine's IP address
must match exactly.
it() an address/mask in the form ipaddr/n where ipaddr is the IP address
and n is the number of one bits in the netmask. All IP addresses which
match the masked IP address will be allowed in.
it() an address/mask in the form ipaddr/maskaddr where ipaddr is the
IP address and maskaddr is the netmask in dotted decimal notation for IPv4,
or similar for IPv6, e.g. ffff:ffff:ffff:ffff:: instead of /64. All IP
addresses which match the masked IP address will be allowed in.
it() a hostname. The hostname as determined by a reverse lookup will
be matched (case insensitive) against the pattern. Only an exact
match is allowed in.
it() a hostname pattern using wildcards. These are matched using the
same rules as normal unix filename matching. If the pattern matches
then the client is allowed in.
)
))
Note IPv6 link-local addresses can have a scope in the address specification:
quote(fe80::1%link1)
quote(fe80::%link1/64)
quote(fe80::%link1/ffff:ffff:ffff:ffff::)
quote(
tt( fe80::1%link1)nl()
tt( fe80::%link1/64)nl()
tt( fe80::%link1/ffff:ffff:ffff:ffff::)nl()
)
You can also combine "hosts allow" with a separate "hosts deny"
option. If both options are specified then the "hosts allow" option s
@@ -326,37 +354,51 @@ 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
phase of the transfer. Normally rsync skips the --delete step if any
I/O errors have occurred in order to prevent disasterous deletion due
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
behaviour.
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. If you want to customize the log formats look at
the log format option.
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.
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.
format used for logging file transfers when transfer logging is enabled.
The format is a text string containing embedded single-character escape
sequences prefixed with a percent (%) character. An optional numeric
field width may also be specified between the percent and the escape
letter (e.g. "%-50n %8l %07p").
The prefixes that are understood are:
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.
(A perl script that will summarize this default log format is included
in the rsync source code distribution in the "support" subdirectory:
rsyncstats.)
itemize(
The single-character escapes that are understood are as follows:
quote(itemize(
it() %h for the remote host name
it() %a for the remote IP address
it() %l for the length of the file in bytes
it() %p for the process ID of this rsync session
it() %o for the operation, which is either "send" or "recv"
it() %f for the filename
it() %o for the operation, which is "send", "recv", or "del."
(the latter includes the trailing period)
it() %f for the filename (long form on sender; no trailing "/")
it() %n for the filename (short form; trailing "/" on dir)
it() %L either the string " -> SYMLINK", or " => HARDLINK" or an
empty string (where bf(SYMLINK) or bf(HARDLINK) is a filename)
it() %P for the module path
it() %m for the module name
it() %t for the current date time
@@ -364,26 +406,41 @@ itemize(
it() %b for the number of bytes actually transferred
it() %c when sending files this gives the number of checksum bytes
received for this file
)
it() %i an itemized list of what is being updated
))
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
is always added to the beginning when using the "log file" option.
For a list of what the characters mean that are output by "%i", see the
bf(--itemize-changes) option in the rsync manpage.
A perl script called rsyncstats to summarize this format is included
in the rsync source code distribution.
Note that some of the logged output changes when talking with older
rsync versions. For instance, deleted files were only output as verbose
messages prior to rsync 2.6.4.
dit(bf(timeout)) The "timeout" option allows you to override the
clients choice for I/O timeout for this module. Using this option you
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. The full names of the options must be
used (i.e., you must use "checksum" not "c" to disable checksumming).
When an option is refused, the server prints an error message and exits.
specify a space-separated list of rsync command line options that will
be refused by your rsync daemon.
You may specify the full option name, its one-letter abbreviation, or a
wild-card string that matches multiple options.
For example, this would refuse bf(--checksum) (bf(-c)) and all the various
delete options:
quote(tt( refuse options = c delete))
The reason the above refuses all delete options is that the options imply
bf(--delete), and implied options are refused just like explicit options.
As an additional safety feature, the refusal of "delete" also refuses
bf(remove-sent-files) when the daemon is the sender; if you want the latter
without the former, instead refuse "delete-*" -- that refuses all the
delete modes without affecting bf(--remove-sent-files).
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.
@@ -394,11 +451,11 @@ during transfer. Compression is expensive in terms of CPU usage so it
is usually good to not try to compress files that won't compress well,
such as already compressed files.
The "dont compress" option takes a space separated list of
The "dont compress" option takes a space-separated list of
case-insensitive wildcard patterns. Any source filename matching one
of the patterns will not be compressed during transfer.
The default setting is verb(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
The default setting is tt(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
enddit()
@@ -411,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.
@@ -419,31 +476,31 @@ 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 --daemon and --rsh (-e) options, it will
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
quote(rsync --server --daemon .)
quote(tt(rsync --server --daemon .))
NOTE: rsync's argument parsing expects the trailing ".", so make sure
that it's there. If you want to use an rsyncd.conf(5)-style
configuration file other than the default, you can added a
--config option to the em(command):
bf(--config) option to the em(command):
quote(rsync --server --daemon --config=em(file) .)
quote(tt(rsync --server --daemon --config=em(file) .))
Note that the "--server" here is the internal option that rsync uses to
run the remote version of rsync that it communicates with, and thus you
should not be using the --server option under normal circumstances.
should not be using the bf(--server) option under normal circumstances.
manpagesection(EXAMPLES)
@@ -456,17 +513,17 @@ verb(
comment = ftp export area
)
A more sophisticated example would be:
uid = nobody nl()
gid = nobody nl()
use chroot = no nl()
max connections = 4 nl()
syslog facility = local5 nl()
verb(
uid = nobody
gid = nobody
use chroot = no
max connections = 4
syslog facility = local5
pid file = /var/run/rsyncd.pid
verb([ftp]
[ftp]
path = /var/ftp/pub
comment = whole ftp area (approx 6.1 GB)
@@ -491,8 +548,10 @@ verb([ftp]
The /etc/rsyncd.secrets file would look something like this:
tridge:mypass nl()
susan:herpass
quote(
tt(tridge:mypass)nl()
tt(susan:herpass)nl()
)
manpagefiles()
@@ -506,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.5pre2 of rsync.
manpagesection(CREDITS)
@@ -535,12 +591,13 @@ 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()
rsync was written by Andrew Tridgell and Paul Mackerras. They may be
contacted via email at tridge@samba.org and
Paul.Mackerras@cs.anu.edu.au
rsync was written by Andrew Tridgell and Paul Mackerras.
Many people have later contributed to it.
Mailing lists for support and development are available at
url(http://lists.samba.org)(lists.samba.org)

View File

@@ -126,12 +126,10 @@ set -e
RUNSHFLAGS='-e'
# for Solaris
PATH="/usr/xpg4/bin/:$PATH"
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
if [ -n "$loglevel" ] && [ "$loglevel" -gt 8 ]
then
if set -x
then
if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
if set -x; then
# If it doesn't work the first time, don't keep trying.
RUNSHFLAGS="$RUNSHFLAGS -x"
fi
@@ -142,33 +140,39 @@ echo "$0 running in `pwd`"
echo " rsync_bin=$rsync_bin"
echo " srcdir=$srcdir"
testuser=`id -un || whoami || echo UNKNOWN`
if [ -f /usr/bin/whoami ]; then
testuser=`/usr/bin/whoami`
elif [ -f /usr/ucb/whoami ]; then
testuser=`/usr/ucb/whoami`
elif [ -f /bin/whoami ]; then
testuser=`/bin/whoami`
else
testuser=`id -un 2>/dev/null || echo ${LOGNAME:-${USERNAME:-${USER:-'UNKNOWN'}}}`
fi
echo " testuser=$testuser"
echo " os=`uname -a`"
# It must be "yes", not just nonnull
if test "x$preserve_scratch" = xyes
then
if [ "x$preserve_scratch" = xyes ]; then
echo " preserve_scratch=yes"
else
echo " preserve_scratch=no"
fi
if test ! -f $rsync_bin
then
if [ ! -f "$rsync_bin" ]; then
echo "rsync_bin $rsync_bin is not a file" >&2
exit 2
fi
if test ! -d $srcdir
then
if [ ! -d "$srcdir" ]; then
echo "srcdir $srcdir is not a directory" >&2
exit 2
fi
RSYNC="$rsync_bin"
#RSYNC="valgrind --tool=addrcheck $rsync_bin"
export rsync_bin RSYNC
@@ -198,14 +202,13 @@ maybe_discard_scratch() {
return 0
}
if [ "x$whichtests" = x ]
then
if [ "x$whichtests" = x ]; then
whichtests="*.test"
fi
for testscript in $suitedir/$whichtests
do
testbase=`echo $testscript | sed 's!.*/!!' | sed -e 's/.test\$//'`
testbase=`echo $testscript | sed -e 's!.*/!!' -e 's/.test\$//'`
scratchdir="$scratchbase.$testbase"
prep_scratch
@@ -250,8 +253,7 @@ do
*)
echo "FAIL $testbase"
failed=`expr $failed + 1`
if [ "x$nopersist" = "xyes" ]
then
if [ "x$nopersist" = xyes ]; then
exit 1
fi
esac

437
sender.c
View File

@@ -20,13 +20,26 @@
#include "rsync.h"
extern int verbose;
extern int csum_length;
extern struct stats stats;
extern int io_error;
extern int dry_run;
extern int do_xfers;
extern int am_server;
extern int am_daemon;
extern int log_before_transfer;
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;
/**
@@ -36,22 +49,6 @@ extern int protocol_version;
* and transmits them to the receiver. The sender process runs on the
* machine holding the source files.
**/
void read_sum_head(int f, struct sum_struct *sum)
{
sum->count = read_int(f);
sum->blength = read_int(f);
if (protocol_version < 27) {
sum->s2length = csum_length;
} else {
sum->s2length = read_int(f);
if (sum->s2length > MD4_SUM_LENGTH) {
rprintf(FERROR, "Invalid checksum length %ld\n",
(long)sum->s2length);
exit_cleanup(RERR_PROTOCOL);
}
}
sum->remainder = read_int(f);
}
/**
* Receive the checksums for a buffer
@@ -59,44 +56,50 @@ void read_sum_head(int f, struct sum_struct *sum)
static struct sum_struct *receive_sums(int f)
{
struct sum_struct *s;
int i;
int32 i;
int lull_mod = allowed_lull * 5;
OFF_T offset = 0;
s = new(struct sum_struct);
if (!s) out_of_memory("receive_sums");
if (!(s = new(struct sum_struct)))
out_of_memory("receive_sums");
read_sum_head(f, s);
s->sums = NULL;
if (verbose > 3) {
rprintf(FINFO, "count=%ld n=%u rem=%u\n",
(long)s->count, s->blength, s->remainder);
rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n",
(double)s->count, (long)s->blength, (long)s->remainder);
}
if (s->count == 0)
return(s);
s->sums = new_array(struct sum_buf, s->count);
if (!s->sums) out_of_memory("receive_sums");
if (!(s->sums = new_array(struct sum_buf, s->count)))
out_of_memory("receive_sums");
for (i = 0; i < (int) s->count; i++) {
for (i = 0; i < s->count; i++) {
s->sums[i].sum1 = read_int(f);
read_buf(f, s->sums[i].sum2, s->s2length);
s->sums[i].offset = offset;
s->sums[i].i = i;
s->sums[i].flags = 0;
if (i == (int) s->count-1 && s->remainder != 0) {
if (i == s->count-1 && s->remainder != 0)
s->sums[i].len = s->remainder;
} else {
else
s->sums[i].len = s->blength;
}
offset += s->sums[i].len;
if (verbose > 3)
rprintf(FINFO, "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
i, s->sums[i].len, (double)s->sums[i].offset, s->sums[i].sum1);
if (allowed_lull && !(i % lull_mod))
maybe_send_keepalive();
if (verbose > 3) {
rprintf(FINFO,
"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
i, s->sums[i].len, (double)s->sums[i].offset,
s->sums[i].sum1);
}
}
s->flength = offset;
@@ -104,27 +107,112 @@ static struct sum_struct *receive_sums(int f)
return s;
}
void successful_send(int ndx)
{
char fname[MAXPATHLEN];
struct file_struct *file;
unsigned int offset;
if (ndx < 0 || ndx >= the_file_list->count)
return;
file = the_file_list->files[ndx];
/* The generator might tell us about symlinks we didn't send. */
if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
return;
if (file->dir.root) {
offset = stringjoin(fname, sizeof fname,
file->dir.root, "/", NULL);
} else
offset = 0;
f_name_to(file, fname + offset);
if (remove_sent_files && do_unlink(fname) == 0 && verbose > 1) {
rprintf(FINFO, "sender removed %s\n",
safe_fname(fname + offset));
}
}
static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
uchar fnamecmp_type, char *buf, int len)
{
write_int(f_out, ndx);
if (protocol_version < 29)
return;
write_shortint(f_out, iflags);
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
write_byte(f_out, fnamecmp_type);
if (iflags & ITEM_XNAME_FOLLOWS)
write_vstring(f_out, buf, len);
}
/* This is also used by receive.c with f_out = -1. */
int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
char *buf, int *len_ptr)
{
int len;
uchar fnamecmp_type = FNAMECMP_FNAME;
int iflags = protocol_version >= 29 ? read_shortint(f_in)
: ITEM_TRANSFER | ITEM_MISSING_DATA;
/* Handle the new keep-alive (no-op) packet. */
if (ndx == the_file_list->count && iflags == ITEM_IS_NEW)
;
else if (ndx < 0 || ndx >= the_file_list->count) {
rprintf(FERROR, "Invalid file index: %d (count=%d) [%s]\n",
ndx, the_file_list->count, who_am_i());
exit_cleanup(RERR_PROTOCOL);
} else if (iflags == ITEM_IS_NEW) {
rprintf(FERROR, "Invalid itemized flag word: %x [%s]\n",
iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
*type_ptr = fnamecmp_type;
if (iflags & ITEM_XNAME_FOLLOWS) {
if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
exit_cleanup(RERR_PROTOCOL);
} else {
*buf = '\0';
len = -1;
}
*len_ptr = len;
if (iflags & ITEM_TRANSFER) {
if (!S_ISREG(the_file_list->files[ndx]->mode)) {
rprintf(FERROR,
"received request to transfer non-regular file: %d [%s]\n",
ndx, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
} else if (f_out >= 0) {
write_ndx_and_attrs(f_out, ndx, iflags,
fnamecmp_type, buf, len);
}
return iflags;
}
void send_files(struct file_list *flist, int f_out, int f_in)
{
int fd = -1;
struct sum_struct *s;
struct map_struct *buf = NULL;
struct map_struct *mbuf = NULL;
STRUCT_STAT st;
char fname[MAXPATHLEN];
int i;
char *fname2, fname[MAXPATHLEN];
char xname[MAXPATHLEN];
uchar fnamecmp_type;
int iflags, xlen;
struct file_struct *file;
int phase = 0;
extern struct stats stats;
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
struct stats initial_stats;
extern int write_batch;
extern int read_batch;
int checksums_match;
int buff_len;
char buff[CHUNK_SIZE];
int j;
int done;
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)
rprintf(FINFO, "send_files starting\n");
@@ -134,175 +222,154 @@ void send_files(struct file_list *flist, int f_out, int f_in)
i = read_int(f_in);
if (i == -1) {
if (phase == 0) {
phase++;
csum_length = SUM_LENGTH;
write_int(f_out, -1);
if (verbose > 2)
rprintf(FINFO, "send_files phase=%d\n", phase);
continue;
}
break;
if (++phase > max_phase)
break;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO, "send_files phase=%d\n", phase);
write_int(f_out, -1);
/* For inplace: redo phase turns off the backup
* flag so that we do a regular inplace send. */
make_backups = 0;
continue;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR, "Invalid file index %d (count=%d)\n",
i, flist->count);
iflags = read_item_attrs(f_in, f_out, i, &fnamecmp_type,
xname, &xlen);
if (iflags == ITEM_IS_NEW) /* no-op packet */
continue;
file = flist->files[i];
if (file->dir.root) {
/* N.B. We're sure that this fits, so offset is OK. */
offset = strlcpy(fname, file->dir.root, sizeof fname);
if (!offset || fname[offset-1] != '/')
fname[offset++] = '/';
} else
offset = 0;
fname2 = f_name_to(file, fname + offset);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
continue;
}
if (phase == 2) {
rprintf(FERROR,
"got transfer request in phase 2 [%s]\n",
who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
file = flist->files[i];
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : !make_backups);
stats.current_file_index = i;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
if (file->basedir) {
/* N.B. We're sure that this fits, so offset is OK. */
offset = strlcpy(fname, file->basedir, sizeof fname);
if (!offset || fname[offset-1] != '/')
fname[offset++] = '/';
} else
offset = 0;
f_name_to(file, fname + offset);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
if (dry_run) {
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname+offset);
}
write_int(f_out, i);
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,
xname, xlen);
continue;
}
initial_stats = stats;
s = receive_sums(f_in);
if (!s) {
if (!(s = receive_sums(f_in))) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "receive_sums failed\n");
return;
}
if (write_batch)
write_batch_csum_info(&i, s);
if (!read_batch) {
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1) {
if (errno == ENOENT) {
enum logcode c = am_daemon
&& protocol_version < 28 ? FERROR
: FINFO;
io_error |= IOERR_VANISHED;
rprintf(c, "file has vanished: %s\n",
full_fname(fname));
} else {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "send_files failed to open %s: %s\n",
full_fname(fname), strerror(errno));
}
free_sums(s);
continue;
}
/* map the local file */
if (do_fstat(fd, &st) != 0) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "fstat failed: %s\n", strerror(errno));
free_sums(s);
close(fd);
return;
}
if (st.st_size > 0) {
buf = map_file(fd, st.st_size);
fd = do_open(fname, O_RDONLY, 0);
if (fd == -1) {
if (errno == ENOENT) {
enum logcode c = am_daemon
&& protocol_version < 28 ? FERROR
: FINFO;
io_error |= IOERR_VANISHED;
rprintf(c, "file has vanished: %s\n",
full_fname(fname));
} else {
buf = NULL;
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno,
"send_files failed to open %s",
full_fname(fname));
}
if (verbose > 2)
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
fname, (double)st.st_size);
write_int(f_out, i);
if (write_batch)
write_batch_delta_file((char *)&i, sizeof i);
write_sum_head(f_out, s);
free_sums(s);
continue;
}
if (verbose > 2 && !read_batch)
rprintf(FINFO, "calling match_sums %s\n", fname);
if (!am_server && verbose) { /* log transfer */
rprintf(FINFO, "%s\n", fname+offset);
/* map the local file */
if (do_fstat(fd, &st) != 0) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "fstat failed");
free_sums(s);
close(fd);
return;
}
if (st.st_size) {
int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
mbuf = map_file(fd, st.st_size, read_size, s->blength);
} else
mbuf = NULL;
if (verbose > 2) {
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
safe_fname(fname), (double)st.st_size);
}
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
write_sum_head(f_xfer, s);
if (verbose > 2) {
rprintf(FINFO, "calling match_sums %s\n",
safe_fname(fname));
}
if (log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FINFO, "%s\n", safe_fname(fname2));
set_compression(fname);
if (read_batch) {
/* read checksums originally computed on sender side */
read_batch_csum_info(i, s, &checksums_match);
if (checksums_match) {
read_batch_delta_file((char*)&j, sizeof (int));
if (j != i) { /* if flist index entries don't match*/
rprintf(FINFO, "index mismatch in send_files\n");
rprintf(FINFO, "read index = %d flist ndx = %d\n", j, i);
close_batch_delta_file();
close_batch_csums_file();
exit_cleanup(1);
} else {
write_int(f_out, j);
write_sum_head(f_out, s);
done = 0;
while (!done) {
read_batch_delta_file((char*)&buff_len, sizeof (int));
write_int(f_out, buff_len);
if (buff_len == 0) {
done = 1;
} else {
if (buff_len > 0) {
read_batch_delta_file(buff, buff_len);
write_buf(f_out, buff, buff_len);
}
}
} /* end while */
read_batch_delta_file( buff, MD4_SUM_LENGTH);
write_buf(f_out, buff, MD4_SUM_LENGTH);
match_sums(f_xfer, s, mbuf, st.st_size);
if (do_progress)
end_progress(st.st_size);
} /* j=i */
} else { /* not checksum match */
rprintf (FINFO, "readbatch & checksums don't match\n");
rprintf (FINFO, "filename=%s is being skipped\n", fname);
continue;
}
} else {
match_sums(f_out, s, buf, st.st_size);
log_send(file, &initial_stats);
}
if (!log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
if (!read_batch) {
if (buf) {
j = unmap_file(buf);
if (j) {
io_error |= IOERR_GENERAL;
rprintf(FERROR,
"read errors mapping %s: (%d) %s\n",
full_fname(fname), j, strerror(j));
}
if (mbuf) {
j = unmap_file(mbuf);
if (j) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, j,
"read errors mapping %s",
full_fname(fname));
}
close(fd);
}
close(fd);
free_sums(s);
if (verbose > 2)
rprintf(FINFO, "sender finished %s\n", fname);
if (verbose > 2) {
rprintf(FINFO, "sender finished %s\n",
safe_fname(fname));
}
/* Flag that we actually sent this entry. */
file->flags |= FLAG_SENT;
}
make_backups = save_make_backups;
if (verbose > 2)
rprintf(FINFO, "send files finished\n");
@@ -310,14 +377,4 @@ void send_files(struct file_list *flist, int f_out, int f_in)
match_report();
write_int(f_out, -1);
if (write_batch || read_batch) {
close_batch_csums_file();
close_batch_delta_file();
}
}

164
socket.c
View File

@@ -33,6 +33,8 @@
#include "rsync.h"
extern char *bind_address;
extern int default_af_hint;
/**
* Establish a proxy connection on an open socket to a web proxy by
@@ -69,15 +71,13 @@ static int establish_proxy_connection(int fd, char *host, int port,
host, port, authhdr, authbuf);
len = strlen(buffer);
if (write(fd, buffer, len) != len) {
rprintf(FERROR, "failed to write to proxy: %s\n",
strerror(errno));
rsyserr(FERROR, errno, "failed to write to proxy");
return -1;
}
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
if (read(fd, cp, 1) != 1) {
rprintf(FERROR, "failed to read from proxy: %s\n",
strerror(errno));
rsyserr(FERROR, errno, "failed to read from proxy");
return -1;
}
if (*cp == '\n')
@@ -90,7 +90,7 @@ static int establish_proxy_connection(int fd, char *host, int port,
if (*cp == '\r')
*cp = '\0';
if (strncmp(buffer, "HTTP/", 5) != 0) {
rprintf(FERROR, "bad response from proxy - %s\n",
rprintf(FERROR, "bad response from proxy -- %s\n",
buffer);
return -1;
}
@@ -98,7 +98,7 @@ static int establish_proxy_connection(int fd, char *host, int port,
while (*cp == ' ')
cp++;
if (*cp != '2') {
rprintf(FERROR, "bad response from proxy - %s\n",
rprintf(FERROR, "bad response from proxy -- %s\n",
buffer);
return -1;
}
@@ -106,8 +106,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
while (1) {
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
if (read(fd, cp, 1) != 1) {
rprintf(FERROR, "failed to read from proxy: %s\n",
strerror(errno));
rsyserr(FERROR, errno,
"failed to read from proxy");
return -1;
}
if (*cp == '\n')
@@ -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;
@@ -198,7 +198,7 @@ int open_socket_out(char *host, int port, const char *bind_address,
strlcpy(buffer, h, sizeof buffer);
/* Is the USER:PASS@ prefix present? */
if ((cp = strchr(buffer, '@')) != NULL) {
if ((cp = strrchr(buffer, '@')) != NULL) {
*cp++ = '\0';
/* The remainder is the HOST:PORT part. */
h = cp;
@@ -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;
@@ -276,8 +276,7 @@ int open_socket_out(char *host, int port, const char *bind_address,
}
freeaddrinfo(res0);
if (s < 0) {
rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
h, strerror(errno));
rsyserr(FERROR, errno, "failed to connect to %s", h);
return -1;
}
return s;
@@ -294,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");
@@ -308,34 +307,29 @@ 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);
}
/**
* Open a socket of the specified type, port and address for incoming data
* Open one or more sockets for incoming data using the specified type,
* port, and address.
*
* Try to be better about handling the results of getaddrinfo(): when
* opening an inbound socket, we might get several address results,
* e.g. for the machine's ipv4 and ipv6 name.
* The getaddrinfo() call may return several address results, e.g. for
* the machine's IPv4 and IPv6 name.
*
* If binding a wildcard, then any one of them should do. If an address
* was specified but it's insufficiently specific then that's not our
* fault.
* We return an array of file-descriptors to the sockets, with a trailing
* -1 value to indicate the end of the list.
*
* However, some of the advertized addresses may not work because e.g. we
* don't have IPv6 support in the kernel. In that case go on and try all
* addresses until one succeeds.
*
* @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;
int s, *sp, *socks, maxs;
int one = 1;
int s, *socks, maxs, i;
struct addrinfo hints, *all_ai, *resp;
char portbuf[10];
int error;
@@ -345,27 +339,23 @@ 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;
}
/* Count max number of sockets we might open. */
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
socks = new_array(int, maxs + 1);
if (!socks) {
rprintf(FERROR,
RSYNC_NAME "couldn't allocate memory for sockets");
return NULL;
}
if (!(socks = new_array(int, maxs + 1)))
out_of_memory("open_socket_in");
/* We may not be able to create the socket, if for example the
* machine knows about IPv6 in the C library, but not in the
* kernel. */
sp = socks + 1; /* Leave room for count at start of array. */
for (resp = all_ai; resp; resp = resp->ai_next) {
for (resp = all_ai, i = 0; resp; resp = resp->ai_next) {
s = socket(resp->ai_family, resp->ai_socktype,
resp->ai_protocol);
@@ -379,8 +369,12 @@ static int *open_socket_in(int type, int port, const char *bind_address,
#ifdef IPV6_V6ONLY
if (resp->ai_family == AF_INET6) {
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(char *)&one, sizeof one);
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(char *)&one, sizeof one) < 0
&& default_af_hint != AF_INET6) {
close(s);
continue;
}
}
#endif
@@ -391,17 +385,17 @@ static int *open_socket_in(int type, int port, const char *bind_address,
continue;
}
*sp++ = s;
socks[i++] = s;
}
*socks = sp - socks - 1; /* Save count. */
socks[i] = -1;
if (all_ai)
freeaddrinfo(all_ai);
if (*socks == 0) {
if (!i) {
rprintf(FERROR,
RSYNC_NAME ": open inbound socket on port %d failed: "
"%s\n", port, strerror(errno));
"unable to bind any inbound sockets on port %d\n",
port);
free(socks);
return NULL;
}
@@ -446,9 +440,7 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
void start_accept_loop(int port, int (*fn)(int, int))
{
fd_set deffds;
int *sp, maxfd, i, j;
extern char *bind_address;
extern int default_af_hint;
int *sp, maxfd, i;
/* open an incoming socket */
sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
@@ -457,12 +449,15 @@ void start_accept_loop(int port, int (*fn)(int, int))
/* ready to listen */
FD_ZERO(&deffds);
maxfd = -1;
for (i = 1; i <= *sp; i++) {
if (listen(sp[i], 5) == -1) {
for (j = 1; j <= i; j++)
close(sp[j]);
free(sp);
for (i = 0, maxfd = -1; sp[i] >= 0; i++) {
if (listen(sp[i], 5) < 0) {
rsyserr(FERROR, errno, "listen() on socket failed");
#ifdef INET6
if (errno == EADDRINUSE && i > 0) {
rprintf(FINFO,
"Try using --ipv4 or --ipv6 to avoid this listen() error.\n");
}
#endif
exit_cleanup(RERR_SOCKETIO);
}
FD_SET(sp[i], &deffds);
@@ -483,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);
@@ -494,8 +489,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
continue;
fd = -1;
for (i = 1; i <= *sp; i++) {
for (i = 0, fd = -1; sp[i] >= 0; i++) {
if (FD_ISSET(sp[i], &fds)) {
fd = accept(sp[i], (struct sockaddr *)&addr,
&addrlen);
@@ -510,18 +504,17 @@ void start_accept_loop(int port, int (*fn)(int, int))
if ((pid = fork()) == 0) {
int ret;
close(sp[i]);
/* open log file in child before possibly giving
* up privileges */
log_open();
for (i = 0; sp[i] >= 0; i++)
close(sp[i]);
/* Re-open log file in child before possibly giving
* up privileges (see logfile_close() above). */
logfile_reopen();
ret = fn(fd, fd);
close_all();
_exit(ret);
} else if (pid < 0) {
rprintf(FERROR,
RSYNC_NAME
": could not create child server process: %s\n",
strerror(errno));
rsyserr(FERROR, errno,
"could not create child server process");
close(fd);
/* This might have happened because we're
* overloaded. Sleep briefly before trying to
@@ -532,7 +525,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
close(fd);
}
}
free(sp);
}
@@ -627,7 +619,7 @@ void set_socket_options(int fd, char *options)
case OPT_ON:
if (got_value)
rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
rprintf(FERROR,"syntax error -- %s does not take a value\n",tok);
{
int on = socket_options[i].value;
@@ -638,9 +630,10 @@ void set_socket_options(int fd, char *options)
break;
}
if (ret != 0)
rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
strerror(errno));
if (ret != 0) {
rsyserr(FERROR, errno,
"failed to set socket option %s", tok);
}
}
free(options);
@@ -660,14 +653,12 @@ void become_daemon(void)
/* detach from the terminal */
#ifdef HAVE_SETSID
setsid();
#else
#ifdef TIOCNOTTY
#elif defined TIOCNOTTY
i = open("/dev/tty", O_RDWR);
if (i >= 0) {
ioctl(i, (int)TIOCNOTTY, (char *)0);
close(i);
}
#endif /* TIOCNOTTY */
#endif
/* make sure that stdin, stdout an stderr don't stuff things
* up (library functions, for example) */
@@ -703,7 +694,7 @@ static int socketpair_tcp(int fd[2])
goto failed;
memset(&sock2, 0, sizeof sock2);
#if HAVE_SOCKADDR_IN_LEN
#ifdef HAVE_SOCKADDR_IN_LEN
sock2.sin_len = sizeof sock2;
#endif
sock2.sin_family = PF_INET;
@@ -733,14 +724,16 @@ static int socketpair_tcp(int fd[2])
goto failed;
close(listener);
listener = -1;
set_blocking(fd[1]);
if (connect_done == 0) {
if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0
&& errno != EISCONN)
goto failed;
}
set_blocking(fd[1]);
/* all OK! */
return 0;
@@ -770,8 +763,7 @@ int sock_exec(const char *prog)
int fd[2];
if (socketpair_tcp(fd) != 0) {
rprintf(FERROR, RSYNC_NAME ": socketpair_tcp failed (%s)\n",
strerror(errno));
rsyserr(FERROR, errno, "socketpair_tcp failed");
return -1;
}
if (verbose >= 2)

6
support/Makefile Normal file
View File

@@ -0,0 +1,6 @@
all: savetransfer
savetransfer: savetransfer.o
clean:
rm -f *.o savetransfer

90
support/atomic-rsync Executable file
View File

@@ -0,0 +1,90 @@
#!/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!
use strict;
use Cwd 'abs_path';
my $RSYNC_PROG = '/usr/bin/rsync';
my $RM_PROG = '/bin/rm';
my $dest_dir = $ARGV[-1];
usage(1) if $dest_dir eq '' || $dest_dir =~ /^--/;
if (!-d $dest_dir) {
print STDERR "$dest_dir is not a directory.\n\n";
usage(1);
}
if (@_ = grep(/^--(link|compare)-dest/, @ARGV)) {
$_ = join(' or ', @_);
print STDERR "You may not use $_ as an rsync option.\n\n";
usage(1);
}
$dest_dir = abs_path($dest_dir);
if ($dest_dir eq '/') {
print STDERR 'You must not use "/" as the destination directory.', "\n\n";
usage(1);
}
my $old_dir = "$dest_dir~old~";
my $new_dir = $ARGV[-1] = "$dest_dir~new~";
system($RM_PROG, '-rf', $old_dir) if -d $old_dir;
if (system($RSYNC_PROG, "--link-dest=$dest_dir", @ARGV)) {
if ($? == -1) {
print "failed to execute $RSYNC_PROG: $!\n";
} elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
} else {
printf "child exited with value %d\n", $? >> 8;
}
exit $?;
}
rename($dest_dir, $old_dir) or die "Unable to rename $new_dir to $old_dir: $!";
rename($new_dir, $dest_dir) or die "Unable to rename $new_dir to $dest_dir: $!";
exit;
sub usage
{
my($ret) = @_;
my $fh = $ret ? *STDERR : *STDOUT;
print $fh <<EOT;
Usage: atomic-rsync [RSYNC-OPTIONS] HOST:/SOURCE/DIR/ /DEST/DIR/
atomic-rsync [RSYNC-OPTIONS] HOST::MOD/DIR/ /DEST/DIR/
This script lets you update a hierarchy of files in an atomic way by first
creating a new hierarchy (using hard-links to leverage the existing files),
and then swapping the new hierarchy into place. You must be pulling files
to a local directory, and that directory must already exist. For example:
atomic-rsync -av host:/remote/files/ /local/files/
This would make the transfer to the directory /local/files~new~ and then
swap out /local/files at the end of the transfer by renaming it to
/local/files~old~ and putting the new directory into its place. The
/local/files~old~ directory will be preserved until the next update, at
which point it will be deleted.
Do NOT specify this command:
atomic-rsync -av host:/remote/files /local/
... UNLESS you want the entire /local dir to be swapped out!
See the "rsync" command for its list of options. You may not use the
--link-dest or --compare-dest options (since this script uses --link-dest
to make the transfer efficient). Also, the destination directory cannot
be "/".
EOT
exit $ret;
}

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;

44
support/mnt-excl Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/perl -w
# This script takes a command-line arg of a source directory
# that will be passed to rsync, and generates a set of excludes
# that will exclude all mount points from the list. This is
# useful if you have "bind" mounts since the --one-file-system
# option won't notice the transition to a different spot on
# the same disk. For example:
#
# mnt-excl /dir | rsync --exclude-from=- ... /dir /dest/
# mnt-excl /dir/ | rsync --exclude-from=- ... /dir/ /dest/
# ssh host mnt-excl /dir | rsync --exclude-from=- ... host:/dir /dest/
#
# Imagine that /dir/foo is a mount point: the first invocation of
# mnt-excl would have output /dir/foo, while the second would have
# output /foo (which are the properly anchored excludes).
#
# NOTE: This script expects /proc/mounts to exist, but could be
# easily adapted to read /etc/mtab or similar.
#
# ADDENDUM: The addition of the --filter option (which has support for
# absolute-anchored excludes) has made this script less useful than it
# was. Beginning with 2.6.4, you can achieve the effect of this script
# through this command:
#
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/
use strict;
use Cwd 'abs_path';
my $file = '/proc/mounts';
my $dir = shift || '/';
$dir = abs_path($dir);
$dir =~ s#([^/]*)$##;
my $trailing = $1;
$trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
$trailing .= '/' if $trailing ne '';
open(IN, $file) or die "Unable to open $file: $!\n";
while (<IN>) {
$_ = (split)[1];
next unless s#^\Q$dir$trailing\E##o && $_ ne '';
print "- /$trailing$_\n";
}
close IN;

74
support/rrsync Normal file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/perl
# Name: /usr/local/bin/rrsync (should also have a symlink in /usr/bin)
# Purpose: Restricts rsync to subdirectory declared in .ssh/authorized_keys
# Author: Joe Smith <js-cgi@inwap.com> 30-Sep-2004
# Modified by Wayne Davison <wayned@samba.org> 12-Jan-2005
use Socket;
use constant LOGFILE => 'rrsync.log';
my $Usage = <<EOM;
Use 'command="$0 [-ro] SUBDIR"'
in front of lines in $ENV{HOME}/.ssh/authorized_keys
EOM
my $ro = (@ARGV and $ARGV[0] eq '-ro') ? shift : ''; # -ro = Read-Only
my $subdir = shift;
die "No subdirectory specified\n$Usage" unless defined $subdir;
# The client uses "rsync -av -e ssh src/ server:dir/", and sshd on the server
# executes this program when .ssh/authorized_keys has 'command="..."'.
# For example:
# command="rrsync logs/client" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAzGhEeNlPr...
# command="rrsync -ro results" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAmkHG1WCjC...
#
# Format of the envrionment variables set by sshd:
# SSH_ORIGINAL_COMMAND=rsync --server -vlogDtpr --partial . dir # push
# SSH_ORIGINAL_COMMAND=rsync --server --sender -vlogDtpr --partial . dir # pull
# SSH_CONNECTION=client_addr client_port server_port
my $command = $ENV{SSH_ORIGINAL_COMMAND};
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 $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;
# Enforce default of $subdir instead of the normal $HOME default.
my $orig = $dir;
my @dirs;
$dir =~ s/^"(.*?)"$/$1/;
$dir =~ s/^\s+//;
$dir =~ s/\s+$//;
foreach (split(/(?<!\\)\s+/, $dir)) {
s/\\(\s)/$1/g; # Unescape any escaped whitespace
if ($subdir eq '/') { # Less checking for '/' access
$dir = '/' if $dir eq '';
} else {
s#^/##; # Don't allow absolute paths
$_ = "$subdir/$_" unless m#^\Q$subdir\E(/|$)#;
1 while s#/\.\.(/|$)#/__/#g; # Don't allow foo/../../etc
}
tr#-_/a-zA-Z0-9.,+@^%: #_#c; # Don't allow '"&;|!=()[]{}<>*?#\$
s/(\s)/\\$1/g; # Re-escape whitespace
push(@dirs, $_);
}
push(@dirs, $subdir) unless @dirs;
$dir = join(' ', @dirs);
if (-f LOGFILE and open LOG,'>>',LOGFILE) {
my ($mm,$hh) = (localtime)[1,2];
my $host = $ENV{SSH_CONNECTION} || 'unknown';
$host =~ s/ .*//; # Keep only the client's IP addr
$host =~ s/^::ffff://;
$host = gethostbyaddr(inet_aton($host),AF_INET) || $host;
my $dir_result = $dir eq $orig ? " OK" : "> \"$dir\"";
printf LOG "%02d:%02d %-13s [%s] =%s\n", $hh, $mm, $host, $command, $dir_result;
close LOG;
}
exec "$cmd \"$dir\"" or die "exec($cmd \"$dir\") failed: $? $!";
# Note: This assumes that the rsync protocol will not be maliciously hijacked.

View File

@@ -1,72 +1,67 @@
#! /usr/bin/perl
# ---------------------------------------------------------------------------
#
# USAGE: rsyncstats <options>
#
# OPTIONS:
# -f <filename> Use <filename> for the log file
# -h include report on hourly traffic
# -d include report on domain traffic
# -t report on total traffic by section
# -D <domain> report only on traffic from <domain>
# -l <depth> Depth of path detail for sections
# -s <section> Section to report on, For example: -s /pub will report
# only on paths under /pub
#!/usr/bin/perl
#
# This script parses the default logfile format produced by rsync when running
# as a daemon with transfer logging enabled. It is derived from the xferstats
# script that comes with wuftpd
# as a daemon with transfer logging enabled. It also parses a slightly tweaked
# version of the default format where %o has been replaced with %i.
#
# This script is derived from the xferstats script that comes with wuftpd. See
# the usage message at the bottom for the options it takes.
#
# Andrew Tridgell, October 1998
# rsync-bugs@samba.org
#
# ---------------------------------------------------------------------------
# edit the next line to customize for your default log file
use Getopt::Long;
# You may wish to edit the next line to customize for your default log file.
$usage_file = "/var/adm/rsyncd.log";
# Edit the following lines for default report settings.
# Entries defined here will be over-ridden by the command line.
$opt_h = 1;
$opt_d = 0;
$opt_t = 1;
$opt_l = 2;
$hourly_report = 0;
$domain_report = 0;
$total_report = 0;
$depth_limit = 9999;
$only_section = '';
require 'getopts.pl';
&Getopts('f:rahdD:l:s:');
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'hourly-report|h' => \$hourly_report,
'domain-report|d' => \$domain_report,
'domain|D:s' => \$only_domain,
'total-report|t' => \$total_report,
'depth-limit|l:i' => \$depth_limit,
'real|r' => \$real,
'anon|a' => \$anon,
'section|s:s' => \$only_section,
'file|f:s' => \$usage_file,
);
if ($opt_r) { $real = 1;}
if ($opt_a) { $anon = 1;}
if ($real == 0 && $anon == 0) { $anon = 1; }
if ($opt_f) {$usage_file = $opt_f;}
$anon = 1 if !$real && !$anon;
open (LOG,$usage_file) || die "Error opening usage log file: $usage_file\n";
open(LOG, $usage_file) || die "Error opening usage log file: $usage_file\n";
if ($opt_D) {print "Transfer Totals include the '$opt_D' domain only.\n";
print "All other domains are filtered out for this report.\n\n";}
if ($only_domain) {
print "Transfer Totals include the '$only_domain' domain only.\n";
print "All other domains are filtered out for this report.\n\n";
}
if ($opt_s) {print "Transfer Totals include the '$opt_s' section only.\n";
print "All other sections are filtered out for this report.\n\n";}
if ($only_section) {
print "Transfer Totals include the '$only_section' section only.\n";
print "All other sections are filtered out for this report.\n\n";
}
line: while (<LOG>) {
@line = split;
next unless ($day,$time,$op,$host,$module,$file,$bytes)
= m#^ (\d+/\d\d/\d\d)\s+(\d\d:\d\d:\d\d)\s+\[\d+\]\s+(send|recv|[<>]f\S+)\s+
(\S+)\s+\[\d+\.\d+\.\d+\.\d+\]\s+(\S+)\s+\(\S*\)\s+(.*)\s+(\d+) $ #x;
$day = $line[0];
$time = $line[1];
$pid = $line[2];
$op = $line[3];
$host = $line[4];
$ip = $line[5];
$module = $line[6];
$user = $line[7];
$file = $line[8];
$bytes = $line[9];
next if ($#line != 9);
next if ($op != "send" && $op != "recv");
# TODO actually divide the data by into send/recv categories
if ($op =~ /^>/) {
$op = 'send';
} elsif ($op =~ /^</) {
$op = 'recv';
}
$daytime = $day;
$hour = substr($time,0,2);
@@ -78,11 +73,13 @@ line: while (<LOG>) {
@path = split(/\//, $file);
$pathkey = "";
for ($i=0; $i <= $#path && $i <= $opt_l;$i++) {
for ($i=0; $i <= $#path && $i <= $depth_limit; $i++) {
$pathkey = $pathkey . "/" . $path[$i];
}
next if (substr($pathkey,0,length("$opt_s")) ne "$opt_s");
if ($only_section ne '') {
next unless (substr($pathkey,0,length($only_section)) eq $only_section);
}
$host =~ tr/A-Z/a-z/;
@@ -92,12 +89,12 @@ line: while (<LOG>) {
if ( int($address[0]) > 0 || $#address < 2 )
{ $domain = "unresolved"; }
if ($opt_D) {
next unless (substr($domain,0,length("$opt_D")) eq "$opt_D");
if ($only_domain ne '') {
next unless (substr($domain,0,length($only_domain)) eq $only_domain);
}
# printf ("c=%d day=%s bytes=%d file=%s path=%s\n",
# printf("c=%d day=%s bytes=%d file=%s path=%s\n",
# $#line, $daytime, $bytes, $file, $pathkey);
$xferfiles++; # total files sent
@@ -117,20 +114,20 @@ line: while (<LOG>) {
}
close LOG;
@syslist = keys(systemfiles);
@dates = sort datecompare keys(xferbytes);
#@syslist = keys %systemfiles;
@dates = sort datecompare keys %xferbytes;
if ($xferfiles == 0) {die "There was no data to process.\n";}
print "TOTALS FOR SUMMARY PERIOD ", $dates[0], " TO ", $dates[$#dates], "\n\n";
printf ("Files Transmitted During Summary Period %12.0f\n", $xferfiles);
printf ("Bytes Transmitted During Summary Period %12.0f\n", $xferbytes);
printf ("Systems Using Archives %12.0f\n\n", $#syslist+1);
printf("Files Transmitted During Summary Period %12.0f\n", $xferfiles);
printf("Bytes Transmitted During Summary Period %12.0f\n", $xferbytes);
#printf("Systems Using Archives %12.0f\n\n", $#syslist+1);
printf ("Average Files Transmitted Daily %12.0f\n",
printf("Average Files Transmitted Daily %12.0f\n",
$xferfiles / ($#dates + 1));
printf ("Average Bytes Transmitted Daily %12.0f\n",
printf("Average Bytes Transmitted Daily %12.0f\n",
$xferbytes / ($#dates + 1));
format top1 =
@@ -150,7 +147,7 @@ $date, $nfiles, $nbytes/(1024*1024), $pctfiles, $pctbytes
$^ = top1;
$~ = line1;
foreach $date ( sort datecompare keys(xferbytes) ) {
foreach $date (sort datecompare keys %xferbytes) {
$nfiles = $xferfiles{$date};
$nbytes = $xferbytes{$date};
@@ -159,7 +156,7 @@ foreach $date ( sort datecompare keys(xferbytes) ) {
write;
}
if ($opt_t) {
if ($total_report) {
format top2 =
Total Transfers from each Archive Section (By bytes)
@@ -179,7 +176,7 @@ $- = 0;
$^ = top2;
$~ = line2;
foreach $section ( sort bytecompare keys(groupfiles) ) {
foreach $section (sort bytecompare keys %groupfiles) {
$files = $groupfiles{$section};
$bytes = $groupbytes{$section};
@@ -193,7 +190,7 @@ if ( $xferfiles < 1 ) { $xferfiles = 1; }
if ( $xferbytes < 1 ) { $xferbytes = 1; }
}
if ($opt_d) {
if ($domain_report) {
format top3 =
Total Transfer Amount By Domain
@@ -212,7 +209,7 @@ $- = 0;
$^ = top3;
$~ = line3;
foreach $domain ( sort domnamcompare keys(domainfiles) ) {
foreach $domain (sort domnamcompare keys %domainfiles) {
if ( $domainsecs{$domain} < 1 ) { $domainsecs{$domain} = 1; }
@@ -226,7 +223,7 @@ foreach $domain ( sort domnamcompare keys(domainfiles) ) {
}
if ($opt_h) {
if ($hourly_report) {
format top8 =
@@ -248,7 +245,7 @@ $- = 0;
$^ = top8;
$~ = line8;
foreach $hour ( sort keys(xfertbytes) ) {
foreach $hour (sort keys %xfertbytes) {
$nfiles = $xfertfiles{$hour};
$nbytes = $xfertbytes{$hour};
@@ -284,3 +281,19 @@ sub faccompare {
}
sub usage
{
die <<EOT;
USAGE: rsyncstats [options]
OPTIONS:
-f FILENAME Use FILENAME for the log file.
-h Include report on hourly traffic.
-d Include report on domain traffic.
-t Report on total traffic by section.
-D DOMAIN Report only on traffic from DOMAIN.
-l DEPTH Set DEPTH of path detail for sections.
-s SECTION Set SECTION to report on. For example, "-s /pub"
will report only on paths under "/pub".
EOT
}

178
support/savetransfer.c Normal file
View File

@@ -0,0 +1,178 @@
/* This program can record the stream of data flowing to or from a program.
* This allows it to be used to check that rsync's data that is flowing
* through a remote shell is not being corrupted (for example).
*
* Usage: savetransfer [-i|-o] OUTPUT_FILE PROGRAM [ARGS...]
* -i Save the input going to PROGRAM to the OUTPUT_FILE
* -o Save the output coming from PROGRAM to the OUTPUT_FILE
*
* If you want to capture the flow of data for an rsync command, use one of
* the following commands (the first two are push commands, the last two are
* pull commands):
*
* rsync -av --rsh="savetransfer -i /tmp/from.sender ssh"
* --rsync-path="savetransfer -i /tmp/to.receiver rsync" FILES HOST:DEST
*
* rsync -av --rsh="savetransfer -o /tmp/to.sender ssh"
* --rsync-path="savetransfer -o /tmp/from.generator rsync" FILES HOST:DEST
*
* rsync -av --rsh="savetransfer -i /tmp/from.generator ssh"
* --rsync-path="savetransfer -i /tmp/to.sender rsync" HOST:FILES DEST
*
* rsync -av --rsh="savetransfer -o /tmp/to.receiver ssh"
* --rsync-path="savetransfer -o /tmp/from.sender rsync" HOST:FILES DEST
*
* Note that this program aborts after 30 seconds of inactivity, so you'll need
* to change it if that is not enough dead time for your transfer. Also, some
* of the above commands will not notice that the transfer is done (if we're
* saving the input to a PROGRAM and the PROGRAM goes away: we won't notice
* that it's gone unless more data comes in) -- when this happens it will delay
* at the end of the transfer until the timeout period expires.
*/
#include "../rsync.h"
#define TIMEOUT_SECONDS 30
void run_program(char **command);
char buf[4096];
int save_data_from_program = 0;
int
main(int argc, char *argv[])
{
int fd_file, len;
struct timeval tv;
fd_set fds;
argv++;
if (--argc && argv[0][0] == '-') {
if (argv[0][1] == 'o')
save_data_from_program = 1;
else if (argv[0][1] == 'i')
save_data_from_program = 0;
else {
fprintf(stderr, "Unknown option: %s\n", argv[0]);
exit(1);
}
argv++;
argc--;
}
if (argc < 2) {
fprintf(stderr, "Usage: savetransfer [-i|-o] OUTPUT_FILE PROGRAM [ARGS...]\n");
fprintf(stderr, "-i Save the input going to PROGRAM to the OUTPUT_FILE\n");
fprintf(stderr, "-o Save the output coming from PROGRAM to the OUTPUT_FILE\n");
exit(1);
}
if ((fd_file = open(*argv, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0644)) < 0) {
fprintf(stderr, "Unable to write to `%s': %s\n", *argv, strerror(errno));
exit(1);
}
set_blocking(fd_file);
signal(SIGPIPE, SIG_IGN);
run_program(argv + 1);
#if defined HAVE_SETMODE && O_BINARY
setmode(STDIN_FILENO, O_BINARY);
setmode(STDOUT_FILENO, O_BINARY);
#endif
set_nonblocking(STDIN_FILENO);
set_blocking(STDOUT_FILENO);
while (1) {
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
tv.tv_sec = TIMEOUT_SECONDS;
tv.tv_usec = 0;
if (!select(STDIN_FILENO+1, &fds, NULL, NULL, &tv))
break;
if (!FD_ISSET(STDIN_FILENO, &fds))
break;
if ((len = read(STDIN_FILENO, buf, sizeof buf)) <= 0)
break;
if (write(STDOUT_FILENO, buf, len) != len) {
fprintf(stderr, "Failed to write data to stdout: %s\n", strerror(errno));
exit(1);
}
if (write(fd_file, buf, len) != len) {
fprintf(stderr, "Failed to write data to fd_file: %s\n", strerror(errno));
exit(1);
}
}
return 0;
}
void
run_program(char **command)
{
int pipe_fds[2], ret;
pid_t pid;
if (pipe(pipe_fds) < 0) {
fprintf(stderr, "pipe failed: %s\n", strerror(errno));
exit(1);
}
if ((pid = fork()) < 0) {
fprintf(stderr, "fork failed: %s\n", strerror(errno));
exit(1);
}
if (pid == 0) {
if (save_data_from_program)
ret = dup2(pipe_fds[1], STDOUT_FILENO);
else
ret = dup2(pipe_fds[0], STDIN_FILENO);
if (ret < 0) {
fprintf(stderr, "Failed to dup (in child): %s\n", strerror(errno));
exit(1);
}
close(pipe_fds[0]);
close(pipe_fds[1]);
set_blocking(STDIN_FILENO);
set_blocking(STDOUT_FILENO);
execvp(command[0], command);
fprintf(stderr, "Failed to exec %s: %s\n", command[0], strerror(errno));
exit(1);
}
if (save_data_from_program)
ret = dup2(pipe_fds[0], STDIN_FILENO);
else
ret = dup2(pipe_fds[1], STDOUT_FILENO);
if (ret < 0) {
fprintf(stderr, "Failed to dup (in parent): %s\n", strerror(errno));
exit(1);
}
close(pipe_fds[0]);
close(pipe_fds[1]);
}
void
set_nonblocking(int fd)
{
int val;
if ((val = fcntl(fd, F_GETFL, 0)) == -1)
return;
if (!(val & NONBLOCK_FLAG)) {
val |= NONBLOCK_FLAG;
fcntl(fd, F_SETFL, val);
}
}
void
set_blocking(int fd)
{
int val;
if ((val = fcntl(fd, F_GETFL, 0)) < 0)
return;
if (val & NONBLOCK_FLAG) {
val &= ~NONBLOCK_FLAG;
fcntl(fd, F_SETFL, val);
}
}

View File

@@ -26,6 +26,10 @@
#include "rsync.h"
#if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
#include <sys/un.h>
#endif
extern int dry_run;
extern int read_only;
extern int list_only;
@@ -55,7 +59,7 @@ int do_symlink(char *fname1, char *fname2)
return symlink(fname1, fname2);
}
#if HAVE_LINK
#ifdef HAVE_LINK
int do_link(char *fname1, char *fname2)
{
if (dry_run) return 0;
@@ -68,17 +72,47 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
#ifndef HAVE_LCHOWN
#define lchown chown
#endif
return lchown(path, owner, group);
}
#if HAVE_MKNOD
int do_mknod(char *pathname, mode_t mode, dev_t dev)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return mknod(pathname, mode, dev);
}
#if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
if (S_ISFIFO(mode))
return mkfifo(pathname, mode);
#endif
#if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
if (S_ISSOCK(mode)) {
int sock;
struct sockaddr_un saddr;
unsigned int len;
saddr.sun_family = AF_UNIX;
len = strlcpy(saddr.sun_path, pathname, sizeof saddr.sun_path);
#ifdef HAVE_SOCKADDR_UN_LEN
saddr.sun_len = len >= sizeof saddr.sun_path
? sizeof saddr.sun_path : len + 1;
#endif
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0
|| (unlink(pathname) < 0 && errno != ENOENT)
|| (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
return -1;
close(sock);
return do_chmod(pathname, mode);
}
#endif
#ifdef HAVE_MKNOD
return mknod(pathname, mode, dev);
#else
return -1;
#endif
}
int do_rmdir(char *pathname)
{
@@ -97,7 +131,7 @@ int do_open(char *pathname, int flags, mode_t mode)
return open(pathname, flags | O_BINARY, mode);
}
#if HAVE_CHMOD
#ifdef HAVE_CHMOD
int do_chmod(const char *path, mode_t mode)
{
int code;
@@ -152,7 +186,7 @@ int do_mkstemp(char *template, mode_t perms)
RETURN_ERROR_IF(dry_run, 0);
RETURN_ERROR_IF(read_only, EROFS);
#if defined(HAVE_SECURE_MKSTEMP) && defined(HAVE_FCHMOD)
#if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
{
int fd = mkstemp(template);
if (fd == -1)
@@ -164,6 +198,9 @@ int do_mkstemp(char *template, mode_t perms)
errno = errno_save;
return -1;
}
#if defined HAVE_SETMODE && O_BINARY
setmode(fd, O_BINARY);
#endif
return fd;
}
#else
@@ -175,27 +212,29 @@ int do_mkstemp(char *template, mode_t perms)
int do_stat(const char *fname, STRUCT_STAT *st)
{
#if HAVE_OFF64_T
#ifdef USE_STAT64_FUNCS
return stat64(fname, st);
#else
return stat(fname, st);
#endif
}
#if SUPPORT_LINKS
int do_lstat(const char *fname, STRUCT_STAT *st)
{
#if HAVE_OFF64_T
#ifdef SUPPORT_LINKS
# ifdef USE_STAT64_FUNCS
return lstat64(fname, st);
#else
# else
return lstat(fname, st);
# endif
#else
return do_stat(fname, st);
#endif
}
#endif
int do_fstat(int fd, STRUCT_STAT *st)
{
#if HAVE_OFF64_T
#ifdef USE_STAT64_FUNCS
return fstat64(fd, st);
#else
return fstat(fd, st);
@@ -204,7 +243,7 @@ int do_fstat(int fd, STRUCT_STAT *st)
OFF_T do_lseek(int fd, OFF_T offset, int whence)
{
#if HAVE_OFF64_T
#ifdef HAVE_LSEEK64
off64_t lseek64();
return lseek64(fd, offset, whence);
#else
@@ -212,20 +251,9 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
#endif
}
#ifdef USE_MMAP
void *do_mmap(void *start, int len, int prot, int flags, int fd, OFF_T offset)
{
#if HAVE_OFF64_T
return mmap64(start, len, prot, flags, fd, offset);
#else
return mmap(start, len, prot, flags, fd, offset);
#endif
}
#endif
char *d_name(struct dirent *di)
{
#if HAVE_BROKEN_READDIR
#ifdef HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;

View File

@@ -28,7 +28,8 @@
int modify_window = 0;
int module_id = -1;
struct exclude_list_struct server_exclude_list;
char *partial_dir;
struct filter_list_struct server_filter_list;
void rprintf(UNUSED(enum logcode code), const char *format, ...)
{
@@ -38,6 +39,16 @@ struct exclude_list_struct server_exclude_list;
va_end(ap);
}
void rsyserr(UNUSED(enum logcode code), int errcode, const char *format, ...)
{
va_list ap;
fputs(RSYNC_NAME ": ", stderr);
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fprintf(stderr, ": %s (%d)\n", strerror(errcode), errcode);
}
void _exit_cleanup(int code, const char *file, int line)
{
fprintf(stderr, "exit(%d): %s(%d)\n",
@@ -45,7 +56,7 @@ struct exclude_list_struct server_exclude_list;
exit(code);
}
int check_exclude(UNUSED(struct exclude_list_struct *listp), UNUSED(char *name),
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(char *name),
UNUSED(int name_is_dir))
{
/* This function doesn't really get called in this test context, so

173
test.sh
View File

@@ -1,173 +0,0 @@
#!/bin/sh
# Copyright (C) 1998,1999 Philip Hands <phil@hands.com>
#
# This program is distributable under the terms of the GNU GPL (see COPYING)
#
# This is a simple test script that tests a few rsync
# features to make sure I haven't broken them before a release.
#
#
# check if we are running under debian-test, and change behaviour to suit
if test -n "${DEBIANTEST_LIB}" ; then
# make sure rsync is installed
test -e /usr/bin/rsync || exit 0
. ${DEBIANTEST_LIB}/functions.sh
Debian=1
else
cat <<EOF
This set of tests is not completely portable. It is intended for developers
not for end users. You may experience failures on some platforms that
do not indicate a problem with rsync.
EOF
RSYNC=`pwd`/rsync
runtest() {
echo -n "Test $1: "
eval "$2"
}
printmsg() {
echo ""
echo "**** ${1}^G ****"
echo ""
}
fi
TMP=/tmp/rsync-test.$$
FROM=${TMP}/from
TO=${TMP}/to
F1=text1
LOG=${TMP}/log
mkdir $TMP
mkdir $FROM
mkdir $TO
# set up test data
touch ${FROM}/empty
mkdir ${FROM}/emptydir
ps ax > ${FROM}/pslist
echo -n "This file has no trailing lf" > ${FROM}/nolf
ln -s nolf ${FROM}/nolf-symlink
# Gather some random text. We need files that will exist and be
# publicly readable on all platforms: hopefully this will work.
cat /etc/*tab /etc/services /etc/*.conf /etc/*rc > ${FROM}/${F1}
mkdir ${FROM}/dir
cp ${FROM}/${F1} ${FROM}/dir/
mkdir ${FROM}/dir/subdir
mkdir ${FROM}/dir/subdir/subsubdir
ls -ltr /etc > ${FROM}/dir/subdir/subsubdir/etc-ltr-list
mkdir ${FROM}/dir/subdir/subsubdir2
ls -lt /bin > ${FROM}/dir/subdir/subsubdir2/bin-lt-list
checkit() {
testnum=`expr 0${testnum} + 1`
log=${LOG}.${testnum}
failed=
echo "Running: \"$1\"" >${log}
echo "">>${log}
eval "$1" >>${log} 2>&1
status=$?
if [ $status != 0 ]; then
failed="YES";
fi
echo "-------------">>${log}
echo "check how the files compare with diff:">>${log}
echo "">>${log}
diff -ur $2 $3 >>${log} 2>&1 || failed=YES
echo "-------------">>${log}
echo "check how the directory listings compare with diff:">>${log}
echo "">>${log}
( cd $2 ; ls -laR ) > ${TMP}/ls-from 2>>${log}
( cd $3 ; ls -laR ) > ${TMP}/ls-to 2>>${log}
diff -u ${TMP}/ls-from ${TMP}/ls-to >>${log} 2>&1 || failed=YES
if [ -z "${failed}" ] ; then
test -z "${Debian}" && echo " done."
rm $log
return 0
else
if test -n "${Debian}" ; then
cat ${log}
rm ${log}
else
echo " FAILED (test # ${testnum} status=$status)."
fi
return 1
fi
}
checkforlogs() {
# skip it if we're under debian-test
if test -n "${Debian}" ; then return 0 ; fi
if [ -f $1 ] ; then
cat <<EOF
Failures have occured.
You can find the output of the tests in these files:
$@
Please hit <RETURN>
EOF
read input
else
rm -rf ${TMP}
echo ""
echo "Tests Completed Successfully :-)"
fi
}
# Main script starts here
runtest "basic operation" 'checkit "$RSYNC -av ${FROM}/ ${TO}" ${FROM}/ ${TO}'
ln ${FROM}/pslist ${FROM}/dir
runtest "hard links" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
rm ${TO}/${F1}
runtest "one file" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
echo "extra line" >> ${TO}/${F1}
runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
cp ${FROM}/${F1} ${TO}/ThisShouldGo
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
LONGDIR=${FROM}/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
mkdir -p ${LONGDIR}
date > ${LONGDIR}/1
ls -la / > ${LONGDIR}/2
runtest "long paths" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
if type ssh >/dev/null 2>&1; then
if [ "`ssh -o'BatchMode yes' localhost echo yes 2>/dev/null`" = "yes" ]; then
rm -rf ${TO}
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
mv ${TO}/${F1} ${TO}/ThisShouldGo
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
else
printmsg "Skipping SSH tests because ssh conection to localhost not authorised"
fi
else
printmsg "Skipping SSH tests because ssh is not in the path"
fi
rm -rf ${TO}
mkdir -p ${FROM}2/dir/subdir
cp -a ${FROM}/dir/subdir/subsubdir ${FROM}2/dir/subdir
cp ${FROM}/dir/* ${FROM}2/dir 2>/dev/null
runtest "excludes" 'checkit "$RSYNC -vv -Hlrt --delete --include /dir/ --include /dir/\* --include /dir/\*/subsubdir --include /dir/\*/subsubdir/\*\* --exclude \*\* ${FROM}/dir ${TO}" ${FROM}2/ ${TO}'
rm -r ${FROM}2
checkforlogs ${LOG}.?

View File

@@ -17,8 +17,8 @@ with the GNU Standards, installcheck does not look for rsync on the
path.
If the tests pass, you should see a report to that effect. Some tests
require being root or some other precondition, and so will normally be
checked -- look at the test scripts for more information.
require being root or some other precondition, and so will normally not
be checked -- look at the test scripts for more information.
If the tests fail, you will see rather more output. The scratch
directory will remain in the build directory. It would be useful if

66
testsuite/backup.test Normal file
View File

@@ -0,0 +1,66 @@
#! /bin/sh
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that the --backup option works right.
. "$suitedir/rsync.fns"
bakdir="$tmpdir/bak"
mkdir "$fromdir" "$bakdir"
name1="$fromdir/name1"
name2="$fromdir/name2"
outfile="$scratchdir/rsync.out"
cat $srcdir/[gr]*.[ch] > "$name1"
cat $srcdir/[et]*.[ch] > "$name2"
checkit "$RSYNC -avv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
cat $srcdir/[fgpr]*.[ch] > "$name1"
cat $srcdir/[etw]*.[ch] > "$name2"
$RSYNC -avv --no-whole-file --backup "$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"
diff $diffopt "$fromdir/$fn" "$todir" || test_fail "copy of $fn failed"
diff $diffopt "$chkdir/$fn" "$todir/$fn~" || test_fail "backup of $fn to $fn~ failed"
mv "$todir/$fn~" "$todir/$fn"
done
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 --del \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
cat $srcdir/[efgr]*.[ch] > "$name1"
cat $srcdir/[ew]*.[ch] > "$name2"
checkit "$RSYNC -avv --inplace --no-whole-file --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"
checkit "$RSYNC -avv --inplace --no-whole-file \"$fromdir/\" \"$bakdir/\"" "$fromdir" "$bakdir"
# The script would have aborted on error, so getting here means we've won.
exit 0

45
testsuite/batch-mode.test Normal file
View File

@@ -0,0 +1,45 @@
#! /bin/sh
# Copyright (C) 2004 by Chris Shoemaker <c.shoemaker@cox.net>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync's --write-batch and --read-batch options
. "$suitedir/rsync.fns"
set -x
hands_setup
cd "$tmpdir"
# Build chkdir for the daemon tests using a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
runtest "local --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"'
rm -rf "$todir"
runtest "--read-batch" 'checkit "$RSYNC -av --read-batch=BATCH \"$todir\"" "$fromdir" "$todir"'
build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
rm -rf "$todir"
runtest "daemon sender --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH rsync://localhost/test-from/ \"$todir\"" "$chkdir" "$todir"'
rm -rf "$todir"
runtest "--read-batch from daemon" 'checkit "$RSYNC -av --read-batch=BATCH \"$todir\"" "$chkdir" "$todir"'
rm -rf "$todir"
runtest "BATCH.sh use of --read-batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"'
rm -rf "$todir"
mkdir "$todir" || test_fail "failed to restore empty destination directory"
runtest "daemon recv --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
# The script would have aborted on error, so getting here means we pass.
exit 0

View File

@@ -9,15 +9,12 @@
# the test is a member of them. Hopefully they're in at least one
# test.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
fromdir="$scratchdir/from"
todir="$scratchdir/to"
mygrps="`rsync_getgroups`" || fail "Can't get groups"
mkdir "$fromdir"
@@ -29,7 +26,7 @@ do
done
sleep 2
checkit "$RSYNC -rtgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
checkit "$RSYNC -rtgpvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -0,0 +1,41 @@
#! /bin/sh
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test that various read-only and set[ug]id permissions work properly,
# even when using a --temp-dir option (which we try to point at a
# different filesystem than the destination dir).
. "$suitedir/rsync.fns"
set -x
hands_setup
tmpdir2=/tmp
sdev=`$TOOLDIR/getfsdev $scratchdir`
tdev=`$TOOLDIR/getfsdev $tmpdir2`
if [ x$sdev = x$tdev ]; then
tmpdir2=/var/tmp
tdev=`$TOOLDIR/getfsdev $tmpdir2`
[ x$sdev = x$tdev ] && test_skipped "Can't find a tmp dir on a different file system"
fi
chmod 440 "$fromdir/text"
chmod 500 "$fromdir/dir/text"
e="$fromdir/dir/subdir/foobar.baz"
chmod 6450 "$e" || chmod 2450 "$e" || chmod 1450 "$e" || chmod 450 "$e"
e="$fromdir/dir/subdir/subsubdir/etc-ltr-list"
chmod 2670 "$e" || chmod 1670 "$e" || chmod 670 "$e"
# First a normal copy.
runtest "normal copy" 'checkit "$RSYNC -avv --temp-dir=\"$tmpdir2\" \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"'
# Then we update all the files.
runtest "update copy" 'checkit "$RSYNC -avvI --no-whole-file --temp-dir=\"$tmpdir2\" \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"'
# The script would have aborted on error, so getting here means we've won.
exit 0

32
testsuite/chmod.test Normal file
View File

@@ -0,0 +1,32 @@
#! /bin/sh
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test that various read-only and set[ug]id permissions work properly,
# even when using a --temp-dir option (which we try to point at a
# different filesystem than the destination dir).
. "$suitedir/rsync.fns"
set -x
hands_setup
chmod 440 "$fromdir/text"
chmod 500 "$fromdir/dir/text"
e="$fromdir/dir/subdir/foobar.baz"
chmod 6450 "$e" || chmod 2450 "$e" || chmod 1450 "$e" || chmod 450 "$e"
e="$fromdir/dir/subdir/subsubdir/etc-ltr-list"
chmod 2670 "$e" || chmod 1670 "$e" || chmod 670 "$e"
# First a normal copy.
runtest "normal copy" 'checkit "$RSYNC -avv \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"'
# Then we update all the files.
runtest "update copy" 'checkit "$RSYNC -avvI --no-whole-file \"$fromdir/\" \"$todir\"" "$fromdir" "$todir"'
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -11,14 +11,21 @@
# We don't know what users will be present on this system, so we just
# use random numeric uids and gids.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh "$0"
fi
;;
esac
fromdir="$scratchdir/from"
todir="$scratchdir/to"
# Build some hardlinks
mkdir "$fromdir"
name1="$fromdir/name1"

View File

@@ -0,0 +1,39 @@
#! /bin/sh
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of the --compare-dest option.
. "$suitedir/rsync.fns"
alt1dir="$tmpdir/alt1"
alt2dir="$tmpdir/alt2"
# Build some files/dirs/links to copy
set -x
hands_setup
# Setup the alt and chk dirs
$RSYNC -av --include=text --include='*/' --exclude='*' "$fromdir/" "$alt1dir/"
$RSYNC -av --include=etc-ltr-list --include='*/' --exclude='*' "$fromdir/" "$alt2dir/"
sleep 1
touch "$fromdir/dir/text"
$RSYNC -av --exclude=/text --exclude=etc-ltr-list "$fromdir/" "$chkdir/"
# Let's do it!
checkit "$RSYNC -avv --no-whole-file \
--compare-dest=\"$alt1dir\" --compare-dest=\"$alt2dir\" \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
checkit "$RSYNC -avv --no-whole-file \
--copy-dest=\"$alt1dir\" --copy-dest=\"$alt2dir\" \
\"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -26,8 +26,14 @@ build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
set -x
hands_setup
checkit "$RSYNC -avvvvz localhost::test-from/ \"$TO/\"" "$FROM" "$TO"
# Build chkdir with a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
checkit "$RSYNC -avvvvz localhost::test-from/ \"$todir/\"" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -20,8 +20,14 @@ build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
set -x
hands_setup
checkit "$RSYNC -avvvvz \"$FROM/\" localhost::test-to/" "$FROM" "$TO"
# Build chkdir with a normal rsync and an --exclude.
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
checkit "$RSYNC -avvvvz \"$fromdir/\" localhost::test-to/" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

29
testsuite/delete.test Normal file
View File

@@ -0,0 +1,29 @@
#! /bin/sh
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of various delete directives.
. "$suitedir/rsync.fns"
set -x
hands_setup
makepath "$chkdir"
# Create two chk dirs, one with a copy of the source files, and one with
# what we expect to be left behind by the copy using --remove-sent-files.
$RSYNC -av "$fromdir/" "$chkdir/copy/"
$RSYNC -av -f 'exclude,! */' "$fromdir/" "$chkdir/empty/"
checkit "$RSYNC -avv --remove-sent-files \
\"$fromdir/\" \"$todir/\"" "$chkdir/copy" "$todir"
diff -r "$chkdir/empty" "$fromdir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -7,19 +7,19 @@
# Test rsync handling of devices. This can only run if you're root.
. $srcdir/testsuite/rsync.fns
set -x
. "$suitedir/rsync.fns"
# Build some hardlinks
fromdir="$scratchdir/from"
todir="$scratchdir/to"
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;
*) test_skipped "Rsync won't copy devices unless we're root" ;;
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh "$0"
fi
test_skipped "Rsync won't copy devices unless we're root"
;;
esac
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
@@ -31,8 +31,9 @@ mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node u
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node unless root"
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node unless root"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node unless root"
mkfifo "$fromdir/fifo" || test_skipped "Can't run mkfifo"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" skip_file_diff
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -19,15 +19,12 @@
# This test is not great, because it is a timing-dependent bug.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
fromdir="$scratchdir/from"
todir="$scratchdir/to"
mkdir "$fromdir"
name1="$fromdir/name1"
name2="$fromdir/name2"

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Copyright (C) 2003 by Wayne Davison <wayned@samba.org>
# Copyright (C) 2003, 2004, 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
@@ -10,46 +10,78 @@
# Test some of the more obscure wildcard handling of exclude/include
# processing.
. $srcdir/testsuite/rsync.fns
set -x
. "$suitedir/rsync.fns"
HOME="$scratchdir"
CVSIGNORE='*.junk'
export HOME CVSIGNORE
set -x
# Build some files/dirs/links to copy
fromdir="$scratchdir/from"
todir="$scratchdir/to"
chkdir="$scratchdir/chk"
echo home-cvs-exclude >"$scratchdir"/.cvsignore
makepath "$fromdir/foo/down/to/you"
makepath "$fromdir/bar/down/to/foo/too"
makepath "$fromdir/bar/down/to/bar/baz"
makepath "$fromdir/mid/for/foo/and/that/is/who"
cat >"$fromdir/.filt" <<EOF
exclude down
: .filt-temp
clear
- .filt
- *.bak
- *.old
EOF
echo kept >"$fromdir/foo/file1"
echo removed >"$fromdir/foo/file2"
echo cvsout >"$fromdir/foo/file2.old"
cat >"$fromdir/foo/.filt" <<EOF
include .filt
- file1
EOF
cat >"$fromdir/bar/.filt" <<EOF
- home-cvs-exclude
dir-merge .filt2
+ to
EOF
echo cvsout >"$fromdir/bar/down/to/home-cvs-exclude"
cat >"$fromdir/bar/down/to/.filt2" <<EOF
- .filt2
EOF
cat >"$fromdir/bar/down/to/foo/.filt2" <<EOF
+ *.junk
EOF
echo keeper >"$fromdir/bar/down/to/foo/file1"
echo cvsout >"$fromdir/bar/down/to/foo/file1.bak"
echo gone >"$fromdir/bar/down/to/foo/file3"
echo lost >"$fromdir/bar/down/to/foo/file4"
echo cvsout >"$fromdir/bar/down/to/foo/file4.junk"
echo weird >"$fromdir/bar/down/to/foo/+ file3"
echo cvsout-but-filtin >"$fromdir/bar/down/to/foo/file4.junk"
echo smashed >"$fromdir/bar/down/to/foo/to"
echo cvsout >"$fromdir/bar/down/to/home-cvs-exclude"
cat >"$fromdir/bar/down/to/bar/.filt2" <<EOF
- *.deep
EOF
echo filtout >"$fromdir/bar/down/to/bar/baz/file5.deep"
# This one should be ineffectual
cat >"$fromdir/mid/.filt2" <<EOF
- extra
EOF
echo cvsout >"$fromdir/mid/one-in-one-out"
echo one-in-one-out >"$fromdir/mid/.cvsignore"
echo cvsin >"$fromdir/mid/one-for-all"
cat >"$fromdir/mid/.filt" <<EOF
:C
EOF
echo cvsin >"$fromdir/mid/for/one-in-one-out"
echo expunged >"$fromdir/mid/for/foo/extra"
echo retained >"$fromdir/mid/for/foo/keep"
echo cvsin >"$fromdir/mid/for/one-in-one-out"
ln -s too "$fromdir/bar/down/to/foo/sym"
# Setup our test exclude/include file.
# Setup our test exclude/include files.
excl="$scratchdir/exclude-from"
cat >"$excl" <<EOF
!
# If the second line of these two lines does anything, it's a bug.
+ **/bar
- /bar
@@ -65,6 +97,10 @@ cat >"$excl" <<EOF
- /mid/for/foo/extra
EOF
cat >"$scratchdir/.cvsignore" <<EOF
home-cvs-exclude
EOF
# Create the chk dir with what we expect to be excluded
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
@@ -83,7 +119,8 @@ $RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files.
checkit "$RSYNC -avv --exclude-from=$excl \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
checkit "$RSYNC -avv --exclude-from=\"$excl\" \
--delete-during \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# Modify the chk dir by removing cvs-ignored files and then tweaking the dir times.
@@ -93,12 +130,70 @@ rm "$chkdir"/bar/down/to/foo/*.junk
rm "$chkdir"/bar/down/to/home-cvs-exclude
rm "$chkdir"/mid/one-in-one-out
$RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
$RSYNC -av --existing --filter='exclude,! */' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files, this time with --cvs-exclude
# and --delete-excluded.
checkit "$RSYNC -avvC --delete-excluded --exclude-from=$excl \
checkit "$RSYNC -avvC --filter=\"merge $excl\" --delete-excluded \
--delete-during \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# Modify the chk dir for our merge-exclude test and then tweak the dir times.
rm "$chkdir"/foo/file1
rm "$chkdir"/bar/down/to/bar/baz/*.deep
cp -p "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp -p "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
$RSYNC -av --existing -f 'show .filt*' -f 'hide,! */' --del "$fromdir/" "$todir/"
echo retained >"$todir"/bar/down/to/bar/baz/nodel.deep
cp -p "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"
# Now, test if rsync excludes the same files, this time with a merge-exclude
# file.
checkit "sed '/!/d' \"$excl\" |
$RSYNC -avv -f dir-merge_.filt -f merge_- \
--delete-during \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# Remove the files that will be deleted.
rm "$chkdir"/.filt
rm "$chkdir"/bar/.filt
rm "$chkdir"/bar/down/to/.filt2
rm "$chkdir"/bar/down/to/foo/.filt2
rm "$chkdir"/bar/down/to/bar/.filt2
rm "$chkdir"/mid/.filt
$RSYNC -av --protocol=28 --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
# Now, try the prior command with --delete-before and some side-specific
# rules.
checkit "sed '/!/d' \"$excl\" |
$RSYNC -avv -f :s_.filt -f .s_- -f P_nodel.deep \
--delete-before \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# Next, we'll test some rule-restricted filter files.
cat >"$fromdir/bar/down/.excl" <<EOF
file3
EOF
cat >"$fromdir/bar/down/to/foo/.excl" <<EOF
+ file3
*.bak
EOF
$RSYNC -av --del "$fromdir/" "$chkdir/"
rm "$chkdir/bar/down/to/foo/file1.bak"
rm "$chkdir/bar/down/to/foo/file3"
rm "$chkdir/bar/down/to/foo/+ file3"
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"
$RSYNC -av --delete-excluded --exclude='*' "$fromdir/" "$todir/"
checkit "$RSYNC -avv -f dir-merge,-_.excl \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.

25
testsuite/fuzzy.test Normal file
View File

@@ -0,0 +1,25 @@
#! /bin/sh
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of the --fuzzy option.
. "$suitedir/rsync.fns"
set -x
mkdir "$fromdir"
mkdir "$todir"
cp -p "$srcdir"/rsync.c "$fromdir"/rsync.c
cp -p "$fromdir"/rsync.c "$todir"/rsync2.c
# Let's do it!
checkit "$RSYNC -avvi --no-whole-file --fuzzy --delete-after \
\"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -11,19 +11,19 @@ hands_setup
# Main script starts here
runtest "basic operation" 'checkit "$RSYNC -av ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest "basic operation" 'checkit "$RSYNC -av \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
ln ${FROM}/filelist ${FROM}/dir
runtest "hard links" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
ln "$fromdir/filelist" "$fromdir/dir"
runtest "hard links" 'checkit "$RSYNC -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
rm ${TO}/text
runtest "one file" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
rm "$todir/text"
runtest "one file" 'checkit "$RSYNC -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
echo "extra line" >> ${TO}/text
runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
echo "extra line" >> "$todir/text"
runtest "extra data" 'checkit "$RSYNC -avH --no-whole-file \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
cp ${FROM}/text ${TO}/ThisShouldGo
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
cp "$fromdir/text" "$todir/ThisShouldGo"
runtest " --delete" 'checkit "$RSYNC --delete -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -10,7 +10,7 @@
# specify -H, then hard links are detected and recreated as hardlinks
# on the other end.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x
@@ -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 -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
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

View File

@@ -7,18 +7,22 @@
. "$suitedir/rsync.fns"
# set -x
set -x
hands_setup
LONGNAME=This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
LONGDIR=$FROM/$LONGNAME/$LONGNAME/$LONGNAME
longname=This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
longdir="$fromdir/$longname/$longname/$longname"
makepath $LONGDIR || test_skipped "unable to create long directory"
touch $LONGDIR/1 || test_skipped "unable to create files in long directory"
date > ${LONGDIR}/1
ls -la / > ${LONGDIR}/2
checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}
makepath "$longdir" || test_skipped "unable to create long directory"
touch "$longdir/1" || test_skipped "unable to create files in long directory"
date > "$longdir/1"
if [ -r /etc ]; then
ls -la /etc >"$longdir/2"
else
ls -la / >"$longdir/2"
fi
checkit "$RSYNC --delete -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -7,23 +7,20 @@
# Make sure we can merge files from multiple directories into one.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x
# Build some files/dirs/links to copy
fromdir="$scratchdir/from"
from1dir="${fromdir}1"
from2dir="${fromdir}2"
from3dir="${fromdir}3"
todir="$scratchdir/to"
chkdir="$scratchdir/chk"
mkdir "$from1dir" "$from2dir" "$from3dir"
mkdir "$from2dir"/sub1 "$from3dir"/sub1
mkdir "$from3dir"/sub2
mkdir "$chkdir" "$chkdir"/sub1 "$chkdir"/sub2
mkdir "$from3dir"/sub2 "$from1dir"/dir-and-not-dir
mkdir "$chkdir" "$chkdir"/sub1 "$chkdir"/sub2 "$chkdir"/dir-and-not-dir
echo "one" >"$from1dir"/one
cp -p "$from1dir"/one "$from2dir"/one
cp -p "$from1dir"/one "$from3dir"/one
@@ -37,13 +34,19 @@ cp -p "$from2dir"/sub1/uno "$from3dir"/sub1/uno
echo "sub2" >"$from3dir"/sub1/dos
echo "sub3" >"$from2dir"/sub1/tres
echo "subby" >"$from3dir"/sub2/subby
echo "extra" >"$from1dir"/dir-and-not-dir/inside
echo "not-dir" >"$from3dir"/dir-and-not-dir
cp -p "$from1dir"/one "$from1dir"/two "$from2dir"/three "$from3dir"/four "$from1dir"/five "$from3dir"/six "$chkdir"
cp -p "$from1dir"/dir-and-not-dir/inside "$chkdir"/dir-and-not-dir
cp -p "$from2dir"/sub1/uno "$from3dir"/sub1/dos "$from2dir"/sub1/tres "$chkdir"/sub1
cp -p "$from3dir"/sub2/subby "$chkdir"/sub2
# Get rid of any directory-time differences
$RSYNC -av --existing --include='*/' --exclude='*' "$from1dir/" "$from2dir/" "$from3dir/" "$chkdir/"
$RSYNC -av --existing -f 'exclude,! */' "$from1dir/" "$from2dir/"
$RSYNC -av --existing -f 'exclude,! */' "$from2dir/" "$from3dir/"
$RSYNC -av --existing -f 'exclude,! */' "$from1dir/" "$chkdir/"
$RSYNC -av --existing -f 'exclude,! */' "$from3dir/" "$chkdir/"
checkit "$RSYNC -aHvv \"$from1dir/\" \"$from2dir/\" \"$from3dir/\" \"$todir/\"" "$chkdir" "$todir"

View File

@@ -18,16 +18,15 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
TMP="$scratchdir"
FROM=${TMP}/from
TO=${TMP}/to
LOG=${TMP}/log
RSYNC="$rsync_bin"
tmpdir="$scratchdir"
fromdir="$tmpdir/from"
todir="$tmpdir/to"
chkdir="$tmpdir/chk"
# Berkley's nice.
PATH="$PATH:/usr/ucb"
if diff -u $srcdir/testsuite/rsync.fns $srcdir/testsuite/rsync.fns >/dev/null 2>&1; then
if diff -u "$srcdir/testsuite/rsync.fns" "$srcdir/testsuite/rsync.fns" >/dev/null 2>&1; then
diffopt="-u"
else
diffopt="-c"
@@ -37,10 +36,10 @@ runtest() {
echo $ECHO_N "Test $1: $ECHO_C"
if eval "$2"
then
echo "${ECHO_T} done."
echo "$ECHO_T done."
return 0
else
echo "${ECHO_T} failed!"
echo "$ECHO_T failed!"
return 1
fi
}
@@ -51,7 +50,7 @@ printmsg() {
rsync_ls_lR() {
find "$@" -print | sort | xargs "$TOOLDIR/tls"
find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
}
rsync_getgroups() {
@@ -60,16 +59,16 @@ rsync_getgroups() {
####################
# Build test directories TO and FROM, with FROM full of files.
# Build test directories $todir and $fromdir, with $fromdir full of files.
hands_setup() {
# Clean before creation
rm -rf $FROM
rm -rf $TO
rm -rf "$fromdir"
rm -rf "$todir"
[ -d $TMP ] || mkdir $TMP
[ -d $FROM ] || mkdir $FROM
[ -d $TO ] || mkdir $TO
[ -d "$tmpdir" ] || mkdir "$tmpdir"
[ -d "$fromdir" ] || mkdir "$fromdir"
[ -d "$todir" ] || mkdir "$todir"
# On some BSD systems, the umask affects the mode of created
# symlinks, even though the mode apparently has no effect on how
@@ -82,29 +81,37 @@ hands_setup() {
# the same. So, we need to set our umask before doing any creations.
# set up test data
touch ${FROM}/empty
mkdir ${FROM}/emptydir
touch "$fromdir/empty"
mkdir "$fromdir/emptydir"
# a hundred lines of text or so
rsync_ls_lR "${srcdir}" > ${FROM}/filelist
rsync_ls_lR "$srcdir" > "$fromdir/filelist"
# This might fail on systems that don't have -n
echo $ECHO_N "This file has no trailing lf$ECHO_C" > ${FROM}/nolf
echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
umask 0
ln -s nolf ${FROM}/nolf-symlink
ln -s nolf "$fromdir/nolf-symlink"
umask 022
cat $srcdir/*.c > ${FROM}/text
mkdir ${FROM}/dir
cp ${FROM}/text ${FROM}/dir
mkdir ${FROM}/dir/subdir
mkdir ${FROM}/dir/subdir/subsubdir
ls -ltr /etc > ${FROM}/dir/subdir/subsubdir/etc-ltr-list
mkdir ${FROM}/dir/subdir/subsubdir2
ls -lt /bin > ${FROM}/dir/subdir/subsubdir2/bin-lt-list
cat $srcdir/*.c > "$fromdir/text"
mkdir "$fromdir/dir"
cp "$fromdir/text" "$fromdir/dir"
mkdir "$fromdir/dir/subdir"
echo some data > "$fromdir/dir/subdir/foobar.baz"
mkdir "$fromdir/dir/subdir/subsubdir"
if [ -r /etc ]; then
ls -ltr /etc > "$fromdir/dir/subdir/subsubdir/etc-ltr-list"
else
ls -ltr / > "$fromdir/dir/subdir/subsubdir/etc-ltr-list"
fi
mkdir "$fromdir/dir/subdir/subsubdir2"
if [ -r /bin ]; then
ls -lt /bin > "$fromdir/dir/subdir/subsubdir2/bin-lt-list"
else
ls -lt / > "$fromdir/dir/subdir/subsubdir2/bin-lt-list"
fi
# echo testing head:
# ls -lR ${srcdir} | head -10 || echo failed
# ls -lR "$srcdir" | head -10 || echo failed
}
@@ -158,21 +165,24 @@ checkit() {
failed="YES";
fi
echo "-------------"
echo "check how the files compare with diff:"
echo ""
for f in `cd "$2"; find . -type f -print `
do
diff $diffopt "$2"/"$f" "$3"/"$f" || failed=YES
done
echo "-------------"
echo "check how the directory listings compare with diff:"
echo ""
( cd "$2" && rsync_ls_lR . ) > ${TMP}/ls-from
( cd "$3" && rsync_ls_lR . ) > ${TMP}/ls-to
diff $diffopt ${TMP}/ls-from ${TMP}/ls-to || failed=YES
if [ -z "${failed}" ] ; then
( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
echo "-------------"
echo "check how the files compare with diff:"
echo ""
if [ "x$4" != x ]; then
echo " === Skipping (as directed) ==="
else
diff -r $diffopt "$2" "$3" || failed=YES
fi
echo "-------------"
if [ -z "$failed" ] ; then
return 0
else
return 1
@@ -189,32 +199,31 @@ build_rsyncd_conf() {
pidfile="$scratchdir/rsyncd.pid"
logfile="$scratchdir/rsyncd.log"
cat >$conf <<EOF
cat >"$conf" <<EOF
# rsyncd configuration file autogenerated by $0
pid file = $pidfile
use chroot = no
hosts allow = localhost, 127.0.0.1
log file = $logfile
exclude = foobar.baz
max verbosity = 9
uid = 0
gid = 0
[test-from]
path = $FROM
path = $fromdir
read only = yes
[test-to]
path = $TO
path = $todir
read only = no
EOF
}
build_symlinks() {
fromdir="$scratchdir/from"
todir="$scratchdir/to"
mkdir "$fromdir"
date >"$fromdir/referent"
ln -s referent "$fromdir/relative"
@@ -230,7 +239,7 @@ test_fail() {
test_skipped() {
echo "$@" >&2
echo "$@" > "$TMP/whyskipped"
echo "$@" > "$tmpdir/whyskipped"
exit 77
}

View File

@@ -24,11 +24,11 @@ if ! [ "`ssh -o'BatchMode yes' localhost echo yes`" = "yes" ]; then
fi
# Added by Steve Bonds Feb 2 2003
# Without this, there are no files in the ${FROM} directory, so rsync has
# Without this, there are no files in the $fromdir directory, so rsync has
# nothing to do.
hands_setup
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=\"$RSYNC\" \"$fromdir/\" \"localhost:$todir\"" "$fromdir/" "$todir"'
# Added by Steve Bonds Feb 2 2003
# I assumed that "F1" was intended to hold a single file for testing if
@@ -36,8 +36,8 @@ runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FRO
# it was unset so the "mv" tried to move a parent directory into a
# subdirectory of itself. There is probably a better way of pulling out
# a sample file to rename.
F1=`ls ${TO} | head -5 | tail -1`
F1=`ls "$todir" | head -5 | tail -1`
mv ${TO}/${F1} ${TO}/ThisShouldGo
mv "$todir/$F1" "$todir/ThisShouldGo"
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=\"$RSYNC\" \"$fromdir/\" \"localhost:$todir\"" "$fromdir/" "$todir"'

View File

@@ -8,7 +8,7 @@
# Test rsync's somewhat over-featured symlink control: the default
# behaviour is that symlinks should not be copied at all.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x
@@ -18,19 +18,19 @@ build_symlinks || test_fail "failed to build symlinks"
# should be missing.
$RSYNC -r "$fromdir/" "$todir" || test_fail "$RSYNC returned $?"
[ -f "${todir}/referent" ] || test_fail "referent was not copied"
[ -d "${todir}/from" ] && test_fail "extra level of directories"
if is_a_link "${todir}/dangling"
[ -f "$todir/referent" ] || test_fail "referent was not copied"
[ -d "$todir/from" ] && test_fail "extra level of directories"
if is_a_link "$todir/dangling"
then
test_fail "dangling symlink was copied"
fi
if is_a_link "${todir}/relative"
if is_a_link "$todir/relative"
then
test_fail "relative symlink was copied"
fi
if is_a_link "${todir}/absolute"
if is_a_link "$todir/absolute"
then
test_fail "absolute symlink was copied"
fi

View File

@@ -7,7 +7,7 @@
# Test tiny function to trim trailing slashes.
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x

View File

@@ -4,7 +4,7 @@
# Call directly into unsafe_symlink and test its handling of various filenames
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
test_unsafe() {
# $1 is the target of a symlink

View File

@@ -2,7 +2,7 @@
# Originally by Vladim<69>r Michl <Vladimir.Michl@hlubocky.del.cz>
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
test_symlink() {
is_a_link "$1" || test_fail "File $1 is not a symlink"
@@ -14,7 +14,7 @@ test_regular() {
fi;
};
cd "$TMP"
cd "$tmpdir"
mkdir from

View File

@@ -7,7 +7,7 @@
# Test the wildmatch functionality
. $srcdir/testsuite/rsync.fns
. "$suitedir/rsync.fns"
set -x

23
tls.c
View File

@@ -49,17 +49,16 @@ int list_only = 0;
int preserve_perms = 0;
static void failed (char const *what,
char const *where)
static void failed(char const *what, char const *where)
{
fprintf (stderr, PROGRAM ": %s %s: %s\n",
what, where, strerror (errno));
exit (1);
fprintf(stderr, PROGRAM ": %s %s: %s\n",
what, where, strerror(errno));
exit(1);
}
static void list_file (const char *fname)
static void list_file(const char *fname)
{
STRUCT_STAT buf;
char permbuf[PERMSTRING_SIZE];
@@ -67,8 +66,8 @@ static void list_file (const char *fname)
char datebuf[50];
char linkbuf[4096];
if (do_lstat(fname, &buf) == -1)
failed ("stat", fname);
if (do_lstat(fname, &buf) < 0)
failed("stat", fname);
/* The size of anything but a regular file is probably not
* worth thinking about. */
@@ -114,7 +113,7 @@ static void list_file (const char *fname)
/* TODO: Perhaps escape special characters in fname? */
printf("%s ", permbuf);
if (IS_DEVICE(buf.st_mode)) {
if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) {
printf("%5ld,%6ld",
(long)major(buf.st_rdev),
(long)minor(buf.st_rdev));
@@ -130,13 +129,13 @@ int
main(int argc, char *argv[])
{
if (argc < 2) {
fprintf (stderr, "usage: " PROGRAM " DIR ...\n"
"Trivial file listing program for portably checking rsync\n");
fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
"Trivial file listing program for portably checking rsync\n");
return 1;
}
for (argv++; *argv; argv++) {
list_file (*argv);
list_file(*argv);
}
return 0;

170
token.c
View File

@@ -1,17 +1,17 @@
/*
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -21,23 +21,26 @@
#include "zlib/zlib.h"
extern int do_compression;
extern int module_id;
static int compression_level = Z_DEFAULT_COMPRESSION;
/* determine the compression level based on a wildcard filename list */
void set_compression(char *fname)
{
extern int module_id;
char *dont;
char *tok;
if (!do_compression) return;
if (!do_compression)
return;
compression_level = Z_DEFAULT_COMPRESSION;
dont = lp_dont_compress(module_id);
if (!dont || !*dont) return;
if (!dont || !*dont)
return;
if ((dont[0] == '*') && (!dont[1])) {
if (dont[0] == '*' && !dont[1]) {
/* an optimization to skip the rest of this routine */
compression_level = 0;
return;
@@ -45,12 +48,13 @@ void set_compression(char *fname)
dont = strdup(dont);
fname = strdup(fname);
if (!dont || !fname) return;
if (!dont || !fname)
return;
strlower(dont);
strlower(fname);
for (tok=strtok(dont," ");tok;tok=strtok(NULL," ")) {
for (tok = strtok(dont, " "); tok; tok = strtok(NULL, " ")) {
if (wildmatch(tok, fname)) {
compression_level = 0;
break;
@@ -61,20 +65,22 @@ void set_compression(char *fname)
}
/* non-compressing recv token */
static int simple_recv_token(int f,char **data)
static int32 simple_recv_token(int f, char **data)
{
static int residue;
static int32 residue;
static char *buf;
int n;
int32 n;
if (!buf) {
buf = new_array(char, CHUNK_SIZE);
if (!buf) out_of_memory("simple_recv_token");
if (!buf)
out_of_memory("simple_recv_token");
}
if (residue == 0) {
int i = read_int(f);
if (i <= 0) return i;
int32 i = read_int(f);
if (i <= 0)
return i;
residue = i;
}
@@ -87,33 +93,21 @@ static int simple_recv_token(int f,char **data)
/* non-compressing send token */
static void simple_send_token(int f,int token,
struct map_struct *buf,OFF_T offset,int n)
static void simple_send_token(int f, int32 token, struct map_struct *buf,
OFF_T offset, int32 n)
{
extern int write_batch;
int hold_int;
if (n > 0) {
int l = 0;
while (l < n) {
int n1 = MIN(CHUNK_SIZE,n-l);
write_int(f,n1);
write_buf(f,map_ptr(buf,offset+l,n1),n1);
if (write_batch) {
write_batch_delta_file( (char *) &n1, sizeof(int) );
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
}
l += n1;
int32 len = 0;
while (len < n) {
int32 n1 = MIN(CHUNK_SIZE, n-len);
write_int(f, n1);
write_buf(f, map_ptr(buf, offset+len, n1), n1);
len += n1;
}
}
/* a -2 token means to send data only and no token */
if (token != -2) {
write_int(f,-(token+1));
if (write_batch) {
hold_int = -(token+1);
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
}
}
if (token != -2)
write_int(f, -(token+1));
}
@@ -134,9 +128,9 @@ static void simple_send_token(int f,int token,
#define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
/* For coding runs of tokens */
static int last_token = -1;
static int run_start;
static int last_run_end;
static int32 last_token = -1;
static int32 run_start;
static int32 last_run_end;
/* Deflation state */
static z_stream tx_strm;
@@ -154,13 +148,11 @@ static char *obuf;
/* Send a deflated token */
static void
send_deflated_token(int f, int token,
struct map_struct *buf, OFF_T offset, int nb, int toklen)
send_deflated_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
int32 nb, int32 toklen)
{
int n, r;
int32 n, r;
static int init_done, flush_pending;
extern int write_batch;
char temp_byte;
if (last_token == -1) {
/* initialization */
@@ -193,28 +185,13 @@ send_deflated_token(int f, int token,
n = last_token - run_start;
if (r >= 0 && r <= 63) {
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
if (write_batch) {
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
write_batch_delta_file(&temp_byte,sizeof(char));
}
} else {
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
write_int(f, run_start);
if (write_batch) {
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
write_batch_delta_file(&temp_byte,sizeof(char));
write_batch_delta_file((char *)&run_start,sizeof(run_start));
}
}
if (n != 0) {
write_byte(f, n);
write_byte(f, n >> 8);
if (write_batch) {
temp_byte = (char)n;
write_batch_delta_file(&temp_byte,sizeof(char));
temp_byte = (char)(n >> 8);
write_batch_delta_file(&temp_byte,sizeof(char));
}
}
last_run_end = last_token;
run_start = token;
@@ -273,8 +250,6 @@ send_deflated_token(int f, int token,
obuf[0] = DEFLATED_DATA + (n >> 8);
obuf[1] = n;
write_buf(f, obuf, n+2);
if (write_batch)
write_batch_delta_file(obuf,n+2);
}
}
} while (nb != 0 || tx_strm.avail_out == 0);
@@ -284,24 +259,25 @@ send_deflated_token(int f, int token,
if (token == -1) {
/* end of file - clean up */
write_byte(f, END_FLAG);
if (write_batch) {
temp_byte = END_FLAG;
write_batch_delta_file(&temp_byte,sizeof(char));
}
} else if (token != -2) {
/* add the data in the current block to the compressor's
history and hash table */
tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
tx_strm.avail_in = toklen;
tx_strm.next_out = (Bytef *) obuf;
tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
r = deflate(&tx_strm, Z_INSERT_ONLY);
if (r != Z_OK || tx_strm.avail_in != 0) {
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
r, tx_strm.avail_in);
exit_cleanup(RERR_STREAMIO);
}
/* Add the data in the current block to the compressor's
* history and hash table. */
do {
/* Break up long sections in the same way that
* see_deflate_token() does. */
int32 n1 = toklen > 0xffff ? 0xffff : toklen;
toklen -= n1;
tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n1);
tx_strm.avail_in = n1;
tx_strm.next_out = (Bytef *) obuf;
tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
r = deflate(&tx_strm, Z_INSERT_ONLY);
if (r != Z_OK || tx_strm.avail_in != 0) {
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
r, tx_strm.avail_in);
exit_cleanup(RERR_STREAMIO);
}
} while (toklen > 0);
}
}
@@ -315,16 +291,16 @@ static char *cbuf;
static char *dbuf;
/* for decoding runs of tokens */
static int rx_token;
static int rx_run;
static int32 rx_token;
static int32 rx_run;
/* Receive a deflated token and inflate it */
static int
recv_deflated_token(int f, char **data)
static int32 recv_deflated_token(int f, char **data)
{
int n, r, flag;
static int init_done;
static int saved_flag;
static int32 saved_flag;
int32 n, flag;
int r;
for (;;) {
switch (recv_state) {
@@ -451,9 +427,10 @@ recv_deflated_token(int f, char **data)
* put the data corresponding to a token that we've just returned
* from recv_deflated_token into the decompressor's history buffer.
*/
static void see_deflate_token(char *buf, int len)
static void see_deflate_token(char *buf, int32 len)
{
int r, blklen;
int r;
int32 blklen;
unsigned char hdr[5];
rx_strm.avail_in = 0;
@@ -491,17 +468,16 @@ static void see_deflate_token(char *buf, int len)
/**
* Transmit a verbatim buffer of length @p n followed by a token.
* If token == -1 then we have reached EOF
* If token == -1 then we have reached EOF
* If n == 0 then don't send a buffer
*/
void send_token(int f,int token,struct map_struct *buf,OFF_T offset,
int n,int toklen)
void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
int32 n, int32 toklen)
{
if (!do_compression) {
simple_send_token(f,token,buf,offset,n);
} else {
if (!do_compression)
simple_send_token(f, token, buf, offset, n);
else
send_deflated_token(f, token, buf, offset, n, toklen);
}
}
@@ -511,7 +487,7 @@ void send_token(int f,int token,struct map_struct *buf,OFF_T offset,
* if the return value is -i then it represents token i-1
* if the return value is 0 then the end has been reached
*/
int recv_token(int f,char **data)
int32 recv_token(int f, char **data)
{
int tok;
@@ -526,7 +502,7 @@ int recv_token(int f,char **data)
/*
* look at the data corresponding to a token, if necessary
*/
void see_token(char *data, int toklen)
void see_token(char *data, int32 toklen)
{
if (do_compression)
see_deflate_token(data, toklen);

View File

@@ -26,7 +26,7 @@
#include "rsync.h"
#ifdef HAVE_GETGROUPS
# if !defined(GETGROUPS_T)
# ifndef GETGROUPS_T
# define GETGROUPS_T gid_t
# endif
#endif

675
util.c
View File

@@ -28,7 +28,11 @@
#include "rsync.h"
extern int verbose;
extern struct exclude_list_struct server_exclude_list;
extern int dry_run;
extern int module_id;
extern int modify_window;
extern char *partial_dir;
extern struct filter_list_struct server_filter_list;
int sanitize_paths = 0;
@@ -75,7 +79,7 @@ int fd_pair(int fd[2])
{
int ret;
#if HAVE_SOCKETPAIR
#ifdef HAVE_SOCKETPAIR
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
#else
ret = pipe(fd);
@@ -101,9 +105,9 @@ void print_child_argv(char **cmd)
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
",.-_=+@/") != strlen(*cmd)) {
rprintf(FINFO, "\"%s\" ", *cmd);
rprintf(FINFO, "\"%s\" ", safe_fname(*cmd));
} else {
rprintf(FINFO, "%s ", *cmd);
rprintf(FINFO, "%s ", safe_fname(*cmd));
}
}
rprintf(FINFO, "\n");
@@ -126,23 +130,22 @@ void overflow(char *str)
int set_modtime(char *fname, time_t modtime)
{
extern int dry_run;
if (dry_run)
return 0;
if (verbose > 2) {
rprintf(FINFO, "set modtime of %s to (%ld) %s",
fname, (long) modtime,
safe_fname(fname), (long)modtime,
asctime(localtime(&modtime)));
}
if (dry_run)
return 0;
{
#ifdef HAVE_UTIMBUF
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
return utime(fname,&tbuf);
#elif defined(HAVE_UTIME)
#elif defined HAVE_UTIME
time_t t[2];
t[0] = time(NULL);
t[1] = modtime;
@@ -194,7 +197,7 @@ int create_directory_path(char *fname, int base_umask)
*
* Derived from GNU C's cccp.c.
*/
static int full_write(int desc, char *ptr, size_t len)
int full_write(int desc, char *ptr, size_t len)
{
int total_written;
@@ -242,7 +245,8 @@ static int safe_read(int desc, char *ptr, size_t len)
/** Copy a file.
*
* This is used in conjunction with the --temp-dir option */
* This is used in conjunction with the --temp-dir, --backup, and
* --copy-dest options. */
int copy_file(char *source, char *dest, mode_t mode)
{
int ifd;
@@ -252,29 +256,25 @@ int copy_file(char *source, char *dest, mode_t mode)
ifd = do_open(source, O_RDONLY, 0);
if (ifd == -1) {
rprintf(FERROR,"open %s: %s\n",
full_fname(source), strerror(errno));
rsyserr(FERROR, errno, "open %s", full_fname(source));
return -1;
}
if (robust_unlink(dest) && errno != ENOENT) {
rprintf(FERROR,"unlink %s: %s\n",
full_fname(dest), strerror(errno));
rsyserr(FERROR, errno, "unlink %s", full_fname(dest));
return -1;
}
ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
if (ofd == -1) {
rprintf(FERROR,"open %s: %s\n",
full_fname(dest), strerror(errno));
rsyserr(FERROR, errno, "open %s", full_fname(dest));
close(ifd);
return -1;
}
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) {
rprintf(FERROR,"write %s: %s\n",
full_fname(dest), strerror(errno));
rsyserr(FERROR, errno, "write %s", full_fname(dest));
close(ifd);
close(ofd);
return -1;
@@ -282,21 +282,20 @@ int copy_file(char *source, char *dest, mode_t mode)
}
if (len < 0) {
rprintf(FERROR, "read %s: %s\n",
full_fname(source), strerror(errno));
rsyserr(FERROR, errno, "read %s", full_fname(source));
close(ifd);
close(ofd);
return -1;
}
if (close(ifd) < 0) {
rprintf(FINFO, "close failed on %s: %s\n",
full_fname(source), strerror(errno));
rsyserr(FINFO, errno, "close failed on %s",
full_fname(source));
}
if (close(ofd) < 0) {
rprintf(FERROR, "close failed on %s: %s\n",
full_fname(dest), strerror(errno));
rsyserr(FERROR, errno, "close failed on %s",
full_fname(dest));
return -1;
}
@@ -352,7 +351,7 @@ int robust_unlink(char *fname)
if (verbose > 0) {
rprintf(FINFO,"renaming %s to %s because of text busy\n",
fname, path);
safe_fname(fname), safe_fname(path));
}
/* maybe we should return rename()'s exit status? Nah. */
@@ -364,8 +363,8 @@ int robust_unlink(char *fname)
#endif
}
/* Returns 0 on success, -1 on most errors, and -2 if we got an error
* trying to copy the file across file systems. */
/* Returns 0 on successful rename, 1 if we successfully copied the file
* across filesystems, -2 if copy_file() failed, and -1 on other errors. */
int robust_rename(char *from, char *to, int mode)
{
int tries = 4;
@@ -385,7 +384,7 @@ int robust_rename(char *from, char *to, int mode)
if (copy_file(from, to, mode) != 0)
return -2;
do_unlink(from);
return 0;
return 1;
default:
return -1;
}
@@ -442,7 +441,8 @@ void kill_all(int sig)
int name_to_uid(char *name, uid_t *uid)
{
struct passwd *pass;
if (!name || !*name) return 0;
if (!name || !*name)
return 0;
pass = getpwnam(name);
if (pass) {
*uid = pass->pw_uid;
@@ -455,7 +455,8 @@ int name_to_uid(char *name, uid_t *uid)
int name_to_gid(char *name, gid_t *gid)
{
struct group *grp;
if (!name || !*name) return 0;
if (!name || !*name)
return 0;
grp = getgrnam(name);
if (grp) {
*gid = grp->gr_gid;
@@ -479,14 +480,14 @@ int lock_range(int fd, int offset, int len)
return fcntl(fd,F_SETLK,&lock) == 0;
}
static int exclude_server_path(char *arg)
static int filter_server_path(char *arg)
{
char *s;
if (server_exclude_list.head) {
if (server_filter_list.head) {
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
*s = '\0';
if (check_exclude(&server_exclude_list, arg, 1) < 0) {
if (check_filter(&server_filter_list, arg, 1) < 0) {
/* We must leave arg truncated! */
return 1;
}
@@ -496,75 +497,92 @@ static int exclude_server_path(char *arg)
return 0;
}
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
static void glob_expand_one(char *s, char ***argv_ptr, int *argc_ptr,
int *maxargs_ptr)
{
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
if (!*s) s = ".";
s = argv[*argc] = strdup(s);
exclude_server_path(s);
(*argc)++;
char **argv = *argv_ptr;
int argc = *argc_ptr;
int maxargs = *maxargs_ptr;
#if !defined HAVE_GLOB || !defined HAVE_GLOB_H
if (argc == maxargs) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("glob_expand_one");
*argv_ptr = argv;
*maxargs_ptr = maxargs;
}
if (!*s)
s = ".";
s = argv[argc++] = strdup(s);
filter_server_path(s);
#else
extern int sanitize_paths;
glob_t globbuf;
int i;
if (!*s) s = ".";
if (maxargs <= argc)
return;
if (!*s)
s = ".";
s = argv[*argc] = strdup(s);
if (sanitize_paths) {
sanitize_path(s, NULL);
}
if (sanitize_paths)
s = sanitize_path(NULL, s, "", 0);
else
s = strdup(s);
memset(&globbuf, 0, sizeof globbuf);
if (!exclude_server_path(s))
if (!filter_server_path(s))
glob(s, 0, NULL, &globbuf);
if (globbuf.gl_pathc == 0) {
(*argc)++;
globfree(&globbuf);
return;
if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) {
maxargs += globbuf.gl_pathc + MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("glob_expand_one");
*argv_ptr = argv;
*maxargs_ptr = maxargs;
}
for (i = 0; i < maxargs - *argc && i < (int)globbuf.gl_pathc; i++) {
if (i == 0)
free(s);
argv[*argc + i] = strdup(globbuf.gl_pathv[i]);
if (!argv[*argc + i])
out_of_memory("glob_expand");
if (globbuf.gl_pathc == 0)
argv[argc++] = s;
else {
int j = globbuf.gl_pathc;
free(s);
for (i = 0; i < j; i++) {
if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
out_of_memory("glob_expand_one");
}
}
globfree(&globbuf);
*argc += i;
#endif
*argc_ptr = argc;
}
/* This routine is only used in daemon mode. */
void glob_expand(char *base1, char **argv, int *argc, int maxargs)
void glob_expand(char *base1, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
{
char *s = argv[*argc];
char *s = (*argv_ptr)[*argc_ptr];
char *p, *q;
char *base = base1;
int base_len = strlen(base);
if (!s || !*s) return;
if (!s || !*s)
return;
if (strncmp(s, base, base_len) == 0)
s += base_len;
s = strdup(s);
if (!s) out_of_memory("glob_expand");
if (!(s = strdup(s)))
out_of_memory("glob_expand");
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
if (asprintf(&base," %s/", base1) <= 0)
out_of_memory("glob_expand");
base_len++;
q = s;
while ((p = strstr(q,base)) != NULL && *argc < maxargs) {
/* split it at this point */
*p = 0;
glob_expand_one(q, argv, argc, maxargs);
q = p + base_len;
for (q = s; *q; q = p + base_len) {
if ((p = strstr(q, base)) != NULL)
*p = '\0'; /* split it at this point */
glob_expand_one(q, argv_ptr, argc_ptr, maxargs_ptr);
if (!p)
break;
}
if (*q && *argc < maxargs)
glob_expand_one(q, argv, argc, maxargs);
free(s);
free(base);
}
@@ -575,8 +593,8 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs)
void strlower(char *s)
{
while (*s) {
if (isupper(* (unsigned char *) s))
*s = tolower(* (unsigned char *) s);
if (isupper(*(unsigned char *)s))
*s = tolower(*(unsigned char *)s);
s++;
}
}
@@ -633,118 +651,143 @@ size_t stringjoin(char *dest, size_t destsize, ...)
return ret;
}
void clean_fname(char *name)
int count_dir_elements(const char *p)
{
char *p;
int l;
int modified = 1;
if (!name) return;
while (modified) {
modified = 0;
if ((p = strstr(name,"/./")) != NULL) {
modified = 1;
while (*p) {
p[0] = p[2];
p++;
}
}
if ((p = strstr(name,"//")) != NULL) {
modified = 1;
while (*p) {
p[0] = p[1];
p++;
}
}
if (strncmp(p = name, "./", 2) == 0) {
modified = 1;
do {
p[0] = p[2];
} while (*p++);
}
l = strlen(p = name);
if (l > 1 && p[l-1] == '/') {
modified = 1;
p[l-1] = 0;
int cnt = 0, new_component = 1;
while (*p) {
if (*p++ == '/')
new_component = 1;
else if (new_component) {
new_component = 0;
cnt++;
}
}
return cnt;
}
/**
* Make path appear as if a chroot had occurred:
*
* @li 1. remove leading "/" (or replace with "." if at end)
*
* @li 2. remove leading ".." components (except those allowed by @p reldir)
*
* @li 3. delete any other "<dir>/.." (recursively)
*
* Can only shrink paths, so sanitizes in place.
*
* While we're at it, remove double slashes and "." components like
* clean_fname() does, but DON'T remove a trailing slash because that
* is sometimes significant on command line arguments.
*
* If @p reldir is non-null, it is a sanitized directory that the path will be
* relative to, so allow as many ".." at the beginning of the path as
* there are components in reldir. This is used for symbolic link targets.
* If reldir is non-null and the path began with "/", to be completely like
* a chroot we should add in depth levels of ".." at the beginning of the
* path, but that would blow the assumption that the path doesn't grow and
* it is not likely to end up being a valid symlink anyway, so just do
* the normal removal of the leading "/" instead.
*
* Contributed by Dave Dykstra <dwd@bell-labs.com>
*/
void sanitize_path(char *p, char *reldir)
/* Turns multiple adjacent slashes into a single slash, gets rid of "./"
* elements (but not a trailing dot dir), removes a trailing slash, and
* optionally collapses ".." elements (except for those at the start of the
* string). If the resulting name would be empty, change it into a ".". */
unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
{
char *start, *sanp;
int depth = 0;
int allowdotdot = 0;
char *limit = name - 1, *t = name, *f = name;
int anchored;
if (reldir) {
depth++;
while (*reldir) {
if (*reldir++ == '/') {
depth++;
if (!name)
return 0;
if ((anchored = *f == '/') != 0)
*t++ = *f++;
while (*f) {
/* discard extra slashes */
if (*f == '/') {
f++;
continue;
}
if (*f == '.') {
/* discard "." dirs (but NOT a trailing '.'!) */
if (f[1] == '/') {
f += 2;
continue;
}
/* collapse ".." dirs */
if (collapse_dot_dot
&& f[1] == '.' && (f[2] == '/' || !f[2])) {
char *s = t - 1;
if (s == name && anchored) {
f += 2;
continue;
}
while (s > limit && *--s != '/') {}
if (s != t - 1 && (s < name || *s == '/')) {
t = s + 1;
f += 2;
continue;
}
limit = t + 2;
}
}
while (*f && (*t++ = *f++) != '/') {}
}
start = p;
sanp = p;
while (*p == '/') {
/* remove leading slashes */
p++;
if (t > name+anchored && t[-1] == '/')
t--;
if (t == name)
*t++ = '.';
*t = '\0';
return t - name;
}
/* Make path appear as if a chroot had occurred. This handles a leading
* "/" (either removing it or expanding it) and any leading or embedded
* ".." components that attempt to escape past the module's top dir.
*
* If dest is NULL, a buffer is allocated to hold the result. It is legal
* to call with the dest and the path (p) pointing to the same buffer, but
* rootdir will be ignored to avoid expansion of the string.
*
* The rootdir string contains a value to use in place of a leading slash.
* Specify NULL to get the default of lp_path(module_id).
*
* If depth is >= 0, it is a count of how many '..'s to allow at the start
* of the path. Use -1 to allow unlimited depth.
*
* We also clean the path in a manner similar to clean_fname() but with a
* few differences:
*
* Turns multiple adjacent slashes into a single slash, gets rid of "." dir
* elements (INCLUDING a trailing dot dir), PRESERVES a trailing slash, and
* ALWAYS collapses ".." elements (except for those at the start of the
* string up to "depth" deep). If the resulting name would be empty,
* change it into a ".". */
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
{
char *start, *sanp;
int rlen = 0;
if (dest != p) {
int plen = strlen(p);
if (*p == '/') {
if (!rootdir)
rootdir = lp_path(module_id);
rlen = strlen(rootdir);
depth = 0;
p++;
}
if (dest) {
if (rlen + plen + 1 >= MAXPATHLEN)
return NULL;
} else if (!(dest = new_array(char, rlen + plen + 1)))
out_of_memory("sanitize_path");
if (rlen) {
memcpy(dest, rootdir, rlen);
if (rlen > 1)
dest[rlen++] = '/';
}
}
start = sanp = dest + rlen;
while (*p != '\0') {
/* discard leading or extra slashes */
if (*p == '/') {
p++;
continue;
}
/* this loop iterates once per filename component in p.
* both p (and sanp if the original had a slash) should
* always be left pointing after a slash
*/
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
while (*++p == '/') {
/* skip following slashes */
;
}
p++;
continue;
}
allowdotdot = 0;
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
/* ".." component followed by slash or end */
if (depth > 0 && sanp == start) {
/* allow depth levels of .. at the beginning */
--depth;
allowdotdot = 1;
} else {
if (depth <= 0 || sanp != start) {
p += 2;
if (*p == '/')
p++;
if (sanp != start) {
/* back up sanp one level */
--sanp; /* now pointing at slash */
@@ -755,68 +798,21 @@ void sanitize_path(char *p, char *reldir)
}
continue;
}
}
while (1) {
/* copy one component through next slash */
*sanp++ = *p++;
if (*p == '\0' || p[-1] == '/') {
while (*p == '/') {
/* skip multiple slashes */
p++;
}
break;
}
}
if (allowdotdot) {
/* allow depth levels of .. at the beginning */
depth--;
/* move the virtual beginning to leave the .. alone */
start = sanp;
start = sanp + 3;
}
/* copy one component through next slash */
while (*p && (*sanp++ = *p++) != '/') {}
}
if (sanp == start && !allowdotdot) {
if (sanp == dest) {
/* ended up with nothing, so put in "." component */
/*
* note that the !allowdotdot doesn't prevent this from
* happening in all allowed ".." situations, but I didn't
* think it was worth putting in an extra variable to ensure
* it since an extra "." won't hurt in those situations.
*/
*sanp++ = '.';
}
*sanp = '\0';
}
/* Works much like sanitize_path(), with these differences: (1) a new buffer
* is allocated for the sanitized path rather than modifying it in-place; (2)
* a leading slash gets transformed into the rootdir value (which can be empty
* or NULL if you just want the slash to get dropped); (3) no "reldir" can be
* specified. */
char *alloc_sanitize_path(const char *path, const char *rootdir)
{
char *buf;
int rlen, plen = strlen(path);
if (*path == '/' && rootdir) {
rlen = strlen(rootdir);
if (rlen == 1)
path++;
} else
rlen = 0;
if (!(buf = new_array(char, rlen + plen + 1)))
out_of_memory("alloc_sanitize_path");
if (rlen)
memcpy(buf, rootdir, rlen);
memcpy(buf + rlen, path, plen + 1);
if (rlen > 1)
rlen++;
sanitize_path(buf + rlen, NULL);
if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
if (rlen > 1)
rlen--;
buf[rlen] = '\0';
}
return buf;
return dest;
}
char curr_dir[MAXPATHLEN];
@@ -860,7 +856,7 @@ int push_dir(char *dir)
curr_dir_len += len;
}
clean_fname(curr_dir);
curr_dir_len = clean_fname(curr_dir, 1);
return 1;
}
@@ -881,14 +877,50 @@ int pop_dir(char *dir)
return 1;
}
/* 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];
static int ndx = 0;
int limit = sizeof fbuf / MAX_SAFE_NAMES - 1;
char *t;
ndx = (ndx + 1) % MAX_SAFE_NAMES;
for (t = fbuf[ndx]; *fname; fname++) {
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;
}
}
*t = '\0';
return fbuf[ndx];
}
/**
* Return a quoted string with the full pathname of the indicated filename.
* The string " (in MODNAME)" may also be appended. The returned pointer
* remains valid until the next time full_fname() is called.
**/
char *full_fname(char *fn)
char *full_fname(const char *fn)
{
extern int module_id;
static char *result = NULL;
char *m1, *m2, *m3;
char *p1, *p2;
@@ -896,29 +928,26 @@ char *full_fname(char *fn)
if (result)
free(result);
fn = safe_fname(fn);
if (*fn == '/')
p1 = p2 = "";
else {
p1 = curr_dir;
p2 = "/";
for (p2 = p1; *p2 == '/'; p2++) {}
if (*p2)
p2 = "/";
}
if (module_id >= 0) {
m1 = " (in ";
m2 = lp_name(module_id);
m3 = ")";
if (*p1) {
if (p1 == curr_dir) {
if (!lp_use_chroot(module_id)) {
char *p = lp_path(module_id);
if (*p != '/' || p[1])
p1 += strlen(p);
}
if (!*p1)
p2++;
else
p1++;
}
else
fn++;
} else
m1 = m2 = m3 = "";
@@ -927,6 +956,73 @@ char *full_fname(char *fn)
return result;
}
static char partial_fname[MAXPATHLEN];
char *partial_dir_fname(const char *fname)
{
char *t = partial_fname;
int sz = sizeof partial_fname;
const char *fn;
if ((fn = strrchr(fname, '/')) != NULL) {
fn++;
if (*partial_dir != '/') {
int len = fn - fname;
strncpy(t, fname, len); /* safe */
t += len;
sz -= len;
}
} else
fn = fname;
if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
return NULL;
if (server_filter_list.head) {
static int len;
if (!len)
len = strlen(partial_dir);
t[len] = '\0';
if (check_filter(&server_filter_list, partial_fname, 1) < 0)
return NULL;
t[len] = '/';
if (check_filter(&server_filter_list, partial_fname, 0) < 0)
return NULL;
}
return partial_fname;
}
/* If no --partial-dir option was specified, we don't need to do anything
* (the partial-dir is essentially '.'), so just return success. */
int handle_partial_dir(const char *fname, int create)
{
char *fn, *dir;
if (fname != partial_fname)
return 1;
if (!create && *partial_dir == '/')
return 1;
if (!(fn = strrchr(partial_fname, '/')))
return 1;
*fn = '\0';
dir = partial_fname;
if (create) {
STRUCT_STAT st;
int statret = do_lstat(dir, &st);
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (do_unlink(dir) < 0)
return 0;
statret = -1;
}
if (statret < 0 && do_mkdir(dir, 0700) < 0)
return 0;
} else
do_rmdir(dir);
*fn = '/';
return 1;
}
/** We need to supply our own strcmp function for file list comparisons
to ensure that signed/unsigned usage is consistent between machines. */
int u_strcmp(const char *cs1, const char *cs2)
@@ -973,7 +1069,8 @@ int unsafe_symlink(const char *dest, const char *src)
int depth = 0;
/* all absolute and null symlinks are unsafe */
if (!dest || !*dest || *dest == '/') return 1;
if (!dest || !*dest || *dest == '/')
return 1;
/* find out what our safety margin is */
for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
@@ -1041,7 +1138,6 @@ int msleep(int t)
struct timeval tval, t1, t2;
gettimeofday(&t1, NULL);
gettimeofday(&t2, NULL);
while (tdiff < t) {
tval.tv_sec = (t-tdiff)/1000;
@@ -1072,13 +1168,13 @@ int msleep(int t)
**/
int cmp_modtime(time_t file1, time_t file2)
{
extern int modify_window;
if (file2 > file1) {
if (file2 - file1 <= modify_window) return 0;
if (file2 - file1 <= modify_window)
return 0;
return -1;
}
if (file1 - file2 <= modify_window) return 0;
if (file1 - file2 <= modify_window)
return 0;
return 1;
}
@@ -1135,3 +1231,110 @@ void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
return malloc(size * num);
return realloc(ptr, size * num);
}
/* Take a filename and filename length and return the most significant
* filename suffix we can find. This ignores suffixes such as "~",
* ".bak", ".orig", ".~1~", etc. */
const char *find_filename_suffix(const char *fn, int fn_len, int *len_ptr)
{
const char *suf, *s;
BOOL had_tilde;
int s_len;
/* One or more dots at the start aren't a suffix. */
while (fn_len && *fn == '.') fn++, fn_len--;
/* Ignore the ~ in a "foo~" filename. */
if (fn_len > 1 && fn[fn_len-1] == '~')
fn_len--, had_tilde = True;
else
had_tilde = False;
/* Assume we don't find an suffix. */
suf = "";
*len_ptr = 0;
/* Find the last significant suffix. */
for (s = fn + fn_len; fn_len > 1; ) {
while (*--s != '.' && s != fn) {}
if (s == fn)
break;
s_len = fn_len - (s - fn);
fn_len = s - fn;
if (s_len == 4) {
if (strcmp(s+1, "bak") == 0
|| strcmp(s+1, "old") == 0)
continue;
} else if (s_len == 5) {
if (strcmp(s+1, "orig") == 0)
continue;
} else if (s_len > 2 && had_tilde
&& s[1] == '~' && isdigit(*(uchar*)(s+2)))
continue;
*len_ptr = s_len;
suf = s;
if (s_len == 1)
break;
/* Determine if the suffix is all digits. */
for (s++, s_len--; s_len > 0; s++, s_len--) {
if (!isdigit(*(uchar*)s))
return suf;
}
/* An all-digit suffix may not be that signficant. */
s = suf;
}
return suf;
}
/* This is an implementation of the Levenshtein distance algorithm. It
* was implemented to avoid needing a two-dimensional matrix (to save
* memory). It was also tweaked to try to factor in the ASCII distance
* between changed characters as a minor distance quantity. The normal
* Levenshtein units of distance (each signifying a single change between
* the two strings) are defined as a "UNIT". */
#define UNIT (1 << 16)
uint32 fuzzy_distance(const char *s1, int len1, const char *s2, int len2)
{
uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;
int32 cost;
int i1, i2;
if (!len1 || !len2) {
if (!len1) {
s1 = s2;
len1 = len2;
}
for (i1 = 0, cost = 0; i1 < len1; i1++)
cost += s1[i1];
return (int32)len1 * UNIT + cost;
}
for (i2 = 0; i2 < len2; i2++)
a[i2] = (i2+1) * UNIT;
for (i1 = 0; i1 < len1; i1++) {
diag = i1 * UNIT;
above = (i1+1) * UNIT;
for (i2 = 0; i2 < len2; i2++) {
left = a[i2];
if ((cost = *((uchar*)s1+i1) - *((uchar*)s2+i2)) != 0) {
if (cost < 0)
cost = UNIT - cost;
else
cost = UNIT + cost;
}
diag_inc = diag + cost;
left_inc = left + UNIT + *((uchar*)s1+i1);
above_inc = above + UNIT + *((uchar*)s2+i2);
a[i2] = above = left < above
? (left_inc < diag_inc ? left_inc : diag_inc)
: (above_inc < diag_inc ? above_inc : diag_inc);
diag = left;
}
}
return a[len2-1];
}

View File

@@ -1110,6 +1110,11 @@ local block_state deflate_stored(s, flush)
s->strstart += s->lookahead;
s->lookahead = 0;
if (flush == Z_INSERT_ONLY) {
s->block_start = s->strstart;
continue;
}
/* Emit a stored block if pending_buf will be full: */
max_start = s->block_start + max_block_size;
if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
@@ -1125,6 +1130,11 @@ local block_state deflate_stored(s, flush)
FLUSH_BLOCK(s, 0);
}
}
if (flush == Z_INSERT_ONLY) {
s->block_start = s->strstart;
return need_more;
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
}