Compare commits

...

761 Commits

Author SHA1 Message Date
Wayne Davison
4177f09b83 Preparing for release of 2.6.8 2006-04-22 15:39:57 +00:00
Wayne Davison
acaadb55c1 Mention the phase-unknown changes. 2006-04-21 16:57:13 +00:00
Wayne Davison
b88c2e8ffe - Got rid of the (mostly useless) io_read_phase and io_write_phase
variables.  In the future it might be useful to get rsync to
  mention what kind of a message it was trying to write, but the
  'phase "unknown"' output was ubiquitous and confusing.
- Got rid of the completely unused write_int_named() function.
2006-04-21 16:40:19 +00:00
Wayne Davison
f4ea5f47dc Got rid of the setting of io_write_phase. 2006-04-21 16:36:30 +00:00
Wayne Davison
62ae66d43b Mention the security fix for patches/xattrs.diff. 2006-04-21 00:05:30 +00:00
Wayne Davison
8641d28740 Improved the --owner and --group sections. 2006-04-18 18:58:07 +00:00
Wayne Davison
de3438407c Twiddle the trailing output in non-live mode. 2006-04-18 06:43:17 +00:00
Wayne Davison
434764269c Fixed a typo in the new code. 2006-04-18 06:38:58 +00:00
Wayne Davison
ba212fe0b6 - Fixed --copy-dest behavior on a system where CAN_HARDLINK_SYMLINK
and/or CAN_HARDLINK_SPECIAL is not defined.
- Changed --link-dest behavior on such systems to work just like
  --copy-dest for the non-hard-linkable files.
2006-04-18 05:48:46 +00:00
Wayne Davison
5f93b4d35e A slight improvement to the logic in try_dests_non(). 2006-04-18 05:24:02 +00:00
Wayne Davison
f8db4a8ab4 Mention the latest bugfix. 2006-04-17 19:55:16 +00:00
Wayne Davison
398612ba07 Fixed a bug where special files were not getting hard-linked via
the --link-dest option.
2006-04-17 19:53:41 +00:00
Wayne Davison
77b013afb5 Don't use the -C option to make (since it's not portable). 2006-04-17 18:15:02 +00:00
Wayne Davison
08c0cd8a42 Mention the latest fixes. 2006-04-17 18:00:09 +00:00
Wayne Davison
1c6e9dfabc Use the new CAN_HARDLINK_SYMLINK and CAN_HARDLINK_SPECIAL defines
from configure instead of the old (and not quite correct) run-time
checking.
2006-04-17 17:56:10 +00:00
Wayne Davison
0037bf23fc Added two new checks: 1. Does link() hard-link symlinks (not the
referent)?  2. Does link() hard-link a fifo?
2006-04-17 17:53:47 +00:00
Wayne Davison
285edc9169 Don't use -C with make because it's not portable. 2006-04-17 17:37:13 +00:00
Wayne Davison
c4aa84ad50 Got rid of the unused REPLACE_INET_NTOA and REPLACE_INET_ATON checks. 2006-04-13 16:54:24 +00:00
Wayne Davison
b635bc92d1 Got rid of inet_ntoa -> rep_inet_ntoa tom-foolery because rsync
doesn't use inet_ntoa() anymore.
2006-04-13 16:53:15 +00:00
Wayne Davison
146d2228cc Got rid of the replacement inet_aton() and inet_ntoa() functions
because no code in rsync has used these functions since 2.4.8.
2006-04-13 16:52:15 +00:00
Wayne Davison
b2501ccf12 Improved a sentence. 2006-04-12 16:59:32 +00:00
Wayne Davison
e60bba3fbc A few minor changes to some messages and a couple variable improvements. 2006-04-12 16:35:53 +00:00
Wayne Davison
e26cfccf16 Preparing for release of 2.6.8pre1 2006-04-12 16:23:46 +00:00
Wayne Davison
74f80abce2 Moved the include of netinet/ip.h into socket.c. 2006-04-11 00:48:55 +00:00
Wayne Davison
5899b8cf3e Moved the include of netinet/ip.h here along with its apparent
prerequisite, netinet/in_systm.h .
2006-04-11 00:48:28 +00:00
Wayne Davison
08e0a62956 Tweaked a comment. 2006-04-11 00:28:02 +00:00
Wayne Davison
2bd17a51ae Include netinet/ip.h . 2006-04-09 13:51:56 +00:00
Wayne Davison
c7b9ebb598 Mention the read-position fix. 2006-04-08 16:43:21 +00:00
Wayne Davison
e3db43ffe5 Fixed the value of map->p_fd_offset when a read() fails or is
abbreviated.
2006-04-08 16:37:50 +00:00
Wayne Davison
f61ab01d96 Use --delete-after instead of --delete. 2006-04-08 16:36:57 +00:00
Wayne Davison
ceca8ccac8 We don't need log_initialised exported after all. 2006-04-08 16:04:34 +00:00
Wayne Davison
374c3e1278 Moved the calls to client_addr() and client_name() below the lp_load()
call so that their potential to output log messages can't cause the
log-file to initialize before we know what "log name" to use.
2006-04-08 16:03:16 +00:00
Wayne Davison
e09d8a304c Clarified a few items. 2006-04-06 07:54:03 +00:00
Wayne Davison
2a7d9fe9b8 A slightly better fix than the last version. 2006-04-06 07:38:54 +00:00
Wayne Davison
e63aeb6d68 Made log_initialised public. 2006-04-06 07:33:12 +00:00
Wayne Davison
077d5d4ebc There's no need for lp_load() to check am_daemon. 2006-04-06 07:28:22 +00:00
Wayne Davison
e2d774cdd7 Improved the bind()-failure message to mention what family failed. 2006-04-02 21:15:37 +00:00
Wayne Davison
415b598346 Got rid of duplicate rsync: prefix from an rsyserr() call. 2006-04-02 15:02:02 +00:00
Wayne Davison
69627d66f8 Improved a couple sentences. 2006-04-02 14:23:22 +00:00
Wayne Davison
ac98cd98e3 - Mention the logging fix for a single-use daemon.
- Mention the fatal error for when --daemon can't be honored.
2006-03-31 17:56:19 +00:00
Wayne Davison
91d324b4ea Log the connect message after calling log_init(). 2006-03-31 17:37:21 +00:00
Wayne Davison
89fb50263b - Complain if the user specified --delete without -r or -d.
- Got rid of the saw_delete_* vars.
2006-03-28 23:09:36 +00:00
Wayne Davison
e257c6c20b Use the regular delete* vars instead of the saw_delete* vars
(which are no longer around).
2006-03-28 23:09:07 +00:00
Wayne Davison
43eae40e45 Include the version number when we exit with an error or warning. 2006-03-28 18:23:24 +00:00
Wayne Davison
920240a687 - Mention two omitted --files-from bug-fixes.
- Added a place-holder release line for 2.6.8.
2006-03-28 16:49:23 +00:00
Wayne Davison
f8b9da1a2c Output the who_am_i() info in the "unknown message" error. 2006-03-28 06:12:18 +00:00
Wayne Davison
3c987ee956 Mention latest tweaks. 2006-03-22 18:26:44 +00:00
Wayne Davison
5c6d46329b If open_socket_in() fails, we now log the reasons why. 2006-03-22 17:48:59 +00:00
Wayne Davison
8b3e964d14 Mention the new support/file-attr-restore script. 2006-03-21 18:11:43 +00:00
Wayne Davison
91a93df049 A nice file-attribute maintenance script that lets you restore
permissions, ownership, and group-info on files that may be
different than the originals.
2006-03-21 18:06:26 +00:00
Wayne Davison
19826af5f0 Fixed a few things that looked like yodl macros but were not. 2006-03-21 03:45:03 +00:00
Wayne Davison
49f4cfdf39 Improved a few things that a more modern yodl complained about. 2006-03-21 03:41:00 +00:00
Wayne Davison
b3222792ad Changed where ITEM_REPORT_ATIME goes in the list. 2006-03-17 23:57:19 +00:00
Wayne Davison
0640710115 Go ahead and define upcoming ITEM_REPORT_* defines now. 2006-03-17 21:59:25 +00:00
Wayne Davison
fa65989a8b Added support for using solaris's "setfacl -s" in place of
GNU's "setfacl -k".
2006-03-16 21:37:18 +00:00
Wayne Davison
4209f079dd Make sure that the --relative test creates the implied directories
with user-write permission, and turns any symlinks in the implied
dirs into real dirs.
2006-03-16 20:02:36 +00:00
Wayne Davison
a7704777ce An extra safeguard for msg2sndr_flush(). 2006-03-16 10:08:08 +00:00
Wayne Davison
7d51b8374d Made the new msg2sndr handling even better. 2006-03-16 09:57:32 +00:00
Wayne Davison
a27042b521 Mention fix for stunnel-using rsync. 2006-03-16 03:18:16 +00:00
Wayne Davison
5b51c893c5 Optimized the reacquisition of the code value from the msg2sndr list. 2006-03-16 02:26:27 +00:00
Wayne Davison
408e69396c Fixed the reacquisition of the code value from the msg2sndr list. 2006-03-16 01:27:26 +00:00
Wayne Davison
954bbed84a - Optimized the msg_list_item structure to make the buffer an
integral part of the structure instead of pointer to a
  separately allocated buffer.
- Improved the code that was ensuring that no messages from the
  receiver could be merged into the middle of a partially written
  buffer from the generator.  The new code ensures that we never
  avoid reading the messages from the receiver (like we used to).
  This ensures that the generator will not hang when the receiver
  got a read error on the socket, sent us a message about it, but
  the socket in the generator never becomes writable for it to get
  a similar error (now we are assured of getting the receiver's
  note about their read error, and we know to shut things down).
2006-03-16 00:57:54 +00:00
Wayne Davison
7c329ec72c Mention the log-file.diff. 2006-03-15 18:47:31 +00:00
Wayne Davison
07a8a360a5 Got rid of an errant newline. 2006-03-15 16:54:13 +00:00
Wayne Davison
1618c9e6d1 Improved the regex to match syslog lines and be easier to read. 2006-03-13 16:45:24 +00:00
Wayne Davison
ba0147ac42 Changing the version to 2.6.8cvs. 2006-03-13 16:44:47 +00:00
Wayne Davison
9e88f057b4 Starting the news for 2.6.8. 2006-03-13 16:42:50 +00:00
Wayne Davison
f171bf5b8f Rolling over the NEWS from 2.6.7. 2006-03-13 16:42:33 +00:00
Wayne Davison
1b1628b90a Fixed a bug where the NEWS file got an extra newline inserted when
the release date was added.  Changed "ln -f" to "cp -p" because
samba.org doesn't allow ln to be used at the moment.
2006-03-13 16:42:08 +00:00
Wayne Davison
50cf25672e Added a test of a simple exclude when --relative is enabled. 2006-03-13 01:57:13 +00:00
Wayne Davison
b316862831 Fixed a problem when copying an absolute source path with
the --relative option enabled.
2006-03-13 01:56:19 +00:00
Wayne Davison
38a4b9c297 Block-quote the itemized list in the --stats section so that
it is indented in the manpage.
2006-03-13 00:45:07 +00:00
Wayne Davison
a058cbc410 Preparing for release of 2.6.7 2006-03-11 18:43:42 +00:00
Wayne Davison
1ef7913497 Mention solo-dir fix for a dir without S_IWUSR. 2006-03-11 17:59:37 +00:00
Wayne Davison
88a16c8b4f Don't force S_IWUSR on a solo directory transfer. 2006-03-10 15:57:03 +00:00
Wayne Davison
8030b28ff8 Make extra sure that authbuf can't overflow. 2006-03-07 08:46:29 +00:00
Wayne Davison
1c598b1db8 Mention fix for Proxy-Authorization header. 2006-03-06 18:28:06 +00:00
Wayne Davison
6854bf69a8 Call base4_encode() with "1" for its new "pad" arg so that the
Proxy-Authorization header is properly padded with trailing '='
chars.
2006-03-06 18:22:26 +00:00
Wayne Davison
293def601d The base4_encode() function now takes a "pad" arg which indicates
if the caller wants to pad the value with trailing '=' chars.
2006-03-06 18:22:20 +00:00
Wayne Davison
651dc65efc Tweaked the mode of the files in the tar file. 2006-03-04 08:21:58 +00:00
Wayne Davison
c2b2bd6a93 Since the samba.org rsync is so old that it doesn't handle
out-of-order hard-linked files, changed the script to do the
hard-linking manually.
2006-03-02 23:42:56 +00:00
Wayne Davison
e32a48d256 Preparing for release of 2.6.7pre3 2006-03-02 22:49:27 +00:00
Wayne Davison
b5cf121d70 Mention the get_local_name() change. 2006-03-02 03:56:14 +00:00
Wayne Davison
44c26bf2a1 Don't allow overwriting a non-directory with a directory (just
like cp).
2006-03-02 03:53:42 +00:00
Wayne Davison
cc8c5057fe If get_local_name() fails to stat() the destination for any
reason other than the destination does not exist, mention the
error and exit.
2006-03-02 03:40:09 +00:00
Wayne Davison
b4c7c1ca99 A couple more improvements for --list-only. 2006-03-01 01:04:57 +00:00
Wayne Davison
16d3b31b2c Improved a couple sentences. 2006-03-01 00:59:22 +00:00
Wayne Davison
89a8180c5e One more bugfix. 2006-02-28 21:48:45 +00:00
Wayne Davison
34f961bbf3 Got the order of s1 and s2 right in the debug output. 2006-02-28 21:48:15 +00:00
Wayne Davison
2384f9e1db Update for hash-table change. 2006-02-28 21:21:44 +00:00
Wayne Davison
48cce779a2 Decided to drop the dynamically sized hash table for now. This was
due to timing tests showing that the per-byte modulus calculation
slowed down regular sized files.  Kept the other improvements
because they lessened our memory use and actually sped up the code.
2006-02-28 21:20:08 +00:00
Wayne Davison
6820753732 Renamed sum_table -> hash_table. 2006-02-28 07:32:48 +00:00
Wayne Davison
fbbe9a016d Changed the name of GETTAG() to SUM2HASH(). 2006-02-28 01:00:03 +00:00
Wayne Davison
c64ca7ef58 Eliminated one variable from hash_search(). 2006-02-28 00:31:51 +00:00
Wayne Davison
900cfcb584 - Fixed a problem with the new gettag2() macro by getting rid of the
need for it.
- Fixed a really old bug in the verbose output where it would output
  the wrong sum value (off by one).
- Renamed the tag_hit variables & debug output to hash_hit.
2006-02-28 00:09:19 +00:00
Wayne Davison
beab3078d6 Added --no-H and --no-hard-links. 2006-02-27 23:35:18 +00:00
Wayne Davison
530a2199da Mention the hash table change. 2006-02-27 21:29:44 +00:00
Wayne Davison
d9bca0c32f This is Shachar Shemesh's patch for making the hash-table code
work better with large files.  I further modified it to eliminate
the extra level of indirectness (and the qsort()), which saves
memory.
2006-02-27 21:16:04 +00:00
Wayne Davison
d733de97f5 Added a "chain" item to the struct sum_buf. 2006-02-27 21:11:56 +00:00
Wayne Davison
f06c11ed40 Tweaked a sentence. 2006-02-27 20:53:35 +00:00
Wayne Davison
c638caa63e In read_sum_head(): if we read a negative checksum count, die
with an error.
2006-02-27 03:12:26 +00:00
Wayne Davison
d775372a34 Tweaked a sentence. 2006-02-24 19:50:22 +00:00
Wayne Davison
07affc3d93 Document the latest changes. 2006-02-24 17:58:24 +00:00
Wayne Davison
f2ebbebead - Document the new --copy-dirlinks option.
- Improved the docs for --no-implied-dirs and --keep-dirlinks
  (based on a patch from Matt).
- Improved a few other misc. sentences.
- Shuffled the order of a couple options.
2006-02-24 17:54:47 +00:00
Wayne Davison
a695b379b5 Make sure the receiver resets copy_dirlinks (so that it can't
affect the delete scan).
2006-02-24 17:54:41 +00:00
Wayne Davison
88c2190a7c - Got rid of unused externs.
- Added support for copy_dirlinks.
- Fixed a bug where --copy-links would not affect implied dirs
  unless --copy-unsafe-links was also specified.
2006-02-24 17:54:35 +00:00
Wayne Davison
2dbf36ef55 Added the new --copy-dirlinks (-k) option. 2006-02-24 17:54:30 +00:00
Wayne Davison
cca9208697 Got rid of unused externs. 2006-02-24 16:43:44 +00:00
Wayne Davison
aa37022ef7 A recently added stat() call needed to be do_stat(). 2006-02-24 09:35:47 +00:00
Wayne Davison
85c417579f Made create_directory_path() return -1 if it couldn't create some
portion of the filename's path.
2006-02-24 09:34:44 +00:00
Wayne Davison
baed67efc4 Need to define an orig_umask value now that utils.c uses it. 2006-02-24 01:56:29 +00:00
Wayne Davison
c5b7aa1532 The orig_umask value is now a mode_t. 2006-02-24 01:56:26 +00:00
Wayne Davison
904e5af128 The create_directory_path() function no longer takes a base_umask
arg.
2006-02-24 01:56:21 +00:00
Wayne Davison
a41d110647 - The orig_umask value is now a mode_t.
- Use CHMOD_BITS instead of 07777.
2006-02-24 01:56:18 +00:00
Wayne Davison
a92d6ff13c Moved the orig_umask variable's definition into main.c since it
has nothing to do with option settings.
2006-02-24 01:56:14 +00:00
Wayne Davison
05278935a3 - Call mkdir_defmode() instead of do_mkdir().
- Define orig_umask in this file, not options.c.
- Made orig_umask a mode_t, not an int.
2006-02-24 01:56:10 +00:00
Wayne Davison
a56cdef9b1 Call mkdir_defmode() instead of do_mkdir(). 2006-02-24 01:56:07 +00:00
Wayne Davison
e9357a2deb + Added mkdir_defmode().
+ Changed create_directory_path() to drop the (now) unneeded
  base_umask arg and to call mkdir_defmode().
2006-02-24 01:56:01 +00:00
Wayne Davison
8d94d27af0 Moved an extern into its proper place. 2006-02-24 01:39:10 +00:00
Wayne Davison
6f2a222c59 One more fuzzy tweak. 2006-02-23 20:29:55 +00:00
Wayne Davison
8470a515ef Some improved fuzzy-parent-dir logic. 2006-02-23 20:27:17 +00:00
Wayne Davison
06982ac43b Mention latest fixes. 2006-02-23 20:17:09 +00:00
Wayne Davison
865c3b5f92 The new fuzzy-dir logic once again avoids calling get_dirlist()
until a regular file is found in the current parent directory.
2006-02-23 20:00:48 +00:00
Wayne Davison
8c9e06d7b9 Fixed the creation of symlinks and devices when both --relative
and --no-implied-dirs are specified and the destination dir does
not yet exist.
2006-02-23 19:43:54 +00:00
Wayne Davison
a9cc128308 Renamed fuzzy_dirname -> parent_dirname. 2006-02-23 19:07:33 +00:00
Wayne Davison
ccb16b467b Make sure that the --fuzzy option's dir-scan doesn't generate an
I/O error when --no-relative is used and the destination dir does
not exist yet.
2006-02-23 18:58:30 +00:00
Wayne Davison
1e44aeb92a Mention the --list-arg change. 2006-02-23 00:43:17 +00:00
Wayne Davison
c897f7119a Document the revised --list-only behavior and the ability to use
rsync with one local source arg (i.e. no destination).
2006-02-23 00:40:58 +00:00
Wayne Davison
ee8e2b1547 Rsync no longer returns a usage error when used with one local
source arg and no destination: this now implies the --list-only
option, just like one remote source arg has always done.
2006-02-23 00:38:34 +00:00
Wayne Davison
5fa38cd679 - Improved the way we generate the tar file.
- The second run of verify-patches is in a better spot now.
- Made various improvements to the output.
2006-02-22 19:09:51 +00:00
Wayne Davison
65535b5482 Mentioned that the daemon now logs connections. 2006-02-21 17:19:49 +00:00
Wayne Davison
439a198d02 Log every connect to the daemon. 2006-02-21 17:09:23 +00:00
Wayne Davison
f041b02557 Added a comment. 2006-02-21 00:29:55 +00:00
Wayne Davison
4d8639eb2d A few more tweaks and fixes. 2006-02-20 19:58:06 +00:00
Wayne Davison
519c8de16f - Moved the checkout of the cvs source above the version prompting so
that we can use the version from the configure.in file to provide
  good default values for the user.
- When moving old tar/diff files into the old-* dirs, first hard-link
  them into place, then (if "live"), use rsync to update these new
  files on the server (which saves us later re-sending), and _then_
  delete the old names.
2006-02-20 19:36:56 +00:00
Wayne Davison
7f20af4674 Made the new warning more visible. 2006-02-20 18:35:41 +00:00
Wayne Davison
55d24e5fed Mention if any of the CVS files we're putting in the tar file
aren't up-to-date.
2006-02-20 18:34:27 +00:00
Wayne Davison
81f654e396 Mention a couple more bug fixes. 2006-02-20 18:03:55 +00:00
Wayne Davison
8f1dc165e2 A brief msleep() in option_error() may be helpful to ensure that
an option error always arrives intact from the remote rsync.
2006-02-20 17:58:13 +00:00
Wayne Davison
9a0cfff57f Don't try to obey bwlimit restriction until bwlimit_writemax is set.
This fixes a bug with option errors not getting reported because the
write code gets called with bwlimit != 0 and bwlimit_writemax == 0.
2006-02-20 17:50:36 +00:00
Wayne Davison
d749eb6896 When starting up a transfer, substitute the remember_children()
SIGCHLD handler in place of the minimal one that socket.c enabled.
2006-02-20 17:17:51 +00:00
Wayne Davison
6d59ac192b Made the formerly static sigchld_handler() available as a
public function named remember_children().
2006-02-20 17:16:21 +00:00
Wayne Davison
94d3725cf2 In dest_mode(), we now apply any "incoming chmod" changes from
the daemon.
2006-02-20 00:01:27 +00:00
Wayne Davison
8840ec0f49 Set a new daemon_chmod_modes pointer with the daemon's chmod
(incoming or outgoing) changes.
2006-02-20 00:00:35 +00:00
Wayne Davison
44a8e86d47 Mention the change in how "incoming chmod" works when --perms was
not specified.
2006-02-19 23:58:59 +00:00
Wayne Davison
73abdda442 Slightly tweaked the output in non-live mode. 2006-02-19 23:33:15 +00:00
Wayne Davison
15b03ab1a8 Changed parse_chmod() to return the pointer to the new items on
success.
2006-02-19 23:31:56 +00:00
Wayne Davison
dc5245679a Preparing for release of 2.6.7pre2 2006-02-19 16:21:30 +00:00
Wayne Davison
60414e5bce The tar command needed --no-recursion. 2006-02-19 16:14:39 +00:00
Wayne Davison
af40c7d667 The hide filter rule is no longer needed. 2006-02-19 16:05:08 +00:00
Wayne Davison
7eb2ecda0f Improved the description of a fix in 2.6.4. 2006-02-19 15:52:59 +00:00
Wayne Davison
6d12a859bc The perl script I use to create new rsync releases. This is an
adapted and extended version of an old shell script.
2006-02-18 21:27:54 +00:00
Wayne Davison
920071e242 A perl script I wrote to make a new "nightly" tar file and
maintain the nightly dir on samba.org.
2006-02-18 21:26:48 +00:00
Wayne Davison
2a24b4bd0c Some more refinement of the --checksum section. 2006-02-16 07:40:55 +00:00
Wayne Davison
a753502200 Don't try to help the ACKs for the --remove-sent-file option
when --delay-updates was specified.
2006-02-15 20:09:49 +00:00
Wayne Davison
8958fae362 One last change to make the --checksum distinction very clear. 2006-02-15 19:58:53 +00:00
Wayne Davison
e2d68210d7 Another attempt to make --checksum clearer. 2006-02-15 19:24:39 +00:00
Wayne Davison
99534debc8 Improved the --checksum description and mention our whole-file
checksum verification checksum is different.
2006-02-15 18:20:23 +00:00
Wayne Davison
5b98629747 Improved the while's logic in increment_active_files(). 2006-02-15 08:26:51 +00:00
Wayne Davison
42003f6af3 Mention the change to --remove-sent-files. 2006-02-15 08:16:42 +00:00
Wayne Davison
434573b226 Call increment_active_files() during the first phase of a transfer
where --remove-sent-files was specified.
2006-02-15 08:06:45 +00:00
Wayne Davison
d6081c829c Added increment_active_files() and decrement_active_files() which
allows the generator to ask us to limit the number of files that
are currently active in the transfer when --remove-sent-files is
enabled.
2006-02-15 08:05:31 +00:00
Wayne Davison
58718881ef - Changed "called" to "named".
- Fixed a filter option to have the right syntax.
- Mention --prune-empty-dirs in a couple more places.
2006-02-14 16:45:38 +00:00
Wayne Davison
ac669e8b92 Tweaked a comment. 2006-02-14 16:44:11 +00:00
Wayne Davison
567f1566a9 List more of the doc improvements, list some of the best diffs in
the patches dir, and unified the discussion of the "dest" options.
2006-02-13 18:45:04 +00:00
Wayne Davison
59a5687105 Modified the sentence about doc improvements. 2006-02-13 18:19:59 +00:00
Wayne Davison
7b13ff9704 Document what all the items in the --stats output mean. 2006-02-13 18:19:26 +00:00
Wayne Davison
5e7b826a4f Made the receiver count the size of symlinks in the total_size
value, just like the sender does.
2006-02-13 18:08:45 +00:00
Wayne Davison
cbc63b9b48 Added missing release-history lines for 2.6.6 and 2.6.7. 2006-02-12 19:15:35 +00:00
Wayne Davison
71a84cbab0 Mention the ignoring of SIGXFSZ. 2006-02-11 02:37:58 +00:00
Wayne Davison
55e54e464b We now ignore the SIGXFSZ signal (if it is defined). 2006-02-11 02:36:35 +00:00
Wayne Davison
467688dc06 More improvements for "--help", and a couple hyphenation fixes. 2006-02-11 00:02:15 +00:00
Wayne Davison
375d8f913b Added a backward-compatibility note about -h to the --help option
in the help text.
2006-02-11 00:01:22 +00:00
Wayne Davison
021849204a Fixed some typos, got rid of some extraneous spaces, got rid of
a hyphen in hard-link (since we consistently use it unhyphenated),
and refer to "unix" as "*nix".
2006-02-09 17:32:36 +00:00
Wayne Davison
b635f2e964 The -h was missing from the daemon's option summary. 2006-02-09 11:56:33 +00:00
Wayne Davison
1e2b96bbee - Improved the description of how 'D' because 'D' and 'S' for -i.
- Improved the --devices and --specials item, and moved it next to
  the --super item.
- Mention that "rsync -h" still works as before.
2006-02-09 10:25:25 +00:00
Wayne Davison
2857451ca2 Got rid of an statement that is no longer true. 2006-02-09 04:08:38 +00:00
Wayne Davison
2bc3835ee0 Preparing for release of 2.6.7pre1 2006-02-09 03:59:17 +00:00
Wayne Davison
4f417448b4 Updated the %i section. 2006-02-09 01:27:03 +00:00
Wayne Davison
503f163446 Decided against shortening the output of --itemize-changes. 2006-02-09 01:17:01 +00:00
Wayne Davison
f17e769e28 There's no need to send --size-only to a remote sender. 2006-02-09 01:15:04 +00:00
Wayne Davison
f65e6a1276 Tweaked the mention of --human-readable. 2006-02-08 17:03:00 +00:00
Wayne Davison
4c248a3615 Documented the change in the --human-readable option. 2006-02-08 16:54:10 +00:00
Wayne Davison
7794db7c0d Tweaked the --human-readable code to work with the new option parsing. 2006-02-08 16:52:51 +00:00
Wayne Davison
3ca9e5d8ad Changed -h to mean powers of 1000 when used once, and powers of 1024
when repeated.  Got rid of --si.
2006-02-08 16:52:25 +00:00
Wayne Davison
5ca8a90c24 Tweaked the name of one of dest_mode()'s args. 2006-02-08 02:34:06 +00:00
Wayne Davison
0679ac4ca9 Tweaked a comment. 2006-02-08 02:32:35 +00:00
Wayne Davison
20a0269782 Mention --dry-run doesn't force --verbose. 2006-02-07 20:08:30 +00:00
Wayne Davison
a892d905bb Don't force verbose for --dry-run; let the user decide. 2006-02-07 20:06:43 +00:00
Wayne Davison
bc880cb8d2 Don't look for $RSYNC_PARTIAL_DIR on the server side. 2006-02-07 19:12:37 +00:00
Wayne Davison
2243a9353e Clarified something in "incoming chmod". 2006-02-07 18:45:16 +00:00
Wayne Davison
10f994a52a Moved the delay-bit functions into util.c, making them more generic. 2006-02-07 18:15:51 +00:00
Wayne Davison
0f86c74eba Call renamed cmp_time() function (was cmp_modtime()). 2006-02-07 18:15:46 +00:00
Wayne Davison
c2b5407678 - Renamed cmp_modtime() -> cmp_time().
- Moved the delay-bit functions here from receiver.c and transformed
  them into some more generic "bitbag" functions.
2006-02-07 18:15:37 +00:00
Wayne Davison
350879d8d1 Only call the just-added "touch" if autoheader succeeded. 2006-02-07 17:30:35 +00:00
Wayne Davison
a6a276027c Changed --8-bit to --8-bit-output. 2006-02-06 18:51:25 +00:00
Wayne Davison
45b79c8959 Mentioned --8-bit (-8). 2006-02-06 18:45:48 +00:00
Wayne Davison
d0022dd908 Document --8-bit (-8). 2006-02-06 18:43:12 +00:00
Wayne Davison
e0f4a661be Don't setup ic_chck if --8-bit was specified. 2006-02-06 18:42:46 +00:00
Wayne Davison
507433f6ca Don't call isprint() if --8-bit was specified. 2006-02-06 18:42:02 +00:00
Wayne Davison
5974c662ff Added the --8-bit (-8) option. 2006-02-06 18:41:32 +00:00
Wayne Davison
aa0bec8a52 Ensure that the timestamp for config.h.in is changed after
running autoheader.
2006-02-06 18:27:45 +00:00
Wayne Davison
2d2f71fb27 Got rid of a newly-added trailing tab. 2006-02-06 18:00:37 +00:00
Wayne Davison
36f59b5802 Mention the new output-escaping idiom and the multibyte support. 2006-02-06 17:58:29 +00:00
Wayne Davison
7fc87d2daf Allow the iconv_open() call to fail since we can now fall-back on
isprint().  Got rid of the "646" mapping kluge too.
2006-02-06 16:55:01 +00:00
Wayne Davison
3648ab3a24 - The iconv-supporting code can now ask filtered_fwrite() to use
isprint() when iconv() could not be setup.
- Changed the output idiom for escaped chars to use \#123 instead
  of \0123 because that makes it possible for a script to know for
  sure what version of rsync did the output (and thus, what the
  unescape rules are).
2006-02-06 16:54:12 +00:00
Wayne Davison
7a9d183fc4 Have default_charset() try mapping "646" -> "ASCII" instead of "ascii". 2006-02-06 09:04:20 +00:00
Wayne Davison
2a62f5ee19 Added "const" to the default_charset() return. 2006-02-06 09:00:37 +00:00
Wayne Davison
f9cfaae952 Solaris 9 and HP-UX 11.11 need us to look for libiconv_open,
not iconv_open (perhaps because iconf.h wasn't included in
the autoconf test).
2006-02-06 08:57:16 +00:00
Wayne Davison
bd4576fe4b Check to see if we need to include the iconv library. 2006-02-06 08:35:18 +00:00
Wayne Davison
4e194bf178 Mention the prepare-source script and the changes in the patches
dir.
2006-02-06 07:57:03 +00:00
Wayne Davison
ef4e0d5e7e Added dependencies for proto.h. 2006-02-06 05:06:52 +00:00
Wayne Davison
e6d8e70925 The "proto" target now builds target "proto.h" from the new
prepare-source.mak makefile.
2006-02-06 04:54:30 +00:00
Wayne Davison
a6c5741c37 Changed the "proto" target to "proto.h". 2006-02-06 04:53:02 +00:00
Wayne Davison
3ea7fc6ccf Moved the targets "gen", "proto", and "man" to prepare-source.mak. 2006-02-06 04:09:48 +00:00
Wayne Davison
20926fbd63 An easy way to run all the commands in prepare-source.mak. 2006-02-06 04:08:14 +00:00
Wayne Davison
2a3f3ba45d Moved the rules for generating files such as configure, config.h.in,
proto.h, and the manpages into this separate makefile, allowing it to
be used without first running configure (which builds the Makefile).
2006-02-06 04:07:49 +00:00
Wayne Davison
662127e6c7 Include --no-g in the popt-alias example in --perms. 2006-02-05 15:31:31 +00:00
Wayne Davison
0be05d6038 In default_charset(): if nl_langinfo() gives us "646", return "ascii". 2006-02-05 07:20:10 +00:00
Wayne Davison
1f77038ef2 Added a missing comma. 2006-02-05 07:00:21 +00:00
Wayne Davison
77ed253c73 Some more improvements to --perms and --executability from Matt and me. 2006-02-05 06:40:18 +00:00
Wayne Davison
b988781801 Allow itemize() to flag ITEM_REPORT_PERMS anytime the permissions
change (even if -p or -E aren't set).
2006-02-05 06:13:34 +00:00
Wayne Davison
595251de24 Make sure that we don't try to use iconv() without iconv.h. 2006-02-05 04:52:11 +00:00
Wayne Davison
c85631421d Changed HAVE_ICONV to HAVE_ICONV_OPEN. 2006-02-05 04:45:23 +00:00
Wayne Davison
12c8cd02fc Switched back to checking for iconv_open() due to HP-UX. 2006-02-04 23:06:39 +00:00
Wayne Davison
9656de5d13 Call setup_iconv(). 2006-02-04 22:03:44 +00:00
Wayne Davison
9a31746b10 Use iconv() (when available) to allow us to output multibyte
characters that are legal in the current locale.
2006-02-04 22:03:39 +00:00
Wayne Davison
ceccbacc34 The new function setup_iconv() initializes the ic_chck var. 2006-02-04 22:03:33 +00:00
Wayne Davison
ff2e2ccfc1 - Changed the check for iconv_open() to just iconv().
- Got rid of the --enable-iconv option for now.
2006-02-04 22:03:21 +00:00
Wayne Davison
12bda6f710 Don't do so much memory copying in mplex_write(). 2006-02-04 21:52:32 +00:00
Wayne Davison
c53b6fd0ac In the compatibility comments: mention why we don't use grep -q. 2006-02-04 19:44:19 +00:00
Wayne Davison
b31243b472 Test directory setgid inheritence when --perms is not in effect. 2006-02-04 19:42:47 +00:00
Wayne Davison
c8d19f90a6 Added a missing '(' in the opening comments. 2006-02-04 19:29:13 +00:00
Wayne Davison
114bafe0d0 Added a special permission (o+t) to one of the files in the test. 2006-02-04 19:28:45 +00:00
Wayne Davison
5ef8c5c6d4 Tweaked a function declaraion. 2006-02-04 19:27:07 +00:00
Wayne Davison
9b499e9537 - When not preserving permissions, ensure that a newly-created
directory's inherited sgid bit is preserved.
- When not preserving permissions, ensure that newly-created
  files/dirs don't inherit any special permissions.
2006-02-04 19:09:46 +00:00
Wayne Davison
00f00f846b Ignore setfacl unless it tells us that it supports the -k option. 2006-02-04 18:41:47 +00:00
Wayne Davison
998113fedf Needed to make %G output "DEFAULT" when gid == GID_NONE. 2006-02-04 18:40:41 +00:00
Wayne Davison
ee5544112a Improved the --partial-dir section. 2006-02-03 23:50:16 +00:00
Wayne Davison
7eaabd8fac Decided to undo the last change to avoid backward compatibility
inconsistencies (it would have been the right thing to do if it
were done that way from the start, but not now).
2006-02-03 23:40:37 +00:00
Wayne Davison
4fc808dd98 Avoid adding our own exclude of the partial-dir name if the
user's filter rules already match it.
2006-02-03 23:16:46 +00:00
Wayne Davison
7cfb250c93 Made the new %M escape handle multiple spaces in the timestamp
(which can occur if the user's system doesn't have strftime()).
2006-02-03 22:41:19 +00:00
Wayne Davison
47f480b619 Removed completed items. 2006-02-03 20:49:25 +00:00
Wayne Davison
fa9e950b1a Mention who is outputting the "rsync error" or "rsync warning". 2006-02-03 20:39:58 +00:00
Wayne Davison
49f4d850ce Mention latest changes. 2006-02-03 20:32:27 +00:00
Wayne Davison
b3e15181ae Log when someone requests a module list. 2006-02-03 20:28:19 +00:00
Wayne Davison
aca5500aea Document the new "log format" options: %M (modtime), %U (uid),
%G (gid), and %B (perm bits).
2006-02-03 20:00:24 +00:00
Wayne Davison
427b6179b9 - Allow tab characters to appear in rwrite() messages.
- Added %M (modtime), %U (uid), %G (gid), and %B (perm bits) to
  log_formatted().
2006-02-03 19:59:25 +00:00
Wayne Davison
afa73c75b5 A minor optimization to timestring. 2006-02-03 19:40:16 +00:00
Wayne Davison
8261af7422 Allow sigaction() to be used even if sigprocmask() isn't around
(or was manually disabled).
2006-02-03 18:48:26 +00:00
Wayne Davison
44e604f416 Simplified the conditional prior to the SIGACTION code. 2006-02-03 18:46:38 +00:00
Wayne Davison
5173f99e68 A slight tweak to the conditionalized definition of SIGACTION(). 2006-02-03 18:34:09 +00:00
Wayne Davison
8a3d4658eb Decided I don't like "set -x". 2006-02-03 17:58:48 +00:00
Wayne Davison
6b43924848 The calls to check_perms now pass a test number arg and
don't check for failure (it will die on failure).
2006-02-03 17:55:24 +00:00
Wayne Davison
eace352b39 Improved check_perms() to work with a directory, to have better
output on error, and to call test_fail on error.
2006-02-03 17:54:18 +00:00
Wayne Davison
fdbe8989fe Moved check_perms() into rsync.fns and tweaked how it is called. 2006-02-03 17:29:43 +00:00
Wayne Davison
18d7e9f46e Added a new function: check_perms(). 2006-02-03 17:28:03 +00:00
Wayne Davison
c6fbd563d8 Matt's executability test with a few tweaks (e.g. to avoid using
"stat").
2006-02-03 06:47:26 +00:00
Wayne Davison
a5df33bb62 Scratch-dir normalization from Matt: turn off any default ACLs (if
setfacl is available) and disable any directory setgid bit to avoid
confusing some tests.
2006-02-03 06:15:46 +00:00
Wayne Davison
5cf4896050 Mention the sigaction() and sigprocmask() goodness. 2006-02-02 22:38:55 +00:00
Wayne Davison
2fb450bd99 Fixed a hang. 2006-02-02 22:34:30 +00:00
Wayne Davison
4ea58045e2 Moved the potential disabling of __attribute__ above the
relocated UNUSED() define.
2006-02-02 22:24:33 +00:00
Wayne Davison
29433538ff Tweaked a couple lines in the code that handles --version. 2006-02-02 11:40:32 +00:00
Wayne Davison
d382140904 Changed default logfile setting from /var/adm/rsyncd.log to
/var/log/rsyncd.log.
2006-02-02 10:20:13 +00:00
Wayne Davison
b8e9c234e6 Changed sig_int() to use a standard signal-handler prototype. 2006-02-02 02:39:40 +00:00
Wayne Davison
60ee01f517 - Call SIGACTION() instead of signal().
- Umask all the signals we need using sigprocmask() (if available).
2006-02-02 02:39:29 +00:00
Wayne Davison
2b28968dfb Call SIGACTION() instead of signal(). 2006-02-02 02:39:25 +00:00
Wayne Davison
90b13cf606 - Moved definition of UNUSED() above inclusion of proto.h.
- Replaced definition of SIGNAL_CAST with new SIGACTION() define,
  which will use sigaction() if it is available, else signal().
2006-02-02 02:39:19 +00:00
Wayne Davison
d81894fc21 Added checks for sigaction() and sigprocmask(). 2006-02-02 02:32:39 +00:00
Wayne Davison
f5cbae9329 Look for public functions that return RETSIGTYPE. 2006-02-02 02:29:30 +00:00
Wayne Davison
7a6653bc6c Ignore the --quiet option if someone sent it to us (which doesn't
happen when talking to a normal client).
2006-02-01 19:36:37 +00:00
Wayne Davison
72f2d1b384 When complaining about a socket-read problem, use an FSOCKERR
code instead of a normal FERROR.  The generator is the only
process that will receive this, and it uses it to close down
the multi-I/O over the socket so that it won't ever hang trying
to write an error down a dead socket.
2006-02-01 19:35:17 +00:00
Wayne Davison
b66e31bf15 Turn an FSOCKERR into a normal FERROR if it's not going to our
sibling.
2006-02-01 19:33:12 +00:00
Wayne Davison
ea26c854af Added FSOCKERR and MSG_SOCKERR (a sibling-only message). 2006-02-01 19:26:34 +00:00
Wayne Davison
ef1f62807e We should be using wait_process(), not waitpid() directly. 2006-02-01 19:25:34 +00:00
Wayne Davison
d8aeda1e50 Changed a few "ret" variables to have better names. 2006-02-01 19:24:28 +00:00
Wayne Davison
07efba8ec0 The itemize() output now mentions -E permissions changes. 2006-01-31 06:25:46 +00:00
Wayne Davison
2959fe7447 Mention the --executability option. 2006-01-31 03:40:22 +00:00
Wayne Davison
4601589720 Another help-text tweak. 2006-01-31 03:11:07 +00:00
Wayne Davison
9f8225566e Moved where --chmod was listed. 2006-01-31 03:05:24 +00:00
Wayne Davison
5e65c96705 Moved --chmod in the help output. 2006-01-31 03:04:00 +00:00
Wayne Davison
a9d6e6fcac When permissions aren't being preserved, set them via the new
dest_mode() function.
2006-01-31 02:30:09 +00:00
Wayne Davison
860dcf68ad Got rid of the orig_umask-based file->mode tweak in receive_file()
(which got moved into the dest_mode() function).
2006-01-31 02:30:05 +00:00
Wayne Davison
812848323b Added the dest_mode() function: it figures out the permissions for
a file when we aren't preserving permissions, including the honoring
of the new --executability option.
2006-01-31 02:30:02 +00:00
Wayne Davison
344f9ba7fa Added the --executability (-E) option. 2006-01-31 02:29:58 +00:00
Wayne Davison
2d5279ac9a Documented the new --executability (-E) option, with improvements
to the --perms and --chmod sections as well.
2006-01-31 02:29:55 +00:00
Wayne Davison
fa3e4a0548 Mention the chmod utility's manpage number. 2006-01-31 02:26:49 +00:00
Wayne Davison
656c20715e Mention that --chmod's work can still be masked by the receiving
end's umask when permissions are not being preserved.
2006-01-30 22:10:33 +00:00
Wayne Davison
a72885e042 Mention files-to-excludes. 2006-01-30 21:54:00 +00:00
Wayne Davison
b587adda1f This perl script automates the conversion of a list of pathnames
to a set of includes/excludes needed for rsync to copy just the
listed files.
2006-01-30 21:52:17 +00:00
Wayne Davison
50fd4832c2 Mentioned the new "outgoing chmod" daemon option. 2006-01-30 21:47:23 +00:00
Wayne Davison
c094d9320d Documented the new "outgoing chmod" daemon option. 2006-01-30 21:47:08 +00:00
Wayne Davison
aaccaa887d Added support for the new "outgoing chmod" daemon option. 2006-01-30 21:47:02 +00:00
Wayne Davison
5481e42cd6 Mentioned the early-EOF bugfix (which was fixed a while ago). 2006-01-30 20:09:46 +00:00
Wayne Davison
b3964d1d86 Improved the documentation for --force. 2006-01-30 18:46:17 +00:00
Wayne Davison
e35d9f2d6d I realized that there were instances where --force could still be
required to be combined with a delete option (if a non-dir was
overwriting a dir in a directory that was not included in the
transfer), so I extended the change I just made for --delete-after
to include all delete modes.
2006-01-30 18:45:57 +00:00
Wayne Davison
4d16780366 Allow --force to work even if --recurse was not specified. 2006-01-30 18:35:54 +00:00
Wayne Davison
1661fe9b0c Made get_dirlist() always include directories. 2006-01-30 18:32:47 +00:00
Wayne Davison
63344ad4e1 Mention the latest improvements. 2006-01-30 18:19:55 +00:00
Wayne Davison
90cf7d199f Allow a non-empty dir to be overwritten by a non-dir with all the
delete options (--delete-after used to require --force).
2006-01-30 18:14:02 +00:00
Wayne Davison
730df9d222 If the module has defined an "incoming chmod" option, call
parse_chmod() on it.
2006-01-30 17:53:38 +00:00
Wayne Davison
882d8c1cab Added the "incoming chmod" config option. 2006-01-30 17:53:32 +00:00
Wayne Davison
17af842d2d Document the new "incoming chmod" config option. 2006-01-30 17:53:27 +00:00
Wayne Davison
bbe42182df Call the parse_chmod() with its new syntax. 2006-01-30 17:53:19 +00:00
Wayne Davison
81b096feef Changed the way the parse_chmod() function is called. 2006-01-30 17:53:13 +00:00
Wayne Davison
7627e92c54 Added extern for io_write_phase. 2006-01-30 17:39:43 +00:00
Wayne Davison
f7bce90cf0 - Got rid of the externs for io_read_phase and io_write_phase.
- Added stub definition for chmod_mode_struct.
2006-01-30 17:39:34 +00:00
Wayne Davison
b33ce4c800 Moved the filter_outfile() function to rsync.fns. 2006-01-30 08:12:17 +00:00
Wayne Davison
757287d8a5 Moved the filter_outfile() function here since it was identical
in devices.test and itemize.test.
2006-01-30 08:11:50 +00:00
Wayne Davison
3ed8eafccb The robust_rename() function now takes a "partialptr" arg that, if
non-NULL, will be used if we are forced to copy the file.
2006-01-30 07:18:16 +00:00
Wayne Davison
d8b1c923ef The finish_transfer() function now takes a "partialptr" arg that, if
non-NULL, will be used if robust_rename() is forced to copy the temp
file.
2006-01-30 07:18:13 +00:00
Wayne Davison
4a4d2b1ba0 Call finish_transfer() with a valid partialptr string, when
appropriate.
2006-01-30 07:18:10 +00:00
Wayne Davison
12fa790ea0 Call finish_transfer() with its newly-added arg. 2006-01-30 07:18:06 +00:00
Wayne Davison
21955d9c92 Call robust_rename() with its newly-added arg. 2006-01-30 07:18:03 +00:00
Wayne Davison
a0d9819f8c Document the side-effect that --partial-dir can have on --temp-dir. 2006-01-30 07:18:00 +00:00
Wayne Davison
a9af5d8eba More improvements to --temp-dir. 2006-01-30 06:34:57 +00:00
Wayne Davison
65854cf91a Changed the mode arg from an int to a mode_t. 2006-01-30 00:39:59 +00:00
Wayne Davison
9ec1ef2535 Improved the --temp-dir description and a couple other sentences. 2006-01-29 20:31:59 +00:00
Wayne Davison
36119f6e2a - Renamed set_perms() to set_file_attrs().
- Use the renamed PERMS_* defines: ATTRS_*.
2006-01-29 20:30:24 +00:00
Wayne Davison
e912bd4dfb - Use the renamed PERMS_* defines: ATTRS_*.
- Call the new name of set_perms():  set_file_attrs().
2006-01-29 20:30:18 +00:00
Wayne Davison
c3ef136d41 Call the new name of set_perms(): set_file_attrs(). 2006-01-29 20:30:12 +00:00
Wayne Davison
8eda7a4bb8 Renamed the PERMS_* defines to ATTRS_* defines. 2006-01-29 20:30:07 +00:00
Wayne Davison
78d146e866 Use PERMSTRING_SIZE rather than a hard-wired "11". 2006-01-29 20:30:02 +00:00
Wayne Davison
77860bacd0 No need to send --partial when we're the receiver. 2006-01-29 19:17:13 +00:00
Wayne Davison
63cf5ae72c Made a bunch of char* args const. 2006-01-29 18:52:53 +00:00
Wayne Davison
120cde9562 Avoid forwarding the --temp-dir option to the server when we're
the receiver.
2006-01-29 07:19:38 +00:00
Wayne Davison
e6ffb966dd Made the new --prune-empty-dirs code a little more memory efficient. 2006-01-28 19:20:02 +00:00
Wayne Davison
207522aef5 Tweaked a variable name in flist_find(). 2006-01-28 08:12:16 +00:00
Wayne Davison
a1cc199b34 We enforce at least protocol 29 for --prune-empty-dirs because the
file-list's sort order can be slightly wrong in older versions.
2006-01-28 07:40:52 +00:00
Wayne Davison
c22260706c Don't add the "protect" filter rule for backup-suffix filenames
if --backup was not specified.
2006-01-28 01:55:55 +00:00
Wayne Davison
d5782b52a2 - We need to send exclude info from the client to a server-receiver
when --prune-empty-dirs was specified.
- Changed the output of debug include/exclude/show/hide/risk/protect
  messages to use the appropriate filter terminology instead of
  always using the (potentially unclear) include/exclude terms.
2006-01-28 00:14:02 +00:00
Wayne Davison
85aecef6c3 The user can now use a "protect" filter to avoid pruning one or
more empty directories when --prune-empty-dirs is in effect.
2006-01-28 00:13:59 +00:00
Wayne Davison
876c993680 Changed --skip-empty-dirs (-k) to --prune-empty-dirs (-m). 2006-01-28 00:13:55 +00:00
Wayne Davison
a272ff8c1b Changed --skip-empty-dirs (-k) to --prune-empty-dirs (-m) and
improved the docs a bit more, including documenting how "protect"
filtering affects empty dirs.
2006-01-28 00:13:52 +00:00
Wayne Davison
7402d58369 Improved flist_find()'s empty-entry handling to deal with the case
where more entries may have been removed since the last find.
2006-01-27 14:29:58 +00:00
Wayne Davison
c0b134a445 Optimized flist_find() so that we never scan a series of empty
file-list items twice (which can be very important with the new
--skip-empty-dirs option).  Also optimized the code that strips
root slashes in clean_flist().
2006-01-27 12:59:07 +00:00
Wayne Davison
a324d49bfc Mention the --skip-empty-dirs option. 2006-01-27 01:20:11 +00:00
Wayne Davison
9c000f5e7b Implement the new --skip-empty-dirs (-k) option. 2006-01-27 00:32:57 +00:00
Wayne Davison
0e887ef29a Added the --skip-empty-dirs (-k) option. 2006-01-27 00:32:53 +00:00
Wayne Davison
fb72aaba48 Document the new --skip-empty-dirs (-k) option. 2006-01-27 00:32:49 +00:00
Wayne Davison
a3869e9227 Include popt.h using <popt.h> instead of "popt.h". 2006-01-26 22:32:59 +00:00
Wayne Davison
d671ccfc8e Mention the change in the --itemize-changes output. 2006-01-26 22:32:18 +00:00
Wayne Davison
35bf8fa084 - Include popt.h using <popt.h>, not "popt.h".
- A minor twiddle in server_options().
2006-01-26 22:28:08 +00:00
Wayne Davison
f7916cbf3f Mention --sockopts and an improvement to the testsuite environment. 2006-01-26 22:10:08 +00:00
Wayne Davison
2b7dab686c The setting of HOME got moved to rsync.fns. 2006-01-26 21:23:25 +00:00
Wayne Davison
a98cad00eb Set $HOME to $scratchdir so that our tests are not affected by
anything unexpected, such as a ~/.popt file.
2006-01-26 21:22:57 +00:00
Wayne Davison
facdce2c1f Fixed two typos. 2006-01-26 12:41:52 +00:00
Wayne Davison
34937987a6 Make use of the new sockopts variable. 2006-01-26 12:31:47 +00:00
Wayne Davison
831f06a5a5 Added the --sockopts option. 2006-01-26 12:31:24 +00:00
Wayne Davison
5fe3c86f25 Mention the --sockopts option. 2006-01-26 12:31:14 +00:00
Wayne Davison
04f48837d1 Document the new --sockopts option. 2006-01-26 12:30:20 +00:00
Wayne Davison
f5b14759fb Mentioned the --super option. 2006-01-26 11:14:10 +00:00
Wayne Davison
def97ff9a9 Added the --super option. 2006-01-26 11:10:32 +00:00
Wayne Davison
d38772e06f Document the new --super option and how it affects other options. 2006-01-26 11:10:28 +00:00
Wayne Davison
351f5e2f6c Check MY_UID() directly instead of accessing am_root. 2006-01-26 11:01:00 +00:00
Wayne Davison
8778174936 Mention new --specials option and --devices change. 2006-01-26 10:50:18 +00:00
Wayne Davison
e5f6a04d15 The itemized output for the fifo changed. 2006-01-26 10:39:04 +00:00
Wayne Davison
f8d47c1cb4 Added 'S' to the itemized output for special files. 2006-01-26 10:39:01 +00:00
Wayne Davison
b5c6a6aeeb Handle separated devices and special files. 2006-01-26 10:38:58 +00:00
Wayne Davison
4e7d07c8d4 Document the new --specials option and how -D and --devices now work. 2006-01-26 10:38:54 +00:00
Wayne Davison
fc2dd77ec7 One more minor tweak. 2006-01-25 17:34:39 +00:00
Wayne Davison
7b6fa00ff8 Decided to hold off on the potential memory savings of indexed
uid/gid pairs until the next release.
2006-01-25 17:10:29 +00:00
Wayne Davison
9ac3591366 Added testing of the --itemize-changes output for devices. 2006-01-24 22:23:51 +00:00
Wayne Davison
6a819e02da Changed to handle removed 'a' slot in %i output. 2006-01-24 22:23:14 +00:00
Wayne Davison
4cff7c50db Fixed a problem in the output of %i's 'T' flag on devices and
got rid of the unused 'a' flag.
2006-01-24 22:22:17 +00:00
Wayne Davison
669302a172 Got rid of the description of 'a' in the %i flags. 2006-01-24 22:14:40 +00:00
Wayne Davison
c738605098 Got rid of some debug code. 2006-01-24 21:40:43 +00:00
Wayne Davison
90cf838b18 Dump some debug code. 2006-01-24 21:39:10 +00:00
Wayne Davison
67e4043e8c Optimized id_pair() so that clumps of IDs get handled more
efficiently.
2006-01-24 19:39:09 +00:00
Wayne Davison
5e58e3f9cf The uid & gid are now stored using an id_pair structure. 2006-01-24 19:02:55 +00:00
Wayne Davison
49140b27c6 Another small improvement to the --one-file-system option. 2006-01-24 19:02:48 +00:00
Wayne Davison
9cdadbb13a The in_del_hier code needs to use lastname instead of thisname
because the latter gets cleaned and (possibly) sanitized.
2006-01-24 17:26:24 +00:00
Wayne Davison
0ace7b2567 FERROR messages also need to leave leading newlines unmangled. 2006-01-24 01:07:19 +00:00
Wayne Davison
ccb8f5788b Tweaked the copyright message. 2006-01-23 18:48:12 +00:00
Wayne Davison
4e5baafedf More improvements to the -x option (some from Matt & some from me). 2006-01-22 21:04:21 +00:00
Wayne Davison
0e82af2d27 New -x code had some problems, so restore the old code for now
(keeping the more optimal stat() calling, though).
2006-01-22 20:37:00 +00:00
Wayne Davison
535737bf39 New -x code had some problems, so restore the old code for now. 2006-01-22 20:30:56 +00:00
Wayne Davison
6e6cc16399 Matt's disambiguation. 2006-01-21 21:02:13 +00:00
Wayne Davison
bb0d8edfad - Got rid of the filesystem_dev variable now that --one-file-system
is handled in a new way.
- Moved a stat out of delete_in_dir() into do_delete_pass() to make
  --delete-during more efficient.
- Added a missing "#ifdef SUPPORT_LINKS...#endif" block around some
  symlink code.
2006-01-21 20:59:19 +00:00
Wayne Davison
ebec5eb689 - Changed how --one-file-system works so that we can skip all mount
points (including "bind" mounts).
- The --chmod option now affects devices (only skipping symlinks).
2006-01-21 20:59:16 +00:00
Wayne Davison
5cb31dcf92 Fixed a problem with the FLAG_* defines. 2006-01-21 20:16:37 +00:00
Wayne Davison
0ccffd7c80 Disable popt aliases when we're a server so that any user-redefined
options can't cause a compatibility problem.
2006-01-21 20:15:49 +00:00
Wayne Davison
57b66a2458 A tweak to --dirs and --chmod. 2006-01-21 19:55:47 +00:00
Wayne Davison
b8a39ed58a Use the new saw_delete* variables to ensure that the server side
always reads the exclude information when it is present.
2006-01-21 19:54:14 +00:00
Wayne Davison
f5a910dd73 - We now set some saw_delete* vars to keep track of the case where
we disabled a delete option that the client sent us (since we may
  still need to await exclude information from the client in such a
  case).
- If -d and --delete are in effect without -r, we may need to send
  the -d to the server even if it was implied, and we may need to
  send --no-r to the server to ensure that we don't get into a
  protocol-corrupting situation should the remote rsync disable the
  --delete option (this works because the --no-r option was added in
  the same version as the functionality which allows --delete to
  work with -d sans -r.
2006-01-21 19:52:55 +00:00
Wayne Davison
e16adcdff3 - Allow multiple --chmod options to be specified.
- Call parse_chmod() with its new arg.
2006-01-21 09:14:42 +00:00
Wayne Davison
cf9b4794fd Tweaked parse_chmod() so that it takes a pointer to an existing list
of chmod items (or NULL) and appends the new items onto the end.
2006-01-21 09:14:39 +00:00
Wayne Davison
6d8c6bdbe5 Document the new --one-file-system behavior, with improvements to
the option's text taken from Matt's patch in bugzilla.
2006-01-21 08:10:45 +00:00
Wayne Davison
8bbe41b53b Handle the --chmod option as either the sender or the receiver so
that only the client needs to know about --chmod (but if an older
version sends the option to the server, we'll still handle it).
2006-01-21 08:03:18 +00:00
Wayne Davison
ba30fb5c3c For a local rsync, turn off the --chmod option on the receiving
side so that only the sending side does the work.
2006-01-21 07:58:35 +00:00
Wayne Davison
0938e8eee5 We don't ever need to send the --chmod option to the remote rsync. 2006-01-21 07:53:40 +00:00
Wayne Davison
3b17384631 Implemented the -xx behavior that skips mount-point dirs. 2006-01-21 01:20:03 +00:00
Wayne Davison
243c995f5f Allow the -x option to be repeated. 2006-01-21 00:36:15 +00:00
Wayne Davison
96b87581ff - Changed send_file_entry() into a static function again.
- Made send_file_entry() derive the base_flag value from *file.
- Added a flags arg to make_file().
- The flag we send to send_file_name() is a FLAG_* value, not an
  XMIT_* value.
2006-01-20 21:21:43 +00:00
Wayne Davison
3de73827d7 Call make_file() with one more arg (the base flags). 2006-01-20 21:21:36 +00:00
Wayne Davison
458aeea4a6 Mentioned the addition of -ii. 2006-01-20 19:33:24 +00:00
Wayne Davison
14cbb64539 Document the behavior of -ii. 2006-01-20 18:52:52 +00:00
Wayne Davison
a9e4762634 Handle the extra output needed when log_format_has_i > 1. 2006-01-20 18:49:38 +00:00
Wayne Davison
487094a0d7 Allow the --itemize-changes (-i) option to be repeated to indicate
that unchanged files should also be itemized.
2006-01-20 18:49:07 +00:00
Wayne Davison
f608ebb106 Got rid of unused function u_strcmp(). 2006-01-20 00:14:04 +00:00
Wayne Davison
87001ac6c2 Improved a sentence. 2006-01-19 21:21:28 +00:00
Wayne Davison
ede1f0ebc9 The code in send_file_list() needed a little more improvement to
handle --relative really well:
- We must set "is_dot_dir" when we strip off a trailing "/" or "/.".
- If a trailing "/" or "/." caused us to treat a symlink as a dir,
  we now pass our stat() info down to make_file() so that it will
  always treat the cleaned-up name as a dir too.
- We must not strip a leading "/".
- Improved the check for ".." elements in the implied dirs.
2006-01-19 21:16:44 +00:00
Wayne Davison
b435d7174c Added a new arg to the make_file() call. 2006-01-19 21:16:40 +00:00
Wayne Davison
2a59d2cc31 Another bugfix. 2006-01-19 19:05:49 +00:00
Wayne Davison
b8595e609a In delete_in_dir(), skip a directory that isn't really a directory on
the local disk (can easily happen if --dry-run was specified).
2006-01-19 18:53:48 +00:00
Wayne Davison
d37bc73a48 Mention the changes made in recent checkins. 2006-01-19 07:34:41 +00:00
Wayne Davison
1902a7652f When --relative is active, simply trim off trailing slashes and
dot dirs.  Also, reject a ".." dir if it would be sent as part
of the relative path.
2006-01-19 01:43:10 +00:00
Wayne Davison
6ab423a5b6 - Fixed the --help and --version output to avoid using embedded
newlines (which are no longer allowed in rprint()).
- Updated the Copyright info for 2006.
2006-01-17 04:26:12 +00:00
Wayne Davison
c2be690cc6 Got rid of a few empty lines. 2006-01-17 02:16:57 +00:00
Wayne Davison
f5a49d0e44 Got rid of a now-unused static variable. 2006-01-17 01:26:35 +00:00
Wayne Davison
03e23e0730 A few more items to check for, including libcharset.h, langinfo.h,
locale_charset(), and nl_langinfo().
2006-01-15 14:52:12 +00:00
Wayne Davison
eb598fac4f - Improved get_local_name() using ideas from Matt McCutchen's
version:  lots more comments, and a "local name" copy now
  does a chdir to the parent dir of the destination file.
- Moved the setlocale() call prior to the parse_arguments() call.
2006-01-15 07:11:23 +00:00
Wayne Davison
be0602ec3c - We now filter all rwrite() output when it goes out to the terminal
to make sure that it contains readable characters.
- Got rid of the buf[len] = '\0' in rwrite().
- Call f_name() with revised args (which also replaces f_name_to()).
2006-01-14 20:26:28 +00:00
Wayne Davison
6cbde57d88 Call f_name() with revised args (which also replaces f_name_to()). 2006-01-14 20:26:23 +00:00
Wayne Davison
5e4ff5f9c5 Merged f_name() with f_name_to(). 2006-01-14 20:26:20 +00:00
Wayne Davison
18e1289f27 Defined new FNAME logcode enum (only used on the client side when
logging a filename).
2006-01-14 20:26:17 +00:00
Wayne Davison
99aaa6ca25 Fixed a couple out-of-memory function-name strings in make_file(). 2006-01-14 17:19:12 +00:00
Wayne Davison
24172e4b2f If the --human-readable option is in effect, output the size of
each file in human-readable units instead of a raw byte count.
2006-01-14 17:10:52 +00:00
Wayne Davison
beaf495400 Added a "continue" missing from a recent change. 2006-01-14 00:29:50 +00:00
Wayne Davison
79f48760f3 Added --enable-iconv and cleaned up the other enable/disable options. 2006-01-13 23:05:16 +00:00
Wayne Davison
785abd4802 Got rid of the safe_fname() function and the calls to it. 2006-01-13 22:06:34 +00:00
Wayne Davison
0ee6ca9800 Got rid of calls to the (soon to vanish) safe_fname() function. 2006-01-13 22:06:31 +00:00
Wayne Davison
7543020807 Fixed a bug in the explode_mode code that was causing a crash
on BSD systems.
2006-01-13 21:40:26 +00:00
Wayne Davison
47b50b9bd0 We now use lib/compat.o when building wildtest. 2006-01-13 21:38:43 +00:00
Wayne Davison
45c49b52a4 Got rid of calls to (the soon to vanish) safe_fname() function. 2006-01-13 21:17:09 +00:00
Wayne Davison
0ee32c62d3 Improved a couple sentences. 2006-01-13 21:10:11 +00:00
Wayne Davison
70e98a4348 Changed RSYNC_ARGn to RSYNC_ARG#. 2006-01-12 19:35:54 +00:00
Wayne Davison
fddf529df9 Mention the new RSYNC_ARGn environment variables for pre-xfer exec. 2006-01-12 19:24:25 +00:00
Wayne Davison
141c62659e We now send all the option args to the pre-exec command. 2006-01-12 19:15:31 +00:00
Wayne Davison
61e16468f0 We need to call clearerr() when getc() returns EOF with errno == EINTR. 2006-01-06 22:20:07 +00:00
Wayne Davison
b74b3d538e + Changed two buffers to use BIGPATHBUFLEN instead of MAXPATHLEN+512.
+ Changed a strncpy() call into a (more appropriate) memcpy() call.
+ Made the ellipsis[] string static because some older compilers may
  not like the dynamic initialization of a character string.
+ Expanded some 1-line "case ... break;" statements onto separate
  lines.
2006-01-05 02:29:16 +00:00
Wayne Davison
d3db3eef1b Document the new "dir/***" feature. 2006-01-02 17:46:32 +00:00
Wayne Davison
90d5b12e72 Added a test for the new "dir/***" feature. 2006-01-02 17:46:27 +00:00
Wayne Davison
955a3a3ded We now test all the patterns using both a normal wildtest run and
a wildtest run with various -x and -e options.
2006-01-02 17:46:24 +00:00
Wayne Davison
aec75b037b Added -x and -e options, which are used to exercise wildmatch_array(). 2006-01-02 17:46:21 +00:00
Wayne Davison
e5daa2731a We use the new wildmatch_array() and litmatch_array() functions to
make our include/exclude code easier to read and maintain, and to
eliminate a buffer copy when handling an absolute-path pattern
(which eliminated the full_name[] buffer).  Also added handling
for the new MATCHFLG_WILD3_SUFFIX define that allows a string that
ends with "dir/***" to match the "dir" as well as its contents.
2006-01-02 17:46:18 +00:00
Wayne Davison
390621a7ab Added a new function, wildmatch_array(), that lets the caller pass
the text-string as an array of strings (with a terminating NULL
pointer at the end).  Also added litmatch_array(), which does a
literal match (no wildcards or special chars) against an array of
strings.
2006-01-02 17:46:15 +00:00
Wayne Davison
478bb47c40 The latest prototypes. 2006-01-02 17:46:12 +00:00
Wayne Davison
685517abd1 Added MATCHFLG_WILD3_SUFFIX define, shuffling a few others to put
it in a nice spot.
2006-01-02 17:46:09 +00:00
Wayne Davison
515afe7cf1 Mention dont-compress fix. 2005-12-30 07:24:17 +00:00
Wayne Davison
ec497df1a0 Optimized set_compression() to remove the per-file strdup(), strlower(),
and free() calls (it now uses iwildmatch()).
2005-12-30 07:19:16 +00:00
Wayne Davison
8e74463643 - Added a new public function, iwildmatch(), which will treat all
upper-case letters in the "text" as lower-case.
- Renamed variable "ch" -> "p_ch" and "prev" -> "prev_ch".
- Added variable "t_ch" to hold the current *text value.
- Return ABORT_ALL if we reach the end of the text string with
  more pattern to match.
2005-12-30 07:12:48 +00:00
Wayne Davison
933d1dfd0f Added a prototype for iwildmatch(). 2005-12-30 07:09:34 +00:00
Wayne Davison
0fe987e226 Fixed a bug in set_compression() where the default dont-compress
patterns (e.g. *.gz) would not match a pathname containing a slash.
2005-12-30 06:03:40 +00:00
Wayne Davison
770de8994e - Renamed match_start -> anchored_match.
- Twiddled one comment and added another.
- Twiddled the placement of two else statements.
2005-12-24 08:00:12 +00:00
Wayne Davison
37cf7b4191 Improved the usage info in the opening comment. 2005-12-19 16:57:55 +00:00
Wayne Davison
1a3ef40da9 A few extra directory-style matching tests. 2005-12-19 02:30:59 +00:00
Wayne Davison
0314302e9c Added an anchored exclude to a filter file. 2005-12-19 02:23:57 +00:00
Wayne Davison
9639c71842 + Put --existing back in the main option summary.
+ Improved the discussion of wildcard characters.
2005-12-19 02:18:16 +00:00
Wayne Davison
d2da915cd0 Made --existing the main option, with --ignore-non-existing
as its alias.
2005-12-19 01:59:00 +00:00
Wayne Davison
e725abcf4e Added a comment, improved a comment, tweaked the recursive function's
name, tweaked the arg names to wildmatch(), and tweaked the style of
the "else" statements when they follow a brace.
2005-12-18 19:40:50 +00:00
Wayne Davison
de01941274 Tweaked the name of the first arg to wildmatch(). 2005-12-18 19:38:47 +00:00
Wayne Davison
d802ea54da Fixed one config-file reference that was misspelled. 2005-12-18 15:48:00 +00:00
Wayne Davison
c81a20fb7a Tweaked the debug output for cvs_filter_list and server_filter_list. 2005-12-17 21:03:25 +00:00
Wayne Davison
6bf32edb8c Return RERR_SIGNAL1 from sigusr1_handler(). 2005-12-16 23:48:34 +00:00
Wayne Davison
4a50a2176e Added RERR_SIGNAL1's message and tweaked ERR_SIGNAL. 2005-12-16 23:48:31 +00:00
Wayne Davison
9e90555fd1 Added RERR_SIGNAL1 to separate SIGUSR1 from the rest of the
signals that return RERR_SIGNAL.
2005-12-16 23:48:28 +00:00
Wayne Davison
2067ec7342 Mentioned the auto-protect rule for --backup. 2005-12-16 17:20:22 +00:00
Wayne Davison
c2c5682c0b If the user specifies --backup with --delete (but without --backup-dir
and --delete-excluded), append a protect-filter rule onto the list of
filter rules.  We run this on both the client and server side so that
an older client talking to a newer server still gets the protection
rule.  (This rule will not cause compatibility problems with older
versions of rsync due to the graceful way that a protect rule turns
into an exclude rule if it needs to be sent to an older server.)
2005-12-16 17:18:29 +00:00
Wayne Davison
4c72f27dd9 Document the new auto-added protect filter-rule when using --backup
with --delete (but without --backup-dir and --delete-excluded).
2005-12-16 17:18:26 +00:00
Wayne Davison
36d8d1a626 - Added a comment about configure figuring out the default user
and group to use in daemon mode.
- Belatedly updated the version of popt that comes with rsync.
- Updated the Mac OS X info.
2005-12-16 16:57:26 +00:00
Wayne Davison
3447d61048 Fixed a bug in the hard-linking of a group of fifos/devices in a
transfer where the leader got hard-linked to a --link-dest item.
2005-12-16 04:02:54 +00:00
Wayne Davison
a3887c2644 Improved the RERR_SIGNAL message to include all possible signals. 2005-12-16 00:18:41 +00:00
Wayne Davison
8a1f3153b9 Mention the improvements in the comare-dest/link-dest/copy-dest handling. 2005-12-15 23:00:23 +00:00
Wayne Davison
165dd4a636 Improved the tests we run to test more output variations and to work
with the new way link-dest handles symlinks.
2005-12-15 23:00:05 +00:00
Wayne Davison
541b23d144 When compare-dest/link-dest/copy-dest are in effect, we now check
if the file we're about to hard-link to the leader is present in
one of the dest dirs -- if it is, we adjust the text we output
accordingly.
2005-12-15 23:00:02 +00:00
Wayne Davison
7987ece7cc The ITEM_NO_DEST_AND_NO_UPDATE define is no longer needed. 2005-12-15 22:59:59 +00:00
Wayne Davison
48224e4c43 Improved the compare-dest/link-dest/copy-dest code to make it more
readable, to make it output properly in double-verbose mode, and
to allow the hard-linking of symlinks and devices (if supported by
the OS).
2005-12-15 22:59:56 +00:00
Wayne Davison
6d4ecad122 - Eliminate an all-dot itemization for a locally-copied file.
- Got rid of some redundant output in maybe_log_item().
2005-12-15 22:59:53 +00:00
Wayne Davison
1578919c37 Improved an old bullet point. 2005-12-15 21:23:44 +00:00
Wayne Davison
10a1d6b4a0 Use AC_SEARCH_LIBS() instead of AC_CHECK_LIB() to figure out if
we need to include libresolv or not.
2005-12-14 22:54:54 +00:00
Wayne Davison
2b7e12924d Mention that the MD4 password protection is weaker than
previously thought.
2005-12-14 22:14:26 +00:00
Wayne Davison
82f0c63e8a Parse single- and double-quotes in the --rsh/-e option (and RSYNC_RSH). 2005-12-14 22:00:01 +00:00
Wayne Davison
5d9530fe47 Mention new quote-parsing for the --rsh/-e and RSYNC_RSH handling. 2005-12-14 21:59:11 +00:00
Wayne Davison
37f35d89d1 Made msg_list_push() static and renamed it to msg_list_flush(). 2005-12-08 21:19:22 +00:00
Wayne Davison
08c88178aa Tweaked the msg_list code so that the head and tail pointers
are contained by a structure.
2005-12-08 21:01:38 +00:00
Wayne Davison
0fb2fc4a1d Fixed a typo in a comment. 2005-12-08 16:12:25 +00:00
Wayne Davison
da2d13e3ce Improved/fixed some of the entries. 2005-11-29 15:53:18 +00:00
Wayne Davison
64318670a8 Improved the description of how --delay-updates chooses it's dir. 2005-11-16 16:12:04 +00:00
Wayne Davison
3c19f72c16 Made the parsing in parse_size_arg() a little more strict. 2005-11-15 17:49:59 +00:00
Wayne Davison
8938d67ef8 Fixed a typo in the --help output for --no-OPTION. 2005-11-15 07:05:55 +00:00
Wayne Davison
05724c07cf Changed -h to be an alias for --human-readable (getting rid of -m).
Also added backward-compatibility code so that "rsync -h" shows the
help page on stdout like it would in older versions.
2005-11-15 06:35:27 +00:00
Wayne Davison
955c3145c3 Document the change in the -h option. 2005-11-15 06:35:22 +00:00
Wayne Davison
8ea17b5098 Twiddled some brace positions and removed a superfluous ';' in a macro. 2005-11-14 21:24:30 +00:00
Wayne Davison
b20fe0e6ac Improved an error message. 2005-11-13 17:15:00 +00:00
Wayne Davison
24787acd08 Moved the DEL_* flags into generator.c. 2005-11-12 20:30:40 +00:00
Wayne Davison
d71dad3bd3 Moved the DEL_* flags from rsync.h here and got rid of DEL_NO_RECURSE. 2005-11-12 20:30:36 +00:00
Wayne Davison
889439c205 Mention the latest options. 2005-11-12 20:08:10 +00:00
Wayne Davison
bee9df73c1 Changed the parsing of suffixes for --min-size and --max-size a little. 2005-11-12 20:08:00 +00:00
Wayne Davison
60613dc896 Output the stats and the end-of-run verbose output using the new
human_num() and human_dnum() functions, which both honor the
new --human-readable option.
2005-11-12 19:53:26 +00:00
Wayne Davison
e175fb07f7 Added two new functions: human_num() and human_dnum(), which
output numbers in human-readable units if the --human-readable
option was specified.
2005-11-12 19:53:23 +00:00
Wayne Davison
4a70af6f81 Added the human_readable variable (for linking with util.o). 2005-11-12 19:53:20 +00:00
Wayne Davison
8f14cc496b Parse the new --human-readable (-m) option. 2005-11-12 19:53:17 +00:00
Wayne Davison
3b4ecc6b80 Document the new --human-readable (-m) option. 2005-11-12 19:53:12 +00:00
Wayne Davison
a7e60f0c59 Only call cleanup_set() if keep_partial is set. 2005-11-10 16:57:30 +00:00
Wayne Davison
3d7cc5710d If cleanup_set() gets passed a NULL fnametmp or fname, set
cleanup_fname to NULL.
2005-11-10 16:56:32 +00:00
Wayne Davison
86fc7e6880 Got rid of a superfluous newline. 2005-11-10 16:47:52 +00:00
Wayne Davison
acee11fc60 - Indent the "oom:" label away from column 0.
- Got rid of a superfluous newline.
2005-11-10 16:47:27 +00:00
Wayne Davison
b2e7c91313 Indent the "prepare_to_open:" and "notify_others:" labels away
from column 0.
2005-11-10 16:47:03 +00:00
Wayne Davison
97b7bff4d6 - Got rid of a superfluous empty line.
- Indent the "oom:" and "skip_filters:" labels away from column 0.
2005-11-10 16:45:00 +00:00
Wayne Davison
e16ca9ef31 Got rid of a superfluous empty line. 2005-11-10 16:44:06 +00:00
Wayne Davison
b2e6caa01e Indent the "failure:" label away from column 0. 2005-11-10 16:43:44 +00:00
Wayne Davison
2997e9f769 Indent the "oom:" label away from column 0. 2005-11-10 16:42:46 +00:00
Wayne Davison
2374023982 Mention the big improvement when --delete and --checksum were
specified.
2005-11-10 06:43:10 +00:00
Wayne Davison
902f03d101 In make_file(), only compute the checksum when we're the sender.
This stops computing useless checksums during the delete scan
when --checksum (-c) was specified.
2005-11-10 06:01:55 +00:00
Wayne Davison
cfe3978049 Use the new checksum_len value instead of recomputing the
right value for the current protocol_version over and over.
2005-11-10 03:07:18 +00:00
Wayne Davison
7752df41b7 Compute the right checksum length for the current protocol_version
only once instead of over and over again.
2005-11-10 03:00:38 +00:00
Wayne Davison
d8b108c2a1 If a partial-dir file is present but the main file is up-to-date,
just remove the partial-dir file.
2005-11-10 02:56:58 +00:00
Wayne Davison
184dd27a18 Call delete_in_dir(NULL, NULL, NULL) in do_delete_pass(). 2005-11-09 19:46:42 +00:00
Wayne Davison
0e5665d3ab Made recursively deleting extraneous directories more memory
efficient by removing the need for a MAXPATHLEN buffer on the
stack of delete_item().
2005-11-09 19:39:46 +00:00
Wayne Davison
ef3bb69ad8 Mention the new --chmod option. 2005-11-07 04:47:06 +00:00
Wayne Davison
45d41d08bd Test the --chmod option. 2005-11-07 04:28:52 +00:00
Wayne Davison
dd32e2c3d4 Added support for the new --chmod option. 2005-11-07 04:28:35 +00:00
Wayne Davison
2b7e0f33a6 Call tweak_mode() on regular files and dirs if --chmod was specified. 2005-11-07 04:28:32 +00:00
Wayne Davison
0582cdae8d Added chmod.o to OBJS2. 2005-11-07 04:28:29 +00:00
Wayne Davison
9e8ea423e2 Document the new --chmod option. 2005-11-07 04:28:23 +00:00
Wayne Davison
0c983c1fd4 New --chmod support routines. 2005-11-07 04:23:22 +00:00
Wayne Davison
3381ffa6ea Fixed a sign error in the output. 2005-11-03 19:55:30 +00:00
Wayne Davison
3b15340966 Mention the change in the output of --progress. 2005-11-03 19:46:45 +00:00
Wayne Davison
91683c434b Make the just-updated file-count status even less cryptic. 2005-11-03 19:45:59 +00:00
Wayne Davison
9e7530c414 Improved the output of the transferred-file count and the position
in the flist (which was changed to a countdown of files to check)
so that it's clearer what the numbers mean.
2005-11-03 19:38:14 +00:00
Wayne Davison
8fd30fc43c Got rid of some early-checksum code that accidentally got committed. 2005-11-02 07:22:02 +00:00
Wayne Davison
b1b04fcdd4 Mention lower stack requiements for recursion. 2005-11-01 20:13:20 +00:00
Wayne Davison
56f0c976be Decreased the amount of stack needed for each level of directory
recursion by eliminating the need for a MAXPATHLEN buffer in
send_if_directory().  Also improved a few variable names in
send_file_list().
2005-11-01 20:09:41 +00:00
Wayne Davison
9aacb4df0e Fixed a typo pointed out by Peter Strazovec. 2005-10-30 22:29:59 +00:00
Wayne Davison
0fdb1aa8ff In the device section, avoid calling unlink() if the stat() failed. 2005-10-30 22:28:11 +00:00
Wayne Davison
bad0110609 Document the new --compress-level option. 2005-10-26 16:48:44 +00:00
Wayne Davison
3cc185a088 Handle new def_compress_level setting. 2005-10-26 16:48:07 +00:00
Wayne Davison
e8a8167ad9 Obey new def_compress_level setting. 2005-10-26 16:47:49 +00:00
Wayne Davison
854a1aad35 Added --compress-level option. 2005-10-26 16:47:15 +00:00
Wayne Davison
84e6d6fdcd - Changed the "status" variables into "exit_code" variables.
- Added an error message to wait_process_with_flush() that
  reports the errno we get when waitpid() fails.
- Increased the value of MAXCHILDPROCS.
2005-10-26 15:53:04 +00:00
Wayne Davison
f14a65d94c Tweaked the error message for RERR_WAITCHILD. 2005-10-26 15:50:14 +00:00
Wayne Davison
37439b36e7 Updated the docs for pre-/post-xfer exec. 2005-10-24 21:03:53 +00:00
Wayne Davison
c95ca2a228 Enhanced the "pre-xfer exec" handling so that it gets the user's
request info and puts that into the environment as RSYNC_REQUEST.
2005-10-24 21:03:50 +00:00
Wayne Davison
97d8e7095f Changed wait_process() into a simpler, yet more versatile function,
and used it in the new wait_process_with_flush() function (the old
function's new name).  Made wait_process() public.
2005-10-24 21:03:47 +00:00
Wayne Davison
20c1926a01 Fixed a typo in a comment. 2005-10-20 18:30:33 +00:00
Wayne Davison
d030233def Get rid of some superfluous empty lines. 2005-10-19 07:49:10 +00:00
Wayne Davison
35812ea1f9 One extra tweak to the just-committed code. 2005-10-15 19:15:29 +00:00
Wayne Davison
d649b78920 Added relative_paths extern. 2005-10-15 19:11:36 +00:00
Wayne Davison
7e43da819e If we're sanitizing paths with --relative enabled, we need to
preserve the first /./ dir so that we can use its position to
trim the implied directories.
2005-10-15 19:08:31 +00:00
Wayne Davison
40aaa571b4 Document --ignore-non-existing (not --existing) and what happens
if the option is combined with --ignore-existing.
2005-10-15 16:39:31 +00:00
Wayne Davison
470319d33b Changed the --help text to mention --ignore-non-existing
instead of --existing.
2005-10-15 16:38:35 +00:00
Wayne Davison
1db954e9bc Made parse_size_arg()'s parsing a little stricter. 2005-10-15 06:53:04 +00:00
Wayne Davison
d697314b42 Mention --min-size/--max-size changes. 2005-10-14 20:40:31 +00:00
Wayne Davison
59dd678603 Documented --min-size. 2005-10-14 20:16:21 +00:00
Wayne Davison
02b5cb238b Added code to implement the --min-size logic. 2005-10-14 20:16:09 +00:00
Wayne Davison
74de13d19c Added handling of the --min-size option. 2005-10-14 20:15:18 +00:00
Wayne Davison
837d01dd5a Improved parse_size_arg() a little more. 2005-10-14 19:48:34 +00:00
Wayne Davison
926d86d1f9 Document the extended parsing of --max-size values. 2005-10-14 19:03:05 +00:00
Wayne Davison
aeb213ea0c Improved parse_size_arg() so that it can be told to use powers of
ten instead of binary K/M/G powers, and so that it can be told to
add or subtract one from the result.  We also make sure to pass
the arg to --max-size in a compatible manner with older versions.
2005-10-14 18:56:07 +00:00
Wayne Davison
7c6ea3d8c7 Fixed a typo in an option name. 2005-10-12 23:59:00 +00:00
Wayne Davison
d409c6ac9c Mention va_copy change. 2005-10-11 20:21:56 +00:00
Wayne Davison
92f0b9d6ab If va_copy is defined, use it when defining VA_COPY. 2005-10-11 20:21:03 +00:00
Wayne Davison
2c8c8bbaad Pass XFLG_ABS_IF_SLASH instead of XFLG_ANCHORED2ABS for server excludes. 2005-10-07 18:40:30 +00:00
Wayne Davison
4fc8140a60 Support new XFLG_ABS_IF_SLASH flag. 2005-10-07 18:39:40 +00:00
Wayne Davison
699f7024f1 Added XFLG_ABS_IF_SLASH. 2005-10-07 18:38:25 +00:00
Wayne Davison
ce0da32a9c Mention recent changes. 2005-10-07 18:24:35 +00:00
Wayne Davison
82360c6b17 Clarify how the fitler rule "-/" works. 2005-10-07 18:18:16 +00:00
Wayne Davison
493568465b Improved the usage comments. 2005-10-04 04:12:28 +00:00
Wayne Davison
bf485d3d6b A simple filter script to output messages from a single module. 2005-10-03 18:40:59 +00:00
Wayne Davison
e90aab4982 Changed the variable names for --existing and --ignore-existing. 2005-09-29 18:07:55 +00:00
Wayne Davison
550d4e2346 Reverted one xfer_dirs change from the last commit that should not
have gone in.
2005-09-29 17:27:11 +00:00
Wayne Davison
991daf008d Keeping silent about stat() errors is never a good idea -- it hides
files that are not up-to-date.
2005-09-29 17:07:45 +00:00
Wayne Davison
505ada146c Mention that --delete now works with --dirs. 2005-09-29 08:15:34 +00:00
Wayne Davison
75c51953f1 - When --dirs is specified w/o --recursive, avoid marking solo dirs
with the XMIT_TOP_DIR flag.
- Only set in_del_hier if --recursive is enabled.
2005-09-29 07:48:05 +00:00
Wayne Davison
8d6c1c4e97 Allow deletions to occur in directories transferred with the
--dirs option in addition to the regular --recursive behavior.
2005-09-29 07:41:50 +00:00
Wayne Davison
10a1a3f511 Fixed a poorly-worded sentence and a misspelled word. 2005-09-29 07:37:00 +00:00
Wayne Davison
40e6752fba Some systems don't define WCOREDUMP(), so #ifdef that code. 2005-09-26 17:41:14 +00:00
Wayne Davison
dbefb6b4e4 Fixed wait_process() to handle cases where waitpid() fails or
the child process did not exit cleanly.
2005-09-26 17:12:13 +00:00
Wayne Davison
6016841086 Changed RERR_CRASH to RERR_CRASHED. 2005-09-26 17:11:03 +00:00
Wayne Davison
0047f535ef Handle new RERR_CRASH AND RERR_TERMINATED exit codes. 2005-09-26 17:07:50 +00:00
Wayne Davison
90eca40d27 Defined RERR_CRASH and RERR_TERMINATED. 2005-09-26 17:06:33 +00:00
Wayne Davison
0417c34e2d Mention some chanages in the patches dir. 2005-09-26 04:47:25 +00:00
Wayne Davison
d64c2b226a Use AC_HELP_STRING() in the two AC_ARG_WITH() macros that used a
hard-wired string.
2005-09-24 17:17:30 +00:00
Wayne Davison
868676dc15 Reordered the usage lines to cover push, then pull (which has a
better visible pattern than covering push & pull for each host-type).
2005-09-21 22:39:49 +00:00
Wayne Davison
e31058d41e Cast some time values to (int), just to silence some warnings on
Stratus VOS.
2005-09-21 17:42:15 +00:00
Wayne Davison
ea8291d8f7 Include limits.h (if it exists), which defines NAME_MAX on some
systems.
2005-09-21 17:38:44 +00:00
Wayne Davison
1348267518 If we get less data than expected from a read() in map_ptr(), we
need to try to keep reading to see if we get an error or more data.
2005-09-21 17:37:41 +00:00
Wayne Davison
f0323d68eb Check for limits.h. 2005-09-21 17:35:51 +00:00
Wayne Davison
12a01be14f Tweaked the output that the mknod() tests generate. 2005-09-21 17:15:58 +00:00
Wayne Davison
e0a18ce3f7 Tweaked some comments. 2005-09-19 17:21:00 +00:00
Wayne Davison
8ad5cea371 Changed one strcpy() into a strlcpy(). 2005-09-17 21:49:24 +00:00
Wayne Davison
9059e0ac2f Improved the sDefault initialization so that the prefixed
comments exactly match the variable names (making sure that
they will sort exactly the same way as the variables).
2005-09-16 20:35:05 +00:00
Wayne Davison
29fad7a3d8 Got rid of some old command-line parsing code that was only
useful when talking to a 1.x client.
2005-09-16 16:40:30 +00:00
Wayne Davison
02efda9f01 Mention '!' fix. 2005-09-16 16:14:24 +00:00
Wayne Davison
35a388b141 Really fix '!' in a .cvsignore file this time. 2005-09-16 16:10:01 +00:00
Wayne Davison
9a4a237ede Tweaked the code a little in the always_checksum handling of the
send & receive file-list functions.
2005-09-16 05:52:54 +00:00
Wayne Davison
5efbddbadb Mention that the dir used with --delay-updates cannot be on a
different filesystem from the destination files.
2005-09-15 22:27:14 +00:00
Wayne Davison
6a94c58b00 Added a comment. 2005-09-15 22:25:55 +00:00
Wayne Davison
e3f8395360 Mention doc changes. 2005-09-15 17:19:30 +00:00
Wayne Davison
f2b4c0840e Removed conflicting ssh citation in the SETUP section. 2005-09-15 15:36:27 +00:00
Wayne Davison
08d82b84cb The --help text was outputting some incomplete information on how
SRC is expanded or word-split, so I removed that text and replaced
it with an explaination of how ':' differs from '::' & 'rsync://'.
2005-09-13 01:02:54 +00:00
Wayne Davison
fbe57fdc95 Mention the latest fix. 2005-09-09 17:07:39 +00:00
Wayne Davison
92cdc39372 When pop_dir(olddir) fails, pass the right string pointer
in the error message.
2005-09-09 16:17:01 +00:00
Wayne Davison
78be8e0fc9 Improved the -F, --exclude-from, and --include-from sections. 2005-09-09 07:27:25 +00:00
Wayne Davison
a5b786d80f Tweaked the calculation that goes into sum->count so that it cannot
overflow into a negative value (which is particularly important if
configure didn't find a real int64 type).
2005-09-06 18:12:38 +00:00
Wayne Davison
f853b777be Complicate the lseek64() function prototype because some systems
don't have off64_t.
2005-09-03 16:56:53 +00:00
Wayne Davison
fed1f3f4fe Make use of the per-module "temp dir" setting. 2005-09-03 16:50:20 +00:00
Wayne Davison
18cad44967 Added a per-module "temp dir" setting. 2005-09-03 16:24:23 +00:00
Wayne Davison
d17c9a4486 Sorted some of the data structures (using vim's "!sort" command
makes it easy).
2005-09-03 16:22:06 +00:00
Wayne Davison
b6e22a47d3 - Allow --no-v and --no-verbose in the daemon options.
- If a too-long --temp-dir is specified when starting a daemon,
  omplain to the daemon-starting user, not later to the client.
2005-08-30 16:13:54 +00:00
Wayne Davison
ec69bdbd64 Mention latest changes. 2005-08-30 05:12:49 +00:00
Wayne Davison
a8cbb57c9b Mention how --inplace conflicts with --sparse and how --append
does not.
2005-08-30 05:10:51 +00:00
Wayne Davison
b8cc35874e Allow --temp-dir to be specified with --daemon to set the default. 2005-08-30 05:00:56 +00:00
Wayne Davison
c3851185f3 Fixed a comment. 2005-08-30 02:59:30 +00:00
Wayne Davison
e7ee91defc When --append is entering the redo phase, make sure that
sparse_files is disabled (because it conflicts with an
inplace update).
2005-08-30 02:58:42 +00:00
Wayne Davison
cfce9f6dc3 Reject attempts to combine --sparse with --inplace. 2005-08-30 02:57:19 +00:00
Wayne Davison
4afcb709a7 Forgot the --no-v option. 2005-08-28 00:43:51 +00:00
Wayne Davison
a912a980ec Mention the new --no-* options. 2005-08-28 00:34:46 +00:00
Wayne Davison
2c64b25827 A small improvement to the daemon-connecting instructions. 2005-08-28 00:25:44 +00:00
Wayne Davison
38b9170c52 One more tweak to the option data. 2005-08-27 21:12:44 +00:00
Wayne Davison
f40aa6fb07 Documented the new --no-* options. 2005-08-27 21:07:27 +00:00
Wayne Davison
b616493883 Added the ability to prefix "no-" to various options, which gives the
user an easy way to override implied option switches.
2005-08-27 21:01:45 +00:00
Wayne Davison
e86e2fa173 A little more reordering of the option data. 2005-08-27 20:43:35 +00:00
Wayne Davison
11bfaf6351 Reordered some of the option data to make their grouping more logical. 2005-08-27 20:01:45 +00:00
Wayne Davison
d37d1c44ff Make the --append docs a little better. 2005-08-20 17:21:06 +00:00
Wayne Davison
c89330313e Moved a variable in glob_expand_one(). 2005-08-03 04:51:29 +00:00
Wayne Davison
c9dc1300ba Got rid of the argp var that is not needed now that argv is no
longer a literal array.
2005-08-03 04:42:56 +00:00
Wayne Davison
53cf0b8bfb Improved the --relative section a little more. 2005-08-03 01:13:15 +00:00
Wayne Davison
56961becc2 Mention the latest changes. 2005-08-01 22:18:11 +00:00
Wayne Davison
1dc42d123d Improved the --relative section, including mentioning the addition
of dot-dir path trimming.
2005-08-01 22:18:00 +00:00
Wayne Davison
d2ea5980ba Allow the user to specify a dot dir in the source path when
using --relative, making it trim the duplicated dirs.
2005-08-01 21:58:16 +00:00
Wayne Davison
15cf186b85 Don't recreate a device if just the permissions bits have changed
in the st_mode.
2005-08-01 04:09:58 +00:00
Wayne Davison
4fdb03a648 Mention hard-link fix. 2005-07-31 23:21:46 +00:00
Wayne Davison
8f5b554f0b Hard-link a device in order to test that this works properly. 2005-07-31 23:20:12 +00:00
Wayne Davison
8cd3db27b6 There is no longer a need to check file->link_u.links at the start
of hard_link_check() (because the caller has already checked it).
2005-07-31 23:19:42 +00:00
Wayne Davison
273a7ed59f Fixed the handling of hard-linked symlinks and devices. 2005-07-31 23:18:28 +00:00
Wayne Davison
23deb0bcee Export RUNSHFLAGS. 2005-07-31 23:15:38 +00:00
Wayne Davison
7ea7bebf6b Mention the --inplace new-file permissions fix. 2005-07-30 16:17:21 +00:00
Wayne Davison
97894c6473 - The combination of --update and --progress now outputs progress
information during the checksum scan of the already-sent data.
- When --inplace creates a file, give it 0600 permissions, not 0000.
2005-07-30 16:14:22 +00:00
Wayne Davison
1f86fcf5dc The combination of --update and --progress now outputs progress
information during the checksum scan of the already-sent data.
2005-07-30 16:13:19 +00:00
Wayne Davison
bb9bdba4c9 Improved the text around the last example in the USAGE section. 2005-07-29 19:52:50 +00:00
Wayne Davison
5b9cc6953a Mention the latest changes. 2005-07-29 18:48:58 +00:00
Wayne Davison
33544bf422 - Use BIGPATHBUFLEN for the length of several buffers.
- If io_printf() tries to overflow the buffer, die with
  an error instead of sending a truncated buffer.
2005-07-29 18:31:12 +00:00
Wayne Davison
20accf4d06 - Use BIGPATHBUFLEN for the length of two line buffers.
- Improved the handling of the start_glob variable.
- Made the line buffer in start_daemon() a little bigger.
2005-07-29 18:31:10 +00:00
Wayne Davison
3fac51e21e Use BIGPATHBUFLEN for the length of two line buffers. 2005-07-29 18:31:07 +00:00
Wayne Davison
d999d312c4 Use BIGPATHBUFLEN for the length of a line buffer. 2005-07-29 18:31:05 +00:00
Wayne Davison
a22ca88565 Define BIGPATHBUFLEN -- a roomy line-buffer that can hold a
MAXPATHLEN string plus a message, and it's at least 4096+1024
bytes for those systems where MAXPATHLEN is overly short.
2005-07-29 18:31:03 +00:00
Wayne Davison
9ec8bd87bb Updated to match 2.6.6 release (which occurred on a branch). 2005-07-28 20:00:43 +00:00
Wayne Davison
f11ece28ff Changed the version to 2.6.7cvs. 2005-07-28 19:49:47 +00:00
Wayne Davison
f90f71498e Updated to reflect new 2.6.7cvs status. 2005-07-28 19:49:24 +00:00
Wayne Davison
32199c6b00 Removed a duplicated item. 2005-07-28 18:17:56 +00:00
Wayne Davison
870dddc5eb Mention the recent changes. 2005-07-28 17:42:56 +00:00
Wayne Davison
9d0d18b590 If the user has specified "pre-xfer exec" or "post-xfer exec", run
the indicated command(s), each at the appropriate time.
2005-07-28 17:15:47 +00:00
Wayne Davison
bec617b934 Added 2 new config options: "pre-xfer exec" and "post-xfer exec". 2005-07-28 17:15:44 +00:00
Wayne Davison
c20936b88b Document the new pre-/post-xfer exec config options. 2005-07-28 17:15:42 +00:00
Wayne Davison
0869881764 Regenerated. 2005-07-28 16:58:04 +00:00
Wayne Davison
a840b5c736 Removed one more client-oriented command-line syntax sentence. 2005-07-28 09:40:08 +00:00
Wayne Davison
2907884f94 Removed erroneous section on using daemon features over a
remote-shell connection -- client-use is better described in the
rsync manpage, and the advanced restricted-ssh section needs a
better treatment (perhaps as a support script).
2005-07-28 09:36:12 +00:00
Wayne Davison
754a080ffc Improved the sections dicussing the various types of transfer
connections and how a normal transfer differs from a daemon
transfer.
2005-07-28 09:18:20 +00:00
Wayne Davison
94f20a9f45 Document new --append option. 2005-07-28 01:46:16 +00:00
Wayne Davison
6cc1198288 Support new --append option. 2005-07-28 01:46:12 +00:00
Wayne Davison
a015788d21 Added the --append option. 2005-07-28 01:46:09 +00:00
Wayne Davison
c8d3465726 - Call set_modtime() with its new mode arg.
- Don't mask the mode bits being sent to do_chmod().
- Don't skip calling set_modtime() or do_chmod() when the item
  is a symlink.
2005-07-27 23:30:58 +00:00
Wayne Davison
00b9618460 - Fixed the mode comparison in itemize() to mask off the bits
outside of the CHMOD_BITS mask.
- Don't call do_chmod() unless HAVE_CHMOD is defined.
- Don't mask the mode bits being sent to do_chmod().
2005-07-27 23:30:55 +00:00
Wayne Davison
d11f5c6e2b - Don't call do_chmod() unless HAVE_CHMOD is defined.
- Made do_chmod() handle symlinks or return 1 if not possible.
- We now mask off the mode bits in do_chmod() sing CHMOD_BITS.
2005-07-27 23:30:53 +00:00
Wayne Davison
25007999df - Changed set_modtime() to take the file's mode as an arg.
- Made set_modtime() handle symlinks or return 1 if not possible.
2005-07-27 23:30:51 +00:00
Wayne Davison
8ce6546310 Check for the lchmod() and lutimes() functions. 2005-07-27 23:18:28 +00:00
Wayne Davison
151f59f155 Tweaked a comment and some null-char assignments. 2005-07-22 19:09:45 +00:00
Wayne Davison
89f2a4c231 Changed implied_dirs to only be non-0 if relative_paths is non-0. 2005-07-22 19:05:25 +00:00
Wayne Davison
496be30db6 Got rid of some unused externs. 2005-07-22 17:59:21 +00:00
Wayne Davison
cd426074e1 Updated to zlib 1.2.3. 2005-07-22 15:54:43 +00:00
Wayne Davison
3f7bfac2a0 Avoid newest test when no destination was specified. 2005-07-15 19:10:03 +00:00
Wayne Davison
9425918d74 Output a syntax error if both the source and destination are remote. 2005-07-15 19:06:43 +00:00
Wayne Davison
cc637fcc51 Preparing for release of 2.6.6pre1 2005-07-07 22:53:59 +00:00
Wayne Davison
9db1743490 Mentioned the zlib changes and tweaked a couple sentences. 2005-07-07 22:50:12 +00:00
Wayne Davison
ba3542cfcb - Attempt to make the discussion of host-specifying args less confusing.
- Fixed the names of the uid and gid daemon options in a sentence.
2005-07-07 21:33:40 +00:00
Wayne Davison
81f5b275db Changes for new zlib. 2005-07-07 21:29:57 +00:00
Wayne Davison
f3ee726894 Fixed a typo. 2005-07-07 21:19:14 +00:00
Wayne Davison
b5be9e6c5f Fix latest zlib security exploit (CAN-2005-2096). 2005-07-07 21:14:29 +00:00
Wayne Davison
1e1cf68934 Upgraded to version 1.2.2. 2005-07-07 20:48:02 +00:00
Wayne Davison
4a2744cee3 One more "#undef BAD" for AIX. 2005-07-07 20:37:31 +00:00
Wayne Davison
12febd804f Use a define to handle conflicting function read_buf instead of
renaming it in the code.
2005-07-07 20:17:35 +00:00
Wayne Davison
687c6b14a0 Changed "Overflow" back to "overflow". 2005-07-07 20:16:41 +00:00
Wayne Davison
a1f99493b3 Changed overflow() to overflow_exit(). 2005-07-07 19:49:14 +00:00
Wayne Davison
9819f005b6 Changed zBAD back to BAD (with a simpler kluge for AIX). 2005-07-07 19:31:23 +00:00
Wayne Davison
2a6793bf1f Fixed some whitespace to match the original source. 2005-07-07 19:22:55 +00:00
Wayne Davison
bf287ee946 Got rid of bogus RCS keyword expansions (that create differences
between these files and the original zlib source).
2005-07-07 19:15:44 +00:00
Wayne Davison
b8b0668e85 Mention the EEXIST fix. 2005-06-30 17:18:30 +00:00
Wayne Davison
092906933b Ignore EEXIST on second mkdir() call. 2005-06-30 17:03:14 +00:00
Wayne Davison
e8432be95f Mention the latest time-comparing fixes. 2005-06-28 00:15:44 +00:00
Wayne Davison
6ff2f4ba67 Use cmp_modtime() in a couple more spots where a local modtime is
compared with a remote modtime.
2005-06-28 00:12:08 +00:00
Wayne Davison
309a5be873 Fixed test to work when objdir != srcdir (thanks to Art Haas). 2005-06-24 02:14:12 +00:00
Wayne Davison
26c87bb630 Changed the arg-splitting code so that it can handle a literal
backslash prior to whitespace without treating it as escaped
whitespace (e.g. if we receive "foo\\ bar", it is two args,
while "foo\ bar" and "foo\\\ bar" are each just one).
2005-06-23 15:58:57 +00:00
Wayne Davison
ea9b2add97 Tweaked a comment in the perl code we output. 2005-06-23 15:53:26 +00:00
Wayne Davison
301569f081 Improved a couple sentences. 2005-06-20 07:01:29 +00:00
Wayne Davison
b21456102a Changed the code to use the single long-option hash from cull_options. 2005-06-17 23:23:00 +00:00
Wayne Davison
b8a47c9bc6 - Fixed a bug where the --*-dest options weren't being culled.
- Simplified the output format by putting all the long-name
  options into a single hash.
2005-06-17 23:16:22 +00:00
Wayne Davison
85fbfa10a8 - Improved some comments (some taken from the new cull-options output).
- Made the user-config sections easier to find.
- Default to running a fully-specified rsync executable so that there
  are not PATH surprises.
- A few minor tweaks to the arg-checking code to make it clearer without
  actually changing its logic.
2005-06-17 16:48:02 +00:00
Wayne Davison
555bc0e31a Another readability improvement in the perl code we output. 2005-06-17 16:29:21 +00:00
Wayne Davison
ef1233cbb3 Improved some of the comments that are output into the perl code. 2005-06-17 16:12:05 +00:00
Wayne Davison
1524815ed3 - Make sure that the command contained the '.' arg at the end of the
options.
- Fixed the expanding of wildcards for a restriction of '/'.
2005-06-17 05:14:15 +00:00
Wayne Davison
985af7035e - Be restrictive on matching the --sender option so that the user
can't fool us into thinking we're the sender by using a filename
  of --sender (or similar ploy).
- Make sure that our '..' check can't be fooled by sly backslashing.
- Tweaked some comments.
2005-06-17 04:50:22 +00:00
Wayne Davison
b3181708f2 Output a leading comment and surrounding blank lines. 2005-06-17 04:46:02 +00:00
Wayne Davison
3f6c17cf14 Mention rrsync changes. 2005-06-17 01:26:33 +00:00
Wayne Davison
2e5a7629c0 If SUBDIR is specified as a non-absolute path, make it absolute. 2005-06-17 01:17:44 +00:00
Wayne Davison
70318468df - Made it easy to configure the path of the rsync executable.
- Fully parse all legal options that might come from a stock rsync and
  validate/restrict any option's args (previously we rejected options
  with args).
- Made it easy to disable specific options.
- Properly handle a multi-arg copy's multiple args.
- Make sure that the restricted dir actually exists and we can chdir
  to it.
- Just reject any dangerous args that have .. in them instead of trying
  to munge them.
- We don't treat single-or double-quotes specially, just backslash-
  escaped characters.
- Turn on strict mode.
- Use the array-arg version of exec() so that we don't spawn a shell.
- Use File::Glob to glob wildcards in args.
- Tweaked the log-file format so that it logs the modified command
  without any "OK" suffix.
2005-06-16 19:30:53 +00:00
Wayne Davison
782d109121 A developer-oriented script that outputs perl code for valid server
options.
2005-06-16 19:17:47 +00:00
Wayne Davison
30e7b0b28d Mention latest fix. 2005-06-12 06:10:14 +00:00
Wayne Davison
910ee8c92e In clean_flist(), fixed the setting of the flist->high value for an
empty list so that it can't cause a crash if it gets passed to
flist_find().
2005-06-12 06:07:23 +00:00
Wayne Davison
8af1bc9011 - Added a comment to the filter_outfile function.
- Twiddled where the calls to filter_outfile happen.
2005-06-10 23:36:57 +00:00
Wayne Davison
6a12f0d619 Simplified the regular expressions for sed due to problems on some
OSes.
2005-06-10 21:56:52 +00:00
Wayne Davison
4f3be36e30 - Put the output we're expecting into an rsync.chk file, for easier
debugging on failures.
- Added the function filter_outfile() and used it in place of the
  various output-filtering commands.
- Use the sed rules for filtering the combination of --itemized
  output with double-verbose output so that we're sure there's no
  superfluous lines being output (which the old grep filtering
  would have ignored).
2005-06-10 20:33:57 +00:00
Wayne Davison
fc9d64c947 Several expansions of $srcdir were not double-quoted. 2005-06-10 20:04:42 +00:00
Wayne Davison
db10766ab2 One expansion of $srcdir wasn't double-quoted. 2005-06-10 20:04:11 +00:00
Wayne Davison
a3dcb79085 One more instance of the umask kluge was needed. 2005-06-10 18:02:14 +00:00
Wayne Davison
20667b6d7f Mention backup change. 2005-06-10 17:58:39 +00:00
Wayne Davison
93e28fbd99 Fixed a problem in the backing up of symlinks and devices: we
need to remove any old symlink/device/file to create the backup.
Also fixed a couple minor logic errors in the handling of symlinks
and devices.  NOTE:  the code still doesn't handle the changing of
a name from a dir to a non-dir or visa versa (which is a very old
deficiency in the code).
2005-06-10 17:57:18 +00:00
Wayne Davison
87a57a3072 Use umask kluge from rsync.fns to try to get rid of a potential
permissions difference when copying symlinks.
2005-06-10 17:51:33 +00:00
Wayne Davison
bad1fa4476 Make the sed commands compatible with Solaris (hopefully). 2005-06-10 17:21:52 +00:00
Wayne Davison
8fe27e7631 Starting NEWS for 2.6.6. 2005-06-10 17:17:38 +00:00
Wayne Davison
a1c75ed05c Aged news from NEWS file. 2005-06-10 17:17:24 +00:00
Wayne Davison
e73ad2be54 Got rid of some potentially unhandled permissions differences. 2005-06-10 17:06:43 +00:00
Wayne Davison
59b0e7a82d Changed the "max verbosity" setting from global to per-module. 2005-06-10 16:57:43 +00:00
Wayne Davison
b4fc3987f2 Use the new NOBODY_USER and NOBODY_GROUP configure defines. 2005-06-10 16:50:09 +00:00
Wayne Davison
58418cb0c4 Added a simple check to see if the /etc/group file has the
group "nobody" or "nogroup".
2005-06-10 16:46:50 +00:00
Wayne Davison
5794112ad0 Test that our outputting of itemized messages (as well as
double-verbose output) is happening correctly.
2005-06-09 22:27:59 +00:00
Wayne Davison
f2b6fe44a6 - Fixed the overzealous outputting of unchanged hard-linked items
when verbose > 1.
- An unchanged hard-link with -i (log-format w/%i) now changes the
  trailing dots to spaces.
2005-06-09 22:27:22 +00:00
Wayne Davison
215b444cae Don't set ITEM_REPORT_TIME when a hard-linked file is already
linked up as it should be and --times was not enabled.
2005-06-09 21:57:45 +00:00
Wayne Davison
a45f581b2a - Never output the '"FOO" is a hard link' message when -i (%i)
output is enabled.
- Go back to outputting '"FOO" is a hard link' message when -i (%i)
  is not enabled and verbose > 1.
2005-06-09 21:56:11 +00:00
Wayne Davison
dfdd71ecff Updated version to 2.6.6cvs. 2005-06-09 21:18:26 +00:00
Wayne Davison
2dfe1c37ad Preparing for release of 2.6.5 2005-06-02 03:57:58 +00:00
Wayne Davison
b9949780f4 Improved a few of the items. 2005-06-02 03:54:00 +00:00
Wayne Davison
5fe857d4be One more configure item. 2005-06-01 16:21:41 +00:00
Wayne Davison
3d86c6b18f Mention HAVE_REMSH fix. 2005-05-31 06:09:42 +00:00
Wayne Davison
0f0b2e66b8 Simplified the last change a bit. 2005-05-27 18:15:18 +00:00
Wayne Davison
5d24ee71ad Test for various past problems with --relative. 2005-05-27 18:09:34 +00:00
Wayne Davison
3a05c5d3ce If we unduplicate '.', make sure we also copy FLAG_DEL_HERE (in
addition to FLAG_TOP_DIR), so that the unduplication of a real
dir and an implied dir (implied by --relative) works right.
2005-05-27 18:04:04 +00:00
Wayne Davison
89ec535af5 - Only define HAVE_REMSH if it is going to have a non-0 value.
- Got rid of ssh warning that was added for 2.6.0.
2005-05-27 16:41:19 +00:00
Wayne Davison
e96d7972c4 Improved the opening comment. 2005-05-26 18:00:09 +00:00
Wayne Davison
962a3f0b6e Mention the latest bug-fix. 2005-05-25 15:52:03 +00:00
Wayne Davison
cbb5fa4f07 Handle nested "." dirs (caused by --relative and a trailing slash or
a trailing "/.") in f_name_cmp() when dirname is not an identical
pointer.
2005-05-25 01:24:01 +00:00
Wayne Davison
b57907efb2 Mention the output change for a mount-dir when -x is used. 2005-05-22 20:53:18 +00:00
Wayne Davison
26beb7861f - Don't stop deleting in a dir if one item fails.
- Don't skip deleting in a dir if the initial rmdir fails
  (2.6.4 only continued if it was a non-empty error).
2005-05-22 20:52:32 +00:00
Wayne Davison
6e8b9f1341 Must check FLAG_MOUNT_POINT in delete_in_dir() to avoid starting a
descent into a mounted directory when -x is specified.
2005-05-22 17:19:16 +00:00
Wayne Davison
6efe94167f Improved the SYMBOLIC LINKS section, as suggested by John. 2005-05-20 17:57:31 +00:00
Wayne Davison
51cc96e469 Improved a --files-from example (as suggested by Paul). 2005-05-20 17:39:10 +00:00
Wayne Davison
bdedced84b Tweaked a sentence. 2005-05-19 22:16:50 +00:00
Wayne Davison
f497ad722d Preparing for release of 2.6.5pre2 2005-05-19 21:45:41 +00:00
Wayne Davison
339eb8943e Tweaked the opening comments. 2005-05-19 21:42:20 +00:00
Wayne Davison
c36864e40e Mentioned the improved keep-alive code. 2005-05-19 21:38:25 +00:00
Wayne Davison
af6155bb0e Clarifications related to --dirs. 2005-05-19 21:36:30 +00:00
Wayne Davison
605fed4b46 Periodically call maybe_send_keepalive() when timeouts are in effect
(this ensures that the receiver doesn't timeout when we're still
doing work reading data from the generator).
2005-05-19 08:52:24 +00:00
Wayne Davison
ac40b74788 The global allowed_lull is now already set, so just set lull_mod. 2005-05-19 08:52:22 +00:00
Wayne Davison
3e6ddb3738 - Call the new set_io_timeout() function to set the timeout value.
- If the user specified a shorter timeout than the config-file,
  don't override the shorter value.
2005-05-19 08:52:19 +00:00
Wayne Davison
9ac756c6ea - The variable allowed_lull is now our global.
- Tweaked the --timeout option handling to call set_io_timeout().
2005-05-19 08:52:17 +00:00
Wayne Davison
3b0a30eba8 - Added set_io_timeout(), which sets all the timeout-dependent
variables when the timeout value changes.
- Split last_io into last_io_in and last_io_out.
- Made select_timeout static.
2005-05-19 08:52:13 +00:00
Wayne Davison
bac7259081 The latest bug-fix. 2005-05-19 00:02:29 +00:00
Wayne Davison
4d474ad513 One place that was testing errno for ENOTEMPTY was failing to
also test for EEXIST (which is returned by some OSes).
2005-05-19 00:00:28 +00:00
Wayne Davison
e50e82ab40 Fixed a typo. 2005-05-18 23:59:12 +00:00
Wayne Davison
4922175589 Two more items. 2005-05-17 15:08:05 +00:00
Wayne Davison
a289f89fbe Treat a trailing ".." dir-name as if "../" had been specified so
that we don't use the name in the destination path and save files
into a higher destination directory.
2005-05-14 18:44:57 +00:00
Wayne Davison
ba64001df8 Mention the latest bug fix. 2005-05-13 23:03:00 +00:00
Wayne Davison
b225b089b8 Have do_delete_pass() immediately return if list_only is set. 2005-05-13 23:00:20 +00:00
Wayne Davison
557a35f55b If adding a trailing dot to a directory name overflows
MAXPATHLEN, die with an overflow error.
2005-05-13 22:02:24 +00:00
Wayne Davison
1848fd6fa1 An example filter script to maintain .cvsinclude files. 2005-05-13 18:37:11 +00:00
Wayne Davison
f2a4853c93 Improved the use of the "remaining" var in readfd_unbuffered() to
make certain that the static value is always set correctly anytime
we call out to another function.
2005-05-12 17:36:29 +00:00
Wayne Davison
e65154085c Got rid of some code from writefd_unbuffered() that was only needed
back when the generator had a writeable pipe to the receiver.
2005-05-12 07:45:21 +00:00
Wayne Davison
e4676bb59b Make the --stats output come out after any delete-after messages. 2005-05-12 07:43:14 +00:00
Wayne Davison
3b968014c9 Improved a few sentences. 2005-05-12 07:34:45 +00:00
Wayne Davison
21b9b93377 Fixed a typo. 2005-05-10 18:31:46 +00:00
123 changed files with 12202 additions and 5934 deletions

23
INSTALL
View File

@@ -1,4 +1,4 @@
To build and install rsync
To build and install rsync:
$ ./configure
$ make
@@ -9,8 +9,15 @@ to ./configure. To see them, use:
$ ./configure --help
Configure tries to figure out if the local system uses group "nobody" or
"nogroup" by looking in the /etc/group file. (This is only used for the
default group of an rsync daemon, which attempts to run with "nobody"
user and group permissions.) You can change the default user and group
for the daemon by editing the NOBODY_USER and NOBODY_GROUP defines in
config.h, or just override them in your /etc/rsyncd.conf file.
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
cut-down copy of release 1.5 is included in the rsync distribution,
cut-down copy of release 1.6.4 is included in the rsync distribution,
and will be used if there is no popt library on your build host, or if
the --with-included-popt option is passed to ./configure.
@@ -18,7 +25,6 @@ If you configure using --enable-maintainer-mode, then rsync will try
to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
useful, but it should be turned off for production builds.
RPM NOTES
---------
@@ -37,16 +43,15 @@ fails:
Install gcc or HP's "ANSI/C Compiler".
MAC OSX NOTES
-------------
Mac OS X (Darwin) seems to have an IPv6 stack, but it does not
completely implement the "New Sockets" API.
Some versions of Mac OS X (Darwin) seem to have an IPv6 stack, but do
not completely implement the "New Sockets" API.
<http://www.ipv6.org/impl/mac.html> says that Apple do not support
IPv6 yet. If your build fails, try again with --disable-ipv6.
<http://www.ipv6.org/impl/mac.html> says that Apple started to support
IPv6 in 10.2 (Jaguar). If your build fails, try again after running
configure with --disable-ipv6.
IBM AIX NOTES
-------------

View File

@@ -28,13 +28,12 @@ VERSION=@VERSION@
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h lib/pool_alloc.h
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
lib/permstring.o lib/pool_alloc.o @LIBOBJS@
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
zlib/zutil.o zlib/adler32.o
ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o \
main.o checksum.o match.o syscall.o log.o backup.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
fileio.o batch.o clientname.o
fileio.o batch.o clientname.o chmod.o
OBJS3=progress.o pipe.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
@@ -91,29 +90,14 @@ 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)
gen: $(srcdir)/configure $(srcdir)/config.h.in proto man
gen:
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
man: $(srcdir)/rsync.1 $(srcdir)/rsyncd.conf.5
$(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
$(srcdir)/rsyncd.conf.5: $(srcdir)/rsyncd.conf.yo
yodl2man -o $(srcdir)/rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
man:
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
proto:
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
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS)
@@ -161,8 +145,8 @@ check: all $(CHECK_PROGS)
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin=`pwd`/rsync$(EXEEXT) srcdir="$(srcdir)" $(srcdir)/runtests.sh
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
wildtest$(EXEEXT): wildtest.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o @BUILD_POPT@ $(LIBS)
wildtest$(EXEEXT): wildtest.o lib/compat.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o @BUILD_POPT@ $(LIBS)
# This does *not* depend on building or installing: you can use it to
# check a version installed from a binary or some other source tree,

161
NEWS
View File

@@ -1,142 +1,67 @@
NEWS for rsync 2.6.5 (UNRELEASED)
NEWS for rsync 2.6.8 (22 Apr 2006)
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 an "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.
Changes since 2.6.7:
BUG FIXES:
- 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.
- 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.
- Fixed a case where the generator might try to tweak the write
permissions of a read-only directory in list-only mode.
- 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
- Fixed a bug in the exclude code where an anchored exclude without any
wildcards fails to match an absolute source arg, but only when --relative
is in effect.
- Fixed the accidental disabling of --backup during the --delete-after
processing.
- Improved the I/O code for the generator to fix a potential hang when the
receiver gets an EOF on the socket but the generator's select() call
never indicates that the socket is writable for it to be notified about
the EOF. (This can happen when using stunnel).
- Restored the ability to use the --address option in client mode (in
addition to its use in daemon mode).
- Fixed a problem with the file-reading code where a failed read (such as
that caused by a bad sector) would not advance the file's read-position
beyond the failed read's data.
- Make sure that some temporary progress information from the delete
processing does not get left on the screen when it is followed by a
newline.
- Fixed a logging bug where the "log file" directive was not being honored
in a single-use daemon (one spawned by a remote-shell connection or by
init).
- When --existing skips a directory with extra verbosity, don't refer
to it as a "file".
- If rsync cannot honor the --delete option, we output an error and exit
instead of silently ignoring the option.
- 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.
- Fixed a bug in the --link-dest code that prevented special files (such as
fifos) from being linked.
- Fixed a bug where hard-linking a group of files might fail if the
generator hasn't created a needed destination directory yet.
- 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.
- 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.
- 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.)
- The ability to hard-link symlinks and special files is now determined at
configure time instead of at runtime. This fixes a bug with --link-dest
creating a hard-link to a symlink's referent on a BSD system.
ENHANCEMENTS:
- 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).
- In daemon mode, if rsync fails to bind to the requested port, the
error(s) returned by socket() and/or bind() are now logged.
- 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.
- When we output a fatal error, we now output the version of rsync in the
message.
- 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.)
- Improved the documentation for the --owner and --group options.
- 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).
- The rsyncstats script in "support" has an improved line-parsing regex
that is easier to read and also makes it to parse syslog-generated lines.
- If the daemon can't open the log-file specified in rsyncd.conf, fall
back to using syslog. This is better than a (typically) totally
silent failure (since a daemon is not usually run with --no-detach).
- A new script in "support": file-attr-restore, can be used to restore the
attributes of a file-set (the permissions, ownership, and group info)
taken from the cached output of a "find ARG... -ls" command.
- The man pages now consistently refer to an rsync daemon as a "daemon"
to distinguish it from a server in a non-daemon transfer.
DEVELOPER RELATED:
- 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).
- Removed the unused function write_int_named(), the unused variable
io_read_phase, and the rarely used variable io_write_phase. This also
elides the confusing 'phase "unknown"' part of one error message.
INTERNAL:
- Removed two unused configure checks and two related (also unused)
compatibility functions.
- Rsync now calls setlocale(LC_CTYPE, "").
- The xattrs.diff patch received a security fix that prevents a potential
buffer overflow in the receive_xattr() code.
- Improved the naming of the logfile-open/-reopen/-close functions.
- The acls.diff patch has been improved quite a bit, with more to come.
- Removed some protocol compatibility code that was only needed to help
someone running a pre-release of 2.6.4.
BUILD CHANGES:
- Fixed a bug in the SUPPORT{,_HARD}_LINKS defines which prevented
rsync from being built without symlink or hard-link support.
- You can use --disable-locale to turn off any use of setlocale().
- Configure now disables the use of mkstemp() under HP-UX (since they
refuse to fix its broken handling of large files).
- Configure now explicitly checks for the lseek64() function so that
the code can use HAVE_LSEEK64 instead of inferring lseek64()'s
presence based on the presence of the off64_t type.
- Some minor enhancements to the test scripts.
- Added a couple new diffs to the patches dir.
- A new patch was added: log-file.diff. This contains an early version of
a future option, --log-file=FILE, that will allow any rsync to log its
actions to a file (something that only a daemon supports at present).

600
OLDNEWS
View File

@@ -1,3 +1,573 @@
NEWS for rsync 2.6.7 (11 Mar 2006)
Protocol: 29 (unchanged)
Changes since 2.6.6:
OUTPUT CHANGES:
- The letter 'D' in the itemized output was being used for both devices
(character or block) as well as other special files (such as fifos and
named sockets). This has changed to separate non-device special files
under the 'S' designation (e.g. "cS+++++++ path/fifo"). See also the
"--specials" option, below.
- The way rsync escapes unreadable characters has changed. First, rsync
now has support for recognizing valid multibyte character sequences in
your current locale, allowing it to escape fewer characters than before
for a locale such as UTF-8. Second, it now uses an escape idiom of
"\#123", which is the literal string "\#" followed by exactly 3 octal
digits. Rsync no longer doubles a backslash character in a filename
(e.g. it used to output "foo\\bar" when copying "foo\bar") -- now it only
escapes a backslash that is followed by a hash-sign and 3 digits (0-9)
(e.g. it will output "foo\#134#789" when copying "foo\#789"). See also
the --8-bit-output (-8) option, mentioned below.
Script writers: the local rsync is the one that outputs escaped names,
so if you need to support unescaping of filenames for older rsyncs, I'd
suggest that you parse the output of "rsync --version" and only use the
old unescaping rules for 2.6.5 and 2.6.6.
BUG FIXES:
- Fixed a really old bug that caused --checksum (-c) to checksum all the
files encountered during the delete scan (ouch).
- Fixed a potential hang in a remote generator: when the receiver gets a
read-error on the socket, it now signals the generator about this so that
the generator does not try to send any of the terminating error messages
to the client (avoiding a potential hang in some setups).
- Made hard-links work with symlinks and devices again.
- If the sender gets an early EOF reading a source file, we propagate this
error to the receiver so that it can discard the file and try requesting
it again (which is the existing behavior for other kinds of read errors).
- If a device-file/special-file changes permissions, rsync now updates the
permissions without recreating the file.
- If the user specifies a remote-host for both the source and destination,
we now output a syntax error rather than trying to open the destination
hostspec as a filename.
- When --inplace creates a new destination file, rsync now creates it with
permissions 0600 instead of 0000 -- this makes restarting possible when
the transfer gets interrupted in the middle of sending a new file.
- Reject the combination of --inplace and --sparse since the sparse-output
algorithm doesn't work when overwriting existing data.
- Fixed the directory name in the error that is output when pop_dir()
fails.
- Really fixed the parsing of a "!" entry in .cvsignore files this time.
- If the generator gets a stat() error on a file, output it (this used to
require at least -vv for the error to be seen).
- If waitpid() fails or the child rsync didn't exit cleanly, we now handle
the exit status properly and generate a better error.
- Fixed some glitches in the double-verbose output when using --copy-dest,
--link-dest, or --compare-dest. Also improved how the verbose output
handles hard-links (within the transfer) that had an up-to-date alternate
"dest" file, and copied files (via --copy-dest).
- Fixed the matching of the dont-compress items (e.g. *.gz) against files
that have a path component containing a slash.
- If code reading a filter/exclude file an EINTR error, rsync now clears
the error flag on the file handle so it can keep on reading.
- If --relative is active, the sending side cleans up trailing "/" or "/."
suffixes to avoid triggering a bug in older rsync versions. Also, we now
reject a ".." dir if it would be sent as a relative dir.
- If a non-directory is in the way of a directory and rsync is run with
--dry-run and --delete, rsync no longer complains about not being able
to opendir() the not-yet present directory.
- When --list-only is used and a non-existent local destination dir was
also specified as a destination, rsync no longer generates a warning
about being unable to create the missing directory.
- Fixed some problems with --relative --no-implied-dirs when the
destination directory did not yet exist: we can now create a symlink or
device when it is the first thing in the missing dir, and --fuzzy no
longer complains about being unable to open the missing dir.
- Fixed a bug where the --copy-links option would not affect implied
directories without --copy-unsafe-links (see --relative).
- Got rid of the need for --force to be used in some circumstances with
--delete-after (making it consistent with --delete-before/-during).
- Rsync now ignores the SIGXFSZ signal, just in case your OS sends this
when a file is too large (rsync handles the write error).
- Fixed a bug in the Proxy-Authorization header's base64-encoded value: it
was not properly padded with trailing '=' chars. This only affects a
user that need to use a password-authenticated proxy for an outgoing
daemon-rsync connection.
- If we're transferring an empty directory to a new name, rsync no longer
forces S_IWUSR if it wasn't already set, nor does it accidentally leave
it set.
- Fixed a bug in the debug output (-vvvvv) that could mention the wrong
checksum for the current file offset.
- Rsync no longer allows a single directory to be copied over a non-
directory destination arg.
ENHANCEMENTS:
- Added the --append option that makes rsync append data onto files that
are longer on the source than the destination (this includes new files).
- Added the --min-size=SIZE option to exclude small files from the
transfer.
- Added the --compress-level option to allow you to set how aggressive
rsync's compression should be (this option implies --compress).
- Enhanced the parsing of the SIZE value for --min-size and --max-size to
allow easy entry of multiples of 1000 (instead of just multiples of 1024)
and off-by-one values too (e.g. --max-size=8mb-1).
- Added the --8-bit-output (-8) option, which tells rsync to avoid escaping
high-bit characters that it thinks are unreadable in the current locale.
- The new option --human-readable (-h) changes the output of --progress,
--stats, and the end-of-run summary to be easier to read. If repeated,
the units become powers of 1024 instead of powers of 1000. (The old
meaning of -h, as a shorthand for --help, still works as long as you
just use it on its own, as in "rsync -h".)
- If lutimes() and/or lchmod() are around, use them to allow the
preservation of attributes on symlinks.
- The --link-dest option now affects symlinks and devices (when possible).
- Added two config items to the rsyncd.conf parsing: "pre-xfer exec" and
"post-xfer exec". These allow a command to be specified on a per-module
basis that will be run before and/or after a daemon-mode transfer. (See
the man page for a list of the environment variables that are set with
information about the transfer.)
- When using the --relative option, you can now insert a dot dir in
the source path to indicate where the replication of the source dirs
should start. For example, if you specify a source path of
rsync://host/module/foo/bar/./baz/dir with -R, rsync will now only
replicate the "baz/dir" part of the source path (note: a trailing
dot dir is unaffected unless it also has a trailing slash).
- Added some new --no-FOO options that make it easier to override unwanted
implied or default options. For example, "-a --no-o" (aka "--archive
--no-owner") can be used to turn off the preservation of file ownership
that is implied by -a.
- Added the --chmod=MODE option that allows the destination permissions to
be changed from the source permissions. E.g. --chmod=g+w,o-rwx
- Added the "incoming chmod" and "outgoing chmod" daemon options that allow
a module to specify what permissions changes should be applied to all
files copied to and from the daemon.
- Allow the --temp-dir option to be specified when starting a daemon, which
sets the default temporary directory for incoming files.
- If --delete is combined with --dirs without --recursive, rsync will now
delete in any directory whose content is being synchronized.
- If --backup is combined with --delete without --backup-dir (and without
--delete-excluded), we add a "protect" filter-rule to ensure that files
with the backup suffix are not deleted.
- The file-count stats that are output by --progress were improved to
better indicate what the numbers mean. For instance, the output:
"(xfer#5, to-check=8383/9999)" indicates that this was the fifth file
to be transferred, and we still need to check 8383 more files out of
a total of 9999.
- The include/exclude code now allows a dir/*** directive (with 3 trailing
stars) to match both the dir itself as well as all the content below the
dir (dir/** would not match the dir).
- Added the --prune-empty-dirs (-m) option that makes the receiving rsync
discard empty chains of directories from the file-list. This makes it
easier to selectively copy files from a source hierarchy and end up with
just the directories needed to hold the resulting files.
- If the --itemize-changes (-i) option is repeated, rsync now includes
unchanged files in the itemized output (similar to -vv, but without all
the other verbose messages that can get in the way). Of course, the
client must be version 2.6.7 for this to work, but the remote rsync only
needs to be 2.6.7 if you're pushing files.
- Added the --specials option to tell rsync to copy non-device special
files (which rsync now attempts even as a normal user). The --devices
option now requests the copying of just devices (character and block).
The -D option still requests both (e.g. --devices and --specials), -a
still implies -D, and non-root users still get a silent downgrade that
omits device copying.
- Added the --super option to make the receiver always attempt super-user
activities. This is useful for systems that allow things such as devices
to be created or ownership to be set without being UID 0, and is also
useful for someone who wants to ensure that errors will be output if the
receiving rsync isn't being run as root.
- Added the --sockopts option for those few who want to customize the TCP
options used to contact a daemon rsync.
- Added a way for the --temp-dir option to be combined with a partial-dir
setting that lets rsync avoid non-atomic updates (for those times when
--temp-dir is not being used because space is tight).
- A new support script, files-to-excludes, will transform a list of files
into a set of include/exclude directives that will copy those files.
- A new option, --executability (-E) can be used to preserve just the
execute bit on files, for those times when using the --perms option is
not desired.
- The daemon now logs each connection and also each module-list request
that it receives.
- New log-format options: %M (modtime), %U (uid), %G (gid), and %B
(permission bits, e.g. "rwxr-xrwt").
- The --dry-run option no longer forces the enabling of --verbose.
- The --remove-sent-files option now does a better job of incrementally
removing the sent files on the sending side (older versions tended to
clump up all the removals at the end).
- A daemon now supersedes its minimal SIGCHLD handler with the standard
PID-remembering version after forking. This ensures that the generator
can get the child-exit status from the receiver.
- Use of the --bwlimit option no longer interferes with the remote rsync
sending error messages about invalid/refused options.
- Rsync no longer returns a usage error when used with one local source arg
and no destination: this now implies the --list-only option, just like
the comparable situation with a remote source arg.
- Added the --copy-dirlinks option, a more limited version of --copy-links.
- Various documentation improvements, including: a better synopsis, some
improved examples, a better discussion of the presence and absence of
--perms (including how it interacts with the new --executability and
--chmod options), an extended discussion of --temp-dir, an improved
discussion of --partial-dir, a better description of rsync's pattern
matching characters, an improved --no-implied-dirs section, and the
documenting of what the --stats option outputs.
- Various new and updated diffs in the patches dir, including: acls.diff,
xattrs.diff, atimes.diff, detect-renamed.diff, and slp.diff.
INTERNAL:
- We now use sigaction() and sigprocmask() if possible, and fall back on
signal() if not. Using sigprocmask() ensures that rsync enables all the
signals that it needs, just in case it was started in a masked state.
- Some buffer sizes were expanded a bit, particularly on systems where
MAXPATHLEN is overly small (e.g. cygwin).
- If io_printf() tries to format more data than fits in the buffer, exit
with an error instead of transmitting a truncated buffer.
- If a va_copy macro is defined, lib/snprintf.c will use it when defining
the VA_COPY macro.
- Reduced the amount of stack memory needed for each level of directory
recursion by nearly MAXPATHLEN bytes.
- The wildmatch function was extended to allow an array of strings to be
supplied as the string to match. This allows the exclude code to do less
string copying.
- Got rid of the safe_fname() function (and all the myriad calls) and
replaced it with a new function in the log.c code that filters all the
output going to the terminal.
- Unified the f_name() and the f_name_to() functions.
- Improved the hash-table code the sender uses to handle checksums to make
it use slightly less memory and run just a little faster.
DEVELOPER RELATED:
- The diffs in the patches dir now require "patch -p1 <DIFF" instead of
the previous -p0. Also, the version included in the release tar now
affect generated files (e.g. configure, rsync.1, proto.h, etc.), so
it is no longer necessary to run autoconf and/or yodl unless you're
applying a patch that was checked out from CVS.
- Several diffs in the patches dir now use the proper --enable-FOO
configure option instead of --with-FOO to turn on the inclusion of
the newly patched feature.
- There is a new script, "prepare-source" than can be used to update the
various generated files (proto.h, configure, etc.) even before configure
has created the Makefile (this is mainly useful when patching the source
with a patch that doesn't affect generated files).
- The testsuite now sets HOME so that it won't be affected by a file such
as ~/.popt.
NEWS for rsync 2.6.6 (28 Jul 2005)
Protocol: 29 (unchanged)
Changes since 2.6.5:
SECURITY FIXES:
- The zlib code was upgraded to version 1.2.3 in order to make it more
secure. While the widely-publicized security problem in zlib 1.2.2 did
not affect rsync, another security problem surfaced that affects rsync's
zlib 1.1.4.
BUG FIXES:
- The setting of flist->high in clean_flist() was wrong for an empty list.
This could cause flist_find() to crash in certain rare circumstances
(e.g. if just the right directory setup was around when --fuzzy was
combined with --link-dest).
- The outputting of hard-linked files when verbosity was > 1 was not right:
(1) Without -i it would output the name of each hard-linked file as
though it had been changed; it now outputs a "is hard linked" message for
the file. (2) With -i it would output all dots for the unchanged
attributes of a hard-link; it now changes those dots to spaces, as is
done for other totally unchanged items.
- When backing up a changed symlink or device, get rid of any old backup
item so that we don't get an "already exists" error.
- A couple places that were comparing a local and a remote modification-
time were not honoring the --modify-window option.
- Fixed a bug where the 'p' (permissions) itemized-changes flag might get
set too often (if some non-significant mode bits differed).
- Fixed a really old, minor bug that could cause rsync to warn about being
unable to mkdir() a path that ends in "/." because it just created the
directory (required --relative, --no-implied-dirs, a source path that
ended in either a trailing slash or a trailing "/.", and a non-existing
destination dir to tickle the bug in a recent version).
ENHANCEMENTS:
- Made the "max verbosity" setting in the rsyncd.conf file settable on a
per-module basis (which now matches the documentation).
- The support/rrsync script has been upgraded to verify the args of options
that take args (instead of rejecting any such options). The script was
also changed to try to be more secure and to fix a problem in the parsing
of a pull operation that has multiple sources.
- Improved the documentation that explains the difference between a
normal daemon transfer and a daemon-over remote-shell transfer.
- Some of the diffs supplied in the patches dir were fixed and/or
improved.
BUILD CHANGES:
- Made configure define NOBODY_USER (currently hard-wired to "nobody") and
NOBODY_GROUP (set to either "nobody" or "nogroup" depending on what we
find in the /etc/group file).
- Added a test to the test suite, itemized.test, that tests the output of
-i (log-format w/%i) and some double-verbose messages.
NEWS for rsync 2.6.5 (1 Jun 2005)
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:
- 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.
- Fixed a bug in the transfer of a single file when -H is specified
(rsync would either infinite loop or perhaps crash).
- Fixed a case where the generator might try (and fail) to tweak the
write-permissions of a read-only directory in list-only mode (this
only caused an annoying warning message).
- If --compare-dest or --link-dest uses a locally-copied file as the
basis for an updated version, log this better when --verbose or -i
is in effect.
- Fixed the accidental disabling of --backup during the --delete-after
processing.
- Restored the ability to use the --address option in client mode (in
addition to its use in daemon mode).
- 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.
- When --existing skips a directory with extra verbosity, refer to it
as a "directory", not a "file".
- 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.
- Fixed a bug where hard-linking a group of files might fail if the
generator hasn't created a needed destination directory yet.
- 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.
- When deleting files with the --one-file-system (-x) option set, rsync
no longer tries to remove files from inside a mount-point on the
receiving side. Also, we don't complain about being unable to remove
the mount-point dir.
- 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 omission of some directories in the delete processing when
--relative (-R) was combined with a source path that had a trailing
slash.
- Fixed a case where rsync would erroneously delete some files and then
re-transfer them when the options --relative (-R) and --recursive
(-r) were both enabled (along with --delete) and a source path had a
trailing slash.
- 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 pathname ends with a filename of "..", treat it as if
"../" had been specified (so that we don't copy files to the parent
dir of the destination).
- 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 (for
compatibility with OS variations).
ENHANCEMENTS:
- 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).
- 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.
- Improved the keep-alive code to handle a long silence between the
sender and the receiver that can occur when the sender is receiving
the checksum data for a large file.
- 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!)
- 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).
- If the daemon can't open the log-file specified in rsyncd.conf, fall
back to using syslog and log an appropriate warning. This is better
than what was typically a totally silent (and fatal) failure (since a
daemon is not usually run with the --no-detach option that was
necessary to see the error on stderr).
- The man pages now consistently refer to an rsync daemon as a "daemon"
instead of a "server" (to distinguish it from the server process in a
non-daemon transfer).
- 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:
- Rsync now calls setlocale(LC_CTYPE, ""). This enables isprint() to
better discern which filename characters need to be escaped in
messages (which should result in fewer escaped characters in some
locales).
- Improved the naming of the log-file open/reopen/close functions.
- Removed some protocol-compatibility code that was only needed to help
someone running a pre-release of 2.6.4.
BUILD CHANGES:
- Added configure option "--disable-locale" to disable any use of
setlocale() in the binary.
- Fixed a bug in the SUPPORT{,_HARD}_LINKS #defines which prevented
rsync from being built without symlink or hard-link support.
- Only #define HAVE_REMSH if it is going to be set to 1.
- Configure now disables the use of mkstemp() under HP-UX (since they
refuse to fix its broken handling of large files).
- Configure now explicitly checks for the lseek64() function so that
the code can use HAVE_LSEEK64 instead of inferring lseek64()'s
presence based on the presence of the off64_t type.
- Configure no longer mentions the change in the default remote-shell
(from rsh to ssh) that occurred for the 2.6.0 release.
- Some minor enhancements to the test scripts.
- Added a few new *.diff files to the patches dir, including a patch
that enables the optional copying of extended attributes.
NEWS for rsync 2.6.4 (30 March 2005)
Protocol: 29 (changed)
Changes since 2.6.3:
@@ -45,7 +615,7 @@ Changes since 2.6.3:
- 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.)
mkstemp(). (Fix derived from 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.
@@ -110,9 +680,11 @@ Changes since 2.6.3:
(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.)
- The output of the items that are being updated by the generator (dirs,
symlinks, devices) is now intermingled in the proper order with the
output from the items that the receiver is updating (regular files)
when pulling. This misordering was particularly bad when --progress
was specified. (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
@@ -188,7 +760,11 @@ Changes since 2.6.3:
29.)
- Added the --dirs (-d) option for an easier way to copy directories
without recursion.
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
@@ -385,6 +961,8 @@ Changes since 2.6.3:
- 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:
@@ -513,6 +1091,8 @@ Changes since 2.6.2:
user chose to combine the output of rsync's stdout and stderr (e.g.
using the "2>&1").
- Fixed an option-parsing bug when --files-from got passed to a daemon.
ENHANCEMENTS:
- Added the --partial-dir=DIR option that lets you specify where to
@@ -726,7 +1306,7 @@ Changes since 2.6.0:
- 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
than the current basis file when no new data has been transferred
over the wire for that file.
- Fixed a byte-order problem in --batch-mode on big-endian machines.
@@ -779,6 +1359,9 @@ Changes since 2.6.0:
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
- Fixed an option-parsing bug when --files-from was sent to a server
sender.
INTERNAL:
- Most of the I/O is now buffered, which results in a pretty large
@@ -1430,7 +2013,10 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? May 2005 2.6.5 29
22 Apr 2006 2.6.8 29
11 Mar 2006 2.6.7 29
28 Jul 2005 2.6.6 29
01 Jun 2005 2.6.5 29
30 Mar 2005 2.6.4 17 Jan 2005 29
30 Sep 2004 2.6.3 28
30 Apr 2004 2.6.2 28

120
TODO
View File

@@ -1,22 +1,17 @@
-*- indented-text -*-
BUGS ---------------------------------------------------------------
Do not rely on having a group called "nobody"
FEATURES ------------------------------------------------------------
Use chroot only if supported
Allow supplementary groups in rsyncd.conf 2002/04/09
Handling IPv6 on old machines
Other IPv6 stuff:
Other IPv6 stuff
Add ACL support 2001/12/02
Lazy directory creation
proxy authentication 2002/01/23
SOCKS 2002/01/23
FAT support
Allow forcing arbitrary permissions 2002/03/12
--diff david.e.sewell 2002/03/15
Add daemon --no-fork option
Create more granular verbosity jw 2003/05/15
Create more granular verbosity 2003/05/15
DOCUMENTATION --------------------------------------------------------
Keep list of open issues and todos on the web site
@@ -25,22 +20,19 @@ Perhaps redo manual as SGML
LOGGING --------------------------------------------------------------
Memory accounting
Improve error messages
Better statistics: Rasmus 2002/03/08
Better statistics Rasmus 2002/03/08
Perhaps flush stdout like syslog
Log deamon sessions that just list modules
Log child death on signal
Log errors with function that reports process of origin
verbose output David Stein 2001/12/20
internationalization
DEVELOPMENT --------------------------------------------------------
Handling duplicate names
Use generic zlib 2002/02/25
TDB: 2002/03/12
TDB 2002/03/12
Splint 2002/03/12
PERFORMANCE ----------------------------------------------------------
File list structure in memory
Traverse just one directory at a time
Allow skipping MD4 file_sum 2002/04/08
Accelerate MD4
@@ -52,8 +44,6 @@ Test on kernel source
Test large files
Create mutator program for testing
Create configure option to enable dangerous tests
If tests are skipped, say why.
Test daemon feature to disallow particular options.
Create pipe program for testing
Create test makefile target for some tests
@@ -66,17 +56,6 @@ reverse rsync over HTTP Range
BUGS ---------------------------------------------------------------
Do not rely on having a group called "nobody"
http://www.linuxbase.org/spec/refspecs/LSB_1.1.0/gLSB/usernames.html
On Debian it's "nogroup"
-- --
FEATURES ------------------------------------------------------------
@@ -133,7 +112,7 @@ Handling IPv6 on old machines
-- --
Other IPv6 stuff:
Other IPv6 stuff
Implement suggestions from http://www.kame.net/newsletter/19980604/
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
@@ -159,15 +138,6 @@ Add ACL support 2001/12/02
-- --
Lazy directory creation
With the current common --include '*/' --exclude '*' pattern, people
can end up with many empty directories. We might avoid this by
lazily creating such directories.
-- --
proxy authentication 2002/01/23
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
@@ -199,35 +169,6 @@ FAT support
-- --
Allow forcing arbitrary permissions 2002/03/12
On 12 Mar 2002, Dave Dykstra <dwd@bell-labs.com> wrote:
> If we would add an option to do that functionality, I
> would vote for one that was more general which could mask
> off any set of permission bits and possibly add any set of
> bits. Perhaps a chmod-like syntax if it could be
> implemented simply.
I think that would be good too. For example, people uploading files
to a web server might like to say
rsync -avzP --chmod a+rX ./ sourcefrog.net:/home/www/sourcefrog/
Ideally the patch would implement as many of the gnu chmod semantics
as possible. I think the mode parser should be a separate function
that passes back something like (mask,set) description to the rest
of the program. For bonus points there would be a test case for the
parser.
Possibly also --chown
(Debian #23628)
NOTE: there is a patch that implements this in the "patches" subdir.
-- --
--diff david.e.sewell 2002/03/15
Allow people to specify the diff command. (Might want to use wdiff,
@@ -252,7 +193,7 @@ Add daemon --no-fork option
-- --
Create more granular verbosity jw 2003/05/15
Create more granular verbosity 2003/05/15
Control output with the --report option.
@@ -322,14 +263,10 @@ Improve error messages
our load? (Debian #28416) Probably fixed now, but a test case would
be good.
When running as a daemon, some errors should both be returned to the
user and logged. This will make interacting with a daemon less
cryptic.
-- --
Better statistics: Rasmus 2002/03/08
Better statistics Rasmus 2002/03/08
<Rasmus>
hey, how about an rsync option that just gives you the
@@ -355,14 +292,6 @@ Perhaps flush stdout like syslog
-- --
Log deamon sessions that just list modules
At the connections that just get a list of modules are not logged,
but they should be.
-- --
Log child death on signal
If a child of the rsync daemon dies with a signal, we should notice
@@ -371,15 +300,6 @@ Log child death on signal
-- --
Log errors with function that reports process of origin
Use a separate function for reporting errors; prefix it with
"rsync:" or "rsync(remote)", or perhaps even "rsync(local
generator): ".
-- --
verbose output David Stein 2001/12/20
At end of transfer, show how many files were or were not transferred
@@ -445,7 +365,7 @@ Use generic zlib 2002/02/25
-- --
TDB: 2002/03/12
TDB 2002/03/12
Rather than storing the file list in memory, store it in a TDB.
@@ -472,20 +392,6 @@ Splint 2002/03/12
PERFORMANCE ----------------------------------------------------------
File list structure in memory
Rather than one big array, perhaps have a tree in memory mirroring
the directory tree.
This might make sorting much faster! (I'm not sure it's a big CPU
problem, mind you.)
It might also reduce memory use in storing repeated directory names
-- again I'm not sure this is a problem.
-- --
Traverse just one directory at a time
Traverse just one directory at a time. Tridge says it's possible.
@@ -586,16 +492,6 @@ Create configure option to enable dangerous tests
-- --
If tests are skipped, say why.
-- --
Test daemon feature to disallow particular options.
-- --
Create pipe program for testing
Create pipe program that makes slow/jerky connections for

View File

@@ -208,7 +208,7 @@ static int match_address(char *addr, char *tok)
ret = match_binary(a, t, mask, addrlen);
out:
out:
freeaddrinfo(resa);
freeaddrinfo(rest);
return ret;

View File

@@ -21,21 +21,18 @@
#include "rsync.h"
extern char *password_file;
extern int am_root;
/***************************************************************************
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
***************************************************************************/
void base64_encode(char *buf, int len, char *out)
void base64_encode(char *buf, int len, char *out, int pad)
{
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
unsigned char *d = (unsigned char *)buf;
int bytes = (len*8 + 5)/6;
memset(out, 0, bytes+1);
for (i = 0; i < bytes; i++) {
byte_offset = (i*6)/8;
bit_offset = (i*6)%8;
@@ -49,6 +46,11 @@ void base64_encode(char *buf, int len, char *out)
}
out[i] = b64[idx];
}
while (pad && (i % 4))
out[i++] = '=';
out[i] = '\0';
}
/* Generate a challenge buffer and return it base64-encoded. */
@@ -70,7 +72,7 @@ static void gen_challenge(char *addr, char *challenge)
sum_update(input, sizeof input);
sum_end(md4_out);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge, 0);
}
@@ -90,13 +92,13 @@ static int get_secret(int module, char *user, char *secret, int len)
return 0;
if (do_stat(fname, &st) == -1) {
rsyserr(FLOG, errno, "stat(%s)", safe_fname(fname));
rsyserr(FLOG, errno, "stat(%s)", fname);
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
ok = 0;
} else if (am_root && (st.st_uid != 0)) {
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
ok = 0;
}
@@ -160,19 +162,19 @@ static char *getpassf(char *filename)
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FERROR, errno, "could not open password file \"%s\"",
safe_fname(filename));
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)", safe_fname(filename));
rsyserr(FERROR, errno, "stat(%s)", filename);
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FERROR,"password file must not be other-accessible\n");
ok = 0;
} else if (am_root && st.st_uid != 0) {
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FERROR,"password file must be owned by root when running as root\n");
ok = 0;
}
@@ -209,7 +211,7 @@ static void generate_hash(char *in, char *challenge, char *out)
sum_update(challenge, strlen(challenge));
sum_end(buf);
base64_encode(buf, MD4_SUM_LENGTH, out);
base64_encode(buf, MD4_SUM_LENGTH, out, 0);
}
/* Possibly negotiate authentication with the client. Use "leader" to
@@ -223,7 +225,7 @@ char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
{
char *users = lp_auth_users(module);
char challenge[MD4_SUM_LENGTH*2];
char line[MAXPATHLEN];
char line[BIGPATHBUFLEN];
char secret[512];
char pass2[MD4_SUM_LENGTH*2];
char *tok, *pass;

View File

@@ -21,7 +21,6 @@
#include "rsync.h"
extern int verbose;
extern int backup_suffix_len;
extern int backup_dir_len;
extern unsigned int backup_dir_remainder;
extern char backup_dir_buf[MAXPATHLEN];
@@ -30,9 +29,8 @@ extern char *backup_dir;
extern int am_root;
extern int preserve_devices;
extern int preserve_specials;
extern int preserve_links;
extern int preserve_hard_links;
extern int orig_umask;
extern int safe_symlinks;
/* make a complete pathname for backup file */
@@ -65,8 +63,7 @@ static int make_simple_backup(char *fname)
if (do_rename(fname, fnamebak) == 0) {
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
safe_fname(fname),
safe_fname(fnamebak));
fname, fnamebak);
}
break;
}
@@ -81,7 +78,7 @@ static int make_simple_backup(char *fname)
continue;
rsyserr(FERROR, rename_errno, "rename %s to backup %s",
safe_fname(fname), safe_fname(fnamebak));
fname, fnamebak);
errno = rename_errno;
return 0;
}
@@ -112,7 +109,7 @@ static int make_bak_dir(char *fullpath)
}
if (*p == '/') {
*p = '\0';
if (do_mkdir(fullpath, 0777 & ~orig_umask) == 0)
if (mkdir_defmode(fullpath) == 0)
break;
if (errno != ENOENT) {
rsyserr(FERROR, errno,
@@ -141,7 +138,7 @@ static int make_bak_dir(char *fullpath)
p += strlen(p);
if (p == end)
break;
if (do_mkdir(fullpath, 0777 & ~orig_umask) < 0) {
if (mkdir_defmode(fullpath) < 0) {
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
full_fname(fullpath));
goto failure;
@@ -149,7 +146,7 @@ static int make_bak_dir(char *fullpath)
}
return 0;
failure:
failure:
while (p != end) {
*p = '/';
p += strlen(p);
@@ -160,8 +157,9 @@ failure:
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(char *src, char *dst)
{
if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT
|| make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0))
if (robust_rename(src, dst, NULL, 0755) < 0
&& (errno != ENOENT || make_bak_dir(dst) < 0
|| robust_rename(src, dst, NULL, 0755) < 0))
return -1;
return 0;
}
@@ -181,25 +179,24 @@ static int keep_backup(char *fname)
if (do_lstat(fname, &st) < 0)
return 1;
if (!(file = make_file(fname, NULL, NO_FILTERS)))
if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
return 1; /* the file could have disappeared */
if (!(buf = get_backup_name(fname)))
return 0;
/* Check to see if this is a device file, or link */
if (IS_DEVICE(file->mode)) {
if (am_root && preserve_devices) {
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",
safe_fname(fname));
}
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
do_unlink(buf);
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);
}
kept = 1;
do_unlink(fname);
@@ -230,21 +227,24 @@ static int keep_backup(char *fname)
full_fname(buf), file->u.link);
}
kept = 1;
} else {
do_unlink(buf);
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),
file->u.link);
}
do_unlink(fname);
kept = 1;
}
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;
}
#endif
if (!kept && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
safe_fname(fname));
fname);
return 1;
}
@@ -252,19 +252,19 @@ static int keep_backup(char *fname)
if (!kept) {
if (robust_move(fname, buf) != 0) {
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
full_fname(fname), safe_fname(buf));
full_fname(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(buf, file, NULL, 0);
set_file_attrs(buf, file, NULL, 0);
free(file);
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
safe_fname(fname), safe_fname(buf));
fname, buf);
}
return 1;
}

59
batch.c
View File

@@ -6,9 +6,9 @@
*/
#include "rsync.h"
#include "zlib/zlib.h"
#include <time.h>
extern int am_sender;
extern int eol_nulls;
extern int recurse;
extern int xfer_dirs;
@@ -19,11 +19,14 @@ extern int preserve_uid;
extern int preserve_gid;
extern int always_checksum;
extern int do_compression;
extern int def_compress_level;
extern int protocol_version;
extern char *batch_name;
extern struct filter_list_struct filter_list;
static int tweaked_compress_level;
static int *flag_ptr[] = {
&recurse, /* 0 */
&preserve_uid, /* 1 */
@@ -33,7 +36,7 @@ static int *flag_ptr[] = {
&preserve_hard_links, /* 5 */
&always_checksum, /* 6 */
&xfer_dirs, /* 7 (protocol 29) */
&do_compression, /* 8 (protocol 29) */
&tweaked_compress_level,/* 8 (protocol 29) */
NULL
};
@@ -54,6 +57,12 @@ void write_stream_flags(int fd)
{
int i, flags;
#if Z_DEFAULT_COMPRESSION == -1
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
#else
#error internal logic error! Fix def_compress_level logic above and below too!
#endif
/* Start the batch file with a bitmap of data-stream-affecting
* flags. */
if (protocol_version < 29)
@@ -88,6 +97,13 @@ void read_stream_flags(int fd)
else if (xfer_dirs < 2)
xfer_dirs = 0;
}
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
do_compression = 0;
else {
do_compression = 1;
def_compress_level = tweaked_compress_level - 2;
}
}
static void write_arg(int fd, char *arg)
@@ -148,7 +164,7 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
S_IRUSR | S_IWUSR | S_IEXEC);
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
safe_fname(filename));
filename);
exit_cleanup(1);
}
@@ -194,42 +210,7 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
write_filter_rules(fd);
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
rsyserr(FERROR, errno, "Batch file %s write error",
safe_fname(filename));
filename);
exit_cleanup(1);
}
}
void show_flist(int index, struct file_struct **fptr)
{
/* for debugging show_flist(flist->count, flist->files * */
int i;
for (i = 0; i < index; i++) {
rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
rprintf(FINFO, "flist->modtime=%#lx\n",
(long unsigned) fptr[i]->modtime);
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",
safe_fname(fptr[i]->basename));
if (fptr[i]->dirname) {
rprintf(FINFO, "flist->dirname=%s\n",
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[])
{
int 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]));
}

205
chmod.c Normal file
View File

@@ -0,0 +1,205 @@
#include "rsync.h"
extern mode_t orig_umask;
#define FLAG_X_KEEP (1<<0)
#define FLAG_DIRS_ONLY (1<<1)
#define FLAG_FILES_ONLY (1<<2)
struct chmod_mode_struct {
struct chmod_mode_struct *next;
int ModeAND, ModeOR;
char flags;
};
#define CHMOD_ADD 1
#define CHMOD_SUB 2
#define CHMOD_EQ 3
#define STATE_ERROR 0
#define STATE_1ST_HALF 1
#define STATE_2ND_HALF 2
/* Parse a chmod-style argument, and break it down into one or more AND/OR
* pairs in a linked list. We return a pointer to new items on succcess
* (appending the items to the specified list), or NULL on error. */
struct chmod_mode_struct *parse_chmod(const char *modestr,
struct chmod_mode_struct **root_mode_ptr)
{
int state = STATE_1ST_HALF;
int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, flags = 0;
struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL,
*prev_mode = NULL;
while (state != STATE_ERROR) {
if (!*modestr || *modestr == ',') {
int bits;
if (!op) {
state = STATE_ERROR;
break;
}
prev_mode = curr_mode;
curr_mode = new_array(struct chmod_mode_struct, 1);
if (prev_mode)
prev_mode->next = curr_mode;
else
first_mode = curr_mode;
curr_mode->next = NULL;
if (where)
bits = where * what;
else {
where = 0111;
bits = (where * what) & ~orig_umask;
}
switch (op) {
case CHMOD_ADD:
curr_mode->ModeAND = CHMOD_BITS;
curr_mode->ModeOR = bits + topoct;
break;
case CHMOD_SUB:
curr_mode->ModeAND = CHMOD_BITS - bits - topoct;
curr_mode->ModeOR = 0;
break;
case CHMOD_EQ:
curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0);
curr_mode->ModeOR = bits + topoct;
break;
}
curr_mode->flags = flags;
if (!*modestr)
break;
modestr++;
state = STATE_1ST_HALF;
where = what = op = topoct = topbits = flags = 0;
}
if (state != STATE_2ND_HALF) {
switch (*modestr) {
case 'D':
if (flags & FLAG_FILES_ONLY)
state = STATE_ERROR;
flags |= FLAG_DIRS_ONLY;
break;
case 'F':
if (flags & FLAG_DIRS_ONLY)
state = STATE_ERROR;
flags |= FLAG_FILES_ONLY;
break;
case 'u':
where |= 0100;
topbits |= 04000;
break;
case 'g':
where |= 0010;
topbits |= 02000;
break;
case 'o':
where |= 0001;
break;
case 'a':
where |= 0111;
break;
case '+':
op = CHMOD_ADD;
state = STATE_2ND_HALF;
break;
case '-':
op = CHMOD_SUB;
state = STATE_2ND_HALF;
break;
case '=':
op = CHMOD_EQ;
state = STATE_2ND_HALF;
break;
default:
state = STATE_ERROR;
break;
}
} else {
switch (*modestr) {
case 'r':
what |= 4;
break;
case 'w':
what |= 2;
break;
case 'X':
flags |= FLAG_X_KEEP;
/* FALL THROUGH */
case 'x':
what |= 1;
break;
case 's':
if (topbits)
topoct |= topbits;
else
topoct = 04000;
break;
case 't':
topoct |= 01000;
break;
default:
state = STATE_ERROR;
break;
}
}
modestr++;
}
if (state == STATE_ERROR) {
free_chmod_mode(first_mode);
return NULL;
}
if (!(curr_mode = *root_mode_ptr))
*root_mode_ptr = first_mode;
else {
while (curr_mode->next)
curr_mode = curr_mode->next;
curr_mode->next = first_mode;
}
return first_mode;
}
/* Takes an existing file permission and a list of AND/OR changes, and
* create a new permissions. */
int tweak_mode(int mode, struct chmod_mode_struct *chmod_modes)
{
int IsX = mode & 0111;
int NonPerm = mode & ~CHMOD_BITS;
for ( ; chmod_modes; chmod_modes = chmod_modes->next) {
if ((chmod_modes->flags & FLAG_DIRS_ONLY) && !S_ISDIR(NonPerm))
continue;
if ((chmod_modes->flags & FLAG_FILES_ONLY) && S_ISDIR(NonPerm))
continue;
mode &= chmod_modes->ModeAND;
if ((chmod_modes->flags & FLAG_X_KEEP) && !IsX && !S_ISDIR(NonPerm))
mode |= chmod_modes->ModeOR & ~0111;
else
mode |= chmod_modes->ModeOR;
}
return mode | NonPerm;
}
/* Free the linked list created by parse_chmod. */
int free_chmod_mode(struct chmod_mode_struct *chmod_modes)
{
struct chmod_mode_struct *next;
while (chmod_modes) {
next = chmod_modes->next;
free(chmod_modes);
chmod_modes = next;
}
return 0;
}

View File

@@ -26,6 +26,10 @@ extern int keep_partial;
extern int log_got_error;
extern char *partial_dir;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Close all open sockets and files, allowing a (somewhat) graceful
* shutdown() of socket connections. This eliminates the abortive
@@ -94,17 +98,18 @@ void _exit_cleanup(int code, const char *file, int line)
}
inside_cleanup++;
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
SIGACTION(SIGUSR1, SIG_IGN);
SIGACTION(SIGUSR2, SIG_IGN);
if (verbose > 3) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, safe_fname(file), line);
code, file, line);
}
if (cleanup_child_pid != -1) {
int status;
if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
if (wait_process(cleanup_child_pid, &status, WNOHANG)
== cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code)
code = status;
@@ -121,8 +126,8 @@ void _exit_cleanup(int code, const char *file, int line)
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
}
finish_transfer(cleanup_new_fname, fname, cleanup_file, 0,
!partial_dir);
finish_transfer(cleanup_new_fname, fname, NULL,
cleanup_file, 0, !partial_dir);
}
io_flush(FULL_FLUSH);
if (cleanup_fname)
@@ -149,7 +154,7 @@ void _exit_cleanup(int code, const char *file, int line)
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);
ocode, file, line, code);
}
close_all();
@@ -166,7 +171,7 @@ void cleanup_disable(void)
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
int fd_r, int fd_w)
{
cleanup_fname = fnametmp;
cleanup_fname = fname ? fnametmp : NULL;
cleanup_new_fname = fname;
cleanup_file = file;
cleanup_fd_r = fd_r;

View File

@@ -34,7 +34,6 @@
#include "rsync.h"
static const char default_name[] = "UNKNOWN";
extern int am_daemon;
extern int am_server;
@@ -321,7 +320,6 @@ int check_name(int fd,
return error;
}
/* Given all these results, we expect that one of them will be
* the same as ss. The comparison is a bit complicated. */
for (res = res0; res; res = res->ai_next) {

View File

@@ -28,6 +28,7 @@
#include "rsync.h"
extern int verbose;
extern int quiet;
extern int list_only;
extern int am_sender;
extern int am_server;
@@ -41,24 +42,31 @@ extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern int io_timeout;
extern int select_timeout;
extern int orig_umask;
extern int no_detach;
extern int default_af_hint;
extern mode_t orig_umask;
extern char *bind_address;
extern struct filter_list_struct server_filter_list;
extern char *sockopts;
extern char *config_file;
extern char *files_from;
extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
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;
struct chmod_mode_struct *daemon_chmod_modes;
/* Length of lp_path() string when in daemon mode & not chrooted, else 0. */
unsigned int module_dirlen = 0;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Run a client connected to an rsyncd. The alternative to this
* function for remote-shell connections is do_cmd().
@@ -98,6 +106,8 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
if (fd == -1)
exit_cleanup(RERR_SOCKETIO);
set_socket_options(fd, sockopts);
ret = start_inband_exchange(user, path, fd, fd, argc);
return ret ? ret : client_run(fd, fd, -1, argc, argv);
@@ -109,7 +119,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
int i;
char *sargs[MAX_ARGS];
int sargc = 0;
char line[MAXPATHLEN];
char line[BIGPATHBUFLEN];
char *p;
if (argc == 0 && !am_sender)
@@ -216,24 +226,62 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
return 0;
}
static char *finish_pre_exec(pid_t pid, int fd, char *request,
int argc, char *argv[])
{
int j, status = -1;
if (request) {
write_buf(fd, request, strlen(request)+1);
for (j = 0; j < argc; j++)
write_buf(fd, argv[j], strlen(argv[j])+1);
}
static int rsync_module(int f_in, int f_out, int i)
write_byte(fd, 0);
close(fd);
if (wait_process(pid, &status, 0) < 0
|| !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
char *e;
if (asprintf(&e, "pre-xfer exec returned failure (%d)\n", status) < 0)
out_of_memory("finish_pre_exec");
return e;
}
return NULL;
}
static int read_arg_from_pipe(int fd, char *buf, int limit)
{
char *bp = buf, *eob = buf + limit - 1;
while (1) {
if (read(fd, bp, 1) != 1)
return -1;
if (*bp == '\0')
break;
if (bp < eob)
bp++;
}
*bp = '\0';
return bp - buf;
}
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
{
int argc = 0;
int maxargs;
char **argv;
char **argp;
char line[MAXPATHLEN];
char line[BIGPATHBUFLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
char *p;
char *addr = client_addr(f_in);
char *host = client_name(f_in);
char *p, *err_msg = NULL;
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int start_glob = 0;
int ret;
int ret, pre_exec_fd = -1;
pid_t pre_exec_pid = 0;
char *request = NULL;
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
@@ -257,7 +305,7 @@ static int rsync_module(int f_in, int f_out, int i)
if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
if (errno) {
rsyserr(FLOG, errno, "failed to open lock file %s",
safe_fname(lp_lock_file(i)));
lp_lock_file(i));
io_printf(f_out, "@ERROR: failed to open lock file\n");
} else {
rprintf(FLOG, "max connections (%d) reached\n",
@@ -327,27 +375,118 @@ static int rsync_module(int f_in, int f_out, int i)
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ANCHORED2ABS);
XFLG_ABS_IF_SLASH);
p = lp_include_from(i);
parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
parse_rule(&server_filter_list, p,
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
parse_filter_file(&server_filter_list, p, 0,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
log_init();
#ifdef HAVE_PUTENV
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", lp_path(i)) < 0
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
out_of_memory("rsync_module");
putenv(modname);
putenv(modpath);
putenv(hostaddr);
putenv(hostname);
putenv(username);
umask(orig_umask);
/* For post-xfer exec, fork a new process to run the rsync
* daemon while this process waits for the exit status and
* runs the indicated command at that point. */
if (*lp_postxfer_exec(i)) {
pid_t pid = fork();
if (pid < 0) {
rsyserr(FLOG, errno, "fork failed");
io_printf(f_out, "@ERROR: fork failed\n");
return -1;
}
if (pid) {
char *ret1, *ret2;
if (wait_process(pid, &status, 0) < 0)
status = -1;
if (asprintf(&ret1, "RSYNC_RAW_STATUS=%d", status) > 0)
putenv(ret1);
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else
status = -1;
if (asprintf(&ret2, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(ret2);
system(lp_postxfer_exec(i));
_exit(status);
}
}
/* For pre-xfer exec, fork a child process to run the indicated
* command, though it first waits for the parent process to
* send us the user's request via a pipe. */
if (*lp_prexfer_exec(i)) {
int fds[2];
if (pipe(fds) < 0 || (pre_exec_pid = fork()) < 0) {
rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
return -1;
}
if (pre_exec_pid == 0) {
char buf[BIGPATHBUFLEN];
int j, len;
close(fds[1]);
set_blocking(fds[0]);
len = read_arg_from_pipe(fds[0], buf, BIGPATHBUFLEN);
if (len <= 0)
_exit(1);
if (asprintf(&p, "RSYNC_REQUEST=%s", buf) < 0)
out_of_memory("rsync_module");
putenv(p);
for (j = 0; ; j++) {
len = read_arg_from_pipe(fds[0], buf,
BIGPATHBUFLEN);
if (len <= 0) {
if (!len)
break;
_exit(1);
}
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) < 0)
out_of_memory("rsync_module");
putenv(p);
}
close(fds[0]);
close(STDIN_FILENO);
close(STDOUT_FILENO);
status = system(lp_prexfer_exec(i));
if (!WIFEXITED(status))
_exit(1);
_exit(WEXITSTATUS(status));
}
close(fds[0]);
set_blocking(fds[1]);
pre_exec_fd = fds[1];
}
umask(0);
}
#endif
if (use_chroot) {
/*
* XXX: The 'use chroot' flag is a fairly reliable
@@ -363,14 +502,14 @@ static int rsync_module(int f_in, int f_out, int i)
*/
if (chroot(lp_path(i))) {
rsyserr(FLOG, errno, "chroot %s failed",
safe_fname(lp_path(i)));
lp_path(i));
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/")) {
rsyserr(FLOG, errno, "chdir %s failed\n",
safe_fname(lp_path(i)));
lp_path(i));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
@@ -378,7 +517,7 @@ static int rsync_module(int f_in, int f_out, int i)
} else {
if (!push_dir(lp_path(i))) {
rsyserr(FLOG, errno, "chdir %s failed\n",
safe_fname(lp_path(i)));
lp_path(i));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
@@ -420,6 +559,16 @@ static int rsync_module(int f_in, int f_out, int i)
am_root = (MY_UID() == 0);
}
if (lp_temp_dir(i) && *lp_temp_dir(i)) {
tmpdir = lp_temp_dir(i);
if (strlen(tmpdir) >= MAXPATHLEN - 10) {
rprintf(FLOG,
"the 'temp dir' value for %s is WAY too long -- ignoring.\n",
name);
tmpdir = NULL;
}
}
io_printf(f_out, "@RSYNCD: OK\n");
maxargs = MAX_ARGS;
@@ -444,22 +593,37 @@ static int rsync_module(int f_in, int f_out, int i)
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, &maxargs);
} else
switch (start_glob) {
case 0:
argc++;
if (strcmp(line, ".") == 0)
start_glob = 1;
break;
case 1:
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid,
pre_exec_fd, p,
argc, argv);
pre_exec_pid = 0;
}
request = strdup(p);
start_glob = 2;
/* FALL THROUGH */
default:
if (!err_msg)
glob_expand(name, &argv, &argc, &maxargs);
break;
}
}
if (strcmp(line, ".") == 0)
start_glob = 1;
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
argc, argv);
}
verbose = 0; /* future verbosity is controlled by client options */
argp = argv;
ret = parse_arguments(&argc, (const char ***) &argp, 0);
ret = parse_arguments(&argc, (const char ***) &argv, 0);
quiet = 0; /* Don't let someone try to be tricky. */
if (filesfrom_fd == 0)
filesfrom_fd = f_in;
@@ -479,14 +643,14 @@ static int rsync_module(int f_in, int f_out, int i)
#ifndef DEBUG
/* don't allow the logs to be flooded too fast */
if (verbose > lp_max_verbosity())
verbose = lp_max_verbosity();
if (verbose > lp_max_verbosity(i))
verbose = lp_max_verbosity(i);
#endif
if (protocol_version < 23
&& (protocol_version == 22 || am_sender))
io_start_multiplex_out();
else if (!ret) {
else if (!ret || err_msg) {
/* We have to get I/O multiplexing started so that we can
* get the error back to the client. This means getting
* the protocol setup finished first in later versions. */
@@ -512,19 +676,32 @@ static int rsync_module(int f_in, int f_out, int i)
io_start_multiplex_out();
}
if (!ret) {
option_error();
if (!ret || err_msg) {
if (err_msg)
rprintf(FERROR, err_msg);
else
option_error();
msleep(400);
exit_cleanup(RERR_UNSUPPORTED);
}
if (lp_timeout(i)) {
io_timeout = lp_timeout(i);
if (io_timeout < select_timeout)
select_timeout = io_timeout;
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
set_io_timeout(lp_timeout(i));
/* If we have some incoming/outgoing chmod changes, append them to
* any user-specified changes (making our changes have priority).
* We also get a pointer to just our changes so that a receiver
* process can use them separately if --perms wasn't specified. */
if (am_sender)
p = lp_outgoing_chmod(i);
else
p = lp_incoming_chmod(i);
if (*p && !(daemon_chmod_modes = parse_chmod(p, &chmod_modes))) {
rprintf(FLOG, "Invalid \"%sing chmod\" directive: %s\n",
am_sender ? "outgo" : "incom", p);
}
start_server(f_in, f_out, argc, argp);
start_server(f_in, f_out, argc, argv);
return 0;
}
@@ -550,20 +727,29 @@ static void send_listing(int fd)
here */
int start_daemon(int f_in, int f_out)
{
char line[200];
char *motd;
char line[1024];
char *motd, *addr, *host;
int i;
io_set_sock_fds(f_in, f_out);
/* We must load the config file before calling any function that
* might cause log-file output to occur. This ensures that the
* "log file" param gets honored for the 2 non-forked use-cases
* (when rsync is run by init and run by a remote shell). */
if (!lp_load(config_file, 0))
exit_cleanup(RERR_SYNTAX);
log_init();
addr = client_addr(f_in);
host = client_name(f_in);
rprintf(FLOG, "connect from %s (%s)\n", host, addr);
if (!am_server) {
set_socket_options(f_in, "SO_KEEPALIVE");
set_socket_options(f_in, lp_socket_options());
if (sockopts)
set_socket_options(f_in, sockopts);
else
set_socket_options(f_in, lp_socket_options());
set_nonblocking(f_in);
}
@@ -599,6 +785,8 @@ int start_daemon(int f_in, int f_out)
return -1;
if (!*line || strcmp(line, "#list") == 0) {
rprintf(FLOG, "module-list request from %s (%s)\n",
host, addr);
send_listing(f_out);
return -1;
}
@@ -610,17 +798,19 @@ int start_daemon(int f_in, int f_out)
}
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);
}
#ifdef HAVE_SIGACTION
sigact.sa_flags = SA_NOCLDSTOP;
#endif
SIGACTION(SIGCHLD, remember_children);
return rsync_module(f_in, f_out, i, addr, host);
}
int daemon_main(void)
{
@@ -668,7 +858,7 @@ int daemon_main(void)
0666 & ~orig_umask)) == -1) {
cleanup_set_pid(0);
rsyserr(FLOG, errno, "failed to create pid file %s",
safe_fname(pid_file));
pid_file);
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);

View File

@@ -29,12 +29,12 @@ int remote_protocol = 0;
extern int verbose;
extern int am_server;
extern int am_sender;
extern int inplace;
extern int fuzzy_basis;
extern int read_batch;
extern int checksum_seed;
extern int basis_dir_cnt;
extern int prune_empty_dirs;
extern int protocol_version;
extern char *dest_option;
@@ -78,25 +78,38 @@ 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 (protocol_version < 29) {
if (fuzzy_basis) {
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 && inplace) {
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 (basis_dir_cnt > 1) {
rprintf(FERROR,
"Using more than one %s option requires protocol"
" 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (prune_empty_dirs) {
rprintf(FERROR,
"--prune-empty-dirs requires protocol 29 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
}
if (am_server) {

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=2.6.5pre1
RSYNC_VERSION=2.6.8
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -26,8 +26,7 @@ AC_SUBST(SHELL)
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
if test "x$ac_cv_prog_cc_stdc" = xno
then
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
fi
@@ -38,12 +37,10 @@ fi
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug],
[including debugging symbols and features (default yes)]),
[], [])
AC_HELP_STRING([--disable-debug],
[turn off debugging symbols and features]))
if test x"$enable_debug" = x"no"
then
if test x"$enable_debug" = x"no"; then
AC_MSG_RESULT(no)
CFLAGS=${CFLAGS-"-O"}
else
@@ -54,14 +51,10 @@ else
fi
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],
[turn on CPU profiling (default no)],
[], []))
if test x"$enable_profile" = xyes
then
[turn on CPU profiling]))
if test x"$enable_profile" = x"yes"; then
CFLAGS="$CFLAGS -pg"
fi
@@ -69,10 +62,8 @@ fi
# Specifically, this turns on panic_action handling.
AC_ARG_ENABLE(maintainer-mode,
AC_HELP_STRING([--enable-maintainer-mode],
[turn on extra debug features],
[], []))
if test x"$enable_maintainer_mode" = xyes
then
[turn on extra debug features]))
if test x"$enable_maintainer_mode" = x"yes"; then
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
fi
@@ -82,16 +73,15 @@ fi
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
# If GCC, turn on warnings.
if test x"$GCC" = x"yes"
then
if test x"$GCC" = x"yes"; then
CFLAGS="$CFLAGS -Wall -W"
fi
AC_ARG_WITH(included-popt,
[ --with-included-popt use bundled popt library, not from system])
AC_HELP_STRING([--with-included-popt], [use bundled popt library, not from system]))
AC_ARG_WITH(rsync-path,
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: rsync)],
AC_HELP_STRING([--with-rsync-path=PATH], [set default --rsync-path to PATH (default: rsync)]),
[ RSYNC_PATH="$with_rsync_path" ],
[ RSYNC_PATH="rsync" ])
@@ -122,18 +112,30 @@ AC_ARG_WITH(rsh,
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
if test x$HAVE_REMSH = x1; then
AC_DEFINE(HAVE_REMSH, 1, [Define to 1 if remote shell is remsh, not rsh])
fi
if test x"$with_rsh" != x
then
if test x"$with_rsh" != x; then
RSYNC_RSH="$with_rsh"
else
RSYNC_RSH="ssh"
fi
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
# arrgh. libc in the current debian stable screws up the largefile
AC_MSG_CHECKING([the group for user "nobody"])
if grep '^nobody:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nobody
elif grep '^nogroup:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nogroup
else
NOBODY_GROUP=nobody # test for others?
fi
AC_MSG_RESULT($NOBODY_GROUP)
AC_DEFINE_UNQUOTED(NOBODY_USER, "nobody", [unprivileged user--e.g. nobody])
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
# arrgh. libc in some old debian version screwed up the largefile
# stuff, getting byte range locking wrong
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
AC_TRY_RUN([
@@ -179,21 +181,9 @@ ipv6lib=none
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_HELP_STRING([--disable-ipv6],
[don't even try to use IPv6]))
if test x"$enable_ipv6" != x"no"; then
AC_MSG_CHECKING([ipv6 stack type])
for i in inria kame linux-glibc linux-inet6 toshiba v6d zeta; do
case $i in
@@ -282,6 +272,16 @@ yes
AC_SEARCH_LIBS(getaddrinfo, inet6)
fi
dnl Do you want to disable use of locale functions
AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale],
[turn off locale features]))
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you don't want locale features. By default this is defined.])
if test x"$enable_locale" != x"no"; then
AC_DEFINE(CONFIG_LOCALE)
fi
AC_MSG_CHECKING([whether to call shutdown on all sockets])
case $host_os in
*cygwin* ) AC_MSG_RESULT(yes)
@@ -299,7 +299,7 @@ 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 locale.h \
netdb.h malloc.h float.h)
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
AC_HEADER_MAJOR
AC_CHECK_SIZEOF(int)
@@ -366,7 +366,11 @@ if test x"$ac_cv_func_connect" = x"no"; then
fi
fi
AC_CHECK_LIB(resolv, inet_ntop)
AC_SEARCH_LIBS(inet_ntop, resolv)
# Solaris and HP-UX weirdness:
# Search for libiconv_open (not iconv_open) to discover if -liconv is needed!
AC_SEARCH_LIBS(libiconv_open, iconv)
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
@@ -485,19 +489,20 @@ 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 ftruncate \
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 va_copy __va_copy)
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
strerror putenv iconv_open locale_charset nl_langinfo \
sigaction sigprocmask)
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_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
@@ -508,14 +513,52 @@ AC_CACHE_CHECK([whether chown() dereferences symlinks],rsync_cv_chown_follows_sy
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);
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(1);
exit(0);
}],
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
rsync_cv_chown_modifies_symlink=yes,rsync_cv_chown_modifies_symlink=no,rsync_cv_chown_modifies_symlink=no)])
if test $rsync_cv_chown_modifies_symlink = yes; then
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#define FILENAME "conftest.dangle"
main() {
unlink(FILENAME);
if (symlink("conftest.no-such", FILENAME) < 0) abort();
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_symlink=yes,rsync_cv_can_hardlink_symlink=no,rsync_cv_can_hardlink_symlink=no)])
if test $rsync_cv_can_hardlink_symlink = yes; then
AC_DEFINE(CAN_HARDLINK_SYMLINK, 1, [Define to 1 if link() can hard-link symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link special files],rsync_cv_can_hardlink_special,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#define FILENAME "conftest.fifi"
main() {
unlink(FILENAME);
if (mkfifo(FILENAME, 0777) < 0) abort();
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_special=yes,rsync_cv_can_hardlink_special=no,rsync_cv_can_hardlink_special=no)])
if test $rsync_cv_can_hardlink_special = yes; then
AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
fi
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
#include <sys/types.h>
@@ -530,14 +573,12 @@ if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function])
fi
if test x"$with_included_popt" != x"yes"
then
if test x"$with_included_popt" != x"yes"; then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
fi
AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"
then
if test x"$with_included_popt" = x"yes"; then
AC_MSG_RESULT($srcdir/popt)
BUILD_POPT='$(popt_OBJS)'
CFLAGS="$CFLAGS -I$srcdir/popt"
@@ -646,35 +687,6 @@ if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
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, [Define to 1 if inet_ntoa() needs to be replaced])
fi
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
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, [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>
@@ -682,7 +694,7 @@ AC_TRY_RUN([
#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;}
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_FIFOS=yes,rsync_cv_MKNOD_CREATES_FIFOS=no,rsync_cv_MKNOD_CREATES_FIFOS=cross)])
if test x"$rsync_cv_MKNOD_CREATES_FIFOS" = x"yes"; then
@@ -696,7 +708,7 @@ AC_TRY_RUN([
#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;}
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_SOCKETS=yes,rsync_cv_MKNOD_CREATES_SOCKETS=no,rsync_cv_MKNOD_CREATES_SOCKETS=cross)])
if test x"$rsync_cv_MKNOD_CREATES_SOCKETS" = x"yes"; then
@@ -737,21 +749,6 @@ AC_SUBST(BUILD_POPT)
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT
if test x"$with_rsh" = x; then
if test x"$HAVE_REMSH" = x1; then
rmsh1='remsh:'
rmsh2='=remsh'
else
rmsh1='rsh: '
rmsh2='=rsh '
fi
AC_MSG_RESULT()
AC_MSG_RESULT([ **********************************************************************])
AC_MSG_RESULT([ * As of v2.6.0, the default remote shell is ssh instead of rsh!! *])
AC_MSG_RESULT([ * To use previous default of $rmsh1 ./configure --with-rsh$rmsh2 *])
AC_MSG_RESULT([ **********************************************************************])
fi
AC_MSG_RESULT()
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
AC_MSG_RESULT()

View File

@@ -34,8 +34,11 @@
#define RERR_STREAMIO 12 /* error in rsync protocol data stream */
#define RERR_MESSAGEIO 13 /* errors with program diagnostics */
#define RERR_IPC 14 /* error in IPC code */
#define RERR_CRASHED 15 /* sibling crashed */
#define RERR_TERMINATED 16 /* sibling terminated abnormally */
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#define RERR_SIGNAL1 19 /* status returned when sent SIGUSR1 */
#define RERR_SIGNAL 20 /* status returned when sent SIGINT, SIGTERM, SIGHUP */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_PARTIAL 23 /* partial transfer */

160
exclude.c
View File

@@ -34,6 +34,7 @@ extern int list_only;
extern int recurse;
extern int io_error;
extern int local_server;
extern int prune_empty_dirs;
extern int delete_mode;
extern int delete_excluded;
extern int cvs_exclude;
@@ -46,8 +47,8 @@ extern unsigned int curr_dir_len;
extern unsigned int module_dirlen;
struct filter_list_struct filter_list = { 0, 0, "" };
struct filter_list_struct cvs_filter_list = { 0, 0, " [cvsignore]" };
struct filter_list_struct server_filter_list = { 0, 0, " [server]" };
struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" };
struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
/* Need room enough for ":MODS " prefix plus some room to grow. */
#define MAX_RULE_PREFIX (16)
@@ -133,9 +134,9 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
listp->debug_type);
}
/* This flag also indicates that we're reading a list that
/* These flags also indicate that we're reading a list that
* needs to be filtered now, not post-filtered later. */
if (xflags & XFLG_ANCHORED2ABS) {
if (xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH)) {
uint32 mf = mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE);
if (am_sender) {
if (mf == MATCHFLG_RECEIVER_SIDE)
@@ -150,10 +151,14 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
out_of_memory("add_rule");
memset(ret, 0, sizeof ret[0]);
if (xflags & XFLG_ANCHORED2ABS && *pat == '/'
&& !(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))) {
if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
&& ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
|| (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) {
mflags |= MATCHFLG_ABS_PATH;
ex_len = dirbuf_len - module_dirlen - 1;
if (*pat == '/')
ex_len = dirbuf_len - module_dirlen - 1;
else
ex_len = 0;
} else
ex_len = 0;
if (!(ret->pattern = new_array(char, ex_len + pat_len + 1)))
@@ -170,6 +175,12 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
/* If the pattern starts with **, note that. */
if (cp == ret->pattern)
mflags |= MATCHFLG_WILD2_PREFIX;
/* If the pattern ends with ***, note that. */
if (pat_len >= 3
&& ret->pattern[pat_len-3] == '*'
&& ret->pattern[pat_len-2] == '*'
&& ret->pattern[pat_len-1] == '*')
mflags |= MATCHFLG_WILD3_SUFFIX;
}
}
@@ -292,7 +303,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
}
if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
safe_fname(merge_file));
merge_file);
return NULL;
}
} else {
@@ -305,8 +316,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
goto done;
if (dirbuf_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n",
safe_fname(fn));
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
return NULL;
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
@@ -488,71 +498,69 @@ void pop_local_filters(void *mem)
static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
{
char *p, full_name[MAXPATHLEN];
int match_start = 0;
int slash_handling, str_cnt = 0, anchored_match = 0;
int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
char *pattern = ex->pattern;
char *p, *pattern = ex->pattern;
const char *strings[16]; /* more than enough */
if (!*name)
return 0;
/* If the pattern does not have any slashes AND it does not have
* a "**" (which could match a slash), then we just match the
* name portion of the path. */
if (!ex->u.slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {
/* If the pattern does not have any slashes AND it does
* not have a "**" (which could match a slash), then we
* just match the name portion of the path. */
if ((p = strrchr(name,'/')) != NULL)
name = p+1;
}
else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
} else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
&& curr_dir_len > module_dirlen + 1) {
pathjoin(full_name, sizeof full_name,
curr_dir + module_dirlen + 1, name);
name = full_name;
/* If we're matching against an absolute-path pattern,
* we need to prepend our full path info. */
strings[str_cnt++] = curr_dir + module_dirlen + 1;
strings[str_cnt++] = "/";
} else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') {
/* Allow "**"+"/" to match at the start of the string. */
strings[str_cnt++] = "/";
}
if (ex->match_flags & MATCHFLG_DIRECTORY && !name_is_dir)
strings[str_cnt++] = name;
if (name_is_dir) {
/* Allow a trailing "/"+"***" to match the directory. */
if (ex->match_flags & MATCHFLG_WILD3_SUFFIX)
strings[str_cnt++] = "/";
} else if (ex->match_flags & MATCHFLG_DIRECTORY)
return !ret_match;
strings[str_cnt] = NULL;
if (*pattern == '/') {
match_start = 1;
anchored_match = 1;
pattern++;
if (*name == '/')
name++;
if (strings[0][0] == '/')
strings[0]++;
}
if (!anchored_match && ex->u.slash_cnt
&& !(ex->match_flags & MATCHFLG_WILD2)) {
/* A non-anchored match with an infix slash and no "**"
* needs to match the last slash_cnt+1 name elements. */
slash_handling = ex->u.slash_cnt + 1;
} else if (!anchored_match && !(ex->match_flags & MATCHFLG_WILD2_PREFIX)
&& ex->match_flags & MATCHFLG_WILD2) {
/* A non-anchored match with an infix or trailing "**" (but not
* a prefixed "**") needs to try matching after every slash. */
slash_handling = -1;
} else {
/* The pattern matches only at the start of the path or name. */
slash_handling = 0;
}
if (ex->match_flags & MATCHFLG_WILD) {
/* A non-anchored match with an infix slash and no "**"
* needs to match the last slash_cnt+1 name elements. */
if (!match_start && ex->u.slash_cnt
&& !(ex->match_flags & MATCHFLG_WILD2)) {
int cnt = ex->u.slash_cnt + 1;
for (p = name + strlen(name) - 1; p >= name; p--) {
if (*p == '/' && !--cnt)
break;
}
name = p+1;
}
if (wildmatch(pattern, name))
if (wildmatch_array(pattern, strings, slash_handling))
return ret_match;
if (ex->match_flags & MATCHFLG_WILD2_PREFIX) {
/* If the **-prefixed pattern has a '/' as the next
* character, then try to match the rest of the
* pattern at the root. */
if (pattern[2] == '/' && wildmatch(pattern+3, name))
return ret_match;
}
else if (!match_start && ex->match_flags & MATCHFLG_WILD2) {
/* A non-anchored match with an infix or trailing "**"
* (but not a prefixed "**") needs to try matching
* after every slash. */
while ((name = strchr(name, '/')) != NULL) {
name++;
if (wildmatch(pattern, name))
return ret_match;
}
}
} else if (match_start) {
if (strcmp(name,pattern) == 0)
} else if (str_cnt > 1) {
if (litmatch_array(pattern, strings, slash_handling))
return ret_match;
} else if (anchored_match) {
if (strcmp(strings[0], pattern) == 0)
return ret_match;
} else {
int l1 = strlen(name);
@@ -577,11 +585,13 @@ static void report_filter_result(char const *name,
* case we add it back in here. */
if (verbose >= 2) {
rprintf(FINFO, "[%s] %scluding %s %s because of pattern %s%s%s\n",
who_am_i(),
ent->match_flags & MATCHFLG_INCLUDE ? "in" : "ex",
name_is_dir ? "directory" : "file", name, ent->pattern,
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
static char *actions[2][2]
= { {"show", "hid"}, {"risk", "protect"} };
const char *w = who_am_i();
rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n",
w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
name_is_dir ? "directory" : "file", name, ent->pattern,
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
}
}
@@ -827,7 +837,8 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
len = strlen((char*)s);
if (new_mflags & MATCHFLG_CLEAR_LIST) {
if (!(xflags & XFLG_OLD_PREFIXES) && len) {
if (!(mflags & MATCHFLG_NO_PREFIXES)
&& !(xflags & XFLG_OLD_PREFIXES) && len) {
rprintf(FERROR,
"'!' rule has trailing characters: %s\n", p);
exit_cleanup(RERR_SYNTAX);
@@ -954,7 +965,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
uint32 mflags, int xflags)
{
FILE *fp;
char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
char line[BIGPATHBUFLEN];
char *eob = line + sizeof line - 1;
int word_split = mflags & MATCHFLG_WORD_SPLIT;
@@ -976,7 +987,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
if (verbose > 2) {
rprintf(FINFO, "[%s] parse_filter_file(%s,%x,%x)%s\n",
who_am_i(), safe_fname(fname), mflags, xflags,
who_am_i(), fname, mflags, xflags,
fp ? "" : " [not found]");
}
@@ -985,7 +996,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
rsyserr(FERROR, errno,
"failed to open %sclude file %s",
mflags & MATCHFLG_INCLUDE ? "in" : "ex",
safe_fname(fname));
fname);
exit_cleanup(RERR_FILEIO);
}
return;
@@ -997,8 +1008,10 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
int ch, overflow = 0;
while (1) {
if ((ch = getc(fp)) == EOF) {
if (ferror(fp) && errno == EINTR)
if (ferror(fp) && errno == EINTR) {
clearerr(fp);
continue;
}
break;
}
if (word_split && isspace(ch))
@@ -1135,8 +1148,8 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
/* This is only called by the client. */
void send_filter_list(int f_out)
{
int receiver_wants_list = delete_mode
&& (!delete_excluded || protocol_version >= 29);
int receiver_wants_list = prune_empty_dirs
|| (delete_mode && (!delete_excluded || protocol_version >= 29));
if (local_server || (am_sender && !receiver_wants_list))
f_out = -1;
@@ -1167,16 +1180,17 @@ void send_filter_list(int f_out)
/* This is only called by the server. */
void recv_filter_list(int f_in)
{
char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
char line[BIGPATHBUFLEN];
int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
int receiver_wants_list = delete_mode
&& (!delete_excluded || protocol_version >= 29);
int receiver_wants_list = prune_empty_dirs
|| (delete_mode
&& (!delete_excluded || protocol_version >= 29));
unsigned int len;
if (!local_server && (am_sender || receiver_wants_list)) {
while ((len = read_int(f_in)) != 0) {
if (len >= sizeof line)
overflow("recv_rules");
overflow_exit("recv_rules");
read_sbuf(f_in, line, len);
parse_rule(&filter_list, line, 0, xflags);
}

View File

@@ -22,6 +22,10 @@
*/
#include "rsync.h"
#ifndef ENODATA
#define ENODATA EAGAIN
#endif
extern int sparse_files;
static char last_byte;
@@ -217,34 +221,35 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
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) {
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;
}
if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
if (nread < 0) {
nread = 0;
if (!map->status)
map->status = errno;
}
/* the best we can do is zero the buffer - the file
has changed mid transfer! */
memset(map->p+read_offset+nread, 0, read_size - nread);
}
map->p_fd_offset += nread;
}
if (map->p_fd_offset != read_start) {
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
if (ret != read_start) {
rsyserr(FERROR, errno, "lseek returned %.0f, not %.0f",
(double)ret, (double)read_start);
exit_cleanup(RERR_FILEIO);
}
map->p_fd_offset = read_start;
}
map->p_offset = window_start;
map->p_len = window_size;
while (read_size > 0) {
nread = read(map->fd, map->p + read_offset, read_size);
if (nread <= 0) {
if (!map->status)
map->status = nread ? errno : ENODATA;
/* The best we can do is zero the buffer -- the file
* has changed mid transfer! */
memset(map->p + read_offset, 0, read_size);
break;
}
map->p_fd_offset += nread;
read_offset += nread;
read_size -= nread;
}
return map->p;
}

618
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

51
hlink.c
View File

@@ -20,9 +20,11 @@
#include "rsync.h"
extern int dry_run;
extern int verbose;
extern int link_dest;
extern int make_backups;
extern int log_format_has_i;
extern char *basis_dir[];
extern struct file_list *the_file_list;
#ifdef SUPPORT_HARD_LINKS
@@ -172,26 +174,49 @@ int hard_link_check(struct file_struct *file, int ndx, char *fname,
{
#ifdef SUPPORT_HARD_LINKS
int head;
if (!file->link_u.links)
return 0;
if (skip && !(file->flags & FLAG_HLINK_EOL))
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) {
if (!log_format_has_i && verbose > 1) {
rprintf(FINFO, "\"%s\" is a hard link\n",
safe_fname(f_name(file)));
f_name(file, NULL));
}
if (head_file->F_HLINDEX == FINISHED_LINK) {
STRUCT_STAT st2;
char *toname = f_name(head_file);
STRUCT_STAT st2, st3;
char *toname = f_name(head_file, NULL);
if (link_stat(toname, &st2, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(toname));
return -1;
}
if (statret < 0 && basis_dir[0] != NULL) {
char cmpbuf[MAXPATHLEN];
int j = 0;
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &st3, 0) < 0)
continue;
if (link_dest) {
if (st2.st_dev != st3.st_dev
|| st2.st_ino != st3.st_ino)
continue;
statret = 1;
st = &st3;
if (verbose < 2 || !log_format_has_i)
itemizing = code = 0;
break;
}
if (!unchanged_file(cmpbuf, file, &st3))
continue;
statret = 1;
st = &st3;
if (unchanged_attrs(file, &st3))
break;
} while (basis_dir[++j] != NULL);
}
maybe_hard_link(file, ndx, fname, statret, st,
toname, &st2, itemizing, code);
file->F_HLINDEX = FINISHED_LINK;
@@ -216,7 +241,7 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
} else
code = FERROR;
rsyserr(code, errno, "link %s => %s failed",
full_fname(fname), safe_fname(toname));
full_fname(fname), toname);
return -1;
}
@@ -225,10 +250,8 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
terse ? "" : toname);
}
if (code && verbose && !terse) {
rprintf(code, "%s => %s\n",
safe_fname(fname), safe_fname(toname));
}
if (code && verbose && !terse)
rprintf(code, "%s => %s\n", fname, toname);
return 0;
}
#endif
@@ -244,7 +267,7 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
int statret, ndx = master;
file->F_HLINDEX = FINISHED_LINK;
if (link_stat(f_name_to(file, hlink1), &st1, 0) < 0)
if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
return;
if (!(file->flags & FLAG_HLINK_TOL)) {
while (!(file->flags & FLAG_HLINK_EOL)) {
@@ -257,7 +280,7 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
file = FPTR(ndx);
if (file->F_HLINDEX != SKIPPED_LINK)
continue;
hlink2 = f_name(file);
hlink2 = f_name(file, NULL);
statret = link_stat(hlink2, &st2, 0);
maybe_hard_link(file, ndx, hlink2, statret, &st2,
hlink1, &st1, itemizing, code);

411
io.c
View File

@@ -41,7 +41,6 @@
extern int bwlimit;
extern size_t bwlimit_writemax;
extern int verbose;
extern int io_timeout;
extern int allowed_lull;
extern int am_server;
@@ -49,6 +48,7 @@ extern int am_daemon;
extern int am_sender;
extern int am_generator;
extern int eol_nulls;
extern int read_batch;
extern int csum_length;
extern int checksum_seed;
extern int protocol_version;
@@ -59,27 +59,10 @@ extern struct stats stats;
extern struct file_list *the_file_list;
const char phase_unknown[] = "unknown";
int select_timeout = SELECT_TIMEOUT;
int ignore_timeout = 0;
int batch_fd = -1;
int batch_gen_fd = -1;
/**
* The connection might be dropped at some point; perhaps because the
* remote instance crashed. Just giving the offset on the stream is
* not very helpful. So instead we try to make io_phase_name point to
* something useful.
*
* For buffered/multiplexed I/O these names will be somewhat
* approximate; perhaps for ease of support we would rather make the
* buffer always flush when a single application-level I/O finishes.
*
* @todo Perhaps we want some simple stack functionality, but there's
* no need to overdo it.
**/
const char *io_write_phase = phase_unknown;
const char *io_read_phase = phase_unknown;
/* Ignore an EOF error if non-zero. See whine_about_eof(). */
int kluge_around_eof = 0;
@@ -90,7 +73,8 @@ int sock_f_out = -1;
static int io_multiplexing_out;
static int io_multiplexing_in;
static time_t last_io;
static time_t last_io_in;
static time_t last_io_out;
static int no_flush;
static int write_batch_monitor_in = -1;
@@ -102,7 +86,10 @@ static char io_filesfrom_buf[2048];
static char *io_filesfrom_bp;
static char io_filesfrom_lastchar;
static int io_filesfrom_buflen;
static size_t contiguous_write_len = 0;
static int defer_forwarding_messages = 0;
static int select_timeout = SELECT_TIMEOUT;
static int active_filecnt = 0;
static OFF_T active_bytecnt = 0;
static void read_loop(int fd, char *buf, size_t len);
@@ -117,14 +104,17 @@ struct flist_ndx_list {
static struct flist_ndx_list redo_list, hlink_list;
struct msg_list {
struct msg_list *next;
char *buf;
struct msg_list_item {
struct msg_list_item *next;
int len;
char buf[1];
};
static struct msg_list *msg_list_head;
static struct msg_list *msg_list_tail;
struct msg_list {
struct msg_list_item *head, *tail;
};
static struct msg_list msg2genr, msg2sndr;
static void flist_ndx_push(struct flist_ndx_list *lp, int ndx)
{
@@ -166,17 +156,17 @@ static void check_timeout(void)
if (!io_timeout || ignore_timeout)
return;
if (!last_io) {
last_io = time(NULL);
if (!last_io_in) {
last_io_in = time(NULL);
return;
}
t = time(NULL);
if (t - last_io >= io_timeout) {
if (t - last_io_in >= io_timeout) {
if (!am_server && !am_daemon) {
rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
(int)(t-last_io));
(int)(t-last_io_in));
}
exit_cleanup(RERR_TIMEOUT);
}
@@ -190,6 +180,18 @@ void io_set_sock_fds(int f_in, int f_out)
sock_f_out = f_out;
}
void set_io_timeout(int secs)
{
io_timeout = secs;
if (!io_timeout || io_timeout > SELECT_TIMEOUT)
select_timeout = SELECT_TIMEOUT;
else
select_timeout = io_timeout;
allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
}
/* Setup the fd used to receive MSG_* messages. Only needed during the
* early stages of being a local sender (up through the sending of the
* file list) or when we're the generator (to fetch the messages from
@@ -208,33 +210,22 @@ void set_msg_fd_out(int fd)
}
/* Add a message to the pending MSG_* list. */
static void msg_list_add(int code, char *buf, int len)
static void msg_list_add(struct msg_list *lst, int code, char *buf, int len)
{
struct msg_list *ml;
struct msg_list_item *m;
int sz = len + 4 + sizeof m[0] - 1;
if (!(ml = new(struct msg_list)))
if (!(m = (struct msg_list_item *)new_array(char, sz)))
out_of_memory("msg_list_add");
ml->next = NULL;
if (!(ml->buf = new_array(char, len+4)))
out_of_memory("msg_list_add");
SIVAL(ml->buf, 0, ((code+MPLEX_BASE)<<24) | len);
memcpy(ml->buf+4, buf, len);
ml->len = len+4;
if (msg_list_tail)
msg_list_tail->next = ml;
m->next = NULL;
m->len = len + 4;
SIVAL(m->buf, 0, ((code+MPLEX_BASE)<<24) | len);
memcpy(m->buf + 4, buf, len);
if (lst->tail)
lst->tail->next = m;
else
msg_list_head = ml;
msg_list_tail = ml;
}
void send_msg(enum msgcode code, char *buf, int len)
{
if (msg_fd_out < 0) {
io_multiplex_write(code, buf, len);
return;
}
msg_list_add(code, buf, len);
msg_list_push(NORMAL_FLUSH);
lst->head = m;
lst->tail = m;
}
/* Read a message from the MSG_* fd and handle it. This is called either
@@ -272,6 +263,8 @@ static void read_msg_fd(void)
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, 4);
if (remove_sent_files)
decrement_active_files(IVAL(buf,0));
flist_ndx_push(&redo_list, IVAL(buf,0));
break;
case MSG_DELETED:
@@ -280,7 +273,10 @@ static void read_msg_fd(void)
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, len);
io_multiplex_write(MSG_DELETED, buf, len);
if (defer_forwarding_messages)
msg_list_add(&msg2sndr, MSG_DELETED, buf, len);
else
io_multiplex_write(MSG_DELETED, buf, len);
break;
case MSG_SUCCESS:
if (len != 4 || !am_generator) {
@@ -288,11 +284,23 @@ static void read_msg_fd(void)
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, len);
if (remove_sent_files)
io_multiplex_write(MSG_SUCCESS, buf, len);
if (remove_sent_files) {
decrement_active_files(IVAL(buf,0));
if (defer_forwarding_messages)
msg_list_add(&msg2sndr, MSG_SUCCESS, buf, len);
else
io_multiplex_write(MSG_SUCCESS, buf, len);
}
if (preserve_hard_links)
flist_ndx_push(&hlink_list, IVAL(buf,0));
break;
case MSG_SOCKERR:
if (!am_generator) {
rprintf(FERROR, "invalid message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
close_multiplexing_out();
/* FALL THROUGH */
case MSG_INFO:
case MSG_ERROR:
case MSG_LOG:
@@ -301,22 +309,48 @@ static void read_msg_fd(void)
if (n >= sizeof buf)
n = sizeof buf - 1;
read_loop(fd, buf, n);
rwrite((enum logcode)tag, buf, n);
if (am_generator && am_server && defer_forwarding_messages)
msg_list_add(&msg2sndr, tag, buf, n);
else
rwrite((enum logcode)tag, buf, n);
len -= n;
}
break;
default:
rprintf(FERROR, "unknown message %d:%d\n", tag, len);
rprintf(FERROR, "unknown message %d:%d [%s]\n",
tag, len, who_am_i());
exit_cleanup(RERR_STREAMIO);
}
msg_fd_in = fd;
}
/* This is used by the generator to limit how many file transfers can
* be active at once when --remove-sent-files is specified. Without
* this, sender-side deletions were mostly happening at the end. */
void increment_active_files(int ndx, int itemizing, enum logcode code)
{
/* TODO: tune these limits? */
while (active_filecnt >= (active_bytecnt >= 128*1024 ? 10 : 50)) {
if (hlink_list.head)
check_for_finished_hlinks(itemizing, code);
read_msg_fd();
}
active_filecnt++;
active_bytecnt += the_file_list->files[ndx]->length;
}
void decrement_active_files(int ndx)
{
active_filecnt--;
active_bytecnt -= the_file_list->files[ndx]->length;
}
/* Try to push messages off the list onto the wire. If we leave with more
* to do, return 0. On error, return -1. If everything flushed, return 1.
* This is only active in the receiver. */
int msg_list_push(int flush_it_all)
static int msg2genr_flush(int flush_it_all)
{
static int written = 0;
struct timeval tv;
@@ -325,9 +359,9 @@ int msg_list_push(int flush_it_all)
if (msg_fd_out < 0)
return -1;
while (msg_list_head) {
struct msg_list *ml = msg_list_head;
int n = write(msg_fd_out, ml->buf + written, ml->len - written);
while (msg2genr.head) {
struct msg_list_item *m = msg2genr.head;
int n = write(msg_fd_out, m->buf + written, m->len - written);
if (n < 0) {
if (errno == EINTR)
continue;
@@ -341,18 +375,27 @@ int msg_list_push(int flush_it_all)
tv.tv_usec = 0;
if (!select(msg_fd_out+1, NULL, &fds, NULL, &tv))
check_timeout();
} else if ((written += n) == ml->len) {
free(ml->buf);
msg_list_head = ml->next;
if (!msg_list_head)
msg_list_tail = NULL;
free(ml);
} else if ((written += n) == m->len) {
msg2genr.head = m->next;
if (!msg2genr.head)
msg2genr.tail = NULL;
free(m);
written = 0;
}
}
return 1;
}
void send_msg(enum msgcode code, char *buf, int len)
{
if (msg_fd_out < 0) {
io_multiplex_write(code, buf, len);
return;
}
msg_list_add(&msg2genr, code, buf, len);
msg2genr_flush(NORMAL_FLUSH);
}
int get_redo_num(int itemizing, enum logcode code)
{
while (1) {
@@ -420,7 +463,6 @@ static void whine_about_eof(int fd)
exit_cleanup(RERR_STREAMIO);
}
/**
* Read from a socket with I/O timeout. return the number of bytes
* read. If no bytes can be read then exit, never return a number <= 0.
@@ -434,11 +476,11 @@ static void whine_about_eof(int fd)
*/
static int read_timeout(int fd, char *buf, size_t len)
{
int n, ret = 0;
int n, cnt = 0;
io_flush(NORMAL_FLUSH);
while (ret == 0) {
while (cnt == 0) {
/* until we manage to read *something* */
fd_set r_fds, w_fds;
struct timeval tv;
@@ -448,7 +490,7 @@ static int read_timeout(int fd, char *buf, size_t len)
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
FD_SET(fd, &r_fds);
if (msg_list_head) {
if (msg2genr.head) {
FD_SET(msg_fd_out, &w_fds);
if (msg_fd_out > maxfd)
maxfd = msg_fd_out;
@@ -485,8 +527,8 @@ static int read_timeout(int fd, char *buf, size_t len)
continue;
}
if (msg_list_head && FD_ISSET(msg_fd_out, &w_fds))
msg_list_push(NORMAL_FLUSH);
if (msg2genr.head && FD_ISSET(msg_fd_out, &w_fds))
msg2genr_flush(NORMAL_FLUSH);
if (io_filesfrom_f_out >= 0) {
if (io_filesfrom_buflen) {
@@ -564,21 +606,23 @@ static int read_timeout(int fd, char *buf, size_t len)
continue;
/* Don't write errors on a dead socket. */
if (fd == sock_f_in)
if (fd == sock_f_in) {
close_multiplexing_out();
rsyserr(FERROR, errno, "read error");
rsyserr(FSOCKERR, errno, "read error");
} else
rsyserr(FERROR, errno, "read error");
exit_cleanup(RERR_STREAMIO);
}
buf += n;
len -= n;
ret += n;
cnt += n;
if (fd == sock_f_in && (io_timeout || am_generator))
last_io = time(NULL);
if (fd == sock_f_in && io_timeout)
last_io_in = time(NULL);
}
return ret;
return cnt;
}
/**
@@ -628,7 +672,6 @@ int read_filesfrom_line(int fd, char *fname)
return s - fname;
}
static char *iobuf_out;
static int iobuf_out_cnt;
@@ -641,7 +684,6 @@ void io_start_buffering_out(void)
iobuf_out_cnt = 0;
}
static char *iobuf_in;
static size_t iobuf_in_siz;
@@ -654,7 +696,6 @@ void io_start_buffering_in(void)
out_of_memory("io_start_buffering_in");
}
void io_end_buffering(void)
{
io_flush(NORMAL_FLUSH);
@@ -664,17 +705,15 @@ void io_end_buffering(void)
}
}
void maybe_flush_socket(void)
{
if (iobuf_out && iobuf_out_cnt && time(NULL) - last_io >= 5)
if (iobuf_out && iobuf_out_cnt && time(NULL) - last_io_out >= 5)
io_flush(NORMAL_FLUSH);
}
void maybe_send_keepalive(void)
{
if (time(NULL) - last_io >= allowed_lull) {
if (time(NULL) - last_io_out >= allowed_lull) {
if (!iobuf_out || !iobuf_out_cnt) {
if (protocol_version < 29)
return; /* there's nothing we can do */
@@ -686,7 +725,6 @@ void maybe_send_keepalive(void)
}
}
/**
* Continue trying to read len bytes - don't return until len has been
* read.
@@ -701,7 +739,6 @@ static void read_loop(int fd, char *buf, size_t len)
}
}
/**
* Read from the file descriptor handling multiplexing - return number
* of bytes read.
@@ -712,12 +749,9 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
{
static size_t remaining;
static size_t iobuf_in_ndx;
int tag, ret = 0;
#if MAXPATHLEN < 4096
char line[4096+1024];
#else
char line[MAXPATHLEN+1024];
#endif
size_t msg_bytes;
int tag, cnt = 0;
char line[BIGPATHBUFLEN];
if (!iobuf_in || fd != sock_f_in)
return read_timeout(fd, buf, len);
@@ -727,69 +761,66 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
iobuf_in_ndx = 0;
}
while (ret == 0) {
while (cnt == 0) {
if (remaining) {
len = MIN(len, remaining);
memcpy(buf, iobuf_in + iobuf_in_ndx, len);
iobuf_in_ndx += len;
remaining -= len;
ret = len;
cnt = len;
break;
}
read_loop(fd, line, 4);
tag = IVAL(line, 0);
remaining = tag & 0xFFFFFF;
msg_bytes = tag & 0xFFFFFF;
tag = (tag >> 24) - MPLEX_BASE;
switch (tag) {
case MSG_DATA:
if (remaining > iobuf_in_siz) {
if (msg_bytes > iobuf_in_siz) {
if (!(iobuf_in = realloc_array(iobuf_in, char,
remaining)))
msg_bytes)))
out_of_memory("readfd_unbuffered");
iobuf_in_siz = remaining;
iobuf_in_siz = msg_bytes;
}
read_loop(fd, iobuf_in, remaining);
read_loop(fd, iobuf_in, msg_bytes);
remaining = msg_bytes;
iobuf_in_ndx = 0;
break;
case MSG_DELETED:
if (remaining >= sizeof line) {
rprintf(FERROR, "invalid multi-message %d:%ld\n",
tag, (long)remaining);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
line[remaining] = '\0';
if (msg_bytes >= sizeof line)
goto overflow;
read_loop(fd, line, msg_bytes);
/* A directory name was sent with the trailing null */
if (remaining > 0 && !line[remaining-1])
if (msg_bytes > 0 && !line[msg_bytes-1])
log_delete(line, S_IFDIR);
else
else {
line[msg_bytes] = '\0';
log_delete(line, S_IFREG);
remaining = 0;
}
break;
case MSG_SUCCESS:
if (remaining != 4) {
if (msg_bytes != 4) {
rprintf(FERROR, "invalid multi-message %d:%ld [%s]\n",
tag, (long)remaining, who_am_i());
tag, (long)msg_bytes, who_am_i());
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
read_loop(fd, line, msg_bytes);
successful_send(IVAL(line, 0));
remaining = 0;
break;
case MSG_INFO:
case MSG_ERROR:
if (remaining >= sizeof line) {
if (msg_bytes >= sizeof line) {
overflow:
rprintf(FERROR,
"multiplexing overflow %d:%ld [%s]\n",
tag, (long)remaining, who_am_i());
tag, (long)msg_bytes, who_am_i());
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
rwrite((enum logcode)tag, line, remaining);
remaining = 0;
read_loop(fd, line, msg_bytes);
rwrite((enum logcode)tag, line, msg_bytes);
break;
default:
rprintf(FERROR, "unexpected tag %d [%s]\n",
@@ -801,11 +832,9 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
if (remaining == 0)
io_flush(NORMAL_FLUSH);
return ret;
return cnt;
}
/**
* Do a buffered read from @p fd. Don't return until all @p n bytes
* have been read. If all @p n can't be read then exit with an
@@ -813,12 +842,12 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
**/
static void readfd(int fd, char *buffer, size_t N)
{
int ret;
int cnt;
size_t total = 0;
while (total < N) {
ret = readfd_unbuffered(fd, buffer + total, N-total);
total += ret;
cnt = readfd_unbuffered(fd, buffer + total, N-total);
total += cnt;
}
if (fd == write_batch_monitor_in) {
@@ -830,7 +859,6 @@ static void readfd(int fd, char *buffer, size_t N)
stats.total_read += total;
}
int read_shortint(int f)
{
uchar b[2];
@@ -838,37 +866,36 @@ int read_shortint(int f)
return (b[1] << 8) + b[0];
}
int32 read_int(int f)
{
char b[4];
int32 ret;
int32 num;
readfd(f,b,4);
ret = IVAL(b,0);
if (ret == (int32)0xffffffff)
num = IVAL(b,0);
if (num == (int32)0xffffffff)
return -1;
return ret;
return num;
}
int64 read_longint(int f)
{
int64 ret;
int64 num;
char b[8];
ret = read_int(f);
num = read_int(f);
if ((int32)ret != (int32)0xffffffff)
return ret;
if ((int32)num != (int32)0xffffffff)
return num;
#if SIZEOF_INT64 < 8
rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n");
exit_cleanup(RERR_UNSUPPORTED);
#else
readfd(f,b,8);
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
num = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
#endif
return ret;
return num;
}
void read_buf(int f,char *buf,size_t len)
@@ -913,6 +940,11 @@ int read_vstring(int f, char *buf, int bufsize)
void read_sum_head(int f, struct sum_struct *sum)
{
sum->count = read_int(f);
if (sum->count < 0) {
rprintf(FERROR, "Invalid checksum count %ld [%s]\n",
(long)sum->count, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
sum->blength = read_int(f);
if (sum->blength < 0 || sum->blength > MAX_BLOCK_SIZE) {
rprintf(FERROR, "Invalid block length %ld [%s]\n",
@@ -950,7 +982,6 @@ void write_sum_head(int f, struct sum_struct *sum)
write_int(f, sum->remainder);
}
/**
* Sleep after writing to limit I/O bandwidth usage.
*
@@ -976,7 +1007,7 @@ static void sleep_for_bwlimit(int bytes_written)
#define ONE_SEC 1000000L /* # of microseconds in a second */
if (!bwlimit)
if (!bwlimit_writemax)
return;
total_written += bytes_written;
@@ -1006,9 +1037,8 @@ static void sleep_for_bwlimit(int bytes_written)
total_written = (sleep_usec - elapsed_usec) * bwlimit / (ONE_SEC/1024);
}
/* Write len bytes to the file descriptor fd, looping as necessary to get
* the job done and also (in certain circumstnces) reading any data on
* the job done and also (in certain circumstances) reading any data on
* msg_fd_in to avoid deadlock.
*
* This function underlies the multiplexing system. The body of the
@@ -1017,7 +1047,8 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
{
size_t n, total = 0;
fd_set w_fds, r_fds;
int maxfd, count, ret, using_r_fds;
int maxfd, count, cnt, using_r_fds;
int defer_save = defer_forwarding_messages;
struct timeval tv;
no_flush++;
@@ -1027,7 +1058,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
FD_SET(fd,&w_fds);
maxfd = fd;
if (msg_fd_in >= 0 && len-total >= contiguous_write_len) {
if (msg_fd_in >= 0) {
FD_ZERO(&r_fds);
FD_SET(msg_fd_in,&r_fds);
if (msg_fd_in > maxfd)
@@ -1035,11 +1066,6 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
using_r_fds = 1;
} else
using_r_fds = 0;
if (fd != sock_f_out && iobuf_out_cnt && no_flush == 1) {
FD_SET(sock_f_out, &w_fds);
if (sock_f_out > maxfd)
maxfd = sock_f_out;
}
tv.tv_sec = select_timeout;
tv.tv_usec = 0;
@@ -1062,12 +1088,12 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
continue;
n = len - total;
if (bwlimit && n > bwlimit_writemax)
if (bwlimit_writemax && n > bwlimit_writemax)
n = bwlimit_writemax;
ret = write(fd, buf + total, n);
cnt = write(fd, buf + total, n);
if (ret <= 0) {
if (ret < 0) {
if (cnt <= 0) {
if (cnt < 0) {
if (errno == EINTR)
continue;
if (errno == EWOULDBLOCK || errno == EAGAIN) {
@@ -1080,12 +1106,12 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
if (fd == sock_f_out)
close_multiplexing_out();
rsyserr(FERROR, errno,
"writefd_unbuffered failed to write %ld bytes: phase \"%s\" [%s]",
(long)len, io_write_phase, who_am_i());
"writefd_unbuffered failed to write %ld bytes [%s]",
(long)len, who_am_i());
/* If the other side is sending us error messages, try
* to grab any messages they sent before they died. */
while (fd == sock_f_out && io_multiplexing_in) {
io_timeout = select_timeout = 30;
set_io_timeout(30);
ignore_timeout = 0;
readfd_unbuffered(sock_f_in, io_filesfrom_buf,
sizeof io_filesfrom_buf);
@@ -1093,18 +1119,36 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
exit_cleanup(RERR_STREAMIO);
}
total += ret;
total += cnt;
defer_forwarding_messages = 1;
if (fd == sock_f_out) {
if (io_timeout || am_generator)
last_io = time(NULL);
sleep_for_bwlimit(ret);
last_io_out = time(NULL);
sleep_for_bwlimit(cnt);
}
}
defer_forwarding_messages = defer_save;
no_flush--;
}
static void msg2sndr_flush(void)
{
if (defer_forwarding_messages)
return;
while (msg2sndr.head && io_multiplexing_out) {
struct msg_list_item *m = msg2sndr.head;
if (!(msg2sndr.head = m->next))
msg2sndr.tail = NULL;
stats.total_written += m->len;
defer_forwarding_messages = 1;
writefd_unbuffered(sock_f_out, m->buf, m->len);
defer_forwarding_messages = 0;
free(m);
}
}
/**
* Write an message to a multiplexed stream. If this fails then rsync
@@ -1112,38 +1156,33 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
**/
static void mplex_write(enum msgcode code, char *buf, size_t len)
{
char buffer[4096];
char buffer[1024];
size_t n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
/* When the generator reads messages from the msg_fd_in pipe, it can
* cause output to occur down the socket. Setting contiguous_write_len
* prevents the reading of msg_fd_in once we actually start to write
* this sequence of data (though we might read it before the start). */
if (am_generator && msg_fd_in >= 0)
contiguous_write_len = len + 4;
if (n > sizeof buffer - 4)
n = sizeof buffer - 4;
n = 0;
else
memcpy(buffer + 4, buf, n);
memcpy(&buffer[4], buf, n);
writefd_unbuffered(sock_f_out, buffer, n+4);
len -= n;
buf += n;
if (len)
if (len) {
defer_forwarding_messages = 1;
writefd_unbuffered(sock_f_out, buf, len);
if (am_generator && msg_fd_in >= 0)
contiguous_write_len = 0;
defer_forwarding_messages = 0;
msg2sndr_flush();
}
}
void io_flush(int flush_it_all)
{
msg_list_push(flush_it_all);
msg2genr_flush(flush_it_all);
msg2sndr_flush();
if (!iobuf_out_cnt || no_flush)
return;
@@ -1155,7 +1194,6 @@ void io_flush(int flush_it_all)
iobuf_out_cnt = 0;
}
static void writefd(int fd,char *buf,size_t len)
{
if (fd == msg_fd_out) {
@@ -1190,7 +1228,6 @@ static void writefd(int fd,char *buf,size_t len)
}
}
void write_shortint(int f, int x)
{
uchar b[2];
@@ -1199,7 +1236,6 @@ void write_shortint(int f, int x)
writefd(f, (char *)b, 2);
}
void write_int(int f,int32 x)
{
char b[4];
@@ -1207,15 +1243,6 @@ void write_int(int f,int32 x)
writefd(f,b,4);
}
void write_int_named(int f, int32 x, const char *phase)
{
io_write_phase = phase;
write_int(f, x);
io_write_phase = phase_unknown;
}
/*
* Note: int64 may actually be a 32-bit type if ./configure couldn't find any
* 64-bit types on this platform.
@@ -1277,7 +1304,6 @@ void write_vstring(int f, char *str, int len)
writefd(f, str, len);
}
/**
* Read a line of up to @p maxlen characters into @p buf (not counting
* the trailing null). Strips the (required) trailing newline and all
@@ -1303,11 +1329,10 @@ int read_line(int f, char *buf, size_t maxlen)
return maxlen > 0;
}
void io_printf(int fd, const char *format, ...)
{
va_list ap;
char buf[1024];
char buf[BIGPATHBUFLEN];
int len;
va_start(ap, format);
@@ -1317,10 +1342,14 @@ void io_printf(int fd, const char *format, ...)
if (len < 0)
exit_cleanup(RERR_STREAMIO);
if (len > (int)sizeof buf) {
rprintf(FERROR, "io_printf() was too long for the buffer.\n");
exit_cleanup(RERR_STREAMIO);
}
write_sbuf(fd, buf);
}
/** Setup for multiplexing a MSG_* stream with the data stream. */
void io_start_multiplex_out(void)
{

View File

@@ -150,49 +150,6 @@
}
#endif
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#ifdef WORDS_BIGENDIAN
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif
#ifdef REPLACE_INET_ATON
int inet_aton(const char *cp, struct in_addr *inp)
{
unsigned int a1, a2, a3, a4;
unsigned long ret;
if (strcmp(cp, "255.255.255.255") == 0) {
inp->s_addr = (unsigned) -1;
return 0;
}
if (sscanf(cp, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4 ||
a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255) {
return 0;
}
ret = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
inp->s_addr = htonl(ret);
if (inp->s_addr == (unsigned) -1) {
return 0;
}
return 1;
}
#endif
/* some systems don't take the 2nd argument */
int sys_gettimeofday(struct timeval *tv)
{

View File

@@ -26,8 +26,7 @@
*
* @param buf buffer of at least 11 characters
**/
void permstring(char *perms,
int mode)
void permstring(char *perms, mode_t mode)
{
static const char *perm_map = "rwxrwxrwx";
int i;

View File

@@ -1,3 +1,3 @@
#define PERMSTRING_SIZE 11
void permstring(char *perms, int mode);
void permstring(char *perms, mode_t mode);

View File

@@ -56,8 +56,7 @@ pool_create(size_t size, size_t quantum,
pool->size = size /* round extent size to min alignment reqs */
? (size + MINALIGN - 1) & ~(MINALIGN - 1)
: POOL_DEF_EXTENT;
if (pool->flags & POOL_INTERN)
{
if (pool->flags & POOL_INTERN) {
pool->size -= sizeof (struct pool_extent);
flags |= POOL_APPEND;
}
@@ -77,15 +76,13 @@ pool_destroy(alloc_pool_t p)
if (!pool)
return;
if (pool->live)
{
if (pool->live) {
cur = pool->live;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
}
for (cur = pool->free; cur; cur = next)
{
for (cur = pool->free; cur; cur = next) {
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
@@ -109,16 +106,14 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
if (len > pool->size)
goto bomb;
if (!pool->live || len > pool->live->free)
{
if (!pool->live || len > pool->live->free) {
void *start;
size_t free;
size_t bound;
size_t sqew;
size_t asize;
if (pool->live)
{
if (pool->live) {
pool->live->next = pool->free;
pool->free = pool->live;
}
@@ -137,16 +132,11 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
memset(start, 0, pool->size);
if (pool->flags & POOL_APPEND)
{
pool->live = PTR_ADD(start, free);
}
else if (!(pool->live = (struct pool_extent *) malloc(sizeof (struct pool_extent))))
{
goto bomb;
}
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum))
{
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
bound += sqew;
free -= sqew;
}
@@ -186,8 +176,7 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
else if (pool->quantum > 1 && len % pool->quantum)
len += pool->quantum - len % pool->quantum;
if (!addr && pool->live)
{
if (!addr && pool->live) {
pool->live->next = pool->free;
pool->free = pool->live;
pool->live = NULL;
@@ -197,35 +186,28 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
pool->b_freed += len;
cur = pool->live;
if (cur
&& addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
{
if (addr == PTR_ADD(cur->start, cur->free))
{
if (cur && addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size)) {
if (addr == PTR_ADD(cur->start, cur->free)) {
if (pool->flags & POOL_CLEAR)
memset(addr, 0, len);
pool->b_freed += len;
} else {
} else
cur->bound += len;
}
if (cur->free + cur->bound >= pool->size)
{
if (cur->free + cur->bound >= pool->size) {
size_t sqew;
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum))
{
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
cur->bound += sqew;
cur->free -= sqew;
}
}
return;
}
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next)
{
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next) {
if (addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
break;
@@ -233,16 +215,14 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
if (!cur)
return;
if (prev)
{
if (prev) {
prev->next = cur->next;
cur->next = pool->free;
pool->free = cur;
}
cur->bound += len;
if (cur->free + cur->bound >= pool->size)
{
if (cur->free + cur->bound >= pool->size) {
pool->free = cur->next;
free(cur->start);
@@ -254,11 +234,11 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
}
#define FDPRINT(label, value) \
snprintf(buf, BUFSIZ, label, value), \
write(fd, buf, strlen(buf));
snprintf(buf, sizeof buf, label, value), \
write(fd, buf, strlen(buf))
#define FDEXTSTAT(ext) \
snprintf(buf, BUFSIZ, " %12ld %5ld\n", \
snprintf(buf, sizeof buf, " %12ld %5ld\n", \
(long) ext->free, \
(long) ext->bound), \
write(fd, buf, strlen(buf))
@@ -291,14 +271,10 @@ pool_stats(alloc_pool_t p, int fd, int summarize)
write(fd, "\n", 1);
if (pool->live)
{
FDEXTSTAT(pool->live);
}
strcpy(buf, " FREE BOUND\n");
write(fd, buf, strlen(buf));
for (cur = pool->free; cur; cur = cur->next)
{
FDEXTSTAT(cur);
}
}

View File

@@ -146,7 +146,7 @@
#endif
#ifndef VA_COPY
#ifdef HAVE_VA_COPY
#if defined HAVE_VA_COPY || defined va_copy
#define VA_COPY(dest, src) va_copy(dest, src)
#else
#ifdef HAVE___VA_COPY

View File

@@ -57,173 +57,312 @@
int wildmatch_iteration_count;
#endif
static int domatch(const uchar *p, const uchar *text)
static int force_lower_case = 0;
/* Match pattern "p" against the a virtually-joined string consisting
* of "text" and any strings in array "a". */
static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
{
int matched, special;
uchar ch, prev;
uchar p_ch;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count++;
#endif
for ( ; (ch = *p) != '\0'; text++, p++) {
if (*text == '\0' && ch != '*')
return FALSE;
switch (ch) {
for ( ; (p_ch = *p) != '\0'; text++, p++) {
int matched, special;
uchar t_ch, prev_ch;
while ((t_ch = *text) == '\0') {
if (*a == NULL) {
if (p_ch != '*')
return ABORT_ALL;
break;
}
text = *a++;
}
if (force_lower_case && ISUPPER(t_ch))
t_ch = tolower(t_ch);
switch (p_ch) {
case '\\':
/* Literal match with following character. Note that the test
* in "default" handles the p[1] == '\0' failure case. */
ch = *++p;
p_ch = *++p;
/* FALLTHROUGH */
default:
if (*text != ch)
if (t_ch != p_ch)
return FALSE;
continue;
case '?':
/* Match anything but '/'. */
if (*text == '/')
if (t_ch == '/')
return FALSE;
continue;
case '*':
if (*++p == '*') {
while (*++p == '*') {}
special = TRUE;
}
else
} else
special = FALSE;
if (*p == '\0') {
/* Trailing "**" matches everything. Trailing "*" matches
* only if there are no more slash characters. */
return special? TRUE : strchr((char*)text, '/') == NULL;
if (!special) {
do {
if (strchr((char*)text, '/') != NULL)
return FALSE;
} while ((text = *a++) != NULL);
}
return TRUE;
}
for ( ; *text; text++) {
if ((matched = domatch(p, text)) != FALSE) {
while (1) {
if (t_ch == '\0') {
if ((text = *a++) == NULL)
break;
t_ch = *text;
continue;
}
if ((matched = dowild(p, text, a)) != FALSE) {
if (!special || matched != ABORT_TO_STARSTAR)
return matched;
}
else if (!special && *text == '/')
} else if (!special && t_ch == '/')
return ABORT_TO_STARSTAR;
t_ch = *++text;
}
return ABORT_ALL;
case '[':
ch = *++p;
p_ch = *++p;
#ifdef NEGATE_CLASS2
if (ch == NEGATE_CLASS2)
ch = NEGATE_CLASS;
if (p_ch == NEGATE_CLASS2)
p_ch = NEGATE_CLASS;
#endif
/* Assign literal TRUE/FALSE because of "matched" comparison. */
special = ch == NEGATE_CLASS? TRUE : FALSE;
special = p_ch == NEGATE_CLASS? TRUE : FALSE;
if (special) {
/* Inverted character class. */
ch = *++p;
p_ch = *++p;
}
prev = 0;
prev_ch = 0;
matched = FALSE;
do {
if (!ch)
if (!p_ch)
return ABORT_ALL;
if (ch == '\\') {
ch = *++p;
if (!ch)
if (p_ch == '\\') {
p_ch = *++p;
if (!p_ch)
return ABORT_ALL;
if (*text == ch)
if (t_ch == p_ch)
matched = TRUE;
}
else if (ch == '-' && prev && p[1] && p[1] != ']') {
ch = *++p;
if (ch == '\\') {
ch = *++p;
if (!ch)
} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
p_ch = *++p;
if (p_ch == '\\') {
p_ch = *++p;
if (!p_ch)
return ABORT_ALL;
}
if (*text <= ch && *text >= prev)
if (t_ch <= p_ch && t_ch >= prev_ch)
matched = TRUE;
ch = 0; /* This makes "prev" get set to 0. */
}
else if (ch == '[' && p[1] == ':') {
p_ch = 0; /* This makes "prev_ch" get set to 0. */
} else if (p_ch == '[' && p[1] == ':') {
const uchar *s;
int i;
for (s = p += 2; (ch = *p) && ch != ']'; p++) {}
if (!ch)
for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {}
if (!p_ch)
return ABORT_ALL;
i = p - s - 1;
if (i < 0 || p[-1] != ':') {
/* Didn't find ":]", so treat like a normal set. */
p = s - 2;
ch = '[';
if (*text == ch)
p_ch = '[';
if (t_ch == p_ch)
matched = TRUE;
continue;
}
if (CC_EQ(s,i, "alnum")) {
if (ISALNUM(*text))
if (ISALNUM(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "alpha")) {
if (ISALPHA(*text))
} else if (CC_EQ(s,i, "alpha")) {
if (ISALPHA(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "blank")) {
if (ISBLANK(*text))
} else if (CC_EQ(s,i, "blank")) {
if (ISBLANK(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "cntrl")) {
if (ISCNTRL(*text))
} else if (CC_EQ(s,i, "cntrl")) {
if (ISCNTRL(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "digit")) {
if (ISDIGIT(*text))
} else if (CC_EQ(s,i, "digit")) {
if (ISDIGIT(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "graph")) {
if (ISGRAPH(*text))
} else if (CC_EQ(s,i, "graph")) {
if (ISGRAPH(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "lower")) {
if (ISLOWER(*text))
} else if (CC_EQ(s,i, "lower")) {
if (ISLOWER(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "print")) {
if (ISPRINT(*text))
} else if (CC_EQ(s,i, "print")) {
if (ISPRINT(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "punct")) {
if (ISPUNCT(*text))
} else if (CC_EQ(s,i, "punct")) {
if (ISPUNCT(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "space")) {
if (ISSPACE(*text))
} else if (CC_EQ(s,i, "space")) {
if (ISSPACE(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "upper")) {
if (ISUPPER(*text))
} else if (CC_EQ(s,i, "upper")) {
if (ISUPPER(t_ch))
matched = TRUE;
}
else if (CC_EQ(s,i, "xdigit")) {
if (ISXDIGIT(*text))
} else if (CC_EQ(s,i, "xdigit")) {
if (ISXDIGIT(t_ch))
matched = TRUE;
}
else /* malformed [:class:] string */
} else /* malformed [:class:] string */
return ABORT_ALL;
ch = 0; /* This makes "prev" get set to 0. */
}
else if (*text == ch)
p_ch = 0; /* This makes "prev_ch" get set to 0. */
} else if (t_ch == p_ch)
matched = TRUE;
} while (prev = ch, (ch = *++p) != ']');
if (matched == special || *text == '/')
} while (prev_ch = p_ch, (p_ch = *++p) != ']');
if (matched == special || t_ch == '/')
return FALSE;
continue;
}
}
return *text == '\0';
do {
if (*text)
return FALSE;
} while ((text = *a++) != NULL);
return TRUE;
}
/* Find the pattern (p) in the text string (t). */
int wildmatch(const char *p, const char *t)
/* Match literal string "s" against the a virtually-joined string consisting
* of "text" and any strings in array "a". */
static int doliteral(const uchar *s, const uchar *text, const uchar*const *a)
{
for ( ; *s != '\0'; text++, s++) {
while (*text == '\0') {
if ((text = *a++) == NULL)
return FALSE;
}
if (*text != *s)
return FALSE;
}
do {
if (*text)
return FALSE;
} while ((text = *a++) != NULL);
return TRUE;
}
/* Return the last "count" path elements from the concatenated string.
* We return a string pointer to the start of the string, and update the
* array pointer-pointer to point to any remaining string elements. */
static const uchar *trailing_N_elements(const uchar*const **a_ptr, int count)
{
const uchar*const *a = *a_ptr;
const uchar*const *first_a = a;
while (*a)
a++;
while (a != first_a) {
const uchar *s = *--a;
s += strlen((char*)s);
while (--s >= *a) {
if (*s == '/' && !--count) {
*a_ptr = a+1;
return s+1;
}
}
}
if (count == 1) {
*a_ptr = a+1;
return *a;
}
return NULL;
}
/* Match the "pattern" against the "text" string. */
int wildmatch(const char *pattern, const char *text)
{
static const uchar *nomore[1]; /* A NULL pointer. */
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
return domatch((const uchar*)p, (const uchar*)t) == TRUE;
return dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
}
/* Match the "pattern" against the forced-to-lower-case "text" string. */
int iwildmatch(const char *pattern, const char *text)
{
static const uchar *nomore[1]; /* A NULL pointer. */
int ret;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
force_lower_case = 1;
ret = dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
force_lower_case = 0;
return ret;
}
/* Match pattern "p" against the a virtually-joined string consisting
* of all the pointers in array "texts" (which has a NULL pointer at the
* end). The int "where" can be 0 (normal matching), > 0 (match only
* the trailing N slash-separated filename components of "texts"), or < 0
* (match the "pattern" at the start or after any slash in "texts"). */
int wildmatch_array(const char *pattern, const char*const *texts, int where)
{
const uchar *p = (const uchar*)pattern;
const uchar*const *a = (const uchar*const*)texts;
const uchar *text;
int matched;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
if (where > 0)
text = trailing_N_elements(&a, where);
else
text = *a++;
if (!text)
return FALSE;
if ((matched = dowild(p, text, a)) != TRUE && where < 0
&& matched != ABORT_ALL) {
while (1) {
if (*text == '\0') {
if ((text = (uchar*)*a++) == NULL)
return FALSE;
continue;
}
if (*text++ == '/' && (matched = dowild(p, text, a)) != FALSE
&& matched != ABORT_TO_STARSTAR)
break;
}
}
return matched == TRUE;
}
/* Match literal string "s" against the a virtually-joined string consisting
* of all the pointers in array "texts" (which has a NULL pointer at the
* end). The int "where" can be 0 (normal matching), or > 0 (match
* only the trailing N slash-separated filename components of "texts"). */
int litmatch_array(const char *string, const char*const *texts, int where)
{
const uchar *s = (const uchar*)string;
const uchar*const *a = (const uchar* const*)texts;
const uchar *text;
if (where > 0)
text = trailing_N_elements(&a, where);
else
text = *a++;
if (!text)
return FALSE;
return doliteral(s, text, a) == TRUE;
}

View File

@@ -1,3 +1,6 @@
/* wildmatch.h */
int wildmatch(const char *p, const char *text);
int wildmatch(const char *pattern, const char *text);
int iwildmatch(const char *pattern, const char *text);
int wildmatch_array(const char *pattern, const char*const *texts, int where);
int litmatch_array(const char *string, const char*const *texts, int where);

View File

@@ -98,95 +98,107 @@ struct parm_struct
*/
typedef struct
{
char *motd_file;
char *bind_address;
char *log_file;
char *motd_file;
char *pid_file;
char *socket_options;
char *bind_address;
int syslog_facility;
int max_verbosity;
int rsync_port;
int syslog_facility;
} global;
static global Globals;
/*
* This structure describes a single service.
* This structure describes a single service. Their order must match the
* initializers below, which you can accomplish by keeping each sub-section
* sorted. (e.g. in vim, just visually select each subsection and use !sort.)
*/
typedef struct
{
char *name;
char *path;
char *auth_users;
char *comment;
char *lock_file;
BOOL read_only;
BOOL write_only;
BOOL list;
BOOL use_chroot;
BOOL transfer_logging;
BOOL ignore_errors;
char *uid;
char *dont_compress;
char *exclude;
char *exclude_from;
char *filter;
char *gid;
char *hosts_allow;
char *hosts_deny;
char *auth_users;
char *secrets_file;
BOOL strict_modes;
char *filter;
char *exclude;
char *exclude_from;
char *include;
char *include_from;
char *incoming_chmod;
char *lock_file;
char *log_format;
char *name;
char *outgoing_chmod;
char *path;
char *postxfer_exec;
char *prexfer_exec;
char *refuse_options;
char *dont_compress;
int timeout;
char *secrets_file;
char *temp_dir;
char *uid;
int max_connections;
int max_verbosity;
int timeout;
BOOL ignore_errors;
BOOL ignore_nonreadable;
BOOL list;
BOOL read_only;
BOOL strict_modes;
BOOL transfer_logging;
BOOL use_chroot;
BOOL write_only;
} service;
/* This is a default service used to prime a services structure */
/* This is a default service used to prime a services structure. In order
* to make these easy to keep sorted in the same way as the variables
* above, use the variable name in the leading comment, including a
* trailing ';' (to avoid a sorting problem with trailing digits). */
static service sDefault =
{
NULL, /* name */
NULL, /* path */
NULL, /* comment */
DEFAULT_LOCK_FILE, /* lock file */
True, /* read only */
False, /* write only */
True, /* list */
True, /* use chroot */
False, /* transfer logging */
False, /* ignore errors */
"nobody",/* uid */
/* auth_users; */ NULL,
/* comment; */ NULL,
/* dont_compress; */ "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",
/* exclude; */ NULL,
/* exclude_from; */ NULL,
/* filter; */ NULL,
/* gid; */ NOBODY_GROUP,
/* hosts_allow; */ NULL,
/* hosts_deny; */ NULL,
/* include; */ NULL,
/* include_from; */ NULL,
/* incoming_chmod; */ NULL,
/* lock_file; */ DEFAULT_LOCK_FILE,
/* log_format; */ "%o %h [%a] %m (%u) %f %l",
/* name; */ NULL,
/* outgoing_chmod; */ NULL,
/* path; */ NULL,
/* postxfer_exec; */ NULL,
/* prexfer_exec; */ NULL,
/* refuse_options; */ NULL,
/* secrets_file; */ NULL,
/* temp_dir; */ NULL,
/* uid; */ NOBODY_USER,
/* TODO: This causes problems on Debian, where it is called
* "nogroup". Debian patch this in their version of the
* package, but it would be nice to be consistent. Possibly
* other systems are different again.
*
* What is the best behaviour? Perhaps always using (gid_t)
* -2? */
"nobody",/* gid */
/* max_connections; */ 0,
/* max_verbosity; */ 1,
/* timeout; */ 0,
NULL, /* hosts allow */
NULL, /* hosts deny */
NULL, /* auth users */
NULL, /* secrets file */
True, /* strict modes */
NULL, /* filter */
NULL, /* exclude */
NULL, /* exclude from */
NULL, /* include */
NULL, /* include from */
"%o %h [%a] %m (%u) %f %l", /* log format */
NULL, /* refuse options */
"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz", /* dont compress */
0, /* timeout */
0, /* max connections */
False /* ignore nonreadable */
/* ignore_errors; */ False,
/* ignore_nonreadable; */ False,
/* list; */ True,
/* read_only; */ True,
/* strict_modes; */ True,
/* transfer_logging; */ False,
/* use_chroot; */ True,
/* write_only; */ False,
};
@@ -269,44 +281,51 @@ static struct enum_list enum_facilities[] = {
/* note that we do not initialise the defaults union - it is not allowed in ANSI C */
static struct parm_struct parm_table[] =
{
{"motd file", P_STRING, P_GLOBAL, &Globals.motd_file, NULL, 0},
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"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},
{"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
{"log file", P_STRING, P_GLOBAL,&Globals.log_file, NULL,0},
{"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
{"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
{"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
{"syslog facility", P_ENUM, P_GLOBAL,&Globals.syslog_facility,enum_facilities,0},
{"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
{"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
{"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},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
{"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},
{"include from", P_STRING, P_LOCAL, &sDefault.include_from,NULL, 0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0},
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0},
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL,0},
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors, NULL,0},
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable,NULL,0},
{"include from", P_STRING, P_LOCAL, &sDefault.include_from, NULL,0},
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL,0},
{"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
#ifdef HAVE_PUTENV
{"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec, NULL,0},
{"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL,0},
#endif
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL,0},
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
{"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
{"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL,0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL,0},
{"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL,0},
{NULL, P_BOOL, P_NONE, NULL, NULL,0}
};
@@ -319,7 +338,6 @@ static void init_globals(void)
#ifdef LOG_DAEMON
Globals.syslog_facility = LOG_DAEMON;
#endif
Globals.max_verbosity = 1;
}
/***************************************************************************
@@ -354,43 +372,51 @@ static void init_locals(void)
int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
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_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
FN_LOCAL_STRING(lp_auth_users, auth_users)
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)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
FN_LOCAL_STRING(lp_filter, filter)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
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)
FN_LOCAL_STRING(lp_include_from, include_from)
FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
FN_LOCAL_STRING(lp_lock_file, lock_file)
FN_LOCAL_STRING(lp_log_format, log_format)
FN_LOCAL_STRING(lp_name, name)
FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_write_only, write_only)
/* local prototypes */
static int strwicmp(char *psz1, char *psz2);
@@ -776,7 +802,6 @@ False on failure.
BOOL lp_load(char *pszFname, int globals_only)
{
extern int am_server;
extern int am_daemon;
extern int am_root;
pstring n2;
BOOL bRetval;
@@ -789,7 +814,7 @@ BOOL lp_load(char *pszFname, int globals_only)
if (pszFname)
pstrcpy(n2,pszFname);
else if (am_server && am_daemon && !am_root)
else if (am_server && !am_root)
pstrcpy(n2,RSYNCD_USERCONF);
else
pstrcpy(n2,RSYNCD_SYSCONF);

235
log.c
View File

@@ -26,6 +26,9 @@
<mbp@samba.org>, Oct 2000.
*/
#include "rsync.h"
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#endif
extern int verbose;
extern int dry_run;
@@ -36,12 +39,18 @@ extern int local_server;
extern int quiet;
extern int module_id;
extern int msg_fd_out;
extern int allow_8bit_chars;
extern int protocol_version;
extern int preserve_times;
extern int log_format_has_i;
extern int log_format_has_o_or_i;
extern int daemon_log_format_has_o_or_i;
extern mode_t orig_umask;
extern char *auth_user;
extern char *log_format;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
extern iconv_t ic_chck;
#endif
static int log_initialised;
static int logfile_was_closed;
@@ -65,8 +74,11 @@ struct {
{ RERR_STREAMIO , "error in rsync protocol data stream" },
{ RERR_MESSAGEIO , "errors with program diagnostics" },
{ RERR_IPC , "error in IPC code" },
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
{ RERR_WAITCHILD , "some error returned by waitpid()" },
{ RERR_CRASHED , "sibling process crashed" },
{ RERR_TERMINATED , "sibling process terminated abnormally" },
{ RERR_SIGNAL1 , "received SIGUSR1" },
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
{ RERR_WAITCHILD , "waitpid() failed" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files could not be transferred" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
@@ -80,7 +92,6 @@ struct {
};
/*
* Map from rsync error code to name, or return NULL.
*/
@@ -94,7 +105,6 @@ static char const *rerr_name(int code)
return NULL;
}
static void logit(int priority, char *buf)
{
if (logfile_was_closed)
@@ -134,8 +144,7 @@ static void syslog_init()
static void logfile_open(void)
{
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
mode_t old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
if (!logfile) {
@@ -187,20 +196,41 @@ void logfile_reopen(void)
}
}
static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
{
const char *s, *end = buf + len;
for (s = buf; s < end; s++) {
if ((s < end - 4
&& *s == '\\' && s[1] == '#'
&& isdigit(*(uchar*)(s+2))
&& isdigit(*(uchar*)(s+3))
&& isdigit(*(uchar*)(s+4)))
|| (*s != '\t'
&& ((use_isprint && !isprint(*(uchar*)s))
|| *(uchar*)s < ' '))) {
if (s != buf && fwrite(buf, s - buf, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
fprintf(f, "\\#%03o", *(uchar*)s);
buf = s + 1;
}
}
if (buf != end && fwrite(buf, end - buf, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
}
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG */
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
* certain fatal conditions. */
void rwrite(enum logcode code, char *buf, int len)
{
int trailing_CR_or_NL;
FILE *f = NULL;
/* recursion can happen with certain fatal conditions */
if (quiet && code == FINFO)
return;
if (len < 0)
exit_cleanup(RERR_MESSAGEIO);
buf[len] = 0;
if (quiet && code == FINFO)
return;
if (am_server && msg_fd_out >= 0) {
/* Pass the message to our sibling. */
@@ -208,6 +238,9 @@ void rwrite(enum logcode code, char *buf, int len)
return;
}
if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
code = FERROR;
if (code == FCLIENT)
code = FINFO;
else if (am_daemon) {
@@ -239,31 +272,67 @@ void rwrite(enum logcode code, char *buf, int len)
}
}
if (code == FERROR) {
switch (code) {
case FERROR:
log_got_error = 1;
f = stderr;
goto pre_scan;
case FINFO:
f = am_server ? stderr : stdout;
pre_scan:
while (len > 1 && *buf == '\n') {
fputc(*buf, f);
buf++;
len--;
}
break;
case FNAME:
f = am_server ? stderr : stdout;
break;
default:
exit_cleanup(RERR_MESSAGEIO);
}
if (code == FINFO)
f = am_server ? stderr : stdout;
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;
if (!f)
exit_cleanup(RERR_MESSAGEIO);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
if (ic_chck != (iconv_t)-1) {
char convbuf[1024];
char *in_buf = buf, *out_buf = convbuf;
size_t in_cnt = len, out_cnt = sizeof convbuf - 1;
if (fwrite(buf, len, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
iconv(ic_chck, NULL, 0, NULL, 0);
while (iconv(ic_chck, &in_buf,&in_cnt,
&out_buf,&out_cnt) == (size_t)-1) {
if (out_buf != convbuf) {
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
out_buf = convbuf;
out_cnt = sizeof convbuf - 1;
}
if (errno == E2BIG)
continue;
fprintf(f, "\\#%03o", *(uchar*)in_buf++);
in_cnt--;
}
if (out_buf != convbuf)
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
} else
#endif
filtered_fwrite(f, buf, len, !allow_8bit_chars);
if (buf[len-1] == '\r' || buf[len-1] == '\n')
if (trailing_CR_or_NL) {
fputc(trailing_CR_or_NL, f);
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[MAXPATHLEN+512];
char buf[BIGPATHBUFLEN];
size_t len;
va_start(ap, format);
@@ -274,7 +343,7 @@ void rprintf(enum logcode code, const char *format, ...)
* 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[] = "[...]";
static const char ellipsis[] = "[...]";
/* Reset length, and zero-terminate the end of our buffer */
len = sizeof buf - 1;
@@ -290,7 +359,7 @@ void rprintf(enum logcode code, const char *format, ...)
* 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);
memcpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
if (format[strlen(format)-1] == '\n') {
buf[len-1] = '\n';
}
@@ -299,7 +368,6 @@ void rprintf(enum logcode code, const char *format, ...)
rwrite(code, buf, len);
}
/* This is like rprintf, but it also tries to print some
* representation of the error code. Normally errcode = errno.
*
@@ -311,7 +379,7 @@ void rprintf(enum logcode code, const char *format, ...)
void rsyserr(enum logcode code, int errcode, const char *format, ...)
{
va_list ap;
char buf[MAXPATHLEN+512];
char buf[BIGPATHBUFLEN];
size_t len;
strcpy(buf, RSYNC_NAME ": ");
@@ -331,8 +399,6 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
rwrite(code, buf, len);
}
void rflush(enum logcode code)
{
FILE *f = NULL;
@@ -360,8 +426,6 @@ void rflush(enum logcode code)
fflush(f);
}
/* a generic logging routine for send/recv, with parameter
* substitiution */
static void log_formatted(enum logcode code, char *format, char *op,
@@ -399,51 +463,83 @@ static void log_formatted(enum logcode code, char *format, char *op,
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 'h':
if (am_daemon)
n = client_name(0);
break;
case 'a':
if (am_daemon)
n = client_addr(0);
break;
case 'l':
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(double)file->length);
n = buf2;
break;
case 'U':
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)file->uid);
n = buf2;
break;
case 'G':
if (file->gid == GID_NONE)
n = "DEFAULT";
else {
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)file->gid);
n = buf2;
}
break;
case 'p':
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'M':
n = timestring(file->modtime);
{
char *cp = n;
while ((cp = strchr(cp, ' ')) != NULL)
*cp = '-';
}
break;
case 'B':
n = buf2 + MAXPATHLEN - PERMSTRING_SIZE;
permstring(n - 1, file->mode); /* skip the type char */
break;
case 'o':
n = op;
break;
case 'f':
n = safe_fname(f_name(file));
n = f_name(file, NULL);
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. */
clean_fname(buf2, 0);
if (fmt[1])
strcpy(n, buf2);
strlcpy(n, buf2, MAXPATHLEN);
else
n = buf2;
}
clean_fname(n, 0);
} else
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, "/");
}
n = f_name(file, NULL);
if (S_ISDIR(file->mode))
strlcat(n, "/", MAXPATHLEN);
break;
case 'L':
if (hlink && *hlink) {
n = safe_fname(hlink);
n = hlink;
strcpy(buf2, " => ");
} else if (S_ISLNK(file->mode) && file->u.link) {
n = safe_fname(file->u.link);
n = file->u.link;
strcpy(buf2, " -> ");
} else {
n = "";
@@ -455,10 +551,18 @@ static void log_formatted(enum logcode code, char *format, char *op,
snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
n = buf2;
break;
case 'm': n = lp_name(module_id); break;
case 't': n = timestring(time(NULL)); break;
case 'P': n = lp_path(module_id); break;
case 'u': n = auth_user; break;
case 'm':
n = lp_name(module_id);
break;
case 't':
n = timestring(time(NULL));
break;
case 'P':
n = lp_path(module_id);
break;
case 'u':
n = auth_user;
break;
case 'b':
if (am_sender) {
b = stats.total_written -
@@ -494,17 +598,17 @@ static void log_formatted(enum logcode code, char *format, char *op,
: !(iflags & ITEM_TRANSFER) ? '.'
: !local_server && *op == 's' ? '<' : '>';
n[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: 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';
: !preserve_times || 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[8] = '.';
n[9] = '\0';
if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
@@ -512,7 +616,8 @@ static void log_formatted(enum logcode code, char *format, char *op,
int i;
for (i = 2; n[i]; i++)
n[i] = ch;
} else if (!(iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE))) {
} else if (n[0] == '.' || n[0] == 'h'
|| (n[0] == 'c' && n[1] == 'f')) {
int i;
for (i = 2; n[i]; i++) {
if (n[i] != '.')
@@ -594,7 +699,7 @@ void log_item(struct file_struct *file, struct stats *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, s_or_r,
log_formatted(FNAME, log_format, s_or_r,
file, initial_stats, iflags, hlink);
}
}
@@ -602,12 +707,15 @@ void log_item(struct file_struct *file, struct stats *initial_stats,
void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
char *buf)
{
int see_item = itemizing && (iflags || verbose > 1);
int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS;
int see_item = itemizing && (significant_flags || *buf
|| log_format_has_i > 1 || (verbose > 1 && log_format_has_i));
int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
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))
} else if (see_item || local_change || *buf
|| (S_ISDIR(file->mode) && significant_flags))
log_item(file, &stats, iflags, buf);
}
@@ -639,7 +747,6 @@ void log_delete(char *fname, int mode)
log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
}
/*
* Called when the transfer is interrupted for some reason.
*
@@ -662,11 +769,11 @@ void log_exit(int code, const char *file, int line)
/* VANISHED is not an error, only a warning */
if (code == RERR_VANISHED) {
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d)\n",
name, code, file, line);
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
} else {
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d)\n",
name, code, file, line);
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
}
}
}

428
main.c
View File

@@ -40,17 +40,14 @@ extern int kluge_around_eof;
extern int do_stats;
extern int log_got_error;
extern int module_id;
extern int orig_umask;
extern int copy_links;
extern int copy_dirlinks;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
extern int recurse;
extern int fuzzy_basis;
extern int relative_paths;
extern int rsync_port;
extern int inplace;
extern int make_backups;
extern int whole_file;
extern int read_batch;
extern int write_batch;
@@ -60,22 +57,30 @@ extern int filesfrom_fd;
extern pid_t cleanup_child_pid;
extern struct stats stats;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *basis_dir[];
extern char *rsync_path;
extern char *shell_cmd;
extern char *batch_name;
int local_server = 0;
mode_t orig_umask = 0;
struct file_list *the_file_list;
/* There's probably never more than at most 2 outstanding child processes,
* but set it higher, just in case. */
#define MAXCHILDPROCS 5
#define MAXCHILDPROCS 7
#ifdef HAVE_SIGACTION
# ifdef HAVE_SIGPROCMASK
# define SIGACTMASK(n,h) SIGACTION(n,h), sigaddset(&sigmask,(n))
# else
# define SIGACTMASK(n,h) SIGACTION(n,h)
# endif
static struct sigaction sigact;
#endif
struct pid_status {
pid_t pid;
int status;
int status;
} pid_stat_table[MAXCHILDPROCS];
static time_t starttime, endtime;
@@ -83,38 +88,58 @@ static int64 total_read, total_written;
static void show_malloc_stats(void);
/****************************************************************************
wait for a process to exit, calling io_flush while waiting
****************************************************************************/
void wait_process(pid_t pid, int *status)
/* Works like waitpid(), but if we already harvested the child pid in our
* remember_children(), we succeed instead of returning an error. */
pid_t wait_process(pid_t pid, int *status_ptr, int flags)
{
pid_t waited_pid;
int cnt;
while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
msleep(20);
io_flush(FULL_FLUSH);
}
pid_t waited_pid = waitpid(pid, status_ptr, flags);
if (waited_pid == -1 && errno == ECHILD) {
/* status of requested child no longer available.
* check to see if it was processed by the sigchld_handler.
*/
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
/* Status of requested child no longer available: check to
* see if it was processed by remember_children(). */
int cnt;
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
if (pid == pid_stat_table[cnt].pid) {
*status = pid_stat_table[cnt].status;
*status_ptr = pid_stat_table[cnt].status;
pid_stat_table[cnt].pid = 0;
break;
return pid;
}
}
}
return waited_pid;
}
/* Wait for a process to exit, calling io_flush while waiting. */
static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
{
pid_t waited_pid;
int status;
while ((waited_pid = wait_process(pid, &status, WNOHANG)) == 0) {
msleep(20);
io_flush(FULL_FLUSH);
}
/* TODO: If the child exited on a signal, then log an
* appropriate error message. Perhaps we should also accept a
* message describing the purpose of the child. Also indicate
* this to the caller so that thhey know something went
* wrong. */
*status = WEXITSTATUS(*status);
* this to the caller so that they know something went wrong. */
if (waited_pid < 0) {
rsyserr(FERROR, errno, "waitpid");
*exit_code_ptr = RERR_WAITCHILD;
} else if (!WIFEXITED(status)) {
#ifdef WCOREDUMP
if (WCOREDUMP(status))
*exit_code_ptr = RERR_CRASHED;
else
#endif
if (WIFSIGNALED(status))
*exit_code_ptr = RERR_TERMINATED;
else
*exit_code_ptr = RERR_WAITCHILD;
} else
*exit_code_ptr = WEXITSTATUS(status);
}
/* This function gets called from all 3 processes. We want the client side
@@ -175,7 +200,7 @@ static void handle_stats(int f)
stats.flist_buildtime = read_longint(f);
stats.flist_xfertime = read_longint(f);
}
} else if (write_batch && !am_server) {
} else if (write_batch) {
/* The --read-batch process is going to be a client
* receiver, so we need to give it the stats. */
write_longint(batch_fd, total_read);
@@ -186,19 +211,22 @@ static void handle_stats(int f)
write_longint(batch_fd, stats.flist_xfertime);
}
}
}
static void output_summary(void)
{
if (do_stats) {
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
stats.num_transferred_files);
rprintf(FINFO,"Total file size: %.0f bytes\n",
(double)stats.total_size);
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
(double)stats.total_transferred_size);
rprintf(FINFO,"Literal data: %.0f bytes\n",
(double)stats.literal_data);
rprintf(FINFO,"Matched data: %.0f bytes\n",
(double)stats.matched_data);
rprintf(FINFO,"Total file size: %s bytes\n",
human_num(stats.total_size));
rprintf(FINFO,"Total transferred file size: %s bytes\n",
human_num(stats.total_transferred_size));
rprintf(FINFO,"Literal data: %s bytes\n",
human_num(stats.literal_data));
rprintf(FINFO,"Matched data: %s bytes\n",
human_num(stats.matched_data));
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
if (stats.flist_buildtime) {
rprintf(FINFO,
@@ -208,25 +236,19 @@ static void handle_stats(int f)
"File list transfer time: %.3f seconds\n",
(double)stats.flist_xfertime / 1000);
}
rprintf(FINFO,"Total bytes sent: %.0f\n",
(double)total_written);
rprintf(FINFO,"Total bytes received: %.0f\n",
(double)total_read);
rprintf(FINFO,"Total bytes sent: %s\n",
human_num(total_written));
rprintf(FINFO,"Total bytes received: %s\n",
human_num(total_read));
}
fflush(stdout);
fflush(stderr);
}
static void output_summary(void)
{
if (verbose || do_stats) {
rprintf(FINFO,
"\nsent %.0f bytes received %.0f bytes %.2f bytes/sec\n",
(double)total_written, (double)total_read,
(total_written + total_read)/(0.5 + (endtime - starttime)));
rprintf(FINFO, "total size is %.0f speedup is %.2f\n",
(double)stats.total_size,
"\nsent %s bytes received %s bytes %s bytes/sec\n",
human_num(total_written), human_num(total_read),
human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
rprintf(FINFO, "total size is %s speedup is %.2f\n",
human_num(stats.total_size),
(double)stats.total_size / (total_written+total_read));
}
@@ -281,10 +303,11 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
int i, argc = 0;
char *args[MAX_ARGS];
pid_t ret;
char *tok, *dir = NULL;
char *dir = NULL;
int dash_l_set = 0;
if (!read_batch && !local_server) {
char *t, *f, in_quote = '\0';
char *rsh_env = getenv(RSYNC_RSH_ENV);
if (!cmd)
cmd = rsh_env;
@@ -294,13 +317,39 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
if (!cmd)
goto oom;
for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
for (t = f = cmd; *f; f++) {
if (*f == ' ')
continue;
/* Comparison leaves rooms for server_options(). */
if (argc >= MAX_ARGS - MAX_SERVER_ARGS) {
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
args[argc++] = tok;
args[argc++] = t;
while (*f != ' ' || in_quote) {
if (!*f) {
if (in_quote) {
rprintf(FERROR,
"Missing trailing-%c in remote-shell command.\n",
in_quote);
exit_cleanup(RERR_SYNTAX);
}
f--;
break;
}
if (*f == '\'' || *f == '"') {
if (!in_quote) {
in_quote = *f++;
continue;
}
if (*f == in_quote && *++f != in_quote) {
in_quote = '\0';
continue;
}
}
*t++ = *f++;
}
*t++ = '\0';
}
/* check to see if we've already been given '-l user' in
@@ -353,10 +402,9 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
args[argc] = NULL;
if (verbose > 3) {
rprintf(FINFO,"cmd=");
for (i = 0; i < argc; i++)
rprintf(FINFO, "%s ", safe_fname(args[i]));
rprintf(FINFO,"\n");
rprintf(FINFO, "cmd[%d]=%s ", i, args[i]);
rprintf(FINFO, "\n");
}
if (read_batch) {
@@ -383,62 +431,122 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
return ret;
oom:
oom:
out_of_memory("do_cmd");
return 0; /* not reached */
}
static char *get_local_name(struct file_list *flist,char *name)
/* The receiving side operates in one of two modes:
*
* 1. it receives any number of files into a destination directory,
* placing them according to their names in the file-list.
*
* 2. it receives a single file and saves it using the name in the
* destination path instead of its file-list name. This requires a
* "local name" for writing out the destination file.
*
* So, our task is to figure out what mode/local-name we need and return
* either a NULL for mode 1, or the local-name for mode 2. We also
* change directory if there are any path components in dest_path. */
static char *get_local_name(struct file_list *flist, char *dest_path)
{
STRUCT_STAT st;
int e;
char *cp;
if (verbose > 2)
rprintf(FINFO,"get_local_name count=%d %s\n",
flist->count, NS(name));
if (verbose > 2) {
rprintf(FINFO, "get_local_name count=%d %s\n",
flist->count, NS(dest_path));
}
if (!name)
if (!dest_path || list_only)
return NULL;
if (do_stat(name,&st) == 0) {
/* If the destination path refers to an existing directory, enter
* it and use mode 1. If there is something other than a directory
* at the destination path, we must be transferring one file
* (anything at the destination will be overwritten). */
if (do_stat(dest_path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (!push_dir(name)) {
if (!push_dir(dest_path)) {
rsyserr(FERROR, errno, "push_dir#1 %s failed",
full_fname(name));
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
return NULL;
}
if (flist->count > 1) {
rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
rprintf(FERROR,
"ERROR: destination must be a directory when"
" copying more than 1 file\n");
exit_cleanup(RERR_FILESELECT);
}
return name;
}
if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
return name;
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
rsyserr(FERROR, errno, "mkdir %s failed", full_fname(name));
exit_cleanup(RERR_FILEIO);
}
if (verbose > 0)
rprintf(FINFO, "created directory %s\n", safe_fname(name));
if (dry_run) {
dry_run++;
return NULL;
}
if (!push_dir(name)) {
rsyserr(FERROR, errno, "push_dir#2 %s failed",
full_fname(name));
/* Caution: flist->count could be 0! */
if (flist->count == 1 && S_ISDIR(flist->files[0]->mode)) {
rprintf(FERROR,
"ERROR: cannot overwrite non-directory"
" with a directory\n");
exit_cleanup(RERR_FILESELECT);
}
} else if (errno != ENOENT) {
rsyserr(FERROR, errno, "cannot stat destination %s",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
return NULL;
cp = strrchr(dest_path, '/');
/* If the destination path ends in a slash or we are transferring
* multiple files, create a directory at the destination path,
* enter the new directory, and use mode 1. */
if (flist->count > 1 || (cp && !cp[1])) {
/* Lop off the final slash (if any). */
if (cp && !cp[1])
*cp = '\0';
if (mkdir_defmode(dest_path) != 0) {
rsyserr(FERROR, errno, "mkdir %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILEIO);
}
if (verbose)
rprintf(FINFO, "created directory %s\n", dest_path);
if (dry_run) {
/* Indicate that the destination directory doesn't
* really exist and return mode 1. */
dry_run++;
return NULL;
}
if (!push_dir(dest_path)) {
rsyserr(FERROR, errno, "push_dir#2 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
return NULL;
}
/* Otherwise, we are writing a single file, possibly on top of an
* existing non-directory. Change to the item's parent directory
* (if it has a path component), return the basename of the
* destination file as the local name, and use mode 2. */
if (!cp)
return dest_path;
if (cp == dest_path)
dest_path = "/";
*cp = '\0';
if (!push_dir(dest_path)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
*cp = '/';
return cp + 1;
}
@@ -466,9 +574,8 @@ static void read_final_goodbye(int f_in, int f_out)
}
static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
{
int i;
struct file_list *flist;
char *dir = argv[0];
@@ -497,14 +604,6 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
argc--;
argv++;
if (strcmp(dir,".")) {
int l = strlen(dir);
if (strcmp(dir,"/") == 0)
l = 0;
for (i = 0; i < argc; i++)
argv[i] += l+1;
}
if (argc == 0 && (recurse || list_only)) {
argc = 1;
argv--;
@@ -533,12 +632,12 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
{
int pid;
int status = 0;
int exit_code = 0;
int error_pipe[2];
/* The receiving side mustn't obey this, or an existing symlink that
* points to an identical file won't be replaced by the referent. */
copy_links = 0;
copy_links = copy_dirlinks = 0;
if (preserve_hard_links)
init_hard_links();
@@ -619,14 +718,14 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
set_msg_fd_in(-1);
kill(pid, SIGUSR2);
wait_process(pid, &status);
return status;
wait_process_with_flush(pid, &exit_code);
return exit_code;
}
static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
{
int status;
int exit_code;
struct file_list *flist;
char *local_name = NULL;
char *dir = NULL;
@@ -649,7 +748,6 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
return;
}
if (argc > 0) {
dir = argv[0];
argc--;
@@ -682,17 +780,11 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
the_file_list = flist;
if (argc > 0) {
if (strcmp(dir,".")) {
argv[0] += strlen(dir);
if (argv[0][0] == '/')
argv[0]++;
}
if (argc > 0)
local_name = get_local_name(flist,argv[0]);
}
status = do_recv(f_in,f_out,flist,local_name);
exit_cleanup(status);
exit_code = do_recv(f_in,f_out,flist,local_name);
exit_cleanup(exit_code);
}
@@ -710,6 +802,9 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
io_set_sock_fds(f_in, f_out);
setup_protocol(f_out, f_in);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
setup_iconv();
#endif
if (protocol_version >= 23)
io_start_multiplex_out();
@@ -735,7 +830,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
{
struct file_list *flist = NULL;
int status = 0, status2 = 0;
int exit_code = 0, exit_code2 = 0;
char *local_name = NULL;
cleanup_child_pid = pid;
@@ -746,6 +841,9 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_set_sock_fds(f_in, f_out);
setup_protocol(f_out,f_in);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
setup_iconv();
#endif
if (protocol_version >= 23 && !read_batch)
io_start_multiplex_in();
@@ -787,11 +885,11 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (verbose > 3)
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
io_flush(FULL_FLUSH);
wait_process(pid, &status);
wait_process_with_flush(pid, &exit_code);
}
output_summary();
io_flush(FULL_FLUSH);
exit_cleanup(status);
exit_cleanup(exit_code);
}
if (need_messages_from_generator && !read_batch)
@@ -815,7 +913,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (flist && flist->count > 0) {
local_name = get_local_name(flist, argv[0]);
status2 = do_recv(f_in, f_out, flist, local_name);
exit_code2 = do_recv(f_in, f_out, flist, local_name);
} else {
handle_stats(-1);
output_summary();
@@ -825,10 +923,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (verbose > 3)
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
io_flush(FULL_FLUSH);
wait_process(pid, &status);
wait_process_with_flush(pid, &exit_code);
}
return MAX(status, status2);
return MAX(exit_code, exit_code2);
}
static int copy_argv (char *argv[])
@@ -872,9 +970,16 @@ static int start_client(int argc, char *argv[])
return rc;
if (!read_batch) { /* for read_batch, NO source is specified */
argc--;
shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
if (shell_path) { /* source is remote */
char *dummy1;
int dummy2;
if (--argc
&& check_for_hostspec(argv[argc], &dummy1, &dummy2)) {
rprintf(FERROR,
"The source and destination cannot both be remote.\n");
exit_cleanup(RERR_SYNTAX);
}
argv++;
if (filesfrom_host && *filesfrom_host
&& strcmp(filesfrom_host, shell_machine) != 0) {
@@ -895,12 +1000,14 @@ static int start_client(int argc, char *argv[])
} else { /* source is local, check dest arg */
am_sender = 1;
if (argc < 1) { /* destination required */
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
if (argc > 1)
p = argv[--argc];
else {
p = ".";
list_only = 1;
}
shell_path = check_for_hostspec(argv[argc], &shell_machine, &rsync_port);
shell_path = check_for_hostspec(p, &shell_machine, &rsync_port);
if (shell_path && filesfrom_host && *filesfrom_host
&& strcmp(filesfrom_host, shell_machine) != 0) {
rprintf(FERROR,
@@ -915,7 +1022,7 @@ static int start_client(int argc, char *argv[])
exit_cleanup(RERR_SYNTAX);
}
shell_machine = NULL;
shell_path = argv[argc];
shell_path = p;
} else if (rsync_port) {
if (!shell_cmd) {
return start_socket_client(shell_machine,
@@ -945,10 +1052,10 @@ static int start_client(int argc, char *argv[])
if (verbose > 3) {
rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
shell_cmd ? safe_fname(shell_cmd) : "",
shell_machine ? safe_fname(shell_machine) : "",
shell_user ? safe_fname(shell_user) : "",
shell_path ? safe_fname(shell_path) : "");
shell_cmd ? shell_cmd : "",
shell_machine ? shell_machine : "",
shell_user ? shell_user : "",
shell_path ? shell_path : "");
}
/* for remote source, only single dest arg can remain ... */
@@ -985,7 +1092,7 @@ static int start_client(int argc, char *argv[])
static RETSIGTYPE sigusr1_handler(UNUSED(int val))
{
exit_cleanup(RERR_SIGNAL);
exit_cleanup(RERR_SIGNAL1);
}
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
@@ -998,7 +1105,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
_exit(0);
}
static RETSIGTYPE sigchld_handler(UNUSED(int val))
RETSIGTYPE remember_children(UNUSED(int val))
{
#ifdef WNOHANG
int cnt, status;
@@ -1007,8 +1114,7 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
* get him to explain why he put it in, so rather than taking it
* out we're instead saving the child exit statuses for later use.
* The waitpid() loop presumably eliminates all possibility of leaving
* zombie children, maybe that's why he did it.
*/
* zombie children, maybe that's why he did it. */
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
/* save the child's exit status */
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
@@ -1020,6 +1126,9 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
}
}
#endif
#ifndef HAVE_SIGACTION
signal(SIGCHLD, remember_children);
#endif
}
@@ -1079,16 +1188,23 @@ int main(int argc,char *argv[])
int ret;
int orig_argc = argc;
char **orig_argv = argv;
#ifdef HAVE_SIGACTION
# ifdef HAVE_SIGPROCMASK
sigset_t sigmask;
signal(SIGUSR1, sigusr1_handler);
signal(SIGUSR2, sigusr2_handler);
signal(SIGCHLD, sigchld_handler);
sigemptyset(&sigmask);
# endif
sigact.sa_flags = SA_NOCLDSTOP;
#endif
SIGACTMASK(SIGUSR1, sigusr1_handler);
SIGACTMASK(SIGUSR2, sigusr2_handler);
SIGACTMASK(SIGCHLD, remember_children);
#ifdef MAINTAINER_MODE
signal(SIGSEGV, rsync_panic_handler);
signal(SIGFPE, rsync_panic_handler);
signal(SIGABRT, rsync_panic_handler);
signal(SIGBUS, rsync_panic_handler);
#endif /* def MAINTAINER_MODE */
SIGACTMASK(SIGSEGV, rsync_panic_handler);
SIGACTMASK(SIGFPE, rsync_panic_handler);
SIGACTMASK(SIGABRT, rsync_panic_handler);
SIGACTMASK(SIGBUS, rsync_panic_handler);
#endif
starttime = time(NULL);
am_root = (MY_UID() == 0);
@@ -1102,7 +1218,11 @@ int main(int argc,char *argv[])
/* we set a 0 umask so that correct file permissions can be
* carried across */
orig_umask = (int)umask(0);
orig_umask = umask(0);
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");
#endif
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
/* FIXME: We ought to call the same error-handling
@@ -1111,16 +1231,18 @@ int main(int argc,char *argv[])
exit_cleanup(RERR_SYNTAX);
}
signal(SIGINT,SIGNAL_CAST sig_int);
signal(SIGHUP,SIGNAL_CAST sig_int);
signal(SIGTERM,SIGNAL_CAST sig_int);
SIGACTMASK(SIGINT, sig_int);
SIGACTMASK(SIGHUP, sig_int);
SIGACTMASK(SIGTERM, sig_int);
#if defined HAVE_SIGACTION && HAVE_SIGPROCMASK
sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
#endif
/* Ignore SIGPIPE; we consistently check error codes and will
* see the EPIPE. */
signal(SIGPIPE, SIG_IGN);
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");
SIGACTION(SIGPIPE, SIG_IGN);
#ifdef SIGXFSZ
SIGACTION(SIGXFSZ, SIG_IGN);
#endif
/* Initialize push_dir here because on some old systems getcwd

132
match.c
View File

@@ -20,69 +20,47 @@
#include "rsync.h"
extern int verbose;
extern int am_server;
extern int do_progress;
extern int checksum_seed;
extern int append_mode;
int updating_basis_file;
typedef unsigned short tag;
#define TABLESIZE (1<<16)
#define NULL_TAG (-1)
static int false_alarms;
static int tag_hits;
static int hash_hits;
static int matches;
static int64 data_transfer;
static int total_false_alarms;
static int total_tag_hits;
static int total_hash_hits;
static int total_matches;
extern struct stats stats;
struct target {
tag t;
int32 i;
};
#define TABLESIZE (1<<16)
static struct target *targets;
static int32 *tag_table;
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
static int compare_targets(struct target *t1,struct target *t2)
{
return (int)t1->t - (int)t2->t;
}
static int32 *hash_table;
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
static void build_hash_table(struct sum_struct *s)
{
int32 i;
if (!tag_table)
tag_table = new_array(int32, TABLESIZE);
targets = new_array(struct target, s->count);
if (!tag_table || !targets)
out_of_memory("build_hash_table");
for (i = 0; i < s->count; i++) {
targets[i].i = i;
targets[i].t = gettag(s->sums[i].sum1);
if (!hash_table) {
hash_table = new_array(int32, TABLESIZE);
if (!hash_table)
out_of_memory("build_hash_table");
}
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
for (i = 0; i < TABLESIZE; i++)
tag_table[i] = NULL_TAG;
for (i = s->count; i-- > 0; )
tag_table[targets[i].t] = i;
for (i = 0; i < s->count; i++) {
uint32 t = SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
}
}
@@ -127,7 +105,6 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
sum_update(map_ptr(buf, last_match + j, n1), n1);
}
if (i >= 0)
last_match = offset + s->sums[i].len;
else
@@ -177,20 +154,22 @@ static void hash_search(int f,struct sum_struct *s,
}
do {
tag t = gettag2(s1,s2);
int done_csum2 = 0;
int32 j = tag_table[t];
int32 i;
if (verbose > 4)
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
if (verbose > 4) {
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
}
if (j == NULL_TAG)
goto null_tag;
i = hash_table[SUM2HASH2(s1,s2)];
if (i < 0)
goto null_hash;
sum = (s1 & 0xffff) | (s2 << 16);
tag_hits++;
hash_hits++;
do {
int32 l, i = targets[j].i;
int32 l;
if (sum != s->sums[i].sum1)
continue;
@@ -206,9 +185,11 @@ static void hash_search(int f,struct sum_struct *s,
&& !(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);
if (verbose > 3) {
rprintf(FINFO,
"potential match at %.0f i=%ld sum=%08x\n",
(double)offset, (long)i, sum);
}
if (!done_csum2) {
map = (schar *)map_ptr(buf,offset,l);
@@ -225,8 +206,8 @@ static void hash_search(int f,struct sum_struct *s,
* 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;
int32 i2;
for (i2 = i; i2 >= 0; i2 = s->sums[i2].chain) {
if (s->sums[i2].offset != offset)
continue;
if (i2 != i) {
@@ -241,7 +222,7 @@ static void hash_search(int f,struct sum_struct *s,
* 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);
}
}
/* we've found a match, but now check to see
@@ -267,9 +248,9 @@ static void hash_search(int f,struct sum_struct *s,
s2 = sum >> 16;
matches++;
break;
} while (++j < s->count && targets[j].t == t);
} while ((i = s->sums[i].chain) >= 0);
null_tag:
null_hash:
backup = offset - last_match;
/* We sometimes read 1 byte prior to last_match... */
if (backup < 0)
@@ -324,12 +305,31 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
last_match = 0;
false_alarms = 0;
tag_hits = 0;
hash_hits = 0;
matches = 0;
data_transfer = 0;
sum_init(checksum_seed);
if (append_mode) {
OFF_T j = 0;
for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
CHUNK_SIZE);
last_match = j;
}
if (last_match < s->flength) {
int32 len = s->flength - last_match;
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, len), len);
last_match = s->flength;
}
s->count = 0;
}
if (len > 0 && s->count > 0) {
build_hash_table(s);
@@ -343,7 +343,7 @@ 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 = CHUNK_SIZE; j < len; j += CHUNK_SIZE)
for (j = last_match + CHUNK_SIZE; j < len; j += CHUNK_SIZE)
matched(f, s, buf, j, -2);
matched(f, s, buf, len, -1);
}
@@ -357,16 +357,11 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
if (targets) {
free(targets);
targets=NULL;
}
if (verbose > 2)
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
false_alarms, hash_hits, matches);
total_tag_hits += tag_hits;
total_hash_hits += hash_hits;
total_false_alarms += false_alarms;
total_matches += matches;
stats.literal_data += data_transfer;
@@ -378,8 +373,7 @@ void match_report(void)
return;
rprintf(FINFO,
"total: matches=%d tag_hits=%d false_alarms=%d data=%.0f\n",
total_matches,total_tag_hits,
total_false_alarms,
"total: matches=%d hash_hits=%d false_alarms=%d data=%.0f\n",
total_matches, total_hash_hits, total_false_alarms,
(double)stats.literal_data);
}

View File

@@ -58,7 +58,7 @@ BEGIN {
next;
}
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^uchar|^short|^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|^RETSIGTYPE/ {
next;
}

626
options.c
View File

File diff suppressed because it is too large Load Diff

View File

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

116
packaging/nightly-rsync Executable file
View File

@@ -0,0 +1,116 @@
#!/usr/bin/perl
use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. It also requires a
# pristine CVS checkout of rsync (don't use your normal rsync build dir
# unless you're 100% sure that there are not unchecked-in changes).
#
# If this is run with -ctu, it will make an updated "nightly" tar file in
# the nightly dir. It will also remove any old tar files, regenerate the
# HTML man pages in the nightly dir, and then rsync the changes to the
# samba.org server.
use Getopt::Long;
use Date::Format;
# Choose any dir where a pristine rsync has been checked out of CVS.
our $unpacked = $ENV{HOME} . '/release/nightly';
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
our($cvs_update, $make_tar, $upload, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'cvs-update|c' => \$cvs_update,
'make-tar|t' => \$make_tar,
'upload|u' => \$upload,
'help|h' => \$help_opt,
) || $help_opt;
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
our $ztoday = time2str('%d %b %Y', time);
our $today = $ztoday;
chdir($unpacked) or die $!;
if ($cvs_update) {
print "Updating from cvs...\n";
system 'cvs -q up' and die $!;
}
if ($make_tar) {
print "Generating list of active CVS files...\n";
my($dir, @files);
open(CVS, '-|', 'cvs status 2>&1') or die $!;
while (<CVS>) {
if (/^cvs status: Examining (.*)/) {
if ($1 eq '.') {
$dir = '';
} else {
push(@files, $1);
$dir = $1 . '/';
}
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
push(@files, $dir . $1);
if ($2 ne 'Up-to-date') {
print "*** Not up-to-date: $dir$1\n";
}
}
}
close CVS;
print "Creating $unpacked/$name.tar.gz\n";
chdir('..') or die $!;
rename($unpacked, $name) or die $!;
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $nightly/$name.tar.gz $name") or die $!;
foreach (@files) {
print TAR "$name/$_\n";
}
close TAR;
rename($name, $unpacked) or die $!;
}
chdir($nightly) or die $!;
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
my $html_fn = $fn;
$html_fn =~ s/\.yo/.html/;
open(IN, '<', "$unpacked/$fn") or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
open(OUT, '>', $fn) or die $!;
print OUT $_;
close OUT;
system "yodl2html -o $html_fn $fn";
unlink($fn);
}
system "find . -name 'rsync-HEAD-*' -daystart -mtime +14 | xargs rm -f";
system 'ls -ltr';
if ($upload) {
$ENV{RSYNC_PARTIAL_DIR} = ''; # The rsync on samba.org is OLD.
system "rsync -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
}
exit;
sub usage
{
die <<EOT;
Usage: nightly-rsync [OPTIONS]
-c, --cvs-update update $unpacked via CVS.
-t, --make-tar create a new tar file in $nightly
-u, --upload upload the revised nightly dir to samba.org
-h, --help display this help
EOT
}

320
packaging/release-rsync Executable file
View File

@@ -0,0 +1,320 @@
#!/usr/bin/perl
use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to
# be a copy of the /home/ftp/pub/rsync dir on samba.org. If it is run
# in test mode, it instead expects a dir named ~/tmp/samba-rsync-ftp
# (e.g. copy ~/samba-rsync-ftp into ~/tmp and you can do a trial-run of
# a release without affecting the files in the ~/samba-rsync-ftp dir).
#
# Run this as "release-rsync live" to affect ~/samba-rsync-ftp instead
# of ~/tmp/samba-rsync-ftp.
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $releasedir = $ENV{HOME} . '/release';
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
my $ztoday = time2str('%d %b %Y', time);
my $today = $ztoday;
$today =~ s/^0//;
my $break = <<EOT;
==========================================================================
EOT
my $note = <<EOT;
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
EOT
my $live = shift;
my $skipping = '';
print $break;
if ($live) {
print <<EOT;
== This will release a new version of rsync onto an unsuspecting world. ==
EOT
} else {
print <<EOT;
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
EOT
$dest =~ s#([^/]+$)#tmp/$1#;
$skipping = ' ** SKIPPING **';
}
die "$dest does not exist\n" unless -d $dest;
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
chdir($releasedir) or die $!;
system 'rm -rf rsync';
my(%dirs, @files);
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
while (<CVS>) {
print $_;
next if /\.(cvs)?ignore$/;
if (m#^[UP] rsync/(.*)#) {
my $fn = $1;
my($dir) = $fn =~ m#^(.+)/#;
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
push(@files, $fn);
}
}
chdir('rsync') or die $!;
my($version, $lastversion);
open(IN, 'configure.in') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$version = $lastversion = $1;
last;
}
}
close IN;
$lastversion =~ s/(\d+)cvs$/ $1 - 1 /e;
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
print $break, "\nPlease enter the version number of this release: [$version] ";
chomp($_ = <STDIN>);
if ($_ eq '.') {
$version =~ s/pre\d+//;
} elsif ($_ ne '') {
$version = $_;
}
$version =~ s/[-.]*pre[-.]*/pre/;
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
my $cvstag = "release-$version";
$cvstag =~ s/[.]/-/g;
$cvstag =~ s/pre/-pre/;
print "Enter the previous version to produce a patch against: [$lastversion] ";
chomp($_ = <STDIN>);
$lastversion = $_ if $_ ne '';
$lastversion =~ s/[-.]*pre[-.]*/pre/;
my $release = 1;
print "Please enter the RPM release number of this release: [$release] ";
chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
my $diffdir;
my $skipping2;
if ($lastversion =~ /pre/) {
if ($version !~ /pre/) {
die "You should not diff a release version against a pre-release version.\n";
}
$diffdir = "$dest/old-previews";
$skipping2 = ' ** SKIPPING **';
} elsif ($version =~ /pre/) {
$diffdir = $dest;
$skipping2 = ' ** SKIPPING **';
} else {
$diffdir = "$dest/old-versions";
$skipping2 = '';
}
print "\n", $break, <<EOT;
\$version is "$version"
\$lastversion is "$lastversion"
\$cvstag is "$cvstag"
\$dest is "$dest"
\$releasedir is "$releasedir"
\$diffdir is "$diffdir"
\$release is "$release"
About to:
- make sure that configure, config.h.in, and proto.h are updated
- tweak the version in configure.in, configure, and the spec files
- tweak NEWS and OLDNEWS to update the release date$skipping2
- tweak the date in the *.yo files and re-generate the man pages
- make sure that the patches dir has been updated
- page through the "cvs diff" output
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
my $f_opt = /f/ ? ' -f' : '';
print $break;
system "./prepare-source && touch proto.h";
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in configure ) );
if ($version !~ /pre/) {
push(@tweak_files, qw( NEWS OLDNEWS ));
}
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
if ($fn =~ /configure/) {
s/^RSYNC_VERSION.*/RSYNC_VERSION=$version/m;
} elsif ($fn =~ /\.spec/) {
s/^(Version:) .*/$1 $version/m;
s/^(Release:) .*/$1 $release/m;
} elsif ($fn =~ /\.yo/) {
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
} else {
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/m;
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m;
}
open(OUT, '>', $fn) or die $!;
print OUT $_;
close OUT;
}
system "yodl2man -o rsync.1 rsync.yo";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo";
#system "perl -pi -e \"s/\\\\\\'/\\\\&'/g\" rsync.1 rsyncd.conf.5";
mkdir('patches/tmp') or die $!;
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
print "\n", $break, $note, $break;
system "patches/verify-patches -n -an$f_opt";
print $break;
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
print $break, <<EOT;
About to:
- "cvs commit" all changes$skipping
- "cvs tag" this release as $cvstag$skipping
- change the diffs in the patches dir to include generated files
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
if ($live) {
system "cvs commit -m 'Preparing for release of $version'";
system "cvs tag -F $cvstag .";
}
if (!/skip/i) {
print "\n", $break, $note, $break;
system "patches/verify-patches -pun -an";
}
my $tar_name = "rsync-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $tar_file = "$dest/$tar_name";
my $diff_file = "$dest/$diff_name";
print $break, <<EOT;
About to do the following in the samba-rsync-ftp dir:
- move the old tar/diff files into the appropriate old-* dirs
- copy the moved tar/diff files on samba.org$skipping
- create release tar, "$tar_name"
- create release diffs, "$diff_name"
- update README, *NEWS, TODO, and cvs.log
- update rsync*.html man pages
- gpg-sign the release files$skipping
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
chdir($releasedir) or die $!;
print $break;
system "rm -rf rsync-$version";
rename('rsync', "rsync-$version") or die $!;
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
chdir($dest) or die $!;
print "Shuffling old files ...\n";
# We need to run this regardless of $lastversion's "pre"ness.
my @moved_files;
foreach my $fn (glob('rsync*pre*.tar.gz*'), glob('rsync*pre*-NEWS')) {
my $new_fn = "old-previews/$fn";
rename($fn, $new_fn) or die $!;
push(@moved_files, $new_fn);
}
if ($version !~ /pre/) {
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
next if $fn =~ /^rsync.*pre/;
my $new_fn = "old-versions/$fn";
rename($fn, $new_fn) or die $!;
push(@moved_files, $new_fn);
}
foreach my $fn (glob('rsync*.diffs.gz*')) {
next if $fn =~ /^rsync.*pre/;
my $new_fn = "old-patches/$fn";
rename($fn, $new_fn) or die $!;
push(@moved_files, $new_fn);
}
}
# Optimize our future upload (in the absence of --detect-renamed) by
# copying the above moved files on the remote server.
if ($live) {
my $remote_cmd = '';
foreach (@moved_files) {
my($path, $fn) = m#(.*)/([^/]+)$#;
$remote_cmd .= "cp -p /home/ftp/pub/rsync/{$fn,$path};";
}
system "ssh samba.org '$remote_cmd'";
}
foreach (glob("rsync*pre*.diffs.gz*")) {
unlink($_);
}
chdir($releasedir) or die $!;
}
print "Creating $tar_file ...\n";
system "fakeroot tar czf $tar_file rsync-$version";
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
foreach (@files) {
print TAR "rsync-$version/$_\n";
}
close TAR;
print "Creating $diff_file ...\n";
system "rm -rf rsync-$version rsync-$lastversion";
system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
## TWEAK THE VERSIONS AS DESIRED HERE ##
#mkdir("rsync-$lastversion/support", 0755) or die $!;
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
unlink("rsync-$lastversion/.ignore");
## END ##
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
print "Updating the other files in $dest ...\n";
system "rsync -a rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
unlink("$dest/rsync-$version-NEWS");
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
system "yodl2html -o $dest/rsync.html rsync-$version/rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
system "rm -rf rsync-*";
if ($live) {
chdir($dest) or die $!;
system "gpg -ba $tar_name; gpg -ba $diff_name";
print $break, <<EOT;
All done. Remember to announce the release on *BOTH*
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
EOT
} else {
print $break, "All done.\n";
}

View File

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

21
pipe.c
View File

@@ -24,11 +24,12 @@
extern int am_sender;
extern int am_server;
extern int blocking_io;
extern int orig_umask;
extern int filesfrom_fd;
extern mode_t orig_umask;
extern struct chmod_mode_struct *chmod_modes;
/**
* Create a child connected to use on stdin/stdout.
* Create a child connected to us via its stdin/stdout.
*
* This is derived from CVS code
*
@@ -78,8 +79,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
if (blocking_io > 0)
set_blocking(STDOUT_FILENO);
execvp(command[0], command);
rsyserr(FERROR, errno, "Failed to exec %s",
safe_fname(command[0]));
rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
exit_cleanup(RERR_IPC);
}
@@ -111,6 +111,9 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
int to_child_pipe[2];
int from_child_pipe[2];
/* The parent process is always the sender for a local rsync. */
assert(am_sender);
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {
rsyserr(FERROR, errno, "pipe");
@@ -124,11 +127,10 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
}
if (pid == 0) {
am_sender = !am_sender;
am_sender = 0;
am_server = 1;
if (!am_sender)
filesfrom_fd = -1;
filesfrom_fd = -1;
chmod_modes = NULL; /* Let the sending side handle this. */
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
@@ -144,9 +146,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
child_main(argc, argv);
}
if (!am_sender)
filesfrom_fd = -1;
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rsyserr(FERROR, errno, "Failed to close");

12
prepare-source Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
# Use autoconf, autoheader, yodl, etc. to ready the generated files
# in the release. This is typically used after applying a diff from
# "patches" directory in CVS.
#
# NOTE: if you use a diff from the "patches" directory in a release
# tar, this is not needed (but doesn't hurt anything).
dir=`dirname $0`
if test x"$dir" != x -o x"$dir" != x.; then
cd "$dir"
fi
make -f prepare-source.mak

23
prepare-source.mak Normal file
View File

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

View File

@@ -97,15 +97,14 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
remain_h = (int) (remain / 3600.0);
if (is_last) {
snprintf(eol, sizeof eol, " (%d, %.1f%% of %d)\n",
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
stats.num_transferred_files,
(float)((stats.current_file_index+1) * 100)
/ stats.num_files,
stats.num_files - stats.current_file_index - 1,
stats.num_files);
} else
strcpy(eol, "\r");
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
(double) ofs, pct, rate, units,
rprintf(FINFO, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
human_num(ofs), pct, rate, units,
remain_h, remain_m, remain_s, eol);
}

View File

@@ -34,17 +34,14 @@ 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 io_error;
extern int basis_dir_cnt;
extern int make_backups;
extern int cleanup_got_literal;
extern int remove_sent_files;
extern int module_id;
extern int ignore_errors;
extern int orig_umask;
extern int append_mode;
extern int sparse_files;
extern int keep_partial;
extern int checksum_seed;
extern int inplace;
@@ -57,70 +54,9 @@ extern char *basis_dir[];
extern struct file_list *the_file_list;
extern struct filter_list_struct server_filter_list;
#define SLOT_SIZE (16*1024) /* Desired size in bytes */
#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 struct bitbag *delayed_bits = NULL;
static int phase = 0;
static void init_delayed_bits(int max_ndx)
{
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 void set_delayed_bit(int ndx)
{
int slot = ndx / PER_SLOT_BITS;
ndx %= PER_SLOT_BITS;
if (!delayed_bits[slot]) {
if (!(delayed_bits[slot] = (uint32*)calloc(PER_SLOT_INTS, 4)))
out_of_memory("set_delayed_bit");
}
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;
for ( ; i < PER_SLOT_INTS; i++, mask = 0) {
if (!(bits = delayed_bits[slot][i] & ~mask))
continue;
/* 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... */
}
}
return -1;
}
/*
* get_tmpname() - create a tmp filename for a given filename
@@ -171,8 +107,7 @@ 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",
safe_fname(fname));
rprintf(FERROR, "temporary filename too long: %s\n", fname);
fnametmp[0] = '\0';
return 0;
}
@@ -205,13 +140,39 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
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);
fname_r, (double)size_r);
}
} else
mapbuf = NULL;
sum_init(checksum_seed);
if (append_mode) {
OFF_T j;
sum.flength = (OFF_T)sum.count * sum.blength;
if (sum.remainder)
sum.flength -= sum.blength - sum.remainder;
for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
CHUNK_SIZE);
offset = j;
}
if (offset < sum.flength) {
int32 len = sum.flength - offset;
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, len), len);
offset = sum.flength;
}
if (fd != -1 && do_lseek(fd, offset, SEEK_SET) != offset) {
rsyserr(FERROR, errno, "lseek failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
}
while ((i = recv_token(f_in, &data)) != 0) {
if (do_progress)
show_progress(offset, total_size);
@@ -315,22 +276,22 @@ 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; ) {
for (i = -1; (i = bitbag_next_bit(delayed_bits, i)) >= 0; ) {
struct file_struct *file = flist->files[i];
fname = local_name ? local_name : f_name(file);
fname = local_name ? local_name : f_name(file, NULL);
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));
partialptr, fname);
}
/* We don't use robust_rename() here because the
* partial-dir must be on the same drive. */
if (do_rename(partialptr, fname) < 0) {
rsyserr(FERROR, errno,
"rename failed for %s (from %s)",
full_fname(fname),
safe_fname(partialptr));
full_fname(fname), partialptr);
} else {
if (remove_sent_files
|| (preserve_hard_links
@@ -338,8 +299,7 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS,numbuf,4);
}
handle_partial_dir(partialptr,
PDIR_DELETE);
handle_partial_dir(partialptr, PDIR_DELETE);
}
}
}
@@ -352,7 +312,7 @@ static int get_next_gen_i(int batch_gen_fd, int next_gen_i, int desired_i)
rprintf(FINFO,
"(No batched update for%s \"%s\")\n",
phase ? " resend of" : "",
safe_fname(f_name(the_file_list->files[next_gen_i])));
f_name(the_file_list->files[next_gen_i], NULL));
}
next_gen_i = read_int(batch_gen_fd);
if (next_gen_i == -1)
@@ -395,7 +355,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if (delay_updates)
init_delayed_bits(flist->count);
delayed_bits = bitbag_create(flist->count);
while (1) {
cleanup_disable();
@@ -417,6 +377,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
send_msg(MSG_DONE, "", 0);
if (keep_partial && !partial_dir)
make_backups = 0; /* prevents double backup */
if (append_mode) {
append_mode = 0;
sparse_files = 0;
}
continue;
}
@@ -426,10 +390,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
continue;
file = flist->files[i];
fname = local_name ? local_name : f_name_to(file, fbuf);
fname = local_name ? local_name : f_name(file, fbuf);
if (verbose > 2)
rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
rprintf(FINFO, "recv_files(%s)\n", fname);
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
@@ -470,8 +434,9 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
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));
rprintf(FINFO,
"(Skipping batched update for \"%s\")\n",
fname);
discard_receive_data(f_in, file->length);
continue;
}
@@ -572,16 +537,16 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
fd1 = -1;
}
if (fd1 != -1 && !preserve_perms) {
/* if the file exists already and we aren't preserving
* permissions then act as though the remote end sent
* us the file permissions we already have */
file->mode = st.st_mode;
/* If we're not preserving permissions, change the file-list's
* mode based on the local permissions and some heuristics. */
if (!preserve_perms) {
int exists = fd1 != -1;
file->mode = dest_mode(file->mode, st.st_mode, exists);
}
/* We now check to see if we are writing file "inplace" */
if (inplace) {
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0);
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
if (fd2 == -1) {
rsyserr(FERROR, errno, "open %s failed",
full_fname(fname));
@@ -610,7 +575,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
* 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) {
&& create_directory_path(fnametmp) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
@@ -624,7 +589,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
continue;
}
if (partialptr)
if (keep_partial)
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
}
@@ -632,7 +597,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
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));
rprintf(FINFO, "%s\n", fname);
/* recv file data */
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
@@ -650,17 +615,20 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
finish_transfer(fname, fnametmp, file, recv_ok, 1);
if (partialptr != fname && fnamecmp == partialptr) {
if (partialptr == fname || *partial_dir == '/')
partialptr = NULL;
finish_transfer(fname, fnametmp, partialptr,
file, recv_ok, 1);
if (fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, file, recv_ok,
!partial_dir);
finish_transfer(partialptr, fnametmp, NULL,
file, recv_ok, !partial_dir);
if (delay_updates && recv_ok) {
set_delayed_bit(i);
bitbag_set_bit(delayed_bits, i);
recv_ok = -1;
}
} else {
@@ -695,8 +663,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
rprintf(msgtype,
"%s: %s failed verification -- update %s%s.\n",
errstr, safe_fname(fname),
keptstr, redostr);
errstr, fname, keptstr, redostr);
}
if (!phase) {
SIVAL(numbuf, 0, i);

177
rsync.c
View File

@@ -21,10 +21,20 @@
process */
#include "rsync.h"
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#endif
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
#include <libcharset.h>
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
#include <langinfo.h>
#endif
extern int verbose;
extern int dry_run;
extern int daemon_log_format_has_i;
extern int preserve_perms;
extern int preserve_executability;
extern int preserve_times;
extern int omit_dir_times;
extern int am_root;
@@ -32,13 +42,53 @@ extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int preserve_uid;
extern int preserve_gid;
extern int inplace;
extern int keep_dirlinks;
extern int make_backups;
extern mode_t orig_umask;
extern struct stats stats;
extern struct chmod_mode_struct *daemon_chmod_modes;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
iconv_t ic_chck = (iconv_t)-1;
static const char *default_charset(void)
{
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
return locale_charset();
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
return nl_langinfo(CODESET);
#else
return ""; /* Works with (at the very least) gnu iconv... */
#endif
}
void setup_iconv()
{
if (!am_server && !allow_8bit_chars) {
const char *defset = default_charset();
/* It's OK if this fails... */
ic_chck = iconv_open(defset, defset);
if (verbose > 3) {
if (ic_chck == (iconv_t)-1) {
rprintf(FINFO,
"note: iconv_open(\"%s\", \"%s\") failed (%d)"
" -- using isprint() instead of iconv().\n",
defset, defset, errno);
} else {
rprintf(FINFO,
"note: iconv_open(\"%s\", \"%s\") succeeded.\n",
defset, defset);
}
}
}
}
#endif
/*
free a sums struct
@@ -49,9 +99,31 @@ void free_sums(struct sum_struct *s)
free(s);
}
/* This is only called when we aren't preserving permissions. Figure out what
* the permissions should be and return them merged back into the mode. */
mode_t dest_mode(mode_t flist_mode, mode_t cur_mode, int exists)
{
/* If the file already exists, we'll return the local permissions,
* possibly tweaked by the --executability option. */
if (exists) {
if (preserve_executability && S_ISREG(flist_mode)) {
/* If the source file is executable, grant execute
* rights to everyone who can read, but ONLY if the
* file isn't already executable. */
if (!(flist_mode & 0111))
cur_mode &= ~0111;
else if (!(cur_mode & 0111))
cur_mode |= (cur_mode & 0444) >> 2;
}
} else
cur_mode = flist_mode & ACCESSPERMS & ~orig_umask;
if (daemon_chmod_modes && !S_ISLNK(flist_mode))
cur_mode = tweak_mode(cur_mode, daemon_chmod_modes);
return (flist_mode & ~CHMOD_BITS) | (cur_mode & CHMOD_BITS);
}
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
int flags)
int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
int flags)
{
int updated = 0;
STRUCT_STAT st2;
@@ -66,19 +138,26 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
return 0;
}
st = &st2;
if (!preserve_perms && S_ISDIR(file->mode)
&& st->st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
file->mode |= S_ISGID;
}
}
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) {
if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(st->st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, st->st_mode);
if (ret < 0) {
rsyserr(FERROR, errno, "failed to set times on %s",
full_fname(fname));
return 0;
}
updated = 1;
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
}
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
@@ -94,13 +173,13 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %ld to %ld\n",
safe_fname(fname),
fname,
(long)st->st_uid, (long)file->uid);
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %ld to %ld\n",
safe_fname(fname),
fname,
(long)st->st_gid, (long)file->gid);
}
}
@@ -125,31 +204,31 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
}
#ifdef HAVE_CHMOD
if (!S_ISLNK(st->st_mode)) {
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
updated = 1;
if (do_chmod(fname,(file->mode & CHMOD_BITS)) != 0) {
rsyserr(FERROR, errno, "failed to set permissions on %s",
full_fname(fname));
return 0;
}
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
int ret = do_chmod(fname, file->mode);
if (ret < 0) {
rsyserr(FERROR, errno,
"failed to set permissions on %s",
full_fname(fname));
return 0;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
}
#endif
if (verbose > 1 && flags & PERMS_REPORT) {
if (verbose > 1 && flags & ATTRS_REPORT) {
enum logcode code = daemon_log_format_has_i || dry_run
? FCLIENT : FINFO;
if (updated)
rprintf(code, "%s\n", safe_fname(fname));
rprintf(code, "%s\n", fname);
else
rprintf(code, "%s is uptodate\n", safe_fname(fname));
rprintf(code, "%s is uptodate\n", fname);
}
return updated;
}
void sig_int(void)
RETSIGTYPE sig_int(UNUSED(int val))
{
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
* for a password, then our cleanup's sending of a SIGUSR1
@@ -163,36 +242,39 @@ void sig_int(void)
exit_cleanup(RERR_SIGNAL);
}
/* 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,
int ok_to_set_time, int overwriting_basis)
/* Finish off a file transfer: renaming the file and setting the file's
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
* NULL and the robust_rename() call is forced to copy the temp file, we
* stage the file into the partial-dir and then rename it into place. */
void finish_transfer(char *fname, char *fnametmp, char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
{
int ret;
if (inplace) {
if (verbose > 2)
rprintf(FINFO, "finishing %s\n", safe_fname(fname));
goto do_set_perms;
rprintf(FINFO, "finishing %s\n", fname);
fnametmp = fname;
goto do_set_file_attrs;
}
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);
set_file_attrs(fnametmp, file, NULL,
ok_to_set_time ? 0 : ATTRS_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 (verbose > 2)
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
ret = robust_rename(fnametmp, fname, partialptr,
file->mode & INITACCESSPERMS);
if (ret < 0) {
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), safe_fname(fname));
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname);
do_unlink(fnametmp);
return;
}
@@ -200,8 +282,21 @@ void finish_transfer(char *fname, char *fnametmp, struct file_struct *file,
/* 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);
/* The file was copied, so tweak the perms of the copied file. If it
* was copied to partialptr, move it into its final destination. */
fnametmp = partialptr ? partialptr : fname;
do_set_file_attrs:
set_file_attrs(fnametmp, file, NULL,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
if (partialptr) {
if (do_rename(fnametmp, fname) < 0) {
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
full_fname(fnametmp), fname);
} else
handle_partial_dir(partialptr, PDIR_DELETE);
}
}
const char *who_am_i(void)

92
rsync.h
View File

@@ -58,12 +58,12 @@
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0)
#define FLAG_SENT (1<<1) /* sender */
#define FLAG_HLINK_EOL (1<<1) /* receiver/generator */
#define FLAG_MOUNT_POINT (1<<2) /* sender */
#define FLAG_NO_FUZZY (1<<2) /* generator */
#define FLAG_MOUNT_POINT (1<<2) /* sender/generator */
#define FLAG_DEL_HERE (1<<3) /* receiver/generator */
#define FLAG_SENT (1<<3) /* sender */
#define FLAG_HLINK_TOL (1<<4) /* receiver/generator */
#define FLAG_NO_FUZZY (1<<5) /* generator */
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 29
@@ -115,9 +115,10 @@
#define XFLG_FATAL_ERRORS (1<<0)
#define XFLG_OLD_PREFIXES (1<<1)
#define XFLG_ANCHORED2ABS (1<<2)
#define XFLG_ABS_IF_SLASH (1<<3)
#define PERMS_REPORT (1<<0)
#define PERMS_SKIP_MTIME (1<<1)
#define ATTRS_REPORT (1<<0)
#define ATTRS_SKIP_MTIME (1<<1)
#define FULL_FLUSH 1
#define NORMAL_FLUSH 0
@@ -133,26 +134,22 @@
#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_ATIME (1<<0)
#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_REPORT_ACL (1<<7)
#define ITEM_REPORT_XATTR (1<<8)
#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() */
@@ -160,16 +157,17 @@
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 };
/* Log-message categories. Only FERROR and FINFO get sent over the socket.
* FLOG and FCLIENT are only used on the daemon side for custom logging,
* while FNAME is only used on the client side. */
enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FNAME=5, FSOCKERR=6 };
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_FCLIENT=FCLIENT, /* sibling logging */
MSG_LOG=FLOG, MSG_SOCKERR=FSOCKERR, /* 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 */
@@ -319,6 +317,10 @@ enum msgcode {
#include <compat.h>
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#include <assert.h>
#include "lib/pool_alloc.h"
@@ -463,6 +465,14 @@ struct idev {
#define MAXPATHLEN 1024
#endif
/* We want a roomy line buffer that can hold more than MAXPATHLEN,
* and significantly more than an overly short MAXPATHLEN. */
#if MAXPATHLEN < 4096
#define BIGPATHBUFLEN (4096+1024)
#else
#define BIGPATHBUFLEN (MAXPATHLEN+1024)
#endif
#ifndef NAME_MAX
#define NAME_MAX 255
#endif
@@ -552,6 +562,7 @@ struct sum_buf {
OFF_T offset; /**< offset in file of this chunk */
int32 len; /**< length of chunk of file */
uint32 sum1; /**< simple checksum */
int32 chain; /**< next hash-table collision */
short flags; /**< flag bits */
char sum2[SUM_LENGTH]; /**< checksum */
};
@@ -579,11 +590,11 @@ struct map_struct {
#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 */
#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_WILD2_PREFIX (1<<2) /* pattern starts with "**" */
#define MATCHFLG_WILD3_SUFFIX (1<<3) /* pattern ends with "***" */
#define MATCHFLG_ABS_PATH (1<<4) /* path-match on absolute path */
#define MATCHFLG_INCLUDE (1<<5) /* this is an include, not an exclude */
#define MATCHFLG_DIRECTORY (1<<6) /* this matches only directories */
#define MATCHFLG_WORD_SPLIT (1<<7) /* split rules on whitespace */
#define MATCHFLG_NO_INHERIT (1<<8) /* don't inherit these rules */
#define MATCHFLG_NO_PREFIXES (1<<9) /* parse no prefixes from patterns */
@@ -595,6 +606,7 @@ struct map_struct {
#define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
#define MATCHFLG_CLEAR_LIST (1<<18)/* this item is the "!" token */
#define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
| MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
@@ -631,6 +643,7 @@ struct stats {
int current_file_index;
};
struct chmod_mode_struct;
#include "byteorder.h"
#include "lib/mdfour.h"
@@ -638,6 +651,15 @@ struct stats {
#include "lib/permstring.h"
#include "lib/addrinfo.h"
#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)
#endif
#define UNUSED(x) x __attribute__((__unused__))
#include "proto.h"
/* We have replacement versions of these if they're missing. */
@@ -681,7 +703,12 @@ extern int errno;
#define SUPPORT_HARD_LINKS 1
#endif
#define SIGNAL_CAST (RETSIGTYPE (*)())
#ifdef HAVE_SIGACTION
#define SIGACTION(n,h) sigact.sa_handler=(h), sigaction((n),&sigact,NULL)
#define signal(n,h) we_need_to_call_SIGACTION_not_signal(n,h)
#else
#define SIGACTION(n,h) signal(n,h)
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
@@ -778,7 +805,8 @@ extern int errno;
#define INADDR_NONE 0xffffffff
#endif
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
/* Initial mask on permissions given to temporary files. Mask off setuid
bits and group access because of potential race-condition security
@@ -786,15 +814,7 @@ extern int errno;
#define INITACCESSPERMS 0700
/* handler for null strings in printf format */
#define NS(s) ((s)?safe_fname(s):"<NULL>")
#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)
#endif
#define NS(s) ((s)?(s):"<NULL>")
/* Convenient wrappers for malloc and realloc. Use them. */
#define new(type) ((type *)malloc(sizeof(type)))
@@ -812,10 +832,6 @@ void rsyserr(enum logcode, int, const char *, ...)
__attribute__((format (printf, 3, 4)))
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif
/* Make sure that the O_BINARY flag is defined. */
#ifndef O_BINARY
#define O_BINARY 0
@@ -860,7 +876,3 @@ int inet_pton(int af, const char *src, void *dst);
#ifdef MAINTAINER_MODE
const char *get_panic_action(void);
#endif
#define UNUSED(x) x __attribute__((__unused__))
extern const char *io_write_phase, *io_read_phase;

991
rsync.yo
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(10 May 2005)()()
manpage(rsyncd.conf)(5)(22 Apr 2006)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -52,9 +52,6 @@ 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 "bf(rsync --daemon)" from a suitable startup script.
If run from an rsync client via a remote shell (by specifying both the
bf(--rsh) (bf(-e)) option and 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:
@@ -89,7 +86,7 @@ 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
useful on systems (such as AIX) where code(syslog()) doesn't work for
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
@@ -117,9 +114,10 @@ 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
slower!). Read the man page for the setsockopt() system call for
slower!). Read the man page for the code(setsockopt()) system call for
details on some of the options you may be able to set. By default no
special socket options are set.
special socket options are set. These settings are superseded by the
bf(--sockopts) command-line option.
enddit()
@@ -156,7 +154,7 @@ The default for "use chroot" is true.
In order to preserve usernames and groupnames, rsync needs to be able to
use the standard library functions for looking up names and IDs (i.e.
getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
process in the chroot namespace will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
@@ -166,7 +164,7 @@ 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/uploaded by adding an exclude rule to the rsync.conf file
being downloaded/uploaded by adding an exclude rule to the rsyncd.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
@@ -265,6 +263,25 @@ only superficially equivalent to the client specifying the
bf(--include-from) option with a equivalent file.
See the "exclude" option above.
dit(bf(incoming chmod)) This option allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
incoming files (files that are being received by the daemon). These
changes happen after all other permission calculations, and this will
even override destination-default and/or existing permissions when the
client does not specify bf(--perms).
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(outgoing chmod)) This option allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
outgoing files (files that are being sent out from the daemon). These
changes happen first, making the sent permissions appear to be different
than those stored in the filesystem itself. For instance, you could
disable group write permissions on the server while having it appear to
be on to the clients.
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(auth users)) The "auth users" option specifies a comma and
space-separated list of usernames that will be allowed to connect to
this module. The usernames do not need to exist on the local
@@ -272,12 +289,12 @@ system. The usernames may also contain shell wildcard characters. If
"auth users" is set then the client will be challenged to supply a
username and password to connect to the module. A challenge response
authentication protocol is used for this exchange. The plain text
usernames are passwords are stored in the file specified by the
usernames and 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 "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
PROGRAM" section in rsync(1) for information on how handle an
PROGRAM" section in bf(rsync)(1) for information on how handle an
rsyncd.conf-level username that differs from the remote-shell-level
username when using a remote shell to connect to an rsync daemon.
@@ -389,24 +406,25 @@ rsyncstats.)
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 "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
it() %u for the authenticated username (or the null string)
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() %a the remote IP address
it() %b the number of bytes actually transferred
it() %B the permission bits of the file (e.g. rwxrwxrwt)
it() %c the checksum bytes received for this file (only when sending)
it() %f the filename (long form on sender; no trailing "/")
it() %G the gid of the file (decimal) or "DEFAULT"
it() %h the remote host name
it() %i an itemized list of what is being updated
it() %l the length of the file in bytes
it() %L the string " -> SYMLINK", " => HARDLINK", or "" (where bf(SYMLINK) or bf(HARDLINK) is a filename)
it() %m the module name
it() %M the last-modified time of the file
it() %n the filename (short form; trailing "/" on dir)
it() %o the operation, which is "send", "recv", or "del." (the latter includes the trailing period)
it() %p the process ID of this rsync session
it() %P the module path
it() %t the current date time
it() %u the authenticated username or an empty string
it() %U the uid of the file (decimal)
))
For a list of what the characters mean that are output by "%i", see the
@@ -457,16 +475,45 @@ of the patterns will not be compressed during transfer.
The default setting is tt(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
before and/or after the transfer. If the bf(pre-xfer exec) command fails, the
transfer is aborted before it begins.
The following environment variables will be set, though some are
specific to the pre-xfer or the post-xfer environment:
quote(itemize(
it() bf(RSYNC_MODULE_NAME): The name of the module being accessed.
it() bf(RSYNC_MODULE_PATH): The path configured for the module.
it() bf(RSYNC_HOST_ADDR): The accessing host's IP address.
it() bf(RSYNC_HOST_NAME): The accessing host's name.
it() bf(RSYNC_USER_NAME): The accessing user's name (empty if no user).
it() bf(RSYNC_REQUEST): (pre-xfer only) The module/path info specified
by the user (note that the user can specify multiple source files,
so the request can be something like "mod/path1 mod/path2", etc.).
it() bf(RSYNC_ARG#): (pre-xfer only) The pre-request arguments are set
in these numbered values. RSYNC_ARG0 is always "rsyncd", and the last
value contains a single period.
it() bf(RSYNC_EXIT_STATUS): (post-xfer only) rsync's exit value. This will be 0 for a
successful run, a positive value for an error that rsync returned
(e.g. 23=partial xfer), or a -1 if rsync failed to exit properly.
it() bf(RSYNC_RAW_STATUS): (post-xfer only) the raw exit value from code(waitpid()).
))
Even though the commands can be associated with a particular module, they
are run using the permissions of the user that started the daemon (not the
module's uid/gid setting) without any chroot restrictions.
enddit()
manpagesection(AUTHENTICATION STRENGTH)
The authentication protocol used in rsync is a 128 bit MD4 based
challenge response system. Although I believe that no one has ever
demonstrated a brute-force break of this sort of system you should
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.
challenge response system. This is fairly weak protection, though (with
at least one brute-force hash-finding algorithm publicly available), so
if you want really top-quality security, then I recommend that you run
rsync over ssh. (Yes, a future version of rsync will switch over to a
stronger hashing method.)
Also note that the rsync daemon protocol does not currently provide any
encryption of the data that is transferred over the connection. Only
@@ -476,32 +523,6 @@ encryption.
Future versions of rsync may support SSL for better authentication and
encryption, but that is still being investigated.
manpagesection(RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
If rsync is run with both the bf(--daemon) and bf(--rsh) (bf(-e)) options, it will
spawn an rsync daemon using a remote shell connection. Several
configuration options will not be available unless the remote user is
root (e.g. chroot, setuid/setgid, etc.). There is no need to configure
inetd or the services map to include the rsync daemon port if you run an
rsync daemon only via a remote shell program.
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(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
bf(--config) option to the em(command):
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 bf(--server) option under normal circumstances.
manpagesection(EXAMPLES)
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
@@ -570,7 +591,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.6.5pre1 of rsync.
This man page is current for version 2.6.8 of rsync.
manpagesection(CREDITS)

View File

@@ -85,7 +85,7 @@
# they're explicitly given on the command line.
# Also, we can't count on 'cp -a' or 'mkdir -p', although they're
# pretty handy.
# pretty handy (see function makepath for the latter).
# I think some of the GNU documentation suggests that we shouldn't
# rely on shell functions. However, the Bash manual seems to say that
@@ -100,6 +100,8 @@
# You cannot do "export VAR=VALUE" all on one line; the export must be
# separate from the assignment. (SCO SysV)
# Don't rely on grep -q, as that doesn't work everywhere -- just redirect
# stdout to /dev/null to keep it quiet.
# STILL TO DO:
@@ -124,6 +126,7 @@ set -e
. "./shconfig"
RUNSHFLAGS='-e'
export RUNSHFLAGS
# for Solaris
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
@@ -160,6 +163,14 @@ else
echo " preserve_scratch=no"
fi
# Check if setfacl is around and if it supports the -k or -s option.
if setfacl --help 2>/dev/null | grep ' -k,' >/dev/null; then
setfacl_nodef='setfacl -k'
elif setfacl -s u::7,g::5,o:5 testsuite 2>/dev/null; then
setfacl_nodef='setfacl -s u::7,g::5,o:5'
else
setfacl_nodef=true
fi
if [ ! -f "$rsync_bin" ]; then
echo "rsync_bin $rsync_bin is not a file" >&2
@@ -174,7 +185,7 @@ fi
RSYNC="$rsync_bin"
#RSYNC="valgrind --tool=addrcheck $rsync_bin"
export rsync_bin RSYNC
export rsync_bin RSYNC setfacl_nodef
skipped=0
missing=0
@@ -194,6 +205,9 @@ export scratchdir suitedir
prep_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
mkdir "$scratchdir"
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
$setfacl_nodef "$scratchdir"
chmod g-s "$scratchdir"
return 0
}

View File

@@ -27,7 +27,9 @@ extern int log_before_transfer;
extern int log_format_has_i;
extern int daemon_log_format_has_i;
extern int csum_length;
extern int append_mode;
extern int io_error;
extern int allowed_lull;
extern int protocol_version;
extern int remove_sent_files;
extern int updating_basis_file;
@@ -56,6 +58,7 @@ static struct sum_struct *receive_sums(int f)
{
struct sum_struct *s;
int32 i;
int lull_mod = allowed_lull * 5;
OFF_T offset = 0;
if (!(s = new(struct sum_struct)))
@@ -70,6 +73,13 @@ static struct sum_struct *receive_sums(int f)
(double)s->count, (long)s->blength, (long)s->remainder);
}
if (append_mode) {
s->flength = (OFF_T)s->count * s->blength;
if (s->remainder)
s->flength -= s->blength - s->remainder;
return s;
}
if (s->count == 0)
return(s);
@@ -89,6 +99,9 @@ static struct sum_struct *receive_sums(int f)
s->sums[i].len = s->blength;
offset += s->sums[i].len;
if (allowed_lull && !(i % lull_mod))
maybe_send_keepalive();
if (verbose > 3) {
rprintf(FINFO,
"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
@@ -120,11 +133,9 @@ void successful_send(int ndx)
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));
}
f_name(file, fname + offset);
if (remove_sent_files && do_unlink(fname) == 0 && verbose > 1)
rprintf(FINFO, "sender removed %s\n", fname + offset);
}
static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
@@ -226,6 +237,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
/* For inplace: redo phase turns off the backup
* flag so that we do a regular inplace send. */
make_backups = 0;
append_mode = 0;
continue;
}
@@ -242,7 +254,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
fname[offset++] = '/';
} else
offset = 0;
fname2 = f_name_to(file, fname + offset);
fname2 = f_name(file, fname + offset);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
@@ -317,22 +329,20 @@ void send_files(struct file_list *flist, int f_out, int f_in)
if (verbose > 2) {
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
safe_fname(fname), (double)st.st_size);
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 (verbose > 2)
rprintf(FINFO, "calling match_sums %s\n", 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));
rprintf(FINFO, "%s\n", fname2);
set_compression(fname);
@@ -356,10 +366,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
free_sums(s);
if (verbose > 2) {
rprintf(FINFO, "sender finished %s\n",
safe_fname(fname));
}
if (verbose > 2)
rprintf(FINFO, "sender finished %s\n", fname);
/* Flag that we actually sent this entry. */
file->flags |= FLAG_SENT;

View File

@@ -32,10 +32,16 @@
**/
#include "rsync.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
extern char *bind_address;
extern int default_af_hint;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Establish a proxy connection on an open socket to a web proxy by
* using the CONNECT method. If proxy_user and proxy_pass are not NULL,
@@ -54,13 +60,13 @@ static int establish_proxy_connection(int fd, char *host, int port,
proxy_user, ":", proxy_pass, NULL);
len = strlen(buffer);
if ((len*8 + 5) / 6 >= (int)sizeof authbuf) {
if ((len*8 + 5) / 6 >= (int)sizeof authbuf - 3) {
rprintf(FERROR,
"authentication information is too long\n");
return -1;
}
base64_encode(buffer, len, authbuf);
base64_encode(buffer, len, authbuf, 1);
authhdr = "\r\nProxy-Authorization: Basic ";
} else {
*authbuf = '\0';
@@ -329,9 +335,9 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
int one = 1;
int s, *socks, maxs, i;
int s, *socks, maxs, i, ecnt;
struct addrinfo hints, *all_ai, *resp;
char portbuf[10];
char portbuf[10], **errmsgs;
int error;
memset(&hints, 0, sizeof hints);
@@ -349,17 +355,25 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Count max number of sockets we might open. */
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
if (!(socks = new_array(int, maxs + 1)))
socks = new_array(int, maxs + 1);
errmsgs = new_array(char *, maxs);
if (!socks || !errmsgs)
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. */
for (resp = all_ai, i = 0; resp; resp = resp->ai_next) {
for (resp = all_ai, i = ecnt = 0; resp; resp = resp->ai_next) {
s = socket(resp->ai_family, resp->ai_socktype,
resp->ai_protocol);
if (s == -1) {
int r = asprintf(&errmsgs[ecnt++],
"socket(%d,%d,%d) failed: %s\n",
(int)resp->ai_family, (int)resp->ai_socktype,
(int)resp->ai_protocol, strerror(errno));
if (r < 0)
out_of_memory("open_socket_in");
/* See if there's another address that will work... */
continue;
}
@@ -381,6 +395,11 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Now we've got a socket - we need to bind it. */
if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
/* Nope, try another */
int r = asprintf(&errmsgs[ecnt++],
"bind() failed: %s (address-family %d)\n",
strerror(errno), (int)resp->ai_family);
if (r < 0)
out_of_memory("open_socket_in");
close(s);
continue;
}
@@ -392,6 +411,15 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
if (all_ai)
freeaddrinfo(all_ai);
/* Only output the socket()/bind() messages if we were totally
* unsuccessful, or if the daemon is being run with -vv. */
for (s = 0; s < ecnt; s++) {
if (!i || verbose > 1)
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]));
free(errmsgs[s]);
}
free(errmsgs);
if (!i) {
rprintf(FERROR,
"unable to bind any inbound sockets on port %d\n",
@@ -433,7 +461,9 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
#ifdef WNOHANG
while (waitpid(-1, NULL, WNOHANG) > 0) {}
#endif
#ifndef HAVE_SIGACTION
signal(SIGCHLD, sigchld_handler);
#endif
}
@@ -442,6 +472,10 @@ void start_accept_loop(int port, int (*fn)(int, int))
fd_set deffds;
int *sp, maxfd, i;
#ifdef HAVE_SIGACTION
sigact.sa_flags = SA_NOCLDSTOP;
#endif
/* open an incoming socket */
sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
if (sp == NULL)
@@ -465,7 +499,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
maxfd = sp[i];
}
/* now accept incoming connections - forking a new process
* for each incoming connection */
while (1) {
@@ -500,7 +533,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
if (fd < 0)
continue;
signal(SIGCHLD, sigchld_handler);
SIGACTION(SIGCHLD, sigchld_handler);
if ((pid = fork()) == 0) {
int ret;

View File

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

64
support/cull_options Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/perl
# This script outputs some perl code that parses all possible options
# that the code in options.c might send to the server. This perl code
# is included in the rrsync script.
use strict;
our(%short_no_arg, %short_with_num, %long_opt);
our $last_long_opt;
open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
while (<IN>) {
if (/\Qargstr[x++]\E = '(.)'/) {
$short_no_arg{$1} = 1;
undef $last_long_opt;
} elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {
$short_with_num{$1} = 1;
undef $last_long_opt;
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
$last_long_opt = $1;
$long_opt{$1} = 0;
} elsif (defined($last_long_opt)
&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
$long_opt{$last_long_opt} = 2;
undef $last_long_opt;
} elsif (/dest_option = "--([^"]+)"/) {
$long_opt{$1} = 2;
undef $last_long_opt;
} elsif (/\Qasprintf(\E[^,]+, "--([^"=]+)=/ || /\Qargs[ac++]\E = "--([^"=]+)=/) {
$long_opt{$1} = 1;
undef $last_long_opt;
}
}
close IN;
my $short_no_arg = join('', sort keys %short_no_arg);
my $short_with_num = join('', sort keys %short_with_num);
print <<EOT;
# These options are the only options that rsync might send to the server,
# and only in the option format that the stock rsync produces.
# To disable a short-named option, add its letter to this string:
our \$short_disabled = '';
our \$short_no_arg = '$short_no_arg'; # DO NOT REMOVE ANY
our \$short_with_num = '$short_with_num'; # DO NOT REMOVE ANY
# To disable a long-named option, change its value to a -1. The values mean:
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
# check the arg when receiving; and 3 = always check the arg.
our \%long_opt = (
EOT
foreach my $opt (sort keys %long_opt) {
my $val = $long_opt{$opt};
$val = 1 if $opt =~ /^max-/;
$val = 3 if $opt eq 'files-from';
$val = '$ro ? -1 : ' . $val if $opt =~ /^remove-/;
print " '$opt' => $val,\n";
}
print ");\n\n";

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;

172
support/file-attr-restore Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/perl
# This script will parse the output of "find ARG [ARG...] -ls" and
# apply (at your discretion) the permissions, owner, and group info
# it reads onto any existing files and dirs (it doesn't try to affect
# symlinks). Run this with --help (-h) for a usage summary.
use strict;
use Getopt::Long;
our($p_opt, $o_opt, $g_opt, $map_file, $dry_run, $verbosity, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'all|a' => sub { $p_opt = $o_opt = $g_opt = 1 },
'perms|p' => \$p_opt,
'owner|o' => \$o_opt,
'groups|g' => \$g_opt,
'map|m=s' => \$map_file,
'dry-run|n' => \$dry_run,
'help|h' => \$help_opt,
'verbose|v+' => \$verbosity,
) || $help_opt;
our(%uid_hash, %gid_hash);
$" = ', '; # How to join arrays referenced in double-quotes.
&parse_map_file($map_file) if defined $map_file;
my $detail_line = qr{
^ \s* \d+ \s+ # ignore inode
\d+ \s+ # ignore size
([-bcdlps]) # 1. File type
( [-r][-w][-xsS] # 2. user-permissions
[-r][-w][-xsS] # 3. group-permissions
[-r][-w][-xtT] ) \s+ # 4. other-permissions
\d+ \s+ # ignore number of links
(\S+) \s+ # 5. owner
(\S+) \s+ # 6. group
(?: \d+ \s+ )? # ignore size (when present)
\w+ \s+ \d+ \s+ # ignore month and date
\d+ (?: : \d+ )? \s+ # ignore time or year
([^\r\n]+) $ # 7. name
}x;
while (<>) {
my($type, $perms, $owner, $group, $name) = /$detail_line/;
die "Invalid input line $.:\n$_" unless defined $name;
die "A filename is not properly escaped:\n$_" unless $name =~ /^[^"\\]*(\\(\d\d\d|\D)[^"\\]*)*$/;
my $fn = eval "\"$name\"";
if ($type eq '-') {
undef $type unless -f $fn;
} elsif ($type eq 'd') {
undef $type unless -d $fn;
} elsif ($type eq 'b') {
undef $type unless -b $fn;
} elsif ($type eq 'c') {
undef $type unless -c $fn;
} elsif ($type eq 'p') {
undef $type unless -p $fn;
} elsif ($type eq 's') {
undef $type unless -S $fn;
} else {
if ($verbosity) {
if ($type eq 'l') {
$name =~ s/ -> .*//;
$type = 'symlink';
} else {
$type = "type '$type'";
}
print "Skipping $name ($type ignored)\n";
}
next;
}
if (!defined $type) {
my $reason = -e _ ? "types don't match" : 'missing';
print "Skipping $name ($reason)\n";
next;
}
my($cur_mode, $cur_uid, $cur_gid) = (stat(_))[2,4,5];
$cur_mode &= 07777;
my $highs = join('', $perms =~ /..(.)..(.)..(.)/);
$highs =~ tr/-rwxSTst/00001111/;
$perms =~ tr/-STrwxst/00011111/;
my $mode = $p_opt ? oct('0b' . $highs . $perms) : $cur_mode;
my $uid = $o_opt ? $uid_hash{$owner} : $cur_uid;
if (!defined $uid) {
if ($owner =~ /^\d+$/) {
$uid = $owner;
} else {
$uid = getpwnam($owner);
}
$uid_hash{$owner} = $uid;
}
my $gid = $g_opt ? $gid_hash{$group} : $cur_gid;
if (!defined $gid) {
if ($group =~ /^\d+$/) {
$gid = $group;
} else {
$gid = getgrnam($group);
}
$gid_hash{$group} = $gid;
}
my @changes;
if ($mode != $cur_mode) {
push(@changes, 'permissions');
if (!$dry_run && !chmod($mode, $fn)) {
warn "chmod($mode, \"$name\") failed: $!\n";
}
}
if ($uid != $cur_uid || $gid != $cur_gid) {
push(@changes, 'owner') if $uid != $cur_uid;
push(@changes, 'group') if $gid != $cur_gid;
if (!$dry_run) {
if (!chown($uid, $gid, $fn)) {
warn "chown($uid, $gid, \"$name\") failed: $!\n";
}
if (($mode & 06000) && !chmod($mode, $fn)) {
warn "post-chown chmod($mode, \"$name\") failed: $!\n";
}
}
}
if (@changes) {
print "$name: changed @changes\n";
} elsif ($verbosity) {
print "$name: OK\n";
}
}
exit;
sub parse_map_file
{
my($fn) = @_;
open(IN, $fn) or die "Unable to open $fn: $!\n";
while (<IN>) {
if (/^user\s+(\S+)\s+(\S+)/) {
$uid_hash{$1} = $2;
} elsif (/^group\s+(\S+)\s+(\S+)/) {
$gid_hash{$1} = $2;
} else {
die "Invalid line #$. in mapfile `$fn':\n$_";
}
}
close IN;
}
sub usage
{
die <<EOT;
Usage: file-attr-restore [OPTIONS] FILE [FILE...]
-a, --all Restore all the attributes (-pog)
-p, --perms Restore the permissions
-o, --owner Restore the ownership
-g, --groups Restore the group
-m, --map=FILE Read user/group mappings from FILE
-n, --dry-run Don't actually make the changes
-v, --verbose Increase verbosity
-h, --help Show this help text
The FILE arg(s) should have been created by running the "find"
program with "-ls" as the output specifier.
The input file for the --map option must be in this format:
user FROM TO
group FROM TO
The "FROM" should be an user/group mentioned in the input, and the TO
should be either a uid/gid number, or a local user/group name.
EOT
}

27
support/files-to-excludes Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/perl
# This script takes an input of filenames and outputs a set of
# include/exclude directives that can be used by rsync to copy
# just the indicated files using an --exclude-from=FILE option.
use strict;
my %hash;
while (<>) {
chomp;
s#^/+##;
my $path = '/';
while (m#([^/]+/)/*#g) {
$path .= $1;
print "+ $path\n" unless $hash{$path}++;
}
if (m#([^/]+)$#) {
print "+ $path$1\n";
} else {
delete $hash{$path};
}
}
foreach (sort keys %hash) {
print "- $_*\n";
}
print "- /*\n";

34
support/logfilter Executable file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/perl
# Filter the rsync daemon log messages by module name. The log file can be
# in either syslog format or rsync's own log-file format. Note that the
# MODULE_NAME parameter is used in a regular-expression match in order to
# allow regex wildcards to be used. You can also limit the output by
# directory hierarchy in a module. Examples:
#
# logfilter foo /var/log/rsyncd.log # output lines for module foo
# logfilter foo/dir /var/log/syslog # limit lines to those in dir of foo
use strict;
my $match = shift;
die "Usage: logfilter MODULE_NAME [LOGFILE ...]\n" unless defined $match;
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
my %pids;
while (<>) {
my($pid,$msg) = /^(?:$syslog_prefix|$rsyncd_prefix)\[(\d+)\]:? (.*)/o;
next unless defined $pid;
my($mod_spec) = $msg =~ /^rsync (?:on|to) (\S+) from /;
if (defined $mod_spec) {
if ($mod_spec =~ /^$match(\/\S*)?$/o) {
$pids{$pid} = 1;
} else {
delete $pids{$pid};
}
}
next unless $pids{$pid};
print $_;
}

View File

@@ -20,7 +20,7 @@
# ADDENDUM: The addition of the --filter option (which has support for
# absolute-anchored excludes) has made this script less useful than it
# was. Beginning with 2.6.4, you can achieve the effect of this script
# though this command:
# through this command:
#
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/

View File

@@ -2,18 +2,28 @@
# 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
# Modified by: Wayne Davison <wayned@samba.org>
use strict;
use Socket;
use Cwd 'abs_path';
use File::Glob ':glob';
# You may configure these values to your liking. See also the section
# of options if you want to disable any options that rsync accepts.
use constant RSYNC => '/usr/bin/rsync';
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;
our $ro = (@ARGV && $ARGV[0] eq '-ro') ? shift : ''; # -ro = Read-Only
our $subdir = shift;
die "$0: No subdirectory specified\n$Usage" unless defined $subdir;
$subdir = abs_path($subdir);
die "$0: Restricted directory does not exist!\n" if $subdir ne '/' && !-d $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="..."'.
@@ -22,53 +32,166 @@ die "No subdirectory specified\n$Usage" unless defined $subdir;
# 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_ORIGINAL_COMMAND=rsync --server -vlogDtpr --partial . ARG # push
# SSH_ORIGINAL_COMMAND=rsync --server --sender -vlogDtpr --partial . ARGS # pull
# SSH_CONNECTION=client_addr client_port server_port
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+)/;
die "$0: Not invoked via sshd\n$Usage" unless defined $command;
die "$0: SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ s/^rsync\s+//;
our $am_sender = $command =~ /^--server\s+--sender\s/; # Restrictive on purpose!
die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
my ($cmd,$dir) = $command =~ /^(rsync\s+(?:-[-a-zA-Z]+\s+)+\.) ?("[^"]*"|[^\s"]*)$/;
die "$0: invalid rsync-command syntax or options\n" if !defined $cmd;
### START of options data produced by the cull_options script. ###
# 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, $_);
# These options are the only options that rsync might send to the server,
# and only in the option format that the stock rsync produces.
# To disable a short-named option, add its letter to this string:
our $short_disabled = '';
our $short_no_arg = 'CDHIKLORSWbcdglnoprtuvxz'; # DO NOT REMOVE ANY
our $short_with_num = 'B'; # DO NOT REMOVE ANY
# To disable a long-named option, change its value to a -1. The values mean:
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
# check the arg when receiving; and 3 = always check the arg.
our %long_opt = (
'backup-dir' => 2,
'bwlimit' => 1,
'checksum-seed' => 1,
'compare-dest' => 2,
'copy-dest' => 2,
'copy-unsafe-links' => 0,
'daemon' => 0,
'delay-updates' => 0,
'delete' => 0,
'delete-after' => 0,
'delete-before' => 0,
'delete-during' => 0,
'delete-excluded' => 0,
'existing' => 0,
'files-from' => 3,
'force' => 0,
'from0' => 0,
'fuzzy' => 0,
'ignore-errors' => 0,
'ignore-existing' => 0,
'inplace' => 0,
'link-dest' => 2,
'list-only' => 0,
'log-format' => 1,
'max-delete' => 1,
'max-size' => 1,
'modify-window' => 1,
'no-implied-dirs' => 0,
'no-relative' => 0,
'numeric-ids' => 0,
'only-write-batch' => 1,
'partial' => 0,
'partial-dir' => 2,
'remove-sent-files' => $ro ? -1 : 0,
'safe-links' => 0,
'sender' => 0,
'server' => 0,
'size-only' => 0,
'suffix' => 1,
'temp-dir' => 2,
'timeout' => 1,
);
### END of options data produced by the cull_options script. ###
if ($short_disabled ne '') {
$short_no_arg =~ s/[$short_disabled]//go;
$short_with_num =~ s/[$short_disabled]//go;
}
push(@dirs, $subdir) unless @dirs;
$dir = join(' ', @dirs);
$short_no_arg = "[$short_no_arg]" if length($short_no_arg) > 1;
$short_with_num = "[$short_with_num]" if length($short_with_num) > 1;
if (-f LOGFILE and open LOG,'>>',LOGFILE) {
my $write_log = -f LOGFILE && open(LOG, '>>', LOGFILE);
chdir($subdir) or die "$0: Unable to chdir to restricted dir: $!\n";
my(@opts, @args);
my $in_options = 1;
my $last_opt = '';
my $check_type;
while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
$_ = $1;
if ($check_type) {
push(@opts, check_arg($last_opt, $_, $check_type));
$check_type = 0;
} elsif ($in_options) {
push(@opts, $_);
if ($_ eq '.') {
$in_options = 0;
} else {
next if /^-$short_no_arg+$/o || /^-$short_with_num\d+$/o;
my($opt,$arg) = /^--([^=]+)(?:=(.*))?$/;
my $disabled;
if (defined $opt) {
my $ct = $long_opt{$opt};
last unless defined $ct;
next if $ct == 0;
if ($ct > 0) {
if (!defined $arg) {
$check_type = $ct;
$last_opt = $opt;
next;
}
$arg = check_arg($opt, $arg, $ct);
$opts[-1] =~ s/=.*/=$arg/;
next;
}
$disabled = 1;
$opt = "--$opt";
} elsif ($short_disabled ne '') {
$disabled = /^-$short_no_arg*([$short_disabled])/o;
$opt = "-$1";
}
last unless $disabled; # Generate generic failure
die "$0: option $opt has been disabled on this server.\n";
}
} else {
if ($subdir ne '/') {
# Validate args to ensure they don't try to leave our restricted dir.
s#//+#/#g;
s#^/##;
s#^$#.#;
die "Do not use .. in any path!\n" if m#(^|/)\\?\.\\?\.(\\?/|$)#;
}
push(@args, bsd_glob($_, GLOB_LIMIT|GLOB_NOCHECK|GLOB_BRACE|GLOB_QUOTE));
}
}
die "$0: invalid rsync-command syntax or options\n" if $in_options;
@args = ( '.' ) if !@args;
if ($write_log) {
my ($mm,$hh) = (localtime)[1,2];
my $host = $ENV{SSH_CONNECTION} || 'unknown';
$host =~ s/ .*//; # Keep only the client's IP addr
$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;
printf LOG "%02d:%02d %-13s [%s]\n", $hh, $mm, $host, "@opts @args";
close LOG;
}
exec "$cmd \"$dir\"" or die "exec($cmd \"$dir\") failed: $? $!";
# Note: This assumes that the rsync protocol will not be maliciously hijacked.
exec(RSYNC, @opts, @args) or die "exec(rsync @opts @args) failed: $? $!";
sub check_arg
{
my($opt, $arg, $type) = @_;
$arg =~ s/\\(.)/$1/g;
if ($subdir ne '/' && ($type == 3 || ($type == 2 && !$am_sender))) {
$arg =~ s#//#/#g;
die "Do not use .. in --$opt; anchor the path at the root of your restricted dir.\n"
if $arg =~ m#(^|/)\.\.(/|$)#;
$arg =~ s#^/#$subdir/#;
}
$arg;
}

View File

@@ -12,7 +12,7 @@
use Getopt::Long;
# You may wish to edit the next line to customize for your default log file.
$usage_file = "/var/adm/rsyncd.log";
$usage_file = "/var/log/rsyncd.log";
# Edit the following lines for default report settings.
# Entries defined here will be over-ridden by the command line.
@@ -52,9 +52,22 @@ if ($only_section) {
line: while (<LOG>) {
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
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;
= m{^
( \w\w\w\s+\d+ | \d+/\d\d/\d\d ) \s+ # day
(\d\d:\d\d:\d\d) \s+ # time
[^[]* \[\d+\]:? \s+ # pid (ignored)
(send|recv|[<>]f\S+) \s+ # op (%o or %i)
(\S+) \s+ # host
\[\d+\.\d+\.\d+\.\d+\] \s+ # IP (ignored)
(\S+) \s+ # module
\(\S*\) \s+ # user (ignored)
(.*) \s+ # file name
(\d+) # file length in bytes
$ }x;
# TODO actually divide the data by into send/recv categories
if ($op =~ /^>/) {

View File

@@ -7,20 +7,13 @@
* -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):
* the following commands (the resulting files should be identical):
*
* rsync -av --rsh="savetransfer -i /tmp/from.sender ssh"
* --rsync-path="savetransfer -i /tmp/to.receiver rsync" FILES HOST:DEST
* rsync -av --rsh="savetransfer -i /tmp/to.server ssh"
* --rsync-path="savetransfer -i /tmp/from.client rsync" SOURCE 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
* rsync -av --rsh="savetransfer -o /tmp/from.server ssh"
* --rsync-path="savetransfer -o /tmp/to.client rsync" SOURCE 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

View File

@@ -45,14 +45,14 @@ extern int preserve_perms;
#define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
int do_unlink(char *fname)
int do_unlink(const char *fname)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return unlink(fname);
}
int do_symlink(char *fname1, char *fname2)
int do_symlink(const char *fname1, const char *fname2)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
@@ -60,7 +60,7 @@ int do_symlink(char *fname1, char *fname2)
}
#ifdef HAVE_LINK
int do_link(char *fname1, char *fname2)
int do_link(const char *fname1, const char *fname2)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
@@ -104,7 +104,11 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
|| (bind(sock, (struct sockaddr*)&saddr, sizeof saddr)) < 0)
return -1;
close(sock);
#ifdef HAVE_CHMOD
return do_chmod(pathname, mode);
#else
return 0;
#endif
}
#endif
#ifdef HAVE_MKNOD
@@ -114,14 +118,14 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
#endif
}
int do_rmdir(char *pathname)
int do_rmdir(const char *pathname)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return rmdir(pathname);
}
int do_open(char *pathname, int flags, mode_t mode)
int do_open(const char *pathname, int flags, mode_t mode)
{
if (flags != O_RDONLY) {
RETURN_ERROR_IF(dry_run, 0);
@@ -137,21 +141,27 @@ int do_chmod(const char *path, mode_t mode)
int code;
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
code = chmod(path, mode);
if (S_ISLNK(mode)) {
#ifdef HAVE_LCHMOD
code = lchmod(path, mode & CHMOD_BITS);
#else
code = 1;
#endif
} else
code = chmod(path, mode & CHMOD_BITS);
if (code != 0 && preserve_perms)
return code;
return 0;
}
#endif
int do_rename(char *fname1, char *fname2)
int do_rename(const char *fname1, const char *fname2)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return rename(fname1, fname2);
}
void trim_trailing_slashes(char *name)
{
int l;
@@ -170,7 +180,6 @@ void trim_trailing_slashes(char *name)
}
}
int do_mkdir(char *fname, mode_t mode)
{
if (dry_run) return 0;
@@ -179,7 +188,6 @@ int do_mkdir(char *fname, mode_t mode)
return mkdir(fname, mode);
}
/* like mkstemp but forces permissions */
int do_mkstemp(char *template, mode_t perms)
{
@@ -244,7 +252,11 @@ int do_fstat(int fd, STRUCT_STAT *st)
OFF_T do_lseek(int fd, OFF_T offset, int whence)
{
#ifdef HAVE_LSEEK64
#if !SIZEOF_OFF64_T
OFF_T lseek64();
#else
off64_t lseek64();
#endif
return lseek64(fd, offset, whence);
#else
return lseek(fd, offset, whence);

View File

@@ -28,6 +28,9 @@
int modify_window = 0;
int module_id = -1;
int relative_paths = 0;
int human_readable = 0;
mode_t orig_umask = 002;
char *partial_dir;
struct filter_list_struct server_filter_list;

View File

@@ -17,14 +17,14 @@ name2="$fromdir/name2"
outfile="$scratchdir/rsync.out"
cat $srcdir/[gr]*.[ch] > "$name1"
cat $srcdir/[et]*.[ch] > "$name2"
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"
cat "$srcdir"/[fgpr]*.[ch] > "$name1"
cat "$srcdir"/[etw]*.[ch] > "$name2"
$RSYNC -avv --no-whole-file --backup "$fromdir/" "$todir/" \
| tee "$outfile"
@@ -49,8 +49,8 @@ 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"
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"

View File

@@ -9,8 +9,6 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
cd "$tmpdir"

View File

@@ -11,8 +11,6 @@
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
mygrps="`rsync_getgroups`" || fail "Can't get groups"

View File

@@ -0,0 +1,42 @@
#! /bin/sh
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that the --chmod option functions correctly.
. $srcdir/testsuite/rsync.fns
# Build some files
fromdir="$scratchdir/from"
todir="$scratchdir/to"
checkdir="$scratchdir/check"
mkdir "$fromdir"
name1="$fromdir/name1"
name2="$fromdir/name2"
dir1="$fromdir/dir1"
dir2="$fromdir/dir2"
echo "This is the file" > "$name1"
echo "This is the other file" > "$name2"
mkdir "$dir1" "$dir2"
chmod 4700 "$name1" || test_skipped "Can't chmod"
chmod 700 "$dir1"
chmod 770 "$dir2"
# Copy the files we've created over to another directory
checkit "$RSYNC -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir"
# And then manually make the changes which should occur
umask 002
chmod ug-s,a+rX "$checkdir"/*
chmod +w "$checkdir" "$checkdir"/dir*
checkit "$RSYNC -avv --chmod ug-s,a+rX,D+w \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# 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,
@@ -11,8 +11,6 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
tmpdir2=/tmp

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# 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,
@@ -11,8 +11,6 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
chmod 440 "$fromdir/text"

View File

@@ -13,8 +13,6 @@
. "$suitedir/rsync.fns"
set -x
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync handling of the --compare-dest option.
@@ -14,8 +14,6 @@ alt2dir="$tmpdir/alt2"
# Build some files/dirs/links to copy
set -x
hands_setup
# Setup the alt and chk dirs

View File

@@ -26,8 +26,6 @@ build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
set -x
hands_setup
# Build chkdir with a normal rsync and an --exclude.

View File

@@ -20,8 +20,6 @@ build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
set -x
hands_setup
# Build chkdir with a normal rsync and an --exclude.

View File

@@ -2,15 +2,13 @@
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# 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"

View File

@@ -9,6 +9,9 @@
. "$suitedir/rsync.fns"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
# Build some hardlinks
case `id -u` in
@@ -16,7 +19,7 @@ case `id -u` in
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh "$0"
exec /usr/bin/fakeroot /bin/sh $RUNSHFLAGS "$0"
fi
test_skipped "Rsync won't copy devices unless we're root"
;;
@@ -25,15 +28,66 @@ esac
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
mkdir "$fromdir"
mkdir "$todir"
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node unless root"
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"
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
mkfifo "$fromdir/fifo" || test_skipped "Can't run mkfifo"
touch -r "$fromdir/block" "$fromdir/block2"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" skip_file_diff
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++ block
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -ai "$fromdir/block2" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++ block2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
sleep 1
$RSYNC -Di "$fromdir/block3" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD..T.... block3
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
$RSYNC -aiHvv "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t.... ./
cD..t.... block
cD....... block2
cD+++++++ block3
hD+++++++ block2.5 => block3
cD+++++++ char
cD+++++++ char2
cD+++++++ char3
cS+++++++ fifo
EOT
if test ! -b "$fromdir/block2.5"; then
sed -e '/block2\.5/d' \
<"$chkfile" >"$chkfile.new"
mv "$chkfile.new" "$chkfile"
fi
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
echo "check how the directory listings compare with diff:"
echo ""
( cd "$fromdir" && rsync_ls_lR . ) > "$tmpdir/ls-from"
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
# The script would have aborted on error, so getting here means we've won.
exit 0

41
testsuite/dir-sgid.test Normal file
View File

@@ -0,0 +1,41 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that rsync obeys directory setgid. -- Matt McCutchen
. $srcdir/testsuite/rsync.fns
umask 077
# Call as: testit <dirname> <dirperms> <file-expected> <program-expected> <dir-expected>
testit() {
todir="$scratchdir/$1"
mkdir "$todir"
chmod $2 "$todir"
# Make sure we obey directory setgid when creating a directory to hold multiple transferred files,
# even though the directory itself is outside the transfer
$RSYNC -rvv "$scratchdir/dir" "$scratchdir/file" "$scratchdir/program" "$todir/to/"
check_perms "$todir/to" $5 "Target $1"
check_perms "$todir/to/dir" $5 "Target $1"
check_perms "$todir/to/file" $3 "Target $1"
check_perms "$todir/to/program" $4 "Target $1"
}
echo "File!" >"$scratchdir/file"
echo "#!/bin/sh" >"$scratchdir/program"
mkdir "$scratchdir/dir"
chmod 2764 "$scratchdir/dir" || test_skipped "Can't chmod"
chmod 664 "$scratchdir/file"
chmod 775 "$scratchdir/program"
[ -g "$scratchdir/dir" ] || test_skipped "The directory setgid bit vanished!"
mkdir "$scratchdir/dir/blah"
[ -g "$scratchdir/dir/blah" ] || test_skipped "Your filesystem doesn't use directory setgid; maybe it's BSD."
# Test some target directories
testit setgid-off 700 rw------- rwx------ rwx------
testit setgid-on 2700 rw------- rwx------ rwx--S---
# Hooray
exit 0

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL see
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync handling of duplicate filenames.
@@ -21,8 +21,6 @@
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
mkdir "$fromdir"

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2003, 2004, 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync handling of exclude/include directives.
@@ -12,18 +12,18 @@
. "$suitedir/rsync.fns"
HOME="$scratchdir"
CVSIGNORE='*.junk'
export HOME CVSIGNORE
set -x
export CVSIGNORE
# Build some files/dirs/links to copy
makepath "$fromdir/foo/down/to/you"
makepath "$fromdir/foo/sub"
makepath "$fromdir/bar/down/to/foo/too"
makepath "$fromdir/bar/down/to/bar/baz"
makepath "$fromdir/mid/for/foo/and/that/is/who"
makepath "$fromdir/new/keep/this"
makepath "$fromdir/new/lose/this"
cat >"$fromdir/.filt" <<EOF
exclude down
: .filt-temp
@@ -32,13 +32,14 @@ clear
- *.bak
- *.old
EOF
echo kept >"$fromdir/foo/file1"
echo filtered-1 >"$fromdir/foo/file1"
echo removed >"$fromdir/foo/file2"
echo cvsout >"$fromdir/foo/file2.old"
cat >"$fromdir/foo/.filt" <<EOF
include .filt
- file1
- /file1
EOF
echo not-filtered-1 >"$fromdir/foo/sub/file1"
cat >"$fromdir/bar/.filt" <<EOF
- home-cvs-exclude
dir-merge .filt2
@@ -87,8 +88,12 @@ cat >"$excl" <<EOF
- /bar
# This should match against the whole path, not just the name.
+ foo**too
# This should float at the end of the path.
# These should float at the end of the path.
+ foo/s?b/
- foo/*/
# Test how /** differs from /***
- new/keep/**
- new/lose/***
# Test some normal excludes. Competing lines are paired.
+ t[o]/
- to
@@ -109,6 +114,8 @@ sleep 1 # Ensures that the rm commands will tweak the directory times.
rm -r "$chkdir"/foo/down
rm -r "$chkdir"/mid/for/foo/and
rm -r "$chkdir"/new/keep/this
rm -r "$chkdir"/new/lose
rm "$chkdir"/foo/file[235-9]
rm "$chkdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo/file[235-9]
rm "$chkdir"/mid/for/foo/extra
@@ -196,5 +203,13 @@ $RSYNC -av --delete-excluded --exclude='*' "$fromdir/" "$todir/"
checkit "$RSYNC -avv -f dir-merge,-_.excl \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
relative_opts='--relative --chmod=Du+w --copy-unsafe-links'
$RSYNC -av $relative_opts "$fromdir/foo" "$chkdir/"
rm -rf "$chkdir$fromdir/foo/down"
$RSYNC -av $relative_opts --existing --filter='-! */' "$fromdir/foo" "$chkdir/"
checkit "$RSYNC -avv $relative_opts --exclude=\"$fromdir/foo/down\" \
\"$fromdir/foo\" \"$todir\"" "$chkdir$fromdir/foo" "$todir$fromdir/foo"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -0,0 +1,47 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test the --executability or -E option. -- Matt McCutchen
. $srcdir/testsuite/rsync.fns
# Put some files in the From directory
mkdir "$fromdir"
cat <<EOF >"$fromdir/1"
#!/bin/sh
echo 'Program One!'
EOF
cat <<EOF >"$fromdir/2"
#!/bin/sh
echo 'Program Two!'
EOF
chmod 1700 "$fromdir/1" || test_skipped "Can't chmod"
chmod 600 "$fromdir/2"
$RSYNC -rvv "$fromdir/" "$todir/"
check_perms "$todir/1" rwx------ 1
check_perms "$todir/2" rw------- 1
# Mix up the permissions a bit
chmod 600 "$fromdir/1"
chmod 601 "$fromdir/2"
chmod 604 "$todir/2"
$RSYNC -rvv "$fromdir/" "$todir/"
# No -E, so nothing should have changed
check_perms "$todir/1" rwx------ 2
check_perms "$todir/2" rw----r-- 2
$RSYNC -rvvE "$fromdir/" "$todir/"
# Now things should have happened!
check_perms "$todir/1" rw------- 3
check_perms "$todir/2" rwx---r-x 3
# Hooray
exit 0

View File

@@ -2,15 +2,13 @@
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL see
# 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"

View File

@@ -12,8 +12,6 @@
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
fromdir="$scratchdir/from"

271
testsuite/itemize.test Normal file
View File

@@ -0,0 +1,271 @@
#! /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 the output of various copy commands to ensure itemized output
# and double-verbose output is correct.
. "$suitedir/rsync.fns"
lddir="$tmpdir/ld"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
makepath "$fromdir/foo"
makepath "$fromdir/bar/baz"
cp -p "$srcdir/configure.in" "$fromdir/foo/config1"
cp -p "$srcdir/config.h.in" "$fromdir/foo/config2"
cp -p "$srcdir/rsync.h" "$fromdir/bar/baz/rsync"
chmod 600 "$fromdir"/foo/config? "$fromdir/bar/baz/rsync"
umask 0
ln -s ../bar/baz/rsync "$fromdir/foo/sym"
umask 022
ln "$fromdir/foo/config1" "$fromdir/foo/extra"
$RSYNC -iplr "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++ bar/
cd+++++++ bar/baz/
>f+++++++ bar/baz/rsync
cd+++++++ foo/
>f+++++++ foo/config1
>f+++++++ foo/config2
>f+++++++ foo/extra
cL+++++++ foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
# Ensure there are no accidental directory-time problems.
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
cp -p "$srcdir/configure.in" "$fromdir/foo/config2"
chmod 601 "$fromdir/foo/config2"
$RSYNC -iplrH "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
>f..T.... bar/baz/rsync
>f..T.... foo/config1
>f.sTp... foo/config2
hf..T.... foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
sleep 1 # For directory mod below to ensure time difference
rm "$todir/foo/sym"
umask 0
ln -s ../bar/baz "$todir/foo/sym"
umask 022
cp -p "$srcdir/config.h.in" "$fromdir/foo/config2"
chmod 600 "$fromdir/foo/config2"
chmod 777 "$todir/bar/baz/rsync"
$RSYNC -iplrtc "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.f..tp... bar/baz/rsync
.d..t.... foo/
.f..t.... foo/config1
>fcstp... foo/config2
cL..T.... foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
cp -p "$srcdir/configure.in" "$fromdir/foo/config2"
chmod 600 "$fromdir/foo/config2"
# Lack of -t is for unchanged hard-link stress-test!
$RSYNC -vvplrH "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
bar/baz/rsync is uptodate
foo/config1 is uptodate
foo/config2
"foo/extra" is a hard link
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
chmod 747 "$todir/bar/baz/rsync"
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
$RSYNC -ivvplrtH "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d ./
.d bar/
.d bar/baz/
.f...p... bar/baz/rsync
.d foo/
.f foo/config1
>f..t.... foo/config2
hf foo/extra
.L foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
chmod 757 "$todir/foo/config1"
touch "$todir/foo/config2"
$RSYNC -vplrtH "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
foo/config2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 6 failed"
chmod 757 "$todir/foo/config1"
touch "$todir/foo/config2"
$RSYNC -iplrtH "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.f...p... foo/config1
>f..t.... foo/config2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
mv "$todir" "$lddir"
$RSYNC -ivvplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
cf bar/baz/rsync
cd+++++++ foo/
cf foo/config1
cf foo/config2
hf foo/extra => foo/config1
cL..T.... foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
rm -rf "$todir"
$RSYNC -iplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
hf foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
rm -rf "$todir"
$RSYNC -vvplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
./
bar/
bar/baz/
bar/baz/rsync is uptodate
foo/
foo/config1 is uptodate
foo/config2 is uptodate
"foo/extra" is a hard link
foo/extra => foo/config1
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 10 failed"
rm -rf "$todir"
$RSYNC -ivvplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
hf bar/baz/rsync
cd+++++++ foo/
hf foo/config1
hf foo/config2
hf foo/extra => foo/config1
hL foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
rm -rf "$todir"
$RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
rm -rf "$todir"
$RSYNC -vvplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
./
bar/
bar/baz/
bar/baz/rsync is uptodate
foo/
foo/config1 is uptodate
foo/config2 is uptodate
"foo/extra" is a hard link
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 13 failed"
rm -rf "$todir"
$RSYNC -ivvplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
# TODO fix really-old problem when combining -H with --compare-dest:
# missing output for foo/extra hard-link (and it might not be updated)!
cat <<EOT >"$chkfile"
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
.f bar/baz/rsync
cd+++++++ foo/
.f foo/config1
.f foo/config2
.L foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
rm -rf "$todir"
$RSYNC -iplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
rm -rf "$todir"
$RSYNC -vvplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
./
bar/
bar/baz/
bar/baz/rsync is uptodate
foo/
foo/config1 is uptodate
foo/config2 is uptodate
"foo/extra" is a hard link
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 16 failed"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -7,8 +7,6 @@
. "$suitedir/rsync.fns"
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

View File

@@ -9,8 +9,6 @@
. "$suitedir/rsync.fns"
set -x
# Build some files/dirs/links to copy
from1dir="${fromdir}1"

39
testsuite/relative.test Normal file
View File

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

View File

@@ -32,6 +32,9 @@ else
diffopt="-c"
fi
HOME="$scratchdir"
export HOME
runtest() {
echo $ECHO_N "Test $1: $ECHO_C"
if eval "$2"
@@ -44,15 +47,38 @@ runtest() {
fi
}
# Call this if you want to filter out verbose messages (-v or -vv) from
# the output of an rsync run (whittling the output down to just the file
# messages). This isn't needed if you use -i without -v.
filter_outfile() {
sed -e '/^building file list /d' \
-e '/^created directory /d' \
-e '/^done$/d' \
-e '/ --whole-file$/d' \
-e '/^total: /d' \
-e '/^$/,$d' \
<"$outfile" >"$outfile.new"
mv "$outfile.new" "$outfile"
}
printmsg() {
echo "$1"
}
rsync_ls_lR() {
find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
}
check_perms() {
perms=`"$TOOLDIR/tls" "$1" | sed 's/^[-d]\(.........\).*/\1/'`
if test $perms = $2; then
return 0
fi
echo "permissions: $perms on $1"
echo "should be: $2"
test_fail "failed test $3"
}
rsync_getgroups() {
"$TOOLDIR/getgroups"
}
@@ -92,7 +118,7 @@ hands_setup() {
ln -s nolf "$fromdir/nolf-symlink"
umask 022
cat $srcdir/*.c > "$fromdir/text"
cat "$srcdir"/*.c > "$fromdir/text"
mkdir "$fromdir/dir"
cp "$fromdir/text" "$fromdir/dir"
mkdir "$fromdir/dir/subdir"
@@ -118,7 +144,7 @@ hands_setup() {
####################
# Many machines do not have "mkdir -p", so we have to build up long paths.
# How boring.
makepath () {
makepath() {
echo " makepath $1"
p="$1"
(

View File

@@ -10,8 +10,6 @@
. "$suitedir/rsync.fns"
set -x
build_symlinks || test_fail "failed to build symlinks"
# Copy recursively, but without -l or -L or -a, and all the symlinks

View File

@@ -9,8 +9,6 @@
. "$suitedir/rsync.fns"
set -x
"$TOOLDIR/trimslash" "/usr/local/bin" "/usr/local/bin/" "/usr/local/bin///" \
"//a//" "////" \
"/Users/Wierd Macintosh Name/// Ooh, translucent plastic/" \

View File

@@ -32,8 +32,6 @@ ln -s ../files/file1 "from/safe/links/"
ln -s ../files/file2 "from/safe/links/"
ln -s ../../unsafe/unsafefile "from/safe/links/"
set -x
echo "rsync with relative path and just -a";
$RSYNC -avv from/safe/ to
test_symlink to/links/file1

View File

@@ -9,12 +9,15 @@
. "$suitedir/rsync.fns"
set -x
"$TOOLDIR/wildtest" "$srcdir/wildtest.txt" >"$scratchdir/wild.out"
diff $diffopt "$scratchdir/wild.out" - <<EOF
# This test exercises the wildmatch() function (with no options) and the
# wildmatch_join() function (using -x and/or -e).
for opts in "" -x1 "-x1 -e1" "-x1 -e1se" -x2 "-x2 -ese" -x3 "-x3 -e1" -x4 "-x4 -e2e" -x5 "-x5 -es"; do
echo Running wildtest with "$opts"
"$TOOLDIR/wildtest" $opts "$srcdir/wildtest.txt" >"$scratchdir/wild.out"
diff $diffopt "$scratchdir/wild.out" - <<EOF
No wildmatch errors found.
EOF
done
# The script would have aborted on error, so getting here means we've won.
exit 0

12
tls.c
View File

@@ -100,12 +100,12 @@ static void list_file(const char *fname)
mt = gmtime(&buf.st_mtime);
sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
mt->tm_year + 1900,
mt->tm_mon + 1,
mt->tm_mday,
mt->tm_hour,
mt->tm_min,
mt->tm_sec);
(int)mt->tm_year + 1900,
(int)mt->tm_mon + 1,
(int)mt->tm_mday,
(int)mt->tm_hour,
(int)mt->tm_min,
(int)mt->tm_sec);
} else {
strcpy(datebuf, " ");
}

58
token.c
View File

@@ -22,46 +22,60 @@
extern int do_compression;
extern int module_id;
extern int def_compress_level;
static int compression_level = Z_DEFAULT_COMPRESSION;
static int compression_level, per_file_default_level;
/* determine the compression level based on a wildcard filename list */
void set_compression(char *fname)
{
char *dont;
char *tok;
static char *match_list;
char *s;
if (!do_compression)
return;
compression_level = Z_DEFAULT_COMPRESSION;
dont = lp_dont_compress(module_id);
if (!dont || !*dont)
return;
if (dont[0] == '*' && !dont[1]) {
/* an optimization to skip the rest of this routine */
compression_level = 0;
return;
if (!match_list) {
char *t, *f = lp_dont_compress(module_id);
int len = strlen(f);
if (!(match_list = t = new_array(char, len + 2)))
out_of_memory("set_compression");
while (*f) {
if (*f == ' ') {
f++;
continue;
}
do {
if (isupper(*(unsigned char *)f))
*t++ = tolower(*(unsigned char *)f);
else
*t++ = *f;
} while (*++f != ' ' && *f);
*t++ = '\0';
}
/* Optimize a match-string of "*". */
if (t - match_list == 2 && match_list[0] == '*') {
t = match_list;
per_file_default_level = 0;
} else
per_file_default_level = def_compress_level;
*t++ = '\0';
}
dont = strdup(dont);
fname = strdup(fname);
if (!dont || !fname)
compression_level = per_file_default_level;
if (!*match_list)
return;
strlower(dont);
strlower(fname);
if ((s = strrchr(fname, '/')) != NULL)
fname = s + 1;
for (tok = strtok(dont, " "); tok; tok = strtok(NULL, " ")) {
if (wildmatch(tok, fname)) {
for (s = match_list; *s; s += strlen(s) + 1) {
if (iwildmatch(s, fname)) {
compression_level = 0;
break;
}
}
free(dont);
free(fname);
}
/* non-compressing recv token */

View File

@@ -324,7 +324,6 @@ void recv_uid_list(int f, struct file_list *flist)
}
}
if (preserve_gid && !numeric_ids) {
/* read the gid list */
while ((id = read_int(f)) != 0) {
@@ -337,8 +336,7 @@ void recv_uid_list(int f, struct file_list *flist)
}
}
/* now convert the uid/gid of all files in the list to the mapped
* uid/gid */
/* Now convert all the uids/gids from sender values to our values. */
if (am_root && preserve_uid && !numeric_ids) {
for (i = 0; i < flist->count; i++)
flist->files[i]->uid = match_uid(flist->files[i]->uid);

342
util.c
View File

@@ -31,6 +31,9 @@ extern int verbose;
extern int dry_run;
extern int module_id;
extern int modify_window;
extern int relative_paths;
extern int human_readable;
extern mode_t orig_umask;
extern char *partial_dir;
extern struct filter_list_struct server_filter_list;
@@ -68,7 +71,6 @@ void set_blocking(int fd)
}
}
/**
* Create a file descriptor pair - like pipe() but use socketpair if
* possible (because of blocking issues on pipes).
@@ -93,7 +95,6 @@ int fd_pair(int fd[2])
return ret;
}
void print_child_argv(char **cmd)
{
rprintf(FINFO, "opening connection using ");
@@ -105,34 +106,36 @@ void print_child_argv(char **cmd)
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
",.-_=+@/") != strlen(*cmd)) {
rprintf(FINFO, "\"%s\" ", safe_fname(*cmd));
rprintf(FINFO, "\"%s\" ", *cmd);
} else {
rprintf(FINFO, "%s ", safe_fname(*cmd));
rprintf(FINFO, "%s ", *cmd);
}
}
rprintf(FINFO, "\n");
}
void out_of_memory(char *str)
{
rprintf(FERROR, "ERROR: out of memory in %s\n", str);
exit_cleanup(RERR_MALLOC);
}
void overflow(char *str)
void overflow_exit(char *str)
{
rprintf(FERROR, "ERROR: buffer overflow in %s\n", str);
exit_cleanup(RERR_MALLOC);
}
int set_modtime(char *fname, time_t modtime)
int set_modtime(char *fname, time_t modtime, mode_t mode)
{
#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
if (S_ISLNK(mode))
return 1;
#endif
if (verbose > 2) {
rprintf(FINFO, "set modtime of %s to (%ld) %s",
safe_fname(fname), (long)modtime,
fname, (long)modtime,
asctime(localtime(&modtime)));
}
@@ -140,7 +143,18 @@ int set_modtime(char *fname, time_t modtime)
return 0;
{
#ifdef HAVE_UTIMBUF
#ifdef HAVE_UTIMES
struct timeval t[2];
t[0].tv_sec = time(NULL);
t[0].tv_usec = 0;
t[1].tv_sec = modtime;
t[1].tv_usec = 0;
# ifdef HAVE_LUTIMES
if (S_ISLNK(mode))
return lutimes(fname, t);
# endif
return utimes(fname, t);
#elif defined HAVE_UTIMBUF
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
@@ -151,41 +165,49 @@ int set_modtime(char *fname, time_t modtime)
t[1] = modtime;
return utime(fname,t);
#else
struct timeval t[2];
t[0].tv_sec = time(NULL);
t[0].tv_usec = 0;
t[1].tv_sec = modtime;
t[1].tv_usec = 0;
return utimes(fname,t);
#error No file-time-modification routine found!
#endif
}
}
/* This creates a new directory with default permissions. Since there
* might be some directory-default permissions affecting this, we can't
* force the permissions directly using the original umask and mkdir(). */
int mkdir_defmode(char *fname)
{
int ret;
/**
Create any necessary directories in fname. Unfortunately we don't know
what perms to give the directory when this is called so we need to rely
on the umask
**/
int create_directory_path(char *fname, int base_umask)
umask(orig_umask);
ret = do_mkdir(fname, ACCESSPERMS);
umask(0);
return ret;
}
/* Create any necessary directories in fname. Any missing directories are
* created with default permissions. */
int create_directory_path(char *fname)
{
char *p;
int ret = 0;
while (*fname == '/')
fname++;
while (strncmp(fname, "./", 2) == 0)
fname += 2;
umask(orig_umask);
p = fname;
while ((p = strchr(p,'/')) != NULL) {
*p = 0;
do_mkdir(fname, 0777 & ~base_umask);
*p = '/';
p++;
*p = '\0';
if (do_mkdir(fname, ACCESSPERMS) < 0 && errno != EEXIST)
ret = -1;
*p++ = '/';
}
return 0;
}
umask(0);
return ret;
}
/**
* Write @p len bytes at @p ptr to descriptor @p desc, retrying if
@@ -216,7 +238,6 @@ int full_write(int desc, char *ptr, size_t len)
return total_written;
}
/**
* Read @p len bytes at @p ptr from descriptor @p desc, retrying if
* interrupted.
@@ -242,12 +263,11 @@ static int safe_read(int desc, char *ptr, size_t len)
return n_chars;
}
/** Copy a file.
*
* 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 copy_file(const char *source, const char *dest, mode_t mode)
{
int ifd;
int ofd;
@@ -316,7 +336,7 @@ int copy_file(char *source, char *dest, mode_t mode)
* --delete trying to remove old .rsyncNNN files, hence it renames it
* each time.
**/
int robust_unlink(char *fname)
int robust_unlink(const char *fname)
{
#ifndef ETXTBSY
return do_unlink(fname);
@@ -351,7 +371,7 @@ int robust_unlink(char *fname)
if (verbose > 0) {
rprintf(FINFO,"renaming %s to %s because of text busy\n",
safe_fname(fname), safe_fname(path));
fname, path);
}
/* maybe we should return rename()'s exit status? Nah. */
@@ -364,8 +384,11 @@ int robust_unlink(char *fname)
}
/* 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)
* across filesystems, -2 if copy_file() failed, and -1 on other errors.
* If partialptr is not NULL and we need to do a copy, copy the file into
* the active partial-dir instead of over the destination file. */
int robust_rename(char *from, char *to, char *partialptr,
int mode)
{
int tries = 4;
@@ -381,6 +404,11 @@ int robust_rename(char *from, char *to, int mode)
break;
#endif
case EXDEV:
if (partialptr) {
if (!handle_partial_dir(partialptr,PDIR_CREATE))
return -1;
to = partialptr;
}
if (copy_file(from, to, mode) != 0)
return -2;
do_unlink(from);
@@ -392,7 +420,6 @@ int robust_rename(char *from, char *to, int mode)
return -1;
}
static pid_t all_pids[10];
static int num_pids;
@@ -436,7 +463,6 @@ void kill_all(int sig)
}
}
/** Turn a user name into a uid */
int name_to_uid(char *name, uid_t *uid)
{
@@ -465,7 +491,6 @@ int name_to_gid(char *name, gid_t *gid)
return 0;
}
/** Lock a byte range in a open file */
int lock_range(int fd, int offset, int len)
{
@@ -517,7 +542,6 @@ static void glob_expand_one(char *s, char ***argv_ptr, int *argc_ptr,
filter_server_path(s);
#else
glob_t globbuf;
int i;
if (maxargs <= argc)
return;
@@ -542,9 +566,9 @@ static void glob_expand_one(char *s, char ***argv_ptr, int *argc_ptr,
if (globbuf.gl_pathc == 0)
argv[argc++] = s;
else {
int j = globbuf.gl_pathc;
int i;
free(s);
for (i = 0; i < j; i++) {
for (i = 0; i < (int)globbuf.gl_pathc; i++) {
if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
out_of_memory("glob_expand_one");
}
@@ -745,7 +769,7 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
{
char *start, *sanp;
int rlen = 0;
int rlen = 0, leave_one_dotdir = relative_paths;
if (dest != p) {
int plen = strlen(p);
@@ -780,9 +804,13 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
* always be left pointing after a slash
*/
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
p++;
continue;
if (leave_one_dotdir && p[1])
leave_one_dotdir = 0;
else {
/* skip "." component */
p++;
continue;
}
}
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
/* ".." component followed by slash or end */
@@ -877,43 +905,6 @@ 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
@@ -928,7 +919,6 @@ char *full_fname(const char *fn)
if (result)
free(result);
fn = safe_fname(fn);
if (*fn == '/')
p1 = p2 = "";
else {
@@ -1023,22 +1013,6 @@ int handle_partial_dir(const char *fname, int create)
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)
{
const uchar *s1 = (const uchar *)cs1;
const uchar *s2 = (const uchar *)cs2;
while (*s1 && *s2 && (*s1 == *s2)) {
s1++; s2++;
}
return (int)*s1 - (int)*s2;
}
/**
* Determine if a symlink points outside the current directory tree.
* This is considered "unsafe" because e.g. when mirroring somebody
@@ -1103,6 +1077,63 @@ int unsafe_symlink(const char *dest, const char *src)
return (depth < 0);
}
/* Return the int64 number as a string. If the --human-readable option was
* specified, we may output the number in K, M, or G units. We can return
* up to 4 buffers at a time. */
char *human_num(int64 num)
{
static char bufs[4][128]; /* more than enough room */
static unsigned int n;
char *s;
n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
if (human_readable) {
char units = '\0';
int mult = human_readable == 1 ? 1000 : 1024;
double dnum = 0;
if (num > mult*mult*mult) {
dnum = (double)num / (mult*mult*mult);
units = 'G';
} else if (num > mult*mult) {
dnum = (double)num / (mult*mult);
units = 'M';
} else if (num > mult) {
dnum = (double)num / mult;
units = 'K';
}
if (units) {
sprintf(bufs[n], "%.2f%c", dnum, units);
return bufs[n];
}
}
s = bufs[n] + sizeof bufs[0] - 1;
*s = '\0';
if (!num)
*--s = '0';
while (num) {
*--s = (num % 10) + '0';
num /= 10;
}
return s;
}
/* Return the double number as a string. If the --human-readable option was
* specified, we may output the number in K, M, or G units. We use a buffer
* from human_num() to return our result. */
char *human_dnum(double dnum, int decimal_digits)
{
char *buf = human_num(dnum);
int len = strlen(buf);
if (isdigit(*(uchar*)(buf+len-1))) {
/* There's extra room in buf prior to the start of the num. */
buf -= decimal_digits + 1;
snprintf(buf, len + decimal_digits + 2, "%.*f", decimal_digits, dnum);
}
return buf;
}
/**
* Return the date and time as a string
@@ -1111,6 +1142,7 @@ char *timestring(time_t t)
{
static char TimeBuf[200];
struct tm *tm = localtime(&t);
char *p;
#ifdef HAVE_STRFTIME
strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
@@ -1118,14 +1150,12 @@ char *timestring(time_t t)
strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
#endif
if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
TimeBuf[strlen(TimeBuf)-1] = 0;
}
if ((p = strchr(TimeBuf, '\n')) != NULL)
*p = '\0';
return(TimeBuf);
return TimeBuf;
}
/**
* Sleep for a specified number of milliseconds.
*
@@ -1154,11 +1184,8 @@ int msleep(int t)
return True;
}
/**
* Determine if two file modification times are equivalent (either
* exact or in the modification timestamp window established by
* --modify-window).
/* Determine if two time_t values are equivalent (either exact, or in
* the modification timestamp window established by --modify-window).
*
* @retval 0 if the times should be treated as the same
*
@@ -1166,7 +1193,7 @@ int msleep(int t)
*
* @retval -1 if the 2nd is later
**/
int cmp_modtime(time_t file1, time_t file2)
int cmp_time(time_t file1, time_t file2)
{
if (file2 > file1) {
if (file2 - file1 <= modify_window)
@@ -1212,7 +1239,6 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
}
#endif
#define MALLOC_MAX 0x40000000
void *_new_array(unsigned int size, unsigned long num)
@@ -1338,3 +1364,95 @@ uint32 fuzzy_distance(const char *s1, int len1, const char *s2, int len2)
return a[len2-1];
}
#define BB_SLOT_SIZE (16*1024) /* Desired size in bytes */
#define BB_PER_SLOT_BITS (BB_SLOT_SIZE * 8) /* Number of bits per slot */
#define BB_PER_SLOT_INTS (BB_SLOT_SIZE / 4) /* Number of int32s per slot */
struct bitbag {
uint32 **bits;
int slot_cnt;
};
struct bitbag *bitbag_create(int max_ndx)
{
struct bitbag *bb = new(struct bitbag);
bb->slot_cnt = (max_ndx + BB_PER_SLOT_BITS - 1) / BB_PER_SLOT_BITS;
if (!(bb->bits = (uint32**)calloc(bb->slot_cnt, sizeof (uint32*))))
out_of_memory("bitbag_create");
return bb;
}
void bitbag_set_bit(struct bitbag *bb, int ndx)
{
int slot = ndx / BB_PER_SLOT_BITS;
ndx %= BB_PER_SLOT_BITS;
if (!bb->bits[slot]) {
if (!(bb->bits[slot] = (uint32*)calloc(BB_PER_SLOT_INTS, 4)))
out_of_memory("bitbag_set_bit");
}
bb->bits[slot][ndx/32] |= 1u << (ndx % 32);
}
#if 0 /* not needed yet */
void bitbag_clear_bit(struct bitbag *bb, int ndx)
{
int slot = ndx / BB_PER_SLOT_BITS;
ndx %= BB_PER_SLOT_BITS;
if (!bb->bits[slot])
return;
bb->bits[slot][ndx/32] &= ~(1u << (ndx % 32));
}
int bitbag_check_bit(struct bitbag *bb, int ndx)
{
int slot = ndx / BB_PER_SLOT_BITS;
ndx %= BB_PER_SLOT_BITS;
if (!bb->bits[slot])
return 0;
return bb->bits[slot][ndx/32] & (1u << (ndx % 32)) ? 1 : 0;
}
#endif
/* Call this with -1 to start checking from 0. Returns -1 at the end. */
int bitbag_next_bit(struct bitbag *bb, int after)
{
uint32 bits, mask;
int i, ndx = after + 1;
int slot = ndx / BB_PER_SLOT_BITS;
ndx %= BB_PER_SLOT_BITS;
mask = (1u << (ndx % 32)) - 1;
for (i = ndx / 32; slot < bb->slot_cnt; slot++, i = mask = 0) {
if (!bb->bits[slot])
continue;
for ( ; i < BB_PER_SLOT_INTS; i++, mask = 0) {
if (!(bits = bb->bits[slot][i] & ~mask))
continue;
/* 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*BB_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... */
}
}
return -1;
}

View File

@@ -7,7 +7,7 @@
#define WILD_TEST_ITERATIONS
#include "lib/wildmatch.c"
#include "popt.h"
#include <popt.h>
#ifdef COMPARE_WITH_FNMATCH
#include <fnmatch.h>
@@ -20,10 +20,16 @@ int wildmatch_errors = 0;
typedef char bool;
int output_iterations = 0;
int explode_mod = 0;
int empties_mod = 0;
int empty_at_start = 0;
int empty_at_end = 0;
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"iterations", 'i', POPT_ARG_NONE, &output_iterations, 0, 0, 0},
{"empties", 'e', POPT_ARG_STRING, 0, 'e', 0, 0},
{"explode", 'x', POPT_ARG_INT, &explode_mod, 0, 0, 0},
{0,0,0,0, 0, 0, 0}
};
@@ -40,7 +46,28 @@ run_test(int line, bool matches, bool same_as_fnmatch,
same_as_fnmatch = 0; /* Get rid of unused-variable compiler warning. */
#endif
matched = wildmatch(pattern, text);
if (explode_mod) {
char buf[MAXPATHLEN*2], *texts[MAXPATHLEN];
int pos = 0, cnt = 0, ndx = 0, len = strlen(text);
if (empty_at_start)
texts[ndx++] = "";
/* An empty string must turn into at least one empty array item. */
while (1) {
texts[ndx] = buf + ndx * (explode_mod + 1);
strlcpy(texts[ndx++], text + pos, explode_mod + 1);
if (pos + explode_mod >= len)
break;
pos += explode_mod;
if (!(++cnt % empties_mod))
texts[ndx++] = "";
}
if (empty_at_end)
texts[ndx++] = "";
texts[ndx] = NULL;
matched = wildmatch_array(pattern, (const char**)texts, 0);
} else
matched = wildmatch(pattern, text);
#ifdef COMPARE_WITH_FNMATCH
fn_matched = !fnmatch(pattern, text, flags);
#endif
@@ -66,6 +93,7 @@ int
main(int argc, char **argv)
{
char buf[2048], *s, *string[2], *end[2];
const char *arg;
FILE *fp;
int opt, line, i, flag[2];
poptContext pc = poptGetContext("wildtest", argc, (const char**)argv,
@@ -73,6 +101,16 @@ main(int argc, char **argv)
while ((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case 'e':
arg = poptGetOptArg(pc);
empties_mod = atoi(arg);
if (strchr(arg, 's'))
empty_at_start = 1;
if (strchr(arg, 'e'))
empty_at_end = 1;
if (!explode_mod)
explode_mod = 1024;
break;
default:
fprintf(stderr, "%s: %s\n",
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
@@ -81,9 +119,12 @@ main(int argc, char **argv)
}
}
if (explode_mod && !empties_mod)
empties_mod = 1024;
argv = (char**)poptGetArgs(pc);
if (!argv || argv[1]) {
fprintf(stderr, "Usage: wildtest TESTFILE\n");
fprintf(stderr, "Usage: wildtest [OPTIONS] TESTFILE\n");
exit(1);
}

View File

@@ -50,6 +50,10 @@
0 1 bar/baz/foo */foo
0 0 foo/bar/baz **/bar*
1 1 deep/foo/bar/baz **/bar/*
0 1 deep/foo/bar/baz/ **/bar/*
1 1 deep/foo/bar/baz/ **/bar/**
0 1 deep/foo/bar **/bar/*
1 1 deep/foo/bar/ **/bar/**
1 1 foo/bar/baz **/bar**
1 1 foo/bar/baz/x */bar/**
0 0 deep/foo/bar/baz/x */bar/**

View File

@@ -1,5 +1,379 @@
ChangeLog file for zlib
ChangeLog file for zlib
Changes in 1.2.3 (18 July 2005)
- Apply security vulnerability fixes to contrib/infback9 as well
- Clean up some text files (carriage returns, trailing space)
- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
Changes in 1.2.2.4 (11 July 2005)
- Add inflatePrime() function for starting inflation at bit boundary
- Avoid some Visual C warnings in deflate.c
- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
compile
- Fix some spelling errors in comments [Betts]
- Correct inflateInit2() error return documentation in zlib.h
- Added zran.c example of compressed data random access to examples
directory, shows use of inflatePrime()
- Fix cast for assignments to strm->state in inflate.c and infback.c
- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
- Add cast in trees.c t avoid a warning [Oberhumer]
- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
- Update make_vms.com [Zinser]
- Initialize state->write in inflateReset() since copied in inflate_fast()
- Be more strict on incomplete code sets in inflate_table() and increase
ENOUGH and MAXD -- this repairs a possible security vulnerability for
invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
discovering the vulnerability and providing test cases.
- Add ia64 support to configure for HP-UX [Smith]
- Add error return to gzread() for format or i/o error [Levin]
- Use malloc.h for OS/2 [Necasek]
Changes in 1.2.2.3 (27 May 2005)
- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
- Typecast fread() return values in gzio.c [Vollant]
- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
- Fix crc check bug in gzread() after gzungetc() [Heiner]
- Add the deflateTune() function to adjust internal compression parameters
- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
- Remove an incorrect assertion in examples/zpipe.c
- Add C++ wrapper in infback9.h [Donais]
- Fix bug in inflateCopy() when decoding fixed codes
- Note in zlib.h how much deflateSetDictionary() actually uses
- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
- Add gzdirect() function to indicate transparent reads
- Update contrib/minizip [Vollant]
- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
- Add casts in crc32.c to avoid warnings [Oberhumer]
- Add contrib/masmx64 [Vollant]
- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
Changes in 1.2.2.2 (30 December 2004)
- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
avoid implicit memcpy calls (portability for no-library compilation)
- Increase sprintf() buffer size in gzdopen() to allow for large numbers
- Add INFLATE_STRICT to check distances against zlib header
- Improve WinCE errno handling and comments [Chang]
- Remove comment about no gzip header processing in FAQ
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
- Add updated make_vms.com [Coghlan], update README
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
- Add FAQ entry and comments in deflate.c on uninitialized memory access
- Add Solaris 9 make options in configure [Gilbert]
- Allow strerror() usage in gzio.c for STDC
- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
- Use z_off_t for adler32_combine() and crc32_combine() lengths
- Make adler32() much faster for small len
- Use OS_CODE in deflate() default gzip header
Changes in 1.2.2.1 (31 October 2004)
- Allow inflateSetDictionary() call for raw inflate
- Fix inflate header crc check bug for file names and comments
- Add deflateSetHeader() and gz_header structure for custom gzip headers
- Add inflateGetheader() to retrieve gzip headers
- Add crc32_combine() and adler32_combine() functions
- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
- Use zstreamp consistently in zlib.h (inflate_back functions)
- Remove GUNZIP condition from definition of inflate_mode in inflate.h
and in contrib/inflate86/inffast.S [Truta, Anderson]
- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
- Update projects/README.projects and projects/visualc6 [Truta]
- Update win32/DLL_FAQ.txt [Truta]
- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
- Use a new algorithm for setting strm->data_type in trees.c [Truta]
- Do not define an exit() prototype in zutil.c unless DEBUG defined
- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
- Fix Darwin build version identification [Peterson]
Changes in 1.2.2 (3 October 2004)
- Update zlib.h comments on gzip in-memory processing
- Set adler to 1 in inflateReset() to support Java test suite [Walles]
- Add contrib/dotzlib [Ravn]
- Update win32/DLL_FAQ.txt [Truta]
- Update contrib/minizip [Vollant]
- Move contrib/visual-basic.txt to old/ [Truta]
- Fix assembler builds in projects/visualc6/ [Truta]
Changes in 1.2.1.2 (9 September 2004)
- Update INDEX file
- Fix trees.c to update strm->data_type (no one ever noticed!)
- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown]
- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE)
- Add limited multitasking protection to DYNAMIC_CRC_TABLE
- Add NO_vsnprintf for VMS in zutil.h [Mozilla]
- Don't declare strerror() under VMS [Mozilla]
- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize
- Update contrib/ada [Anisimkov]
- Update contrib/minizip [Vollant]
- Fix configure to not hardcode directories for Darwin [Peterson]
- Fix gzio.c to not return error on empty files [Brown]
- Fix indentation; update version in contrib/delphi/ZLib.pas and
contrib/pascal/zlibpas.pas [Truta]
- Update mkasm.bat in contrib/masmx86 [Truta]
- Update contrib/untgz [Truta]
- Add projects/README.projects [Truta]
- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta]
- Update win32/DLL_FAQ.txt [Truta]
- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta]
- Remove an unnecessary assignment to curr in inftrees.c [Truta]
- Add OS/2 to exe builds in configure [Poltorak]
- Remove err dummy parameter in zlib.h [Kientzle]
Changes in 1.2.1.1 (9 January 2004)
- Update email address in README
- Several FAQ updates
- Fix a big fat bug in inftrees.c that prevented decoding valid
dynamic blocks with only literals and no distance codes --
Thanks to "Hot Emu" for the bug report and sample file
- Add a note to puff.c on no distance codes case.
Changes in 1.2.1 (17 November 2003)
- Remove a tab in contrib/gzappend/gzappend.c
- Update some interfaces in contrib for new zlib functions
- Update zlib version number in some contrib entries
- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
- Support shared libraries on Hurd and KFreeBSD [Brown]
- Fix error in NO_DIVIDE option of adler32.c
Changes in 1.2.0.8 (4 November 2003)
- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
- Add experimental NO_DIVIDE #define in adler32.c
- Possibly faster on some processors (let me know if it is)
- Correct Z_BLOCK to not return on first inflate call if no wrap
- Fix strm->data_type on inflate() return to correctly indicate EOB
- Add deflatePrime() function for appending in the middle of a byte
- Add contrib/gzappend for an example of appending to a stream
- Update win32/DLL_FAQ.txt [Truta]
- Delete Turbo C comment in README [Truta]
- Improve some indentation in zconf.h [Truta]
- Fix infinite loop on bad input in configure script [Church]
- Fix gzeof() for concatenated gzip files [Johnson]
- Add example to contrib/visual-basic.txt [Michael B.]
- Add -p to mkdir's in Makefile.in [vda]
- Fix configure to properly detect presence or lack of printf functions
- Add AS400 support [Monnerat]
- Add a little Cygwin support [Wilson]
Changes in 1.2.0.7 (21 September 2003)
- Correct some debug formats in contrib/infback9
- Cast a type in a debug statement in trees.c
- Change search and replace delimiter in configure from % to # [Beebe]
- Update contrib/untgz to 0.2 with various fixes [Truta]
- Add build support for Amiga [Nikl]
- Remove some directories in old that have been updated to 1.2
- Add dylib building for Mac OS X in configure and Makefile.in
- Remove old distribution stuff from Makefile
- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
- Update links in README
Changes in 1.2.0.6 (13 September 2003)
- Minor FAQ updates
- Update contrib/minizip to 1.00 [Vollant]
- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
- Update POSTINC comment for 68060 [Nikl]
- Add contrib/infback9 with deflate64 decoding (unsupported)
- For MVS define NO_vsnprintf and undefine FAR [van Burik]
- Add pragma for fdopen on MVS [van Burik]
Changes in 1.2.0.5 (8 September 2003)
- Add OF to inflateBackEnd() declaration in zlib.h
- Remember start when using gzdopen in the middle of a file
- Use internal off_t counters in gz* functions to properly handle seeks
- Perform more rigorous check for distance-too-far in inffast.c
- Add Z_BLOCK flush option to return from inflate at block boundary
- Set strm->data_type on return from inflate
- Indicate bits unused, if at block boundary, and if in last block
- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
- Add condition so old NO_DEFLATE define still works for compatibility
- FAQ update regarding the Windows DLL [Truta]
- INDEX update: add qnx entry, remove aix entry [Truta]
- Install zlib.3 into mandir [Wilson]
- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
- Adapt the zlib interface to the new DLL convention guidelines [Truta]
- Introduce ZLIB_WINAPI macro to allow the export of functions using
the WINAPI calling convention, for Visual Basic [Vollant, Truta]
- Update msdos and win32 scripts and makefiles [Truta]
- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
- Add contrib/ada [Anisimkov]
- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
- Add contrib/masm686 [Truta]
- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
[Truta, Vollant]
- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
- Remove contrib/delphi2; add a new contrib/delphi [Truta]
- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream,
and fix some method prototypes [Truta]
- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
[Truta]
- Avoid the use of backslash (\) in contrib/minizip [Vollant]
- Fix file time handling in contrib/untgz; update makefiles [Truta]
- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
[Vollant]
- Remove contrib/vstudio/vc15_16 [Vollant]
- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
- Update README.contrib [Truta]
- Invert the assignment order of match_head and s->prev[...] in
INSERT_STRING [Truta]
- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
[Truta]
- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
- Fix prototype of syncsearch in inflate.c [Truta]
- Introduce ASMINF macro to be enabled when using an ASM implementation
of inflate_fast [Truta]
- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
- Modify test_gzio in example.c to take a single file name as a
parameter [Truta]
- Exit the example.c program if gzopen fails [Truta]
- Add type casts around strlen in example.c [Truta]
- Remove casting to sizeof in minigzip.c; give a proper type
to the variable compared with SUFFIX_LEN [Truta]
- Update definitions of STDC and STDC99 in zconf.h [Truta]
- Synchronize zconf.h with the new Windows DLL interface [Truta]
- Use SYS16BIT instead of __32BIT__ to distinguish between
16- and 32-bit platforms [Truta]
- Use far memory allocators in small 16-bit memory models for
Turbo C [Truta]
- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
zlibCompileFlags [Truta]
- Cygwin has vsnprintf [Wilson]
- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
Changes in 1.2.0.4 (10 August 2003)
- Minor FAQ updates
- Be more strict when checking inflateInit2's windowBits parameter
- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
- Add gzip wrapper option to deflateInit2 using windowBits
- Add updated QNX rule in configure and qnx directory [Bonnefoy]
- Make inflate distance-too-far checks more rigorous
- Clean up FAR usage in inflate
- Add casting to sizeof() in gzio.c and minigzip.c
Changes in 1.2.0.3 (19 July 2003)
- Fix silly error in gzungetc() implementation [Vollant]
- Update contrib/minizip and contrib/vstudio [Vollant]
- Fix printf format in example.c
- Correct cdecl support in zconf.in.h [Anisimkov]
- Minor FAQ updates
Changes in 1.2.0.2 (13 July 2003)
- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
- Attempt to avoid warnings in crc32.c for pointer-int conversion
- Add AIX to configure, remove aix directory [Bakker]
- Add some casts to minigzip.c
- Improve checking after insecure sprintf() or vsprintf() calls
- Remove #elif's from crc32.c
- Change leave label to inf_leave in inflate.c and infback.c to avoid
library conflicts
- Remove inflate gzip decoding by default--only enable gzip decoding by
special request for stricter backward compatibility
- Add zlibCompileFlags() function to return compilation information
- More typecasting in deflate.c to avoid warnings
- Remove leading underscore from _Capital #defines [Truta]
- Fix configure to link shared library when testing
- Add some Windows CE target adjustments [Mai]
- Remove #define ZLIB_DLL in zconf.h [Vollant]
- Add zlib.3 [Rodgers]
- Update RFC URL in deflate.c and algorithm.txt [Mai]
- Add zlib_dll_FAQ.txt to contrib [Truta]
- Add UL to some constants [Truta]
- Update minizip and vstudio [Vollant]
- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
- Expand use of NO_DUMMY_DECL to avoid all dummy structures
- Added iostream3 to contrib [Schwardt]
- Replace rewind() with fseek() for WinCE [Truta]
- Improve setting of zlib format compression level flags
- Report 0 for huffman and rle strategies and for level == 0 or 1
- Report 2 only for level == 6
- Only deal with 64K limit when necessary at compile time [Truta]
- Allow TOO_FAR check to be turned off at compile time [Truta]
- Add gzclearerr() function [Souza]
- Add gzungetc() function
Changes in 1.2.0.1 (17 March 2003)
- Add Z_RLE strategy for run-length encoding [Truta]
- When Z_RLE requested, restrict matches to distance one
- Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
- Correct FASTEST compilation to allow level == 0
- Clean up what gets compiled for FASTEST
- Incorporate changes to zconf.in.h [Vollant]
- Refine detection of Turbo C need for dummy returns
- Refine ZLIB_DLL compilation
- Include additional header file on VMS for off_t typedef
- Try to use _vsnprintf where it supplants vsprintf [Vollant]
- Add some casts in inffast.c
- Enchance comments in zlib.h on what happens if gzprintf() tries to
write more than 4095 bytes before compression
- Remove unused state from inflateBackEnd()
- Remove exit(0) from minigzip.c, example.c
- Get rid of all those darn tabs
- Add "check" target to Makefile.in that does the same thing as "test"
- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
- Update contrib/inflate86 [Anderson]
- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
- Add msdos and win32 directories with makefiles [Truta]
- More additions and improvements to the FAQ
Changes in 1.2.0 (9 March 2003)
- New and improved inflate code
- About 20% faster
- Does not allocate 32K window unless and until needed
- Automatically detects and decompresses gzip streams
- Raw inflate no longer needs an extra dummy byte at end
- Added inflateBack functions using a callback interface--even faster
than inflate, useful for file utilities (gzip, zip)
- Added inflateCopy() function to record state for random access on
externally generated deflate streams (e.g. in gzip files)
- More readable code (I hope)
- New and improved crc32()
- About 50% faster, thanks to suggestions from Rodney Brown
- Add deflateBound() and compressBound() functions
- Fix memory leak in deflateInit2()
- Permit setting dictionary for raw deflate (for parallel deflate)
- Fix const declaration for gzwrite()
- Check for some malloc() failures in gzio.c
- Fix bug in gzopen() on single-byte file 0x1f
- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
and next buffer doesn't start with 0x8b
- Fix uncompress() to return Z_DATA_ERROR on truncated input
- Free memory at end of example.c
- Remove MAX #define in trees.c (conflicted with some libraries)
- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
- Declare malloc() and free() in gzio.c if STDC not defined
- Use malloc() instead of calloc() in zutil.c if int big enough
- Define STDC for AIX
- Add aix/ with approach for compiling shared library on AIX
- Add HP-UX support for shared libraries in configure
- Add OpenUNIX support for shared libraries in configure
- Use $cc instead of gcc to build shared library
- Make prefix directory if needed when installing
- Correct Macintosh avoidance of typedef Byte in zconf.h
- Correct Turbo C memory allocation when under Linux
- Use libz.a instead of -lz in Makefile (assure use of compiled library)
- Update configure to check for snprintf or vsnprintf functions and their
return value, warn during make if using an insecure function
- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
is lost when library is used--resolution is to build new zconf.h
- Documentation improvements (in zlib.h):
- Document raw deflate and inflate
- Update RFCs URL
- Point out that zlib and gzip formats are different
- Note that Z_BUF_ERROR is not fatal
- Document string limit for gzprintf() and possible buffer overflow
- Note requirement on avail_out when flushing
- Note permitted values of flush parameter of inflate()
- Add some FAQs (and even answers) to the FAQ
- Add contrib/inflate86/ for x86 faster inflate
- Add contrib/blast/ for PKWare Data Compression Library decompression
- Add contrib/puff/ simple inflate for deflate format description
Changes in 1.1.4 (11 March 2002)
- ZFREE was repeated on same allocation on some error conditions.
@@ -10,7 +384,7 @@ Changes in 1.1.4 (11 March 2002)
less than 32K.
- force windowBits > 8 to avoid a bug in the encoder for a window size
of 256 bytes. (A complete fix will be available in 1.1.5).
Changes in 1.1.3 (9 July 1998)
- fix "an inflate input buffer bug that shows up on rare but persistent
occasions" (Mark)
@@ -166,7 +540,7 @@ Changes in 1.0.7 (20 Jan 1998)
Changes in 1.0.6 (19 Jan 1998)
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
- Fix a deflate bug occuring only with compression level 0 (thanks to
- Fix a deflate bug occurring only with compression level 0 (thanks to
Andy Buckler for finding this one).
- In minigzip, pass transparently also the first byte for .Z files.
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
@@ -184,13 +558,13 @@ Changes in 1.0.6 (19 Jan 1998)
- added Makefile.nt (thanks to Stephen Williams)
- added the unsupported "contrib" directory:
contrib/asm386/ by Gilles Vollant <info@winimage.com>
386 asm code replacing longest_match().
386 asm code replacing longest_match().
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
A C++ I/O streams interface to the zlib gz* functions
contrib/iostream2/ by Tyge L<>vset <Tyge.Lovset@cmr.no>
Another C++ I/O streams interface
Another C++ I/O streams interface
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
A very simple tar.gz file extractor using zlib
A very simple tar.gz file extractor using zlib
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
How to use compress(), uncompress() and the gz* functions from VB.
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
@@ -217,7 +591,7 @@ Changes in 1.0.6 (19 Jan 1998)
- add NEED_DUMMY_RETURN for Borland
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
- allow compilation with CC
- defined STDC for OS/2 (David Charlap)
- defined STDC for OS/2 (David Charlap)
- limit external names to 8 chars for MVS (Thomas Lund)
- in minigzip.c, use static buffers only for 16-bit systems
- fix suffix check for "minigzip -d foo.gz"
@@ -242,7 +616,7 @@ Changes in 1.0.5 (3 Jan 98)
- Eliminate memory leaks on error conditions in inflate
- Removed some vestigial code in inflate
- Update web address in README
Changes in 1.0.4 (24 Jul 96)
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
bit, so the decompressor could decompress all the correct data but went

View File

@@ -1,175 +0,0 @@
# Makefile for zlib
# Copyright (C) 1995-2002 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h
# To compile and test, type:
# ./configure; make test
# The call of configure is optional if you don't have special requirements
# If you wish to build zlib as a shared library, use: ./configure -s
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
# make install
# To install in $HOME instead of /usr/local, use:
# make install prefix=$HOME
CC=cc
CFLAGS=-O
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
#CFLAGS=-g -DDEBUG
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
# -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS=-L. -lz
LDSHARED=$(CC)
CPP=$(CC) -E
VER=1.1.4
LIBS=libz.a
SHAREDLIB=libz.so
AR=ar rc
RANLIB=ranlib
TAR=tar
SHELL=/bin/sh
prefix = /usr/local
exec_prefix = ${prefix}
libdir = ${exec_prefix}/lib
includedir = ${prefix}/include
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
OBJA =
# to use the asm code: make OBJA=match.o
TEST_OBJS = example.o minigzip.o
DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \
algorithm.txt zlib.3 zlib.html \
msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \
nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \
contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \
contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \
contrib/asm[56]86/*.S contrib/iostream/*.cpp \
contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \
contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \
contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \
contrib/delphi*/*.???
all: example minigzip
test: all
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
echo hello world | ./minigzip | ./minigzip -d || \
echo ' *** minigzip test FAILED ***' ; \
if ./example; then \
echo ' *** zlib test OK ***'; \
else \
echo ' *** zlib test FAILED ***'; \
fi
libz.a: $(OBJS) $(OBJA)
$(AR) $@ $(OBJS) $(OBJA)
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
match.o: match.S
$(CPP) match.S > _match.s
$(CC) -c _match.s
mv _match.o match.o
rm -f _match.s
$(SHAREDLIB).$(VER): $(OBJS)
$(LDSHARED) -o $@ $(OBJS)
rm -f $(SHAREDLIB) $(SHAREDLIB).1
ln -s $@ $(SHAREDLIB)
ln -s $@ $(SHAREDLIB).1
example: example.o $(LIBS)
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
minigzip: minigzip.o $(LIBS)
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
install: $(LIBS)
-@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi
-@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi
cp zlib.h zconf.h $(includedir)
chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
cp $(LIBS) $(libdir)
cd $(libdir); chmod 755 $(LIBS)
-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \
rm -f $(SHAREDLIB) $(SHAREDLIB).1; \
ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \
ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \
(ldconfig || true) >/dev/null 2>&1; \
fi
# The ranlib in install is needed on NeXTSTEP which checks file times
# ldconfig is for Linux
uninstall:
cd $(includedir); \
v=$(VER); \
if test -f zlib.h; then \
v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \
rm -f zlib.h zconf.h; \
fi; \
cd $(libdir); rm -f libz.a; \
if test -f $(SHAREDLIB).$$v; then \
rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \
fi
clean:
rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \
_match.s maketree
distclean: clean
zip:
mv Makefile Makefile~; cp -p Makefile.in Makefile
rm -f test.c ztest*.c contrib/minizip/test.zip
v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
zip -ul9 zlib$$v $(DISTFILES)
mv Makefile~ Makefile
dist:
mv Makefile Makefile~; cp -p Makefile.in Makefile
rm -f test.c ztest*.c contrib/minizip/test.zip
d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
rm -f $$d.tar.gz; \
if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \
files=""; \
for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \
cd ..; \
GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \
if test ! -d $$d; then rm -f $$d; fi
mv Makefile~ Makefile
tags:
etags *.[ch]
depend:
makedepend -- $(CFLAGS) -- *.[ch]
# DO NOT DELETE THIS LINE -- make depend depends on it.
adler32.o: zlib.h zconf.h
compress.o: zlib.h zconf.h
crc32.o: zlib.h zconf.h
deflate.o: deflate.h zutil.h zlib.h zconf.h
example.o: zlib.h zconf.h
gzio.o: zutil.h zlib.h zconf.h
infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
infcodes.o: zutil.h zlib.h zconf.h
infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
inffast.o: zutil.h zlib.h zconf.h inftrees.h
inffast.o: infblock.h infcodes.h infutil.h inffast.h
inflate.o: zutil.h zlib.h zconf.h infblock.h
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
minigzip.o: zlib.h zconf.h
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
uncompr.o: zlib.h zconf.h
zutil.o: zutil.h zlib.h zconf.h

View File

@@ -1,110 +1,86 @@
zlib 1.1.4 is a general purpose data compression library. All the code
is thread safe. The data format used by the zlib library
is described by RFCs (Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
format) and rfc1952.txt (gzip format). These documents are also available in
other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.3 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
and rfc1952.txt (gzip format). These documents are also available in other
formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
example of the library is given in the file example.c which also tests that
the library is working correctly. Another example is given in the file
minigzip.c. The compression library itself is composed of all source files
except example.c and minigzip.c.
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
of the library is given in the file example.c which also tests that the library
is working correctly. Another example is given in the file minigzip.c. The
compression library itself is composed of all source files except example.c and
minigzip.c.
To compile all files and run the test program, follow the instructions
given at the top of Makefile. In short "make test; make install"
should work for most machines. For Unix: "./configure; make test; make install"
For MSDOS, use one of the special makefiles such as Makefile.msc.
For VMS, use Make_vms.com or descrip.mms.
To compile all files and run the test program, follow the instructions given at
the top of Makefile. In short "make test; make install" should work for most
machines. For Unix: "./configure; make test; make install". For MSDOS, use one
of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
Questions about zlib should be sent to <zlib@gzip.org>, or to
Gilles Vollant <info@winimage.com> for the Windows DLL version.
The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/
Before reporting a problem, please check this site to verify that
you have the latest version of zlib; otherwise get the latest version and
check whether the problem still exists or not.
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
<info@winimage.com> for the Windows DLL version. The zlib home page is
http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
please check this site to verify that you have the latest version of zlib;
otherwise get the latest version and check whether the problem still exists or
not.
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html
before asking for help.
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
for help.
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
The changes made in version 1.1.4 are documented in the file ChangeLog.
The only changes made since 1.1.3 are bug corrections:
- ZFREE was repeated on same allocation on some error conditions.
This creates a security problem described in
http://www.zlib.org/advisory-2002-03-11.txt
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
- Avoid accesses before window for invalid distances with inflate window
less than 32K.
- force windowBits > 8 to avoid a bug in the encoder for a window size
of 256 bytes. (A complete fix will be available in 1.1.5).
The beta version 1.1.5beta includes many more changes. A new official
version 1.1.5 will be released as soon as extensive testing has been
completed on it.
The changes made in version 1.2.3 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib".
A Java implementation of zlib is available in the Java Development Kit
http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
See the zlib home page http://www.zlib.org for details.
A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
is in the CPAN (Comprehensive Perl Archive Network) sites
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
CPAN (Comprehensive Perl Archive Network) sites
http://www.cpan.org/modules/by-module/Compress/
A Python interface to zlib written by A.M. Kuchling <amk@magnet.com>
is available in Python 1.5 and later versions, see
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
available in Python 1.5 and later versions, see
http://www.python.org/doc/lib/module-zlib.html
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com>
is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
An experimental package to read and write files in .zip format,
written on top of zlib by Gilles Vollant <info@winimage.com>, is
available at http://www.winimage.com/zLibDll/unzip.html
and also in the contrib/minizip directory of zlib.
An experimental package to read and write files in .zip format, written on top
of zlib by Gilles Vollant <info@winimage.com>, is available in the
contrib/minizip directory of zlib.
Notes for some targets:
- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
The zlib DLL support was initially done by Alessandro Iacopetti and is
now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL
home page at http://www.winimage.com/zLibDll
- For Windows DLL versions, please see win32/DLL_FAQ.txt
From Visual Basic, you can call the DLL functions which do not take
a structure as argument: compress, uncompress and all gz* functions.
See contrib/visual-basic.txt for more information, or get
http://www.tcfb.com/dowseware/cmp-z-it.zip
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
compiler flag). The compiler bug has been reported to SGI.
- For 64-bit Irix, deflate.c must be compiled without any optimization.
With -O, one libpng test fails. The test works in 32 bit mode (with
the -n32 compiler flag). The compiler bug has been reported to SGI.
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
when compiled with cc.
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
it works when compiled with cc.
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
necessary to get gzprintf working correctly. This is done by configure.
- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
is necessary to get gzprintf working correctly. This is done by configure.
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
with other compilers. Use "make test" to check your compiler.
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
other compilers. Use "make test" to check your compiler.
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
- For Turbo C the small model is supported only with reduced performance to
avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
- For PalmOs, see http://palmzlib.sourceforge.net/
- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
Per Harald Myrvang <perm@stud.cs.uit.no>
- When building a shared, i.e. dynamic library on Mac OS X, the library must be
installed before testing (do "make install" before "make test"), since the
library location is specified in the library.
Acknowledgments:
@@ -116,7 +92,7 @@ Acknowledgments:
Copyright notice:
(C) 1995-2002 Jean-loup Gailly and Mark Adler
(C) 1995-2004 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -144,4 +120,6 @@ entirely written by Jean-loup Gailly and Mark Adler; it does not
include third-party code.
If you redistribute modified sources, we would appreciate that you include
in the file ChangeLog history information documenting your changes.
in the file ChangeLog history information documenting your changes. Please
read the FAQ for more information on the distribution of modified source
versions.

View File

@@ -1,48 +1,149 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
#define BASE 65521L /* largest prime smaller than 65536 */
#define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE
# define MOD(a) \
do { \
if (a >= (BASE << 16)) a -= (BASE << 16); \
if (a >= (BASE << 15)) a -= (BASE << 15); \
if (a >= (BASE << 14)) a -= (BASE << 14); \
if (a >= (BASE << 13)) a -= (BASE << 13); \
if (a >= (BASE << 12)) a -= (BASE << 12); \
if (a >= (BASE << 11)) a -= (BASE << 11); \
if (a >= (BASE << 10)) a -= (BASE << 10); \
if (a >= (BASE << 9)) a -= (BASE << 9); \
if (a >= (BASE << 8)) a -= (BASE << 8); \
if (a >= (BASE << 7)) a -= (BASE << 7); \
if (a >= (BASE << 6)) a -= (BASE << 6); \
if (a >= (BASE << 5)) a -= (BASE << 5); \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD4(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
int k;
unsigned long sum2;
unsigned n;
if (buf == Z_NULL) return 1L;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= BASE;
s2 %= BASE;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
return (s2 << 16) | s1;
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* the derivation of this formula is left as an exercise for the reader */
rem = (unsigned)(len2 % BASE);
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}

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