Compare commits

..

223 Commits

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

View File

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

37
.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
*.[oa]
*~
dummy
ID
Makefile
configure.sh
config.cache
config.h
config.h.in
config.log
config.status
/proto.h
/proto.h-tstamp
/rsync.1
/rsyncd.conf.5
/autom4te*.cache
/confdefs.h
/conftest*
/dox
/getgroups
/gmon.out
/rsync
/shconfig
/testdir
/tests-dont-exist
/testtmp
/tls
/trimslash
/t_unsafe
/wildtest
/getfsdev
/rounding.h
/doc/rsync.pdf
/doc/rsync.ps
/testsuite/chown-fake.test
/testsuite/devices-fake.test
/patches

View File

@@ -26,6 +26,7 @@ VERSION=@VERSION@
.SUFFIXES:
.SUFFIXES: .c .o
GENFILES=configure.sh config.h.in proto.h proto.h-tstamp rsync.1 rsyncd.conf.5
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h lib/pool_alloc.h
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o @LIBOBJS@
@@ -50,7 +51,7 @@ CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
# Objects for CHECK_PROGS to clean
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
@@ -58,15 +59,15 @@ CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: rsync$(EXEEXT)
all: conf_stop make_stop rsync$(EXEEXT) @MAKE_MAN@
install: all
-mkdir -p ${DESTDIR}${bindir}
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
-mkdir -p ${DESTDIR}${mandir}/man1
-mkdir -p ${DESTDIR}${mandir}/man5
${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1
${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5
if test -f $(srcdir)/rsync.1; then ${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1; fi
if test -f $(srcdir)/rsyncd.conf.5; then ${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
install-strip:
$(MAKE) INSTALL_STRIP='-s' install
@@ -75,16 +76,25 @@ rsync$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
$(OBJS): $(HEADERS)
$(CHECK_OBJS): $(HEADERS)
flist.o: rounding.h
rounding.h: mkrounding$(EXEEXT)
./mkrounding$(EXEEXT) >rounding.h
mkrounding$(EXEEXT): mkrounding.c rsync.h
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
@rm mkrounding.h
rounding.h: rounding.c rsync.h
@for r in 0 1 3; do \
if $(CC) $(CFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >/dev/null 2>&1; then \
echo "#define EXTRA_ROUNDING $$r" >rounding.h; \
if test -f "$$HOME/build_farm/build_test.fns"; then \
echo "EXTRA_ROUNDING is $$r" >&2; \
fi; \
break; \
fi; \
done
@rm -f rounding
@if test -f rounding.h; then : ; else \
echo "Failed to create rounding.h!"; \
exit 1; \
fi
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
@@ -103,18 +113,55 @@ 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:
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
gen: conf proto.h man
man:
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
gensend: gen
rsync -aivzc $(GENFILES) samba.org:/home/ftp/pub/rsync/generated-files/
proto:
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
conf:
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
conf_stop: configure.sh config.h.in
configure.sh config.h.in: configure.in aclocal.m4
autoconf -o configure.sh
autoheader && touch config.h.in
@echo 'Configure files changed -- perhaps run:'
@echo ' make reconfigure'
@exit 1
reconfigure: configure.sh
./config.status --recheck
./config.status
make_stop: Makefile
Makefile: Makefile.in config.status
@./config.status
@echo "Makefile updated -- rerun your make command."
@exit 1
proto: proto.h-tstamp
proto.h: proto.h-tstamp
@echo ' ' >/dev/null
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
man: rsync.1 rsyncd.conf.5
rsync.1: rsync.yo
yodl2man -o rsync.1 $(srcdir)/rsync.yo
-$(srcdir)/tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
-$(srcdir)/tweak_manpage rsyncd.conf.5
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
mkrounding mkrounding.h rounding.h
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h
cleantests:
rm -rf ./testtmp*
@@ -124,12 +171,14 @@ cleantests:
# the source directory.
distclean: clean
rm -f Makefile config.h config.status
rm -f lib/dummy popt/dummy zlib/dummy
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
rm -f $(srcdir)/lib/dummy $(srcdir)/popt/dummy $(srcdir)/zlib/dummy
rm -f config.cache config.log
rm -f $(srcdir)/config.cache $(srcdir)/config.log
rm -f shconfig $(srcdir)/shconfig
rm -f $(GENFILES)
rm -rf autom4te.cache
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
@@ -160,7 +209,7 @@ check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
wildtest.o: wildtest.c lib/wildmatch.c rsync.h config.h
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)

155
NEWS
View File

@@ -1,4 +1,4 @@
NEWS for rsync 3.0.0 (UNRELEASED)
NEWS for rsync 3.0.0 (1 Mar 2008)
Protocol: 30 (changed)
Changes since 2.6.9:
@@ -11,15 +11,57 @@ Changes since 2.6.9:
an implied dir be duplicated as a symlink, you should specify the
transfer of the symlink and the transfer of the referent directory as
separate args. (See also --keep-dirlinks and --no-implied-dirs.)
Also, exclude rules no longer have a partial effect on implied dirs.
- Requesting a remote file list without specifying -r (--recursive) now
- Requesting a remote file-listing without specifying -r (--recursive) now
sends the -d (--dirs) option to the remote rsync rather than sending -r
along with an extra exclude of /*/*. If the remote rsync does not
understand the -d option (i.e. it is 2.6.3 or older), you will need to
either turn off -d (--no-d), or specify -r --exclude='/*/*' manually.
- In --dry-run mode, the last line of the verbose summary text is output
with a "(DRY RUN)" suffix to help remind you that no updates were made.
Similarly, --only-write-batch outputs "(BATCH ONLY)".
- A writable rsync daemon with "use chroot" disabled now defaults to a
symlink-munging behavior designed to make symlinks safer while also
allowing absolute symlinks to be stored and retrieved. This also has
the effect of making symlinks unusable while they're in the daemon's
hierarchy. See the daemon's "munge symlinks" parameter for details.
- Starting up an extra copy of an rsync daemon will not clobber the pidfile
for the running daemon -- if the pidfile exists, the new daemon will exit
with an error. This means that your wrapper script that starts the rsync
daemon should be made to handle lock-breaking (if you want any automatic
breaking of locks to be done).
BUG FIXES:
- A daemon with "use chroot = no" and excluded items listed in the daemon
config file now properly checks an absolute-path arg specified for these
options: --compare-dest, --link-dest, --copy-dest, --partial-dir,
--backup-dir, --temp-dir, and --files-from.
- A daemon can now be told to disable all user- and group-name translation
on a per-module basis. This avoids a potential problem with a writable
daemon module that has "use chroot" enabled -- if precautions weren't
taken, a user could try to add a missing library and get rsync to use
it. This makes rsync safer by default, and more configurable when id-
translation is not desired. See the daemon's "numeric ids" parameter
for full details.
- A chroot daemon can now indicate which part of its path should affect the
chroot call, and which part should become an inside-chroot path for the
module. This allows you to have outside-the-transfer paths (such as for
libraries) even when you enable chroot protection. The idiom used in the
rsyncd.conf file is: path = /chroot/dirs/./dirs/inside
- If a file's data arrived successfully on the receiving side but the
rename of the temporary file to the destination file failed AND the
--remove-source-files (or the deprecated --remove-sent-files) option
was specified, rsync no longer erroneously removes the associated
source file.
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
@@ -62,15 +104,34 @@ Changes since 2.6.9:
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- Starting up an extra copy of an rsync daemon will not clobber the pidfile
for the running daemon -- if the pidfile exists, the new daemon will exit
with an error.
- The daemon pidfile is checked and created sooner in the startup sequence.
- If a daemon module's "path" value is not an absolute pathname, the code
now makes it absolute internally (making it work properly).
- Ensure that a temporary file always has owner-write permission while we
are writing to it. This avoids problems with some network filesystems
when transfering read-only files.
- Any errors output about password-file reading no longer cause an error at
the end of the run about a partial transfer.
- The --read-batch option for protocol 30 now ensures that several more
options are set correctly for the current batch file: --iconv, --acls,
--xattrs, --inplace, --append, and --append-verify.
- Using --only-write-batch to a daemon receiver now works properly (older
versions would update some files while writing the batch).
- Avoid outputting a "file has vanished" message when the file is a broken
symlink and --copy-unsafe-links or --copy-dirlinks is used (the code
already handled this for --copy-links).
- Fixed the combination of --only-write-batch and --dry-run.
- Fixed rsync's ability to remove files that are not writable by the file's
owner when rsync is running as the same user.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
@@ -89,8 +150,8 @@ Changes since 2.6.9:
- Rsync now allows multiple remote-source args to be specified rather than
having to rely on a special space-splitting side-effect of the remote-
shell. Additional remote args must specify the same host or an empty one
(e.g. empty: :file1 or ::module/file2). This means that local use of
brace expansion now works: rsync -av host:dir/{f1,f2} .
(e.g. empty: :file1 or ::module/file2). For example, this means that
local use of brace expansion now works: rsync -av host:dir/{f1,f2} .
- Added the --protect-args (-s) option, that tells rsync to send most of
the command-line args at the start of the transfer rather than as args
@@ -103,10 +164,10 @@ Changes since 2.6.9:
- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available, and it even
supports OS X ACLs. If you need to have backward compatibility with old,
acl-patched versions of rsync, apply the acls.diff file from the patches
ACL-patched versions of rsync, apply the acls.diff file from the patches
dir.
- Added the --xattrs (-X) option to preserver extended attributes. This is
- Added the --xattrs (-X) option to preserve extended attributes. This is
an improved version of the prior patch that was available, and it even
supports OS X xattrs (which includes their resource fork data). If you
need to have backward compatibility with old, xattr-patched versions of
@@ -115,24 +176,29 @@ Changes since 2.6.9:
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
It even supports the storing of foreign ACL data on your backup server.
There is also an analogous "fake super" option for an rsync daemon.
There is also an analogous "fake super" parameter for an rsync daemon.
- Added the --iconv option, which allows rsync to convert filenames from
one character-set to another during the transfer. The default is to make
this feature available as long as your system has iconv_open(). If
compilation fails, specify --disable-iconv to configure, and then
one character-set to another during the transfer. The default is to
make this feature available as long as your system has iconv_open().
If compilation fails, specify --disable-iconv to configure, and then
rebuild. If you want rsync to perform character-set conversions by
default, you can specify --enable-iconv=CONVERT_STRING with the default
value for the --iconv option that you wish to use. For example,
"--enable-iconv=." is a good choice. See the rsync manpage for an
explanation of the --iconv option's settings.
- A new daemon config parameter, "charset", lets you control the character-
set that is used during an --iconv transfer to/from a daemon module. You
can also set your daemon to refuse "no-iconv" if you want to force the
client to use an --iconv transfer (requiring an rsync 3.x client).
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress.
file suffixes that will not be compressed when using --compress (-z).
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
The matching routine was also optimized to run more quickly.
The name-matching routine was also optimized to run more quickly.
- The --max-delete option now outputs a warning if it skipped any file
deletions, including a count of how many deletions were skipped. (Older
@@ -158,6 +224,10 @@ Changes since 2.6.9:
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- Rsync checks all the alternate-destination args for validity (e.g.
--link-dest). This lets the user know when they specified a directory
that does not exist.
- If we get an error setting the time on a symlink, we don't complain about
it anymore (since some operating systems don't support that, and it's not
that important).
@@ -172,23 +242,29 @@ Changes since 2.6.9:
compatibility with older rsync versions, any use of --append that is
talking protocol 29 or older will revert to the --append-verify method.
- Added the --contimeout=SECONDS option that lets the user specify a
connection timeout for rsync daemon access.
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
that can be used to enhance the client side of a daemon connection.
- Improved the dashes and double-quotes in the nroff manpage output.
- We now support a lot more --no-OPTION override options.
- Rsync now supports a lot more --no-OPTION override options.
INTERNAL:
- The file-list sorting algorithm now uses a sort that keeps any same-
named items in the same order as they were specified. This allows
rsync to always ensure that the first of the duplicates is the one
that will be included in the copy. The new sort was also faster
than the glibc version of qsort() and mergesort() in my testing.
that will be included in the copy. The new sort is also faster
than the glibc version of qsort() and mergesort().
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Made the file-deletion code use a little less stack when recursing
through a directory hierarchy of extraneous files.
- Fixed a build problem with older (2.x) versions of gcc.
- Added some isType() functions that make dealing with signed characters
@@ -209,26 +285,57 @@ Changes since 2.6.9:
- Make sure that a daemon process doesn't mind if the client was weird and
omitted the --server option.
- There are more internal logging categories available in protocol 30 than
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
categories allow some errors and warnings to go to stderr without causing
an erroneous end-of-run warning about some files not being able to be
transferred.
- Improved the use of "const" on pointers.
- Improved J.W.'s pool_alloc routines to add a way of freeing older
sections of a pool's memory.
- Improved J.W.'s pool_alloc routines to add a way of incrementally freeing
older sections of a pool's memory.
- The getaddrinfo.c compatibility code in the "lib" dir was replaced with
some new code (derived from samba, derived from PostgreSQL) that has a
better license than the old code.
DEVELOPER RELATED:
- Rsync is now licensed under the GPLv3 or later.
- Rsync is now being maintained in a "git" repository instead of CVS
(though the old CVS repository still exists for historical access).
Several maintenance scripts were updated to work with git.
- Generated files are no longer committed into the source repository. The
autoconf and autoheader commands are now automatically run during the
normal use of "configure" and "make". The latest dev versions of all
generated files can also be copied from the samba.org web site (see the
prepare-source script's fetch option).
- The "patches" directory of diff files is now built from branches in the
rsync git repository (branch patch/FOO creates file patches/FOO.diff).
This directory is now distributed in a separate separate tar file named
rsync-patches-VERSION.tar.gz instead of the main rsync-VERSION.tar.gz.
- The proto.h file is now built using a simple perl script rather than a
complex awk script, which proved to be more widely compatible.
- When running the tests, we now put our per-test temp dirs into a sub-
directory named testtmp (which is created, if missing). This allows
someone to symlink the testtmp directory to another filesystem (which is
useful if the build dir's filesystem does not support ACLs and xattrs,
but another file system does).
but another filesystem does).
- Rsync now has a way of handling protocol-version changes during the
development of a new protocol version. This causes any out-of-sync
versions to speak an older protocol rather than fail in a cryptic manner.
This addition makes it safe to deploy a pre-release version that may
This addition makes it safer to deploy a pre-release version that may
interact with the public. This new exchange of sub-version info does not
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
does not have enough range to allow the main protocol number to be
incremented for every minor tweak in that happens during development).
- The csprotocol.txt file was updated to mention the daemon protocol change
in the 3.0.0 release.

View File

@@ -2244,7 +2244,7 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? ??? 2007 3.0.0 11 Nov 2006 30
01 Mar 2008 3.0.0 11 Nov 2006 30
06 Nov 2006 2.6.9 29
22 Apr 2006 2.6.8 29
11 Mar 2006 2.6.7 29

View File

@@ -2,7 +2,7 @@
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

23
aclocal.m4 vendored
View File

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

53
acls.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2006 Wayne Davison
* Copyright (C) 2006-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -92,9 +92,19 @@ static item_list default_acl_list = EMPTY_ITEM_LIST;
static const char *str_acl_type(SMB_ACL_TYPE_T type)
{
return type == SMB_ACL_TYPE_ACCESS ? "SMB_ACL_TYPE_ACCESS"
: type == SMB_ACL_TYPE_DEFAULT ? "SMB_ACL_TYPE_DEFAULT"
: "unknown SMB_ACL_TYPE_T";
switch (type) {
case SMB_ACL_TYPE_ACCESS:
#ifdef HAVE_OSX_ACLS
return "ACL_TYPE_EXTENDED";
#else
return "ACL_TYPE_ACCESS";
#endif
case SMB_ACL_TYPE_DEFAULT:
return "ACL_TYPE_DEFAULT";
default:
break;
}
return "unknown ACL type!";
}
static int calc_sacl_entries(const rsync_acl *racl)
@@ -300,7 +310,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
ida->access = access;
}
if (rc) {
rsyserr(FERROR, errno, "unpack_smb_acl: %s()", errfun);
rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
rsync_acl_free(racl);
return False;
}
@@ -356,7 +366,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
static int store_access_in_entry(uint32 access, SMB_ACL_ENTRY_T entry)
{
if (sys_acl_set_access_bits(entry, access)) {
rsyserr(FERROR, errno, "store_access_in_entry sys_acl_set_access_bits()");
rsyserr(FERROR_XFER, errno, "store_access_in_entry sys_acl_set_access_bits()");
return -1;
}
return 0;
@@ -375,7 +385,7 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
SMB_ACL_ENTRY_T entry;
if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
rsyserr(FERROR, errno, "pack_smb_acl: sys_acl_init()");
rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
return False;
}
@@ -424,14 +434,14 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
#ifdef DEBUG
if (sys_acl_valid(*smb_acl) < 0)
rprintf(FERROR, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
rprintf(FERROR_XFER, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
#endif
return True;
error_exit:
if (errfun) {
rsyserr(FERROR, errno, "pack_smb_acl %s()", errfun);
rsyserr(FERROR_XFER, errno, "pack_smb_acl %s()", errfun);
}
sys_acl_free_acl(*smb_acl);
return False;
@@ -476,8 +486,10 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
if ((buf = get_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, &len)) == NULL)
return 0;
cnt = (len - 4*4) / (4+4);
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4)
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4) {
free(buf);
return -1;
}
racl->user_obj = IVAL(buf, 0);
racl->group_obj = IVAL(buf, 4);
@@ -512,7 +524,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
if (type == SMB_ACL_TYPE_ACCESS)
rsync_acl_fake_perms(racl, mode);
} else {
rsyserr(FERROR, errno, "get_acl: sys_acl_get_file(%s, %s)",
rsyserr(FERROR_XFER, errno, "get_acl: sys_acl_get_file(%s, %s)",
fname, str_acl_type(type));
return -1;
}
@@ -554,7 +566,7 @@ static void send_ida_entries(const ida_entries *idal, int f)
for (ida = idal->idas; count--; ida++) {
uint32 xbits = ida->access << 2;
char *name;
const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
name = add_uid(ida->id);
@@ -653,7 +665,7 @@ static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
access |= NAME_IS_USER;
} else if (am_root >= 0 && access & ~SMB_ACL_VALID_OBJ_BITS) {
value_error:
rprintf(FERROR, "recv_acl_access: value out of range: %x\n",
rprintf(FERROR_XFER, "recv_acl_access: value out of range: %x\n",
access);
exit_cleanup(RERR_STREAMIO);
}
@@ -708,7 +720,7 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > racl_list->count) {
rprintf(FERROR, "recv_acl_index: %s ACL index %d > %d\n",
rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
str_acl_type(type), ndx, (int)racl_list->count);
exit_cleanup(RERR_STREAMIO);
}
@@ -853,7 +865,7 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
if (rc) {
error_exit:
if (errfun) {
rsyserr(FERROR, errno, "change_sacl_perms: %s()",
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
errfun);
}
return (mode_t)~0;
@@ -885,7 +897,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
#endif
rc = sys_acl_delete_def_file(fname);
if (rc < 0) {
rsyserr(FERROR, errno, "set_acl: sys_acl_delete_def_file(%s)",
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
fname);
return -1;
}
@@ -930,8 +942,8 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
}
#endif
if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
rsyserr(FERROR, errno, "set_acl: sys_acl_set_file(%s, %s)",
fname, str_acl_type(type));
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
fname, str_acl_type(type));
return -1;
}
if (type == SMB_ACL_TYPE_ACCESS)
@@ -1050,7 +1062,8 @@ int default_perms_for_dir(const char *dir)
}
/* Otherwise fall through. */
default:
rprintf(FERROR, "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
rprintf(FWARNING,
"default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
dir, str_acl_type(SMB_ACL_TYPE_DEFAULT), strerror(errno));
}
return perms;
@@ -1061,7 +1074,7 @@ int default_perms_for_dir(const char *dir)
ok = unpack_smb_acl(sacl, &racl);
sys_acl_free_acl(sacl);
if (!ok) {
rprintf(FERROR, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
rprintf(FWARNING, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
return perms;
}

View File

@@ -2,7 +2,7 @@
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -163,7 +163,7 @@ static const char *getpassf(const char *filename)
return NULL;
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FERROR, errno, "could not open password file \"%s\"",
rsyserr(FWARNING, errno, "could not open password file \"%s\"",
filename);
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
@@ -171,18 +171,18 @@ static const char *getpassf(const char *filename)
}
if (do_stat(filename, &st) == -1) {
rsyserr(FERROR, errno, "stat(%s)", filename);
rsyserr(FWARNING, errno, "stat(%s)", filename);
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FERROR, "password file must not be other-accessible\n");
rprintf(FWARNING, "password file must not be other-accessible\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
rprintf(FERROR, "password file must be owned by root when running as root\n");
rprintf(FWARNING, "password file must be owned by root when running as root\n");
ok = 0;
}
if (!ok) {
close(fd);
rprintf(FERROR, "continuing without password file\n");
rprintf(FWARNING, "continuing without password file\n");
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;

View File

@@ -2,7 +2,7 @@
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

78
batch.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,15 +31,25 @@ extern int preserve_hard_links;
extern int preserve_devices;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_acls;
extern int preserve_xattrs;
extern int always_checksum;
extern int do_compression;
extern int def_compress_level;
extern int inplace;
extern int append_mode;
extern int protocol_version;
extern char *batch_name;
#ifdef ICONV_OPTION
extern char *iconv_opt;
#endif
extern struct filter_list_struct filter_list;
static int tweaked_compress_level;
int batch_stream_flags;
static int tweaked_append;
static int tweaked_append_verify;
static int tweaked_iconv;
static int *flag_ptr[] = {
&recurse, /* 0 */
@@ -50,7 +60,13 @@ static int *flag_ptr[] = {
&preserve_hard_links, /* 5 */
&always_checksum, /* 6 */
&xfer_dirs, /* 7 (protocol 29) */
&tweaked_compress_level,/* 8 (protocol 29) */
&do_compression, /* 8 (protocol 29) */
&tweaked_iconv, /* 9 (protocol 30) */
&preserve_acls, /* 10 (protocol 30) */
&preserve_xattrs, /* 11 (protocol 30) */
&inplace, /* 12 (protocol 30) */
&tweaked_append, /* 13 (protocol 30) */
&tweaked_append_verify, /* 14 (protocol 30) */
NULL
};
@@ -64,6 +80,12 @@ static char *flag_name[] = {
"--checksum (-c)",
"--dirs (-d)",
"--compress (-z)",
"--iconv",
"--acls (-A)",
"--xattrs (-X)",
"--inplace",
"--append",
"--append-verify",
NULL
};
@@ -71,16 +93,14 @@ void write_stream_flags(int fd)
{
int i, flags;
#if Z_DEFAULT_COMPRESSION == -1
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
#else
#error internal logic error! Fix def_compress_level logic above and below too!
tweaked_append = append_mode == 1;
tweaked_append_verify = append_mode == 2;
#ifdef ICONV_OPTION
tweaked_iconv = iconv_opt != NULL;
#endif
/* Start the batch file with a bitmap of data-stream-affecting
* flags. */
if (protocol_version < 29)
flag_ptr[7] = NULL;
for (i = 0, flags = 0; flag_ptr[i]; i++) {
if (*flag_ptr[i])
flags |= 1 << i;
@@ -90,13 +110,31 @@ void write_stream_flags(int fd)
void read_stream_flags(int fd)
{
int i, flags;
batch_stream_flags = read_int(fd);
}
void check_batch_flags(void)
{
int i;
if (protocol_version < 29)
flag_ptr[7] = NULL;
for (i = 0, flags = read_int(fd); flag_ptr[i]; i++) {
int set = flags & (1 << i) ? 1 : 0;
else if (protocol_version < 30)
flag_ptr[9] = NULL;
tweaked_append = append_mode == 1;
tweaked_append_verify = append_mode == 2;
#ifdef ICONV_OPTION
tweaked_iconv = iconv_opt != NULL;
#endif
for (i = 0; flag_ptr[i]; i++) {
int set = batch_stream_flags & (1 << i) ? 1 : 0;
if (*flag_ptr[i] != set) {
if (i == 9) {
rprintf(FERROR,
"%s specify the --iconv option to use this batch file.\n",
set ? "Please" : "Do not");
exit_cleanup(RERR_SYNTAX);
}
if (verbose) {
rprintf(FINFO,
"%sing the %s option to match the batchfile.\n",
@@ -112,12 +150,10 @@ void read_stream_flags(int fd)
xfer_dirs = 0;
}
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
do_compression = 0;
else {
do_compression = 1;
def_compress_level = tweaked_compress_level - 2;
}
if (tweaked_append)
append_mode = 1;
else if (tweaked_append_verify)
append_mode = 2;
}
static void write_arg(int fd, char *arg)
@@ -179,7 +215,7 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
filename);
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
/* Write argvs info to BATCH.sh file */
@@ -225,6 +261,6 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
rsyserr(FERROR, errno, "Batch file %s write error",
filename);
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
}
}

View File

@@ -2,7 +2,7 @@
* Simple byteorder handling.
*
* Copyright (C) 1992-1995 Andrew Tridgell
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -1,7 +1,7 @@
/*
* End-of-run cleanup helper code used by cleanup.c.
*
* Copyright (C) 2006-2007 Wayne Davison
* Copyright (C) 2006-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -2,7 +2,7 @@
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* Copyright (C) 2005-2007 Wayne Davison
* Copyright (C) 2005-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ extern int am_server;
extern int am_daemon;
extern int io_error;
extern int keep_partial;
extern int log_got_error;
extern int got_xfer_error;
extern char *partial_dir;
extern char *logfile_name;
@@ -78,8 +78,8 @@ void close_all(void)
**/
int cleanup_got_literal = 0;
static char *cleanup_fname;
static char *cleanup_new_fname;
static const char *cleanup_fname;
static const char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd_r, cleanup_fd_w;
static pid_t cleanup_pid = 0;
@@ -139,7 +139,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
const char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
@@ -174,7 +174,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
code = exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
if (io_error & IOERR_GENERAL || got_xfer_error)
code = exit_code = RERR_PARTIAL;
}
@@ -213,7 +213,7 @@ void cleanup_disable(void)
}
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
void cleanup_set(const char *fnametmp, const char *fname, struct file_struct *file,
int fd_r, int fd_w)
{
cleanup_fname = fnametmp;

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -266,7 +266,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
fn, ai->ai_addrlen);
fn, (int)ai->ai_addrlen);
return 1;
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
#include "ifuncs.h"
extern int verbose;
extern int dry_run;
extern int output_motd;
extern int list_only;
extern int am_sender;
@@ -34,11 +35,13 @@ extern int ignore_errors;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int sanitize_paths;
extern int numeric_ids;
extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern int io_timeout;
extern int no_detach;
extern int write_batch;
extern int default_af_hint;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
@@ -52,14 +55,20 @@ extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
extern char curr_dir[];
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
char *auth_user;
int read_only = 0;
int module_id = -1;
int munge_symlinks = 0;
struct chmod_mode_struct *daemon_chmod_modes;
/* module_dirlen is the length of the module_dir string when in daemon
* mode, not chrooted, and the path is not "/"; otherwise 0. */
* mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
* enabled module can have a non-"/" module_dir these days.) */
char *module_dir = NULL;
unsigned int module_dirlen = 0;
@@ -111,6 +120,10 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
set_socket_options(fd, sockopts);
#ifdef ICONV_CONST
setup_iconv();
#endif
ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
return ret ? ret : client_run(fd, fd, -1, argc, argv);
@@ -242,7 +255,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
if (list_only && strncmp(*argv, modname, modlen) == 0
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
else
@@ -352,8 +365,12 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
char *bp = buf, *eob = buf + limit - 1;
while (1) {
if (read(fd, bp, 1) != 1)
int got = read(fd, bp, 1);
if (got != 1) {
if (got < 0 && errno == EINTR)
continue;
return -1;
}
if (*bp == '\0')
break;
if (bp < eob)
@@ -367,7 +384,7 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
{
int argc, opt_cnt;
char **argv;
char **argv, *chroot_path = NULL;
char line[BIGPATHBUFLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
@@ -378,6 +395,13 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
pid_t pre_exec_pid = 0;
char *request = NULL;
#ifdef ICONV_OPTION
iconv_opt = lp_charset(i);
if (*iconv_opt)
setup_iconv();
iconv_opt = NULL;
#endif
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
@@ -460,18 +484,32 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
/* TODO: Perhaps take a list of gids, and make them into the
* supplementary groups. */
/* We do a push_dir() without actually calling chdir() in order
* to make sure that the module's path is absolute. After this
* check, module_dir will be set to an absolute path. */
module_dir = lp_path(i);
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0';
p += 2;
} else if ((p = strdup("/")) == NULL)
out_of_memory("rsync_module");
}
/* We do a push_dir() that doesn't actually call chdir()
* just to make a relative path absolute. */
strlcpy(line, curr_dir, sizeof line);
if (!push_dir(module_dir, 1))
goto chdir_failed;
if (strcmp(curr_dir, module_dir) != 0)
module_dir = strdup(curr_dir);
if (strcmp(curr_dir, module_dir) != 0
&& (module_dir = strdup(curr_dir)) == NULL)
out_of_memory("rsync_module");
push_dir(line, 1); /* Restore curr_dir. */
if (use_chroot || (module_dirlen = strlen(module_dir)) == 1) {
if (use_chroot) {
chroot_path = module_dir;
module_dir = p; /* p is "/" or our inside-chroot path */
}
module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
if (module_dirlen == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
@@ -504,8 +542,17 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (!use_chroot)
p = module_dir;
else if (module_dirlen) {
pathjoin(line, sizeof line, chroot_path, module_dir+1);
p = line;
} else
p = chroot_path;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", module_dir) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", p) < 0
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
@@ -605,13 +652,15 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(module_dir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_dir);
if (chroot(chroot_path)) {
rsyserr(FLOG, errno, "chroot %s failed", chroot_path);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0))
if (!push_dir(module_dir, 0))
goto chdir_failed;
if (module_dirlen)
sanitize_paths = 1;
} else {
if (!push_dir(module_dir, 0)) {
chdir_failed:
@@ -622,6 +671,18 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
sanitize_paths = 1;
}
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
munge_symlinks = !use_chroot || module_dirlen;
if (munge_symlinks) {
STRUCT_STAT st;
if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
SYMLINK_PREFIX);
io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
exit_cleanup(RERR_UNSUPPORTED);
}
}
if (am_root) {
/* XXXX: You could argue that if the daemon is started
* by a non-root user and they explicitly specify a
@@ -681,6 +742,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
am_server = 1; /* Don't let someone try to be tricky. */
if (lp_ignore_errors(module_id))
ignore_errors = 1;
if (write_batch < 0)
dry_run = 1;
if (lp_fake_super(i))
am_root = -1;
@@ -747,6 +810,23 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
exit_cleanup(RERR_UNSUPPORTED);
}
#ifdef ICONV_OPTION
if (!iconv_opt) {
if (ic_send != (iconv_t)-1) {
iconv_close(ic_send);
ic_send = (iconv_t)-1;
}
if (ic_recv != (iconv_t)-1) {
iconv_close(ic_recv);
ic_recv = (iconv_t)-1;
}
}
#endif
if (!numeric_ids
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
set_io_timeout(lp_timeout(i));

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) Andrew Tridgell 1996
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -48,25 +48,31 @@ extern int preserve_acls;
extern int preserve_xattrs;
extern int need_messages_from_generator;
extern int delete_mode, delete_before, delete_during, delete_after;
extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */
extern char *shell_cmd;
extern char *partial_dir;
extern char *dest_option;
extern char *files_from;
extern char *filesfrom_host;
extern struct filter_list_struct filter_list;
extern int need_unsorted_flist;
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
/* These index values are for the file-list's extra-attribute array. */
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx;
#ifdef ICONV_OPTION
int ic_ndx;
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
#ifdef ICONV_OPTION
int filesfrom_convert = 0;
#endif
#define CF_INC_RECURSE (1<<0)
#define CF_SYMLINK_TIMES (1<<1)
static const char *client_info;
/* The server makes sure that if either side only supports a pre-release
* version of a protocol, that both sides must speak a compatible version
* of that protocol for it to be advertised as available. */
@@ -80,8 +86,9 @@ static void check_sub_protocol(void)
int our_sub = 0;
#endif
if (!shell_cmd || !(dot = strchr(shell_cmd, '.'))
|| !(their_protocol = atoi(shell_cmd))
/* client_info starts with VER.SUB string if client is a pre-release. */
if (!(their_protocol = atoi(client_info))
|| !(dot = strchr(client_info, '.'))
|| !(their_sub = atoi(dot+1))) {
#if SUBPROTOCOL_VERSION != 0
if (our_sub)
@@ -104,6 +111,8 @@ static void check_sub_protocol(void)
void set_allow_inc_recurse(void)
{
client_info = shell_cmd ? shell_cmd : "";
if (!recurse || use_qsort)
allow_inc_recurse = 0;
else if (!am_sender
@@ -111,7 +120,7 @@ void set_allow_inc_recurse(void)
|| delay_updates || prune_empty_dirs))
allow_inc_recurse = 0;
else if (am_server && !local_server
&& (!shell_cmd || strchr(shell_cmd, 'i') == NULL))
&& (strchr(client_info, 'i') == NULL))
allow_inc_recurse = 0;
}
@@ -172,6 +181,8 @@ void setup_protocol(int f_out,int f_in)
PROTOCOL_VERSION, am_server? "Server" : "Client");
exit_cleanup(RERR_PROTOCOL);
}
if (read_batch)
check_batch_flags();
if (protocol_version < 30) {
if (append_mode == 1)
@@ -232,11 +243,26 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
} else if (protocol_version >= 30) {
int compat_flags;
if (am_server) {
inc_recurse = allow_inc_recurse;
write_byte(f_out, inc_recurse);
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
write_byte(f_out, compat_flags);
} else
inc_recurse = read_byte(f_in);
compat_flags = read_byte(f_in);
/* The inc_recurse var MUST be set to 0 or 1. */
inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0;
if (am_sender) {
receiver_symlink_times = am_server
? strchr(client_info, 'L') != NULL
: !!(compat_flags & CF_SYMLINK_TIMES);
}
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
else
receiver_symlink_times = 1;
#endif
if (inc_recurse && !allow_inc_recurse) {
/* This should only be able to happen in a batch. */
fprintf(stderr,
@@ -247,10 +273,8 @@ void setup_protocol(int f_out,int f_in)
need_messages_from_generator = 1;
}
#ifdef ICONV_OPTION
if (iconv_opt && (!am_sender || inc_recurse))
ic_ndx = ++file_extra_cnt;
#endif
if (need_unsorted_flist && (!am_sender || inc_recurse))
unsort_ndx = ++file_extra_cnt;
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;

25
configure vendored Executable file
View File

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

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=3.0.0pre4
RSYNC_VERSION=3.0.0
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -123,6 +123,11 @@ else
fi
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
AC_CHECK_PROG(HAVE_YODL2MAN, yodl2man, 1, 0)
if test x$HAVE_YODL2MAN = x1; then
MAKE_MAN=man
fi
AC_ARG_WITH(nobody-group,
AC_HELP_STRING([--with-nobody-group=GROUP],
[set the default unprivileged group (default nobody or nogroup)]),
@@ -435,6 +440,10 @@ dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
AC_CHECK_FUNCS(inet_pton, , [AC_LIBOBJ(lib/inet_pton)])
AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>])
AC_HAVE_TYPE([struct sockaddr_storage], [#include <sys/types.h>
#include <sys/socket.h>])
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
# builtin getaddrinfo if one of the defines don't exist
AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
@@ -448,7 +457,7 @@ AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
#endif],
rsync_cv_HAVE_GETADDR_DEFINES=yes,
rsync_cv_HAVE_GETADDR_DEFINES=no)])
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" -a x"$ac_cv_type_struct_addrinfo" = x"yes"; then
# Tru64 UNIX has getaddrinfo() but has it renamed in libc as
# something else so we must include <netdb.h> to get the
# redefinition.
@@ -459,13 +468,11 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_GETADDRINFO, 1,
[Define to 1 if you have the "getaddrinfo" function.])],
[Define to 1 if you have the "getaddrinfo" function and required types.])],
[AC_MSG_RESULT([no])
AC_LIBOBJ(lib/getaddrinfo)])])
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
else
AC_LIBOBJ(lib/getaddrinfo)
AC_LIBOBJ(lib/getnameinfo)
fi
AC_CHECK_MEMBER([struct sockaddr.sa_len],
@@ -494,15 +501,6 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct sockaddr_storage)
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>],
[struct sockaddr_storage x;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
[Define to 1 if you have struct sockaddr_storage.] ),
AC_MSG_RESULT(no))
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
[],
@@ -512,8 +510,7 @@ AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
#include <netinet/in.h>
])
AC_MSG_CHECKING(struct stat64)
AC_TRY_COMPILE([#include <stdio.h>
AC_HAVE_TYPE([struct stat64], [#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
@@ -528,10 +525,7 @@ AC_TRY_COMPILE([#include <stdio.h>
# include <stdlib.h>
# endif
#endif
],[struct stat64 st;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STRUCT_STAT64,1,[Define to 1 if you have struct stat64.]),
AC_MSG_RESULT(no))
])
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
#
@@ -560,6 +554,11 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask setattrlist)
dnl cygwin iconv.h defines iconv_open as libiconv_open
if test x"$ac_cv_func_iconv_open" != x"yes"; then
AC_CHECK_FUNC(libiconv_open, [ac_cv_func_iconv_open=yes; AC_DEFINE(HAVE_ICONV_OPEN, 1)])
fi
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
@@ -689,13 +688,13 @@ if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [Define to 1 if readdir() is broken])
fi
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_STRUCT_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
rsync_cv_HAVE_STRUCT_UTIMBUF=yes,rsync_cv_HAVE_STRUCT_UTIMBUF=no)])
if test x"$rsync_cv_HAVE_STRUCT_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_STRUCT_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
@@ -824,6 +823,7 @@ AC_SUBST(OBJ_SAVE)
AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_SUBST(BUILD_POPT)
AC_SUBST(MAKE_MAN)
AC_CHECK_HEADERS(sys/acl.h acl/libacl.h)
AC_CHECK_FUNCS(_acl __acl _facl __facl)

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
* Error codes returned by rsync.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,6 +45,7 @@
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
#define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */
/* Although it doesn't seem to be specified anywhere,
* ssh and the shell seem to return these values:

View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,7 +26,6 @@ extern int verbose;
extern int am_server;
extern int am_sender;
extern int eol_nulls;
extern int recurse;
extern int io_error;
extern int local_server;
extern int prune_empty_dirs;
@@ -296,7 +295,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
strlcpy(to, merge_file, *len_ptr + 1);
merge_file = to;
}
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
return NULL;
@@ -304,7 +303,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
fn_len = strlen(fn);
} else {
strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
fn_len = clean_fname(fn, 1);
fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS);
}
/* If the name isn't in buf yet, it's wasn't absolute. */
@@ -315,7 +314,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
fn_len = clean_fname(buf, 1);
fn_len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
}
if (len_ptr)
@@ -337,7 +336,7 @@ void set_filter_dir(const char *dir, unsigned int dirlen)
len = 0;
memcpy(dirbuf + len, dir, dirlen);
dirbuf[dirlen + len] = '\0';
dirbuf_len = clean_fname(dirbuf, 1);
dirbuf_len = clean_fname(dirbuf, CFN_COLLAPSE_DOT_DOT_DIRS);
if (dirbuf_len > 1 && dirbuf[dirbuf_len-1] == '.'
&& dirbuf[dirbuf_len-2] == '/')
dirbuf_len -= 2;
@@ -373,7 +372,7 @@ static BOOL setup_merge_file(struct filter_struct *ex,
else
pathjoin(buf, MAXPATHLEN, dirbuf, x);
len = clean_fname(buf, 1);
len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
if (len != 1 && len < MAXPATHLEN-1) {
buf[len++] = '/';
buf[len] = '\0';
@@ -1012,7 +1011,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
if (*fname != '-' || fname[1] || am_server) {
if (server_filter_list.head) {
strlcpy(line, fname, sizeof line);
clean_fname(line, 1);
clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&server_filter_list, line, 0) < 0)
fp = NULL;
else

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

390
flist.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,6 +44,8 @@ extern int filesfrom_fd;
extern int one_file_system;
extern int copy_dirlinks;
extern int keep_dirlinks;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_acls;
extern int preserve_xattrs;
extern int preserve_links;
@@ -63,6 +65,9 @@ extern int copy_links;
extern int copy_unsafe_links;
extern int protocol_version;
extern int sanitize_paths;
extern int munge_symlinks;
extern int need_unsorted_flist;
extern int unsort_ndx;
extern struct stats stats;
extern char *filesfrom_host;
@@ -74,9 +79,7 @@ extern struct filter_list_struct filter_list;
extern struct filter_list_struct server_filter_list;
#ifdef ICONV_OPTION
extern int ic_ndx;
extern int filesfrom_convert;
extern int need_unsorted_flist;
extern iconv_t ic_send, ic_recv;
#endif
@@ -87,11 +90,15 @@ int checksum_len;
dev_t filesystem_dev; /* used to implement -x */
struct file_list *cur_flist, *first_flist, *dir_flist;
int send_dir_ndx = -1, send_dir_depth = 0;
int send_dir_ndx = -1, send_dir_depth = -1;
int flist_cnt = 0; /* how many (non-tmp) file list objects exist */
int file_total = 0; /* total of all active items over all file-lists */
int flist_eof = 0; /* all the file-lists are now known */
#define NORMAL_NAME 0
#define SLASH_ENDING_NAME 1
#define DOT_NAME 2
/* Starting from protocol version 26, we always use 64-bit ino_t and dev_t
* internally, even if this platform does not allow files to have 64-bit inums.
* The only exception is if we're on a platform with no 64-bit type at all.
@@ -116,9 +123,8 @@ static char tmp_sum[MAX_DIGEST_LEN];
static char empty_sum[MAX_DIGEST_LEN];
static int flist_count_offset; /* for --delete --progress */
static int dir_count = 0;
static int high_hlink_ndx;
static void clean_flist(struct file_list *flist, int strip_root);
static void flist_sort_and_clean(struct file_list *flist, int strip_root);
static void output_flist(struct file_list *flist);
void init_flist(void)
@@ -196,6 +202,11 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf)
}
return x_stat(path, stp, NULL);
}
if (munge_symlinks && am_sender && llen > SYMLINK_PREFIX_LEN
&& strncmp(linkbuf, SYMLINK_PREFIX, SYMLINK_PREFIX_LEN) == 0) {
memmove(linkbuf, linkbuf + SYMLINK_PREFIX_LEN,
llen - SYMLINK_PREFIX_LEN + 1);
}
}
return 0;
#else
@@ -342,7 +353,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
static uint32 rdev_major;
static uid_t uid;
static gid_t gid;
static char *user_name, *group_name;
static const char *user_name, *group_name;
static char lastname[MAXPATHLEN];
char fname[MAXPATHLEN];
int first_hlink_ndx = -1;
@@ -380,6 +391,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
/* Initialize starting value of xflags. */
if (protocol_version >= 30 && S_ISDIR(file->mode)) {
dir_count++;
if (file->flags & FLAG_CONTENT_DIR)
xflags = file->flags & FLAG_TOP_DIR;
else if (file->flags & FLAG_IMPLIED_DIR)
@@ -412,24 +424,24 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
}
} else if (protocol_version < 28)
rdev = MAKEDEV(0, 0);
if (uid_ndx) {
if (preserve_uid) {
if ((uid_t)F_OWNER(file) == uid && *lastname)
xflags |= XMIT_SAME_UID;
else {
uid = F_OWNER(file);
if (uid_ndx && !numeric_ids) {
if (!numeric_ids) {
user_name = add_uid(uid);
if (inc_recurse && user_name)
xflags |= XMIT_USER_NAME_FOLLOWS;
}
}
}
if (gid_ndx) {
if (preserve_gid) {
if ((gid_t)F_GROUP(file) == gid && *lastname)
xflags |= XMIT_SAME_GID;
else {
gid = F_GROUP(file);
if (gid_ndx && !numeric_ids) {
if (!numeric_ids) {
group_name = add_gid(gid);
if (inc_recurse && group_name)
xflags |= XMIT_GROUP_NAME_FOLLOWS;
@@ -447,8 +459,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino);
first_hlink_ndx = (int32)(long)np->data - 1;
if (first_hlink_ndx < 0) {
high_hlink_ndx = ndx + first_ndx;
np->data = (void*)(long)(high_hlink_ndx + 1);
np->data = (void*)(long)(first_ndx + ndx + 1);
xflags |= XMIT_HLINK_FIRST;
}
xflags |= XMIT_HLINKED;
@@ -513,7 +524,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
}
if (!(xflags & XMIT_SAME_MODE))
write_int(f, to_wire_mode(mode));
if (uid_ndx && !(xflags & XMIT_SAME_UID)) {
if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
if (protocol_version < 30)
write_int(f, uid);
else {
@@ -525,7 +536,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
}
}
}
if (gid_ndx && !(xflags & XMIT_SAME_GID)) {
if (preserve_gid && !(xflags & XMIT_SAME_GID)) {
if (protocol_version < 30)
write_int(f, gid);
else {
@@ -667,7 +678,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
clean_fname(thisname, 0);
if (sanitize_paths)
sanitize_path(thisname, thisname, "", 0, NULL);
sanitize_path(thisname, thisname, "", 0);
if ((basename = strrchr(thisname, '/')) != NULL) {
int len = basename++ - thisname;
@@ -697,9 +708,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
file_length = F_LENGTH(first);
modtime = first->modtime;
mode = first->mode;
if (uid_ndx)
if (preserve_uid)
uid = F_OWNER(first);
if (gid_ndx)
if (preserve_gid)
gid = F_GROUP(first);
if ((preserve_devices && IS_DEVICE(mode))
|| (preserve_specials && IS_SPECIAL(mode))) {
@@ -721,8 +732,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (protocol_version >= 30) {
modtime = read_varlong(f, 4);
#if SIZEOF_TIME_T < SIZEOF_INT64
if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) {
rprintf(FERROR,
if (!am_generator && (int64)(time_t)modtime != modtime) {
rprintf(FERROR_XFER,
"Time value of %s truncated on receiver.\n",
lastname);
}
@@ -736,7 +747,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (chmod_modes && !S_ISLNK(mode))
mode = tweak_mode(mode, chmod_modes);
if (uid_ndx && !(xflags & XMIT_SAME_UID)) {
if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
if (protocol_version < 30)
uid = (uid_t)read_int(f);
else {
@@ -747,7 +758,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
uid = match_uid(uid);
}
}
if (gid_ndx && !(xflags & XMIT_SAME_GID)) {
if (preserve_gid && !(xflags & XMIT_SAME_GID)) {
if (protocol_version < 30)
gid = (gid_t)read_int(f);
else {
@@ -790,6 +801,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
linkname_len - 1);
overflow_exit("recv_file_entry");
}
if (munge_symlinks)
linkname_len += SYMLINK_PREFIX_LEN;
}
else
#endif
@@ -817,11 +830,6 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
extra_len += EXTRA_LEN;
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
#endif
if (inc_recurse && S_ISDIR(mode)) {
if (one_file_system) {
/* Room to save the dir's device for -x */
@@ -831,6 +839,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
} else
pool = flist->file_pool;
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
#endif
alloc_len = FILE_STRUCT_LEN + extra_len + basename_len
+ linkname_len;
bp = pool_alloc(pool, alloc_len, "recv_file_entry");
@@ -854,16 +867,14 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
}
file->mode = mode;
if (uid_ndx)
if (preserve_uid)
F_OWNER(file) = uid;
if (gid_ndx) {
if (preserve_gid) {
F_GROUP(file) = gid;
file->flags |= gid_flags;
}
#ifdef ICONV_OPTION
if (ic_ndx)
if (unsort_ndx)
F_NDX(file) = flist->used + flist->ndx_start;
#endif
if (basename != thisname) {
file->dirname = lastdir;
@@ -912,10 +923,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (first_hlink_ndx >= flist->ndx_start) {
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
memcpy(bp, F_SYMLINK(first), linkname_len);
} else
} else if (munge_symlinks) {
strlcpy(bp, SYMLINK_PREFIX, linkname_len);
bp += SYMLINK_PREFIX_LEN;
linkname_len -= SYMLINK_PREFIX_LEN;
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths)
sanitize_path(bp, bp, "", lastdir_depth, NULL);
} else {
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths)
sanitize_path(bp, bp, "", lastdir_depth);
}
}
#endif
@@ -923,8 +940,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (preserve_hard_links && xflags & XMIT_HLINKED) {
if (protocol_version >= 30) {
if (xflags & XMIT_HLINK_FIRST) {
high_hlink_ndx = flist->ndx_start + flist->used;
F_HL_GNUM(file) = high_hlink_ndx;
F_HL_GNUM(file) = flist->ndx_start + flist->used;
} else
F_HL_GNUM(file) = first_hlink_ndx;
} else {
@@ -1006,7 +1022,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
}
clean_fname(thisname, 0);
if (sanitize_paths)
sanitize_path(thisname, thisname, "", 0, NULL);
sanitize_path(thisname, thisname, "", 0);
if (stp && S_ISDIR(stp->st_mode)) {
st = *stp; /* Needed for "symlink/." with --relative. */
@@ -1023,24 +1039,30 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
}
if (save_errno == ENOENT) {
#ifdef SUPPORT_LINKS
/* Avoid "vanished" error if symlink points nowhere. */
if (copy_links && x_lstat(thisname, &st, NULL) == 0
&& S_ISLNK(st.st_mode)) {
/* When our options tell us to follow a symlink that
* points nowhere, tell the user about the symlink
* instead of giving a "vanished" message. We only
* dereference a symlink if one of the --copy*links
* options was specified, so there's no need for the
* extra lstat() if one of these options isn't on. */
if ((copy_links || copy_unsafe_links || copy_dirlinks)
&& x_lstat(thisname, &st, NULL) == 0
&& S_ISLNK(st.st_mode)) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "symlink has no referent: %s\n",
rprintf(FERROR_XFER, "symlink has no referent: %s\n",
full_fname(thisname));
} else
#endif
{
enum logcode c = am_daemon && protocol_version < 28
? FERROR : FINFO;
? FERROR : FWARNING;
io_error |= IOERR_VANISHED;
rprintf(c, "file has vanished: %s\n",
full_fname(thisname));
}
} else {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, save_errno, "readlink %s failed",
rsyserr(FERROR_XFER, save_errno, "readlink %s failed",
full_fname(thisname));
}
return NULL;
@@ -1058,20 +1080,18 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
/* -x only affects dirs because we need to avoid recursing
* into a mount-point directory, not to avoid copying a
* symlinked file if -L (or similar) was specified. */
if (one_file_system && flags & FLAG_CONTENT_DIR) {
if (flags & FLAG_TOP_DIR)
filesystem_dev = st.st_dev;
else if (st.st_dev != filesystem_dev) {
if (one_file_system > 1) {
if (verbose > 1) {
rprintf(FINFO,
"[%s] skipping mount-point dir %s\n",
who_am_i(), thisname);
}
return NULL;
if (one_file_system && st.st_dev != filesystem_dev
&& BITS_SETnUNSET(flags, FLAG_CONTENT_DIR, FLAG_TOP_DIR)) {
if (one_file_system > 1) {
if (verbose > 1) {
rprintf(FINFO,
"[%s] skipping mount-point dir %s\n",
who_am_i(), thisname);
}
flags |= FLAG_MOUNT_DIR;
return NULL;
}
flags |= FLAG_MOUNT_DIR;
flags &= ~FLAG_CONTENT_DIR;
}
} else
flags &= ~FLAG_CONTENT_DIR;
@@ -1100,7 +1120,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
extra_len += DIRNODE_EXTRA_CNT * EXTRA_LEN;
if (relative_paths)
extra_len += PTR_EXTRA_CNT * EXTRA_LEN;
dir_count++;
pool = dir_flist->file_pool;
} else
pool = flist->file_pool;
@@ -1182,9 +1201,9 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
}
file->mode = st.st_mode;
if (uid_ndx)
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
F_OWNER(file) = st.st_uid;
if (gid_ndx)
if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
F_GROUP(file) = st.st_gid;
if (basename != thisname)
@@ -1221,13 +1240,14 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
file->mode = save_mode;
}
if (basename_len == 0+1)
if (basename_len == 0+1) {
if (!pool)
unmake_file(file);
return NULL;
}
#ifdef ICONV_OPTION
if (ic_ndx)
F_NDX(file) = dir_count - 1;
#endif
if (unsort_ndx)
F_NDX(file) = dir_count;
return file;
}
@@ -1312,7 +1332,7 @@ static void send_if_directory(int f, struct file_list *flist,
fbuf[--len] = '\0';
if (len >= MAXPATHLEN - 1) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "skipping long-named directory: %s\n",
rprintf(FERROR_XFER, "skipping long-named directory: %s\n",
full_fname(fbuf));
return;
}
@@ -1413,6 +1433,9 @@ static void add_dirs_to_tree(int parent_ndx, struct file_list *from_flist,
dir_flist->files[dir_flist->used++] = file;
dir_cnt--;
if (file->basename[0] == '.' && file->basename[1] == '\0')
continue;
if (dp)
DIR_NEXT_SIBLING(dp) = dir_flist->used - 1;
else if (parent_dp)
@@ -1448,7 +1471,7 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
if (!(d = opendir(fbuf))) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "opendir %s failed", full_fname(fbuf));
rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf));
return;
}
@@ -1485,7 +1508,7 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
if (errno) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "readdir(%s)", full_fname(fbuf));
rsyserr(FERROR_XFER, errno, "readdir(%s)", full_fname(fbuf));
}
closedir(d);
@@ -1503,15 +1526,17 @@ static int lastpath_len = 0;
static struct file_struct *lastpath_struct;
static void send_implied_dirs(int f, struct file_list *flist, char *fname,
char *start, char *limit, int flags, int is_dot_dir)
char *start, char *limit, int flags, char name_type)
{
struct file_struct *file;
item_list *relname_list;
relnamecache **rnpp;
char *slash;
int len, need_new_dir;
struct filter_list_struct save_filter_list = filter_list;
flags = (flags | FLAG_IMPLIED_DIR) & ~(FLAG_TOP_DIR | FLAG_CONTENT_DIR);
filter_list.head = filter_list.tail = NULL; /* Don't filter implied dirs. */
if (inc_recurse) {
if (lastpath_struct && F_PATHNAME(lastpath_struct) == pathname
@@ -1553,11 +1578,11 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
xfer_dirs = save_xfer_dirs;
if (!inc_recurse)
return;
goto done;
}
if (!lastpath_struct)
return; /* dir must have vanished */
goto done; /* dir must have vanished */
len = strlen(limit+1);
memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list);
@@ -1569,8 +1594,11 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32);
if (!(*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len)))
out_of_memory("send_implied_dirs");
(*rnpp)->is_dot_dir = is_dot_dir;
(*rnpp)->name_type = name_type;
strlcpy((*rnpp)->fname, limit+1, len + 1);
done:
filter_list = save_filter_list;
}
static void send1extra(int f, struct file_struct *file, struct file_list *flist)
@@ -1590,8 +1618,19 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
change_local_filter_dir(fbuf, dlen, send_dir_depth);
if (BITS_SETnUNSET(file->flags, FLAG_CONTENT_DIR, FLAG_MOUNT_DIR))
if (file->flags & FLAG_CONTENT_DIR) {
if (one_file_system) {
STRUCT_STAT st;
if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
return;
}
filesystem_dev = st.st_dev;
}
send_directory(f, flist, fbuf, dlen, flags);
}
if (!relative_paths)
return;
@@ -1603,7 +1642,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
for (j = 0; j < relname_list->count; j++) {
char *slash;
relnamecache *rnp = ((relnamecache**)relname_list->items)[j];
int is_dot_dir = rnp->is_dot_dir;
char name_type = rnp->name_type;
fbuf[dlen] = '/';
len = strlcpy(fbuf + dlen + 1, rnp->fname, sizeof fbuf - dlen - 1);
@@ -1613,15 +1652,15 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
slash = strchr(fbuf+dlen+1, '/');
if (slash) {
send_implied_dirs(f, flist, fbuf, fbuf+dlen+1, slash, flags, is_dot_dir);
send_implied_dirs(f, flist, fbuf, fbuf+dlen+1, slash, flags, name_type);
continue;
}
if (is_dot_dir) {
if (name_type != NORMAL_NAME) {
STRUCT_STAT st;
if (link_stat(fbuf, &st, 1) != 0) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "link_stat %s failed",
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
continue;
}
@@ -1638,19 +1677,17 @@ void send_extra_file_list(int f, int at_least)
struct file_list *flist;
int64 start_write;
uint16 prev_flags;
int future_cnt, save_io_error = io_error;
int old_cnt, save_io_error = io_error;
if (flist_eof)
return;
/* Keep sending data until we have the requested number of
* files in the upcoming file-lists. */
if (cur_flist->next) {
flist = first_flist->prev; /* the newest flist */
future_cnt = flist->ndx_end - cur_flist->next->ndx_start + 1;
} else
future_cnt = 0;
while (future_cnt < at_least) {
old_cnt = cur_flist->used;
for (flist = first_flist; flist != cur_flist; flist = flist->next)
old_cnt += flist->used;
while (file_total - old_cnt < at_least) {
struct file_struct *file = dir_flist->sorted[send_dir_ndx];
int dir_ndx, dstart = dir_count;
const char *pathname = F_PATHNAME(file);
@@ -1659,11 +1696,9 @@ void send_extra_file_list(int f, int at_least)
flist = flist_new(0, "send_extra_file_list");
start_write = stats.total_written;
#ifdef ICONV_OPTION
if (ic_ndx)
if (unsort_ndx)
dir_ndx = F_NDX(file);
else
#endif
dir_ndx = send_dir_ndx;
write_ndx(f, NDX_FLIST_OFFSET - dir_ndx);
flist->parent_ndx = dir_ndx;
@@ -1689,26 +1724,20 @@ void send_extra_file_list(int f, int at_least)
write_byte(f, 0);
#ifdef ICONV_OPTION
if (need_unsorted_flist) {
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
out_of_memory("send_extra_file_list");
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
} else
#endif
flist->sorted = flist->files;
clean_flist(flist, 0);
flist->ndx_end = flist->ndx_start + flist->used - 1
- (dir_count - dstart);
flist_sort_and_clean(flist, 0);
add_dirs_to_tree(send_dir_ndx, flist, dir_count - dstart);
flist_done_allocating(flist);
file_total += flist->used;
future_cnt += flist->used;
stats.flist_size += stats.total_written - start_write;
stats.num_files += flist->used;
if (verbose > 3)
@@ -1785,7 +1814,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
disable_buffering = io_start_buffering_out(f);
if (filesfrom_fd >= 0) {
if (argv[0] && !push_dir(argv[0], 0)) {
rsyserr(FERROR, errno, "push_dir %s failed in %s",
rsyserr(FERROR_XFER, errno, "push_dir %s failed in %s",
full_fname(argv[0]), curr_dir);
exit_cleanup(RERR_FILESELECT);
}
@@ -1793,37 +1822,35 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
}
while (1) {
char fbuf[MAXPATHLEN];
char *fn;
int is_dot_dir;
char fbuf[MAXPATHLEN], *fn, name_type;
if (use_ff_fd) {
if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0)
break;
sanitize_path(fbuf, fbuf, "", 0, NULL);
sanitize_path(fbuf, fbuf, "", 0);
} else {
if (argc-- == 0)
break;
strlcpy(fbuf, *argv++, MAXPATHLEN);
if (sanitize_paths)
sanitize_path(fbuf, fbuf, "", 0, NULL);
sanitize_path(fbuf, fbuf, "", 0);
}
len = strlen(fbuf);
if (relative_paths) {
/* We clean up fbuf below. */
is_dot_dir = 0;
name_type = NORMAL_NAME;
} else if (!len || fbuf[len - 1] == '/') {
if (len == 2 && fbuf[0] == '.') {
/* Turn "./" into just "." rather than "./." */
fbuf[1] = '\0';
fbuf[--len] = '\0';
} else {
if (len + 1 >= MAXPATHLEN)
overflow_exit("send_file_list");
fbuf[len++] = '.';
fbuf[len] = '\0';
}
is_dot_dir = 1;
name_type = DOT_NAME;
} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
&& (len == 2 || fbuf[len-3] == '/')) {
if (len + 2 >= MAXPATHLEN)
@@ -1831,11 +1858,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
fbuf[len++] = '/';
fbuf[len++] = '.';
fbuf[len] = '\0';
is_dot_dir = 1;
} else {
is_dot_dir = fbuf[len-1] == '.'
&& (len == 1 || fbuf[len-2] == '/');
}
name_type = DOT_NAME;
} else if (fbuf[len-1] == '.' && (len == 1 || fbuf[len-2] == '/'))
name_type = DOT_NAME;
else
name_type = NORMAL_NAME;
dir = NULL;
@@ -1858,36 +1885,29 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
dir = "/";
else
dir = fbuf;
len -= p - fbuf + 3;
fn = p + 3;
while (*fn == '/')
fn++;
if (!*fn)
*--fn = '\0'; /* ensure room for '.' */
} else
fn = fbuf;
/* Get rid of trailing "/" and "/.". */
while (len) {
if (fn[len - 1] == '/') {
is_dot_dir = 1;
if (!--len && !dir) {
len++;
break;
}
}
else if (len >= 2 && fn[len - 1] == '.'
&& fn[len - 2] == '/') {
is_dot_dir = 1;
if (!(len -= 2) && !dir) {
len++;
break;
}
} else
break;
}
fn[len] = '\0';
len = clean_fname(fn, CFN_KEEP_LEADING_DOT_DIR
| CFN_KEEP_TRAILING_SLASH
| CFN_DROP_TRAILING_DOT_DIR);
if (len == 1) {
if (fn[0] == '/') {
fn = "/.";
len = 2;
name_type = DOT_NAME;
} else if (fn[0] == '.')
is_dot_dir = 1;
name_type = DOT_NAME;
} else if (fn[len-1] == '/') {
fn[--len] = '\0';
if (len == 1 && *fn == '.')
name_type = DOT_NAME;
else
name_type = SLASH_ENDING_NAME;
}
/* Reject a ".." dir in the active part of the path. */
for (p = fn; (p = strstr(p, "..")) != NULL; p += 2) {
@@ -1895,7 +1915,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
&& (p == fn || p[-1] == '/')) {
rprintf(FERROR,
"found \"..\" dir in relative path: %s\n",
fbuf);
fn);
exit_cleanup(RERR_SYNTAX);
}
}
@@ -1904,7 +1924,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (!*fn) {
len = 1;
fn = ".";
is_dot_dir = 1;
name_type = DOT_NAME;
}
dirlen = dir ? strlen(dir) : 0;
@@ -1919,9 +1939,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (fn != fbuf)
memmove(fbuf, fn, len + 1);
if (link_stat(fbuf, &st, copy_dirlinks || is_dot_dir) != 0) {
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "link_stat %s failed",
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
full_fname(fbuf));
continue;
}
@@ -1933,8 +1953,14 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (inc_recurse && relative_paths && *fbuf) {
if ((p = strchr(fbuf+1, '/')) != NULL) {
send_implied_dirs(f, flist, fbuf, fbuf, p, flags, is_dot_dir);
continue;
if (p - fbuf == 1 && *fbuf == '.') {
if ((fn = strchr(p+1, '/')) != NULL)
p = fn;
} else
fn = p;
send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
if (fn == p)
continue;
}
} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
/* Send the implied directories at the start of the
@@ -1952,12 +1978,23 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
send_implied_dirs(f, flist, fbuf, slash, p, flags, 0);
}
if (recurse || (xfer_dirs && is_dot_dir)) {
if (one_file_system)
filesystem_dev = st.st_dev;
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
struct file_struct *file;
int top_flags = FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags;
file = send_file_name(f, flist, fbuf, &st,
top_flags, ALL_FILTERS);
if (file && !inc_recurse)
if (inc_recurse) {
if (name_type == DOT_NAME && file) {
if (send_dir_depth < 0) {
send_dir_depth = 0;
change_local_filter_dir(fbuf, len, send_dir_depth);
}
send_directory(f, flist, fbuf, len, flags);
}
} else if (file)
send_if_directory(f, flist, file, fbuf, len, flags);
} else
send_file_name(f, flist, fbuf, &st, flags, ALL_FILTERS);
@@ -1992,32 +2029,17 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
* receiving side to ask for whatever name it kept. For incremental
* recursion mode, the sender marks duplicate dirs so that it can
* send them together in a single file-list. */
#ifdef ICONV_OPTION
if (need_unsorted_flist) {
if (inc_recurse) {
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
out_of_memory("send_file_list");
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
clean_flist(flist, 0);
} else {
flist->sorted = flist->files;
flist->low = 0;
flist->high = flist->used - 1;
}
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
out_of_memory("send_file_list");
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
} else
#endif
{
flist->sorted = flist->files;
clean_flist(flist, 0);
}
flist_sort_and_clean(flist, 0);
file_total += flist->used;
/* We don't subtract dir_count for the first send since we
* might have one or more dot dirs which need to get sent. */
flist->ndx_end = flist->ndx_start + flist->used - 1;
if (!numeric_ids && !inc_recurse)
if (numeric_ids <= 0 && !inc_recurse)
send_id_list(f);
/* send the io_error flag */
@@ -2039,7 +2061,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
rprintf(FINFO, "send_file_list done\n");
if (inc_recurse) {
send_dir_depth = 1;
add_dirs_to_tree(-1, flist, dir_count);
if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
flist->parent_ndx = -1;
flist_done_allocating(flist);
if (send_dir_ndx < 0) {
write_ndx(f, NDX_FLIST_EOF);
@@ -2079,7 +2104,7 @@ struct file_list *recv_file_list(int f)
flist = flist_new(0, "recv_file_list");
if (inc_recurse) {
if (flist->ndx_start == 0)
if (flist->ndx_start == 1)
dir_flist = flist_new(FLIST_TEMP, "recv_file_list");
dstart = dir_flist->used;
} else {
@@ -2112,17 +2137,12 @@ struct file_list *recv_file_list(int f)
}
file_total += flist->used;
flist->ndx_end = flist->ndx_start + flist->used - 1;
if (inc_recurse && flist->ndx_start)
flist->ndx_end -= dir_flist->used - dstart;
if (verbose > 2)
rprintf(FINFO, "received %d names\n", flist->used);
if (show_filelist_p())
finish_filelist_progress(flist);
#ifdef ICONV_OPTION
if (need_unsorted_flist) {
/* Create an extra array of index pointers that we can sort for
* the generator's use (for wading through the files in sorted
@@ -2134,16 +2154,18 @@ struct file_list *recv_file_list(int f)
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
if (inc_recurse && dir_flist->used > dstart) {
dir_flist->sorted = realloc_array(dir_flist->sorted,
struct file_struct *,
dir_flist->used);
static int dir_flist_malloced = 0;
if (dir_flist_malloced < dir_flist->malloced) {
dir_flist->sorted = realloc_array(dir_flist->sorted,
struct file_struct *,
dir_flist->malloced);
dir_flist_malloced = dir_flist->malloced;
}
memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
(dir_flist->used - dstart) * sizeof (struct file_struct*));
fsort(dir_flist->sorted + dstart, dir_flist->used - dstart);
}
} else
#endif
{
} else {
flist->sorted = flist->files;
if (inc_recurse && dir_flist->used > dstart) {
dir_flist->sorted = dir_flist->files;
@@ -2156,7 +2178,7 @@ struct file_list *recv_file_list(int f)
else if (f >= 0)
recv_id_list(f, flist);
clean_flist(flist, relative_paths);
flist_sort_and_clean(flist, relative_paths);
if (protocol_version < 30) {
/* Recv the io_error flag */
@@ -2164,6 +2186,9 @@ struct file_list *recv_file_list(int f)
read_int(f);
else
io_error |= read_int(f);
} else if (inc_recurse && flist->ndx_start == 1) {
if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
flist->parent_ndx = -1;
}
if (verbose > 3)
@@ -2293,16 +2318,19 @@ struct file_list *flist_new(int flags, char *msg)
if (!flist->file_pool)
out_of_memory(msg);
flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0;
first_flist = cur_flist = flist->prev = flist;
} else {
struct file_list *prev = first_flist->prev;
flist->file_pool = first_flist->file_pool;
flist->ndx_start = first_flist->prev->ndx_end + 2;
if (flist->ndx_start <= high_hlink_ndx)
flist->ndx_start = high_hlink_ndx + 1;
flist->ndx_start = prev->ndx_start + prev->used + 1;
flist->flist_num = prev->flist_num + 1;
flist->prev = first_flist->prev;
flist->prev->next = first_flist->prev = flist;
flist->prev = prev;
prev->next = first_flist->prev = flist;
}
flist->pool_boundary = pool_boundary(flist->file_pool, 0);
flist_cnt++;
@@ -2348,7 +2376,7 @@ void flist_free(struct file_list *flist)
/* This routine ensures we don't have any duplicate names in our file list.
* duplicate names can cause corruption because of the pipelining. */
static void clean_flist(struct file_list *flist, int strip_root)
static void flist_sort_and_clean(struct file_list *flist, int strip_root)
{
char fbuf[MAXPATHLEN];
int i, prev_i;
@@ -2528,10 +2556,10 @@ static void output_flist(struct file_list *flist)
const char *who = who_am_i();
int i;
rprintf(FINFO, "[%s] flist start=%d, end=%d, used=%d, low=%d, high=%d\n",
who, flist->ndx_start, flist->ndx_end, flist->used, flist->low, flist->high);
rprintf(FINFO, "[%s] flist start=%d, used=%d, low=%d, high=%d\n",
who, flist->ndx_start, flist->used, flist->low, flist->high);
for (i = 0; i < flist->used; i++) {
file = flist->sorted[i];
file = flist->files[i];
if ((am_root || am_sender) && uid_ndx) {
snprintf(uidbuf, sizeof uidbuf, " uid=%u",
F_OWNER(file));
@@ -2779,7 +2807,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
prune_empty_dirs = 0;
dirlist->sorted = dirlist->files;
clean_flist(dirlist, 0);
flist_sort_and_clean(dirlist, 0);
prune_empty_dirs = save_prune_empty_dirs;
if (verbose > 3)

View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@ extern int dry_run;
extern int do_xfers;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int receiver_symlink_times;
extern int am_root;
extern int am_server;
extern int am_daemon;
@@ -41,6 +42,7 @@ extern int preserve_links;
extern int preserve_devices;
extern int preserve_specials;
extern int preserve_hard_links;
extern int preserve_executability;
extern int preserve_perms;
extern int preserve_times;
extern int uid_ndx;
@@ -84,20 +86,19 @@ extern int list_only;
extern int read_batch;
extern int safe_symlinks;
extern long block_size; /* "long" because popt can't set an int32. */
extern int unsort_ndx;
extern int max_delete;
extern int force_delete;
extern int one_file_system;
extern struct stats stats;
extern dev_t filesystem_dev;
extern mode_t orig_umask;
extern uid_t our_uid;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct server_filter_list;
#ifdef ICONV_OPTION
extern int ic_ndx;
#endif
int ignore_perishable = 0;
int non_perishable_cnt = 0;
@@ -115,8 +116,16 @@ static int need_retouch_dir_perms;
static const char *solo_file = NULL;
/* For calling delete_item() and delete_dir_contents(). */
#define DEL_RECURSE (1<<1) /* recurse */
#define DEL_NO_UID_WRITE (1<<0) /* file/dir has our uid w/o write perm */
#define DEL_RECURSE (1<<1) /* if dir, delete all contents */
#define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */
#define DEL_FOR_FILE (1<<3) /* making room for a replacement file */
#define DEL_FOR_DIR (1<<4) /* making room for a replacement dir */
#define DEL_FOR_SYMLINK (1<<5) /* making room for a replacement symlink */
#define DEL_FOR_DEVICE (1<<6) /* making room for a replacement device */
#define DEL_FOR_SPECIAL (1<<7) /* making room for a replacement special */
#define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
enum nonregtype {
TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
@@ -127,8 +136,7 @@ enum delret {
};
/* Forward declaration for delete_item(). */
static enum delret delete_dir_contents(char *fname, int flags);
static enum delret delete_dir_contents(char *fname, uint16 flags);
static int is_backup_file(char *fn)
{
@@ -142,7 +150,7 @@ static int is_backup_file(char *fn)
* Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
* a directory! (The buffer is used for recursion, but returned unchanged.)
*/
static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
{
enum delret ret;
char *what;
@@ -150,20 +158,32 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
if (verbose > 2) {
rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n",
fbuf, mode, flags);
fbuf, (int)mode, (int)flags);
}
if (flags & DEL_NO_UID_WRITE)
do_chmod(fbuf, mode | S_IWUSR);
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
int save_uid_ndx = uid_ndx;
/* This only happens on the first call to delete_item() since
* delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
if (!uid_ndx)
uid_ndx = ++file_extra_cnt;
ignore_perishable = 1;
/* If DEL_RECURSE is not set, this just reports emptiness. */
ret = delete_dir_contents(fbuf, flags);
ignore_perishable = 0;
if (!save_uid_ndx) {
--file_extra_cnt;
uid_ndx = 0;
}
if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
goto check_ret;
/* OK: try to delete the directory. */
}
if (!replace && max_delete >= 0 && ++deletion_count > max_delete)
if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)
return DR_AT_LIMIT;
if (S_ISDIR(mode)) {
@@ -178,7 +198,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
}
if (ok) {
if (!replace)
if (!(flags & DEL_MAKE_ROOM))
log_delete(fbuf, mode);
ret = DR_SUCCESS;
} else {
@@ -197,9 +217,18 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
}
check_ret:
if (replace && ret != DR_SUCCESS) {
rprintf(FERROR, "could not make way for new %s: %s\n",
replace, fbuf);
if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {
const char *desc;
switch (flags & DEL_MAKE_ROOM) {
case DEL_FOR_FILE: desc = "regular file"; break;
case DEL_FOR_DIR: desc = "directory"; break;
case DEL_FOR_SYMLINK: desc = "symlink"; break;
case DEL_FOR_DEVICE: desc = "device file"; break;
case DEL_FOR_SPECIAL: desc = "special file"; break;
default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
}
rprintf(FERROR_XFER, "could not make way for new %s: %s\n",
desc, fbuf);
}
return ret;
}
@@ -209,7 +238,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
* DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The
* buffer is used for recursion, but returned unchanged.)
*/
static enum delret delete_dir_contents(char *fname, int flags)
static enum delret delete_dir_contents(char *fname, uint16 flags)
{
struct file_list *dirlist;
enum delret ret;
@@ -244,7 +273,8 @@ static enum delret delete_dir_contents(char *fname, int flags)
remainder = MAXPATHLEN - (p - fname);
/* We do our own recursion, so make delete_item() non-recursive. */
flags = (flags & ~DEL_RECURSE) | DEL_DIR_IS_EMPTY;
flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM|DEL_NO_UID_WRITE))
| DEL_DIR_IS_EMPTY;
for (j = dirlist->used; j--; ) {
struct file_struct *fp = dirlist->files[j];
@@ -260,11 +290,14 @@ static enum delret delete_dir_contents(char *fname, int flags)
}
strlcpy(p, fp->basename, remainder);
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
do_chmod(fname, fp->mode | S_IWUSR);
/* Save stack by recursing to ourself directly. */
if (S_ISDIR(fp->mode)
&& delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
if (delete_item(fname, fp->mode, NULL, flags) != DR_SUCCESS)
if (S_ISDIR(fp->mode)) {
if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
@@ -303,10 +336,12 @@ static int start_delete_delay_temp(void)
static int flush_delete_delay(void)
{
if (deldelay_fd < 0 && !start_delete_delay_temp())
return 0;
if (write(deldelay_fd, deldelay_buf, deldelay_cnt) != deldelay_cnt) {
rsyserr(FERROR, errno, "flush of delete-delay buffer");
delete_during = 0;
delete_after = 1;
delete_after = !inc_recurse;
close(deldelay_fd);
return 0;
}
@@ -314,18 +349,23 @@ static int flush_delete_delay(void)
return 1;
}
static int remember_delete(struct file_struct *file, const char *fname)
static int remember_delete(struct file_struct *file, const char *fname, int flags)
{
int len;
if (deldelay_cnt == deldelay_size && !flush_delete_delay())
return 0;
if (flags & DEL_NO_UID_WRITE)
deldelay_buf[deldelay_cnt++] = '!';
while (1) {
len = snprintf(deldelay_buf + deldelay_cnt,
deldelay_size - deldelay_cnt,
"%x %s%c", (int)file->mode, fname, '\0');
"%x %s%c",
(int)file->mode, fname, '\0');
if ((deldelay_cnt += len) <= deldelay_size)
break;
if (deldelay_fd < 0 && !start_delete_delay_temp())
return 0;
deldelay_cnt -= len;
if (!flush_delete_delay())
return 0;
@@ -334,7 +374,7 @@ static int remember_delete(struct file_struct *file, const char *fname)
return 1;
}
static int read_delay_line(char *buf)
static int read_delay_line(char *buf, int *flags_p)
{
static int read_pos = 0;
int j, len, mode;
@@ -375,6 +415,11 @@ static int read_delay_line(char *buf)
}
bp = deldelay_buf + read_pos;
if (*bp == '!') {
bp++;
*flags_p = DEL_NO_UID_WRITE;
} else
*flags_p = 0;
if (sscanf(bp, "%x ", &mode) != 1) {
invalid_data:
@@ -399,15 +444,15 @@ static int read_delay_line(char *buf)
static void do_delayed_deletions(char *delbuf)
{
int mode;
int mode, flags;
if (deldelay_fd >= 0) {
if (deldelay_cnt && !flush_delete_delay())
return;
lseek(deldelay_fd, 0, 0);
}
while ((mode = read_delay_line(delbuf)) >= 0)
delete_item(delbuf, mode, NULL, DEL_RECURSE);
while ((mode = read_delay_line(delbuf, &flags)) >= 0)
delete_item(delbuf, mode, flags | DEL_RECURSE);
if (deldelay_fd >= 0)
close(deldelay_fd);
}
@@ -423,6 +468,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
struct file_list *dirlist;
char delbuf[MAXPATHLEN];
int dlen, i;
int save_uid_ndx = uid_ndx;
if (!fbuf) {
change_local_filter_dir(NULL, 0, 0);
@@ -454,6 +500,9 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
return;
}
if (!uid_ndx)
uid_ndx = ++file_extra_cnt;
dirlist = get_dirlist(fbuf, dlen, 0);
/* If an item in dirlist is not found in flist, delete it
@@ -469,16 +518,24 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
continue;
}
if (flist_find(cur_flist, fp) < 0) {
int flags = DEL_RECURSE;
if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
flags |= DEL_NO_UID_WRITE;
f_name(fp, delbuf);
if (delete_during == 2) {
if (!remember_delete(fp, delbuf))
if (!remember_delete(fp, delbuf, flags))
break;
} else
delete_item(delbuf, fp->mode, NULL, DEL_RECURSE);
delete_item(delbuf, fp->mode, flags);
}
}
flist_free(dirlist);
if (!save_uid_ndx) {
--file_extra_cnt;
uid_ndx = 0;
}
}
/* This deletes any files on the receiving side that are not present on the
@@ -517,9 +574,20 @@ static void do_delete_pass(void)
int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
{
#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
if (S_ISLNK(file->mode)) {
;
} else
#endif
if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
return 0;
if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
return 0;
if (preserve_executability && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
return 0;
if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
return 0;
@@ -552,8 +620,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
{
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
int keep_time = !preserve_times ? 0
: S_ISDIR(file->mode) ? preserve_times > 1
: !S_ISLNK(file->mode);
: S_ISDIR(file->mode) ? preserve_times > 1 :
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
(receiver_symlink_times && !(file->flags & FLAG_TIME_FAILED)) ||
#endif
!S_ISLNK(file->mode);
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
iflags |= ITEM_REPORT_SIZE;
@@ -567,7 +638,8 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
;
} else
#endif
if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
if ((preserve_perms || preserve_executability)
&& !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
iflags |= ITEM_REPORT_PERMS;
if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
iflags |= ITEM_REPORT_OWNER;
@@ -830,6 +902,40 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist)
return lowest_j;
}
/* Copy a file found in our --copy-dest handling. */
static int copy_altdest_file(const char *src, const char *dest, struct file_struct *file)
{
char buf[MAXPATHLEN];
const char *copy_to, *partialptr;
int ok, fd_w;
if (inplace) {
/* Let copy_file open the destination in place. */
fd_w = -1;
copy_to = dest;
} else {
fd_w = open_tmpfile(buf, dest, file);
if (fd_w < 0)
return -1;
copy_to = buf;
}
cleanup_set(copy_to, NULL, NULL, -1, -1);
if (copy_file(src, copy_to, fd_w, file->mode, 0) < 0) {
if (verbose) {
rsyserr(FINFO, errno, "copy_file %s => %s",
full_fname(src), copy_to);
}
/* Try to clean up. */
unlink(copy_to);
cleanup_disable();
return -1;
}
partialptr = partial_dir ? partial_dir_fname(dest) : NULL;
ok = finish_transfer(dest, copy_to, src, partialptr, file, 1, 0);
cleanup_disable();
return ok ? 0 : -1;
}
/* This is only called for regular files. We return -2 if we've finished
* handling the file, -1 if no dest-linking occurred, or a non-negative
* value if we found an alternate basis file. */
@@ -859,9 +965,6 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
case 2:
if (!unchanged_attrs(cmpbuf, file, sxp))
continue;
if (always_checksum > 0 && preserve_times
&& cmp_time(sxp->st.st_mtime, file->modtime))
continue;
best_match = j;
match_level = 3;
break;
@@ -886,7 +989,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
goto try_a_copy;
if (preserve_hard_links && F_IS_HLINKED(file))
finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j);
if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
if (!maybe_ATTRS_REPORT && (verbose > 1 || stdout_format_has_i > 1)) {
itemize(cmpbuf, file, ndx, 1, sxp,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
0, "");
@@ -904,20 +1007,10 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
#ifdef SUPPORT_HARD_LINKS
try_a_copy: /* Copy the file locally. */
#endif
if (copy_file(cmpbuf, fname, file->mode, 0) < 0) {
if (verbose) {
rsyserr(FINFO, errno, "copy_file %s => %s",
full_fname(cmpbuf), fname);
}
if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0)
return -1;
}
set_file_attrs(fname, file, NULL, cmpbuf, 0);
if (itemizing)
itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
xattr_clear_locals(file);
#endif
if (maybe_ATTRS_REPORT
&& ((!itemizing && verbose && match_level == 2)
|| (verbose > 1 && match_level == 3))) {
@@ -1049,7 +1142,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
#endif
&& !S_ISDIR(file->mode)) {
if (do_link(cmpbuf, fname) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"failed to hard-link %s with %s",
cmpbuf, fname);
return j;
@@ -1138,38 +1231,40 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
uchar fnamecmp_type;
int implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;
int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;
int is_dir = !S_ISDIR(file->mode) ? 0
: inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1
: 1;
if (verbose > 2)
rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx);
if (list_only) {
if (S_ISDIR(file->mode)
&& ((!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
|| (inc_recurse && ndx != cur_flist->ndx_start - 1)))
if (is_dir < 0
|| (is_dir && !implied_dirs && file->flags & FLAG_IMPLIED_DIR))
return;
list_file_entry(file);
return;
}
if (server_filter_list.head) {
int filtered = check_filter(&server_filter_list, fname, is_dir) < 0;
if (is_dir < 0 && filtered)
return;
if (excluded_below >= 0) {
if (F_DEPTH(file) > excluded_below
&& (!implied_dirs_are_missing || f_name_has_prefix(file, excluded_dir)))
goto skipping;
excluded_below = -1;
}
if (check_filter(&server_filter_list, fname,
S_ISDIR(file->mode)) < 0) {
if (S_ISDIR(file->mode)) {
if (filtered) {
if (is_dir) {
excluded_below = F_DEPTH(file);
excluded_dir = file;
}
skipping:
if (verbose) {
rprintf(FINFO,
"skipping server-excluded file \"%s\"\n",
fname);
}
rprintf(FERROR_XFER,
"skipping daemon-excluded file \"%s\"\n",
fname);
return;
}
}
@@ -1181,7 +1276,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
dry_run--;
missing_below = -1;
} else if (!dry_run) {
if (S_ISDIR(file->mode))
if (is_dir)
file->flags |= FLAG_MISSING_DIR;
return;
}
@@ -1206,7 +1301,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (relative_paths && !implied_dirs
&& do_stat(dn, &sx.st) < 0
&& create_directory_path(fname) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"recv_generator: mkdir %s failed",
full_fname(dn));
}
@@ -1229,18 +1324,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
need_fuzzy_dirlist = 0;
}
statret = link_stat(fname, &sx.st,
keep_dirlinks && S_ISDIR(file->mode));
statret = link_stat(fname, &sx.st, keep_dirlinks && is_dir);
stat_errno = errno;
}
if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {
if (verbose > 1) {
rprintf(FINFO, "not creating new %s \"%s\"\n",
S_ISDIR(file->mode) ? "directory" : "file",
fname);
}
if (S_ISDIR(file->mode)) {
if (is_dir) {
if (is_dir < 0)
return;
if (missing_below < 0) {
if (dry_run)
dry_run++;
@@ -1249,13 +1340,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
file->flags |= FLAG_MISSING_DIR;
}
if (verbose > 1) {
rprintf(FINFO, "not creating new %s \"%s\"\n",
is_dir ? "directory" : "file", fname);
}
return;
}
if (S_ISDIR(file->mode)) {
if (statret == 0 && !(sx.st.st_mode & S_IWUSR)
&& !am_root && sx.st.st_uid == our_uid)
del_opts |= DEL_NO_UID_WRITE;
if (is_dir) {
if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
goto cleanup;
if (inc_recurse && ndx != cur_flist->ndx_start - 1) {
if (is_dir < 0) {
/* In inc_recurse mode we want to make sure any missing
* directories get created while we're still processing
* the parent dir (which allows us to touch the parent
@@ -1263,7 +1362,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
* full later (right before we handle its contents). */
if (statret == 0
&& (S_ISDIR(sx.st.st_mode)
|| delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0))
|| delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
goto cleanup; /* Any errors get reported later. */
if (do_mkdir(fname, file->mode & 0700) == 0)
file->flags |= FLAG_DIR_CREATED;
@@ -1275,7 +1374,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
* we need to delete it. If it doesn't exist, then
* (perhaps recursively) create it. */
if (statret == 0 && !S_ISDIR(sx.st.st_mode)) {
if (delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0)
goto skipping_dir_contents;
statret = -1;
}
@@ -1309,7 +1408,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (!relative_paths || errno != ENOENT
|| create_directory_path(fname) < 0
|| (do_mkdir(fname, file->mode) < 0 && errno != EEXIST)) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"recv_generator: mkdir %s failed",
full_fname(fname));
skipping_dir_contents:
@@ -1332,7 +1431,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) {
mode_t mode = file->mode | S_IWUSR;
if (do_chmod(fname, mode) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"failed to modify permissions on %s",
full_fname(fname));
}
@@ -1394,7 +1493,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
if (itemizing)
itemize(fname, file, ndx, 0, &sx, 0, 0, NULL);
#ifdef SUPPORT_HARD_LINKS
#if defined SUPPORT_HARD_LINKS && defined CAN_HARDLINK_SYMLINK
if (preserve_hard_links && F_IS_HLINKED(file))
finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);
#endif
@@ -1404,7 +1503,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
/* Not the right symlink (or not a symlink), so
* delete it. */
if (delete_item(fname, sx.st.st_mode, "symlink", del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_SYMLINK) != 0)
goto cleanup;
} else if (basis_dir[0] != NULL) {
int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
@@ -1429,7 +1528,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
#endif
if (do_symlink(sl, fname) != 0) {
rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
full_fname(fname), sl);
} else {
set_file_attrs(fname, file, NULL, NULL, 0);
@@ -1458,15 +1557,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
uint32 *devp = F_RDEV_P(file);
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
if (statret == 0) {
char *t;
int del_for_flag;
if (IS_DEVICE(file->mode)) {
if (!IS_DEVICE(sx.st.st_mode))
statret = -1;
t = "device file";
del_for_flag = DEL_FOR_DEVICE;
} else {
if (!IS_SPECIAL(sx.st.st_mode))
statret = -1;
t = "special file";
del_for_flag = DEL_FOR_SPECIAL;
}
if (statret == 0
&& BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
@@ -1483,7 +1582,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
goto return_with_success;
goto cleanup;
}
if (delete_item(fname, sx.st.st_mode, t, del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | del_for_flag) != 0)
goto cleanup;
} else if (basis_dir[0] != NULL) {
int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
@@ -1513,7 +1612,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
(long)major(rdev), (long)minor(rdev));
}
if (do_mknod(fname, file->mode, rdev) < 0) {
rsyserr(FERROR, errno, "mknod %s failed",
rsyserr(FERROR_XFER, errno, "mknod %s failed",
full_fname(fname));
} else {
set_file_attrs(fname, file, NULL, NULL, 0);
@@ -1574,7 +1673,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
fnamecmp_type = FNAMECMP_FNAME;
if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
if (delete_item(fname, sx.st.st_mode, "regular file", del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0)
goto cleanup;
statret = -1;
stat_errno = ENOENT;
@@ -1631,7 +1730,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
#endif
if (stat_errno == ENOENT)
goto notify_others;
rsyserr(FERROR, stat_errno, "recv_generator: failed to stat %s",
rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s",
full_fname(fname));
goto cleanup;
}
@@ -1680,7 +1779,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
goto cleanup;
if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
goto pretend_missing;
if (copy_file(fname, backupptr, back_file->mode, 1) < 0) {
if (copy_file(fname, backupptr, -1, back_file->mode, 1) < 0) {
unmake_file(back_file);
back_file = NULL;
goto cleanup;
@@ -1721,7 +1820,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
goto pretend_missing;
}
if (robust_unlink(backupptr) && errno != ENOENT) {
rsyserr(FERROR, errno, "unlink %s",
rsyserr(FERROR_XFER, errno, "unlink %s",
full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
@@ -1731,7 +1830,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0
&& (errno != ENOENT || make_bak_dir(backupptr) < 0
|| (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) {
rsyserr(FERROR, errno, "open %s",
rsyserr(FERROR_XFER, errno, "open %s",
full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
@@ -1866,57 +1965,63 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
char fbuf[MAXPATHLEN];
int ndx;
while (1) {
#ifdef SUPPORT_HARD_LINKS
while (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
flist = flist_for_ndx(ndx);
assert(flist != NULL);
file = flist->files[ndx - flist->ndx_start];
assert(file->flags & FLAG_HLINKED);
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
flist->in_progress--;
}
if (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
flist = flist_for_ndx(ndx);
assert(flist != NULL);
file = flist->files[ndx - flist->ndx_start];
assert(file->flags & FLAG_HLINKED);
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
flist->in_progress--;
continue;
}
#endif
while (check_redo && (ndx = get_redo_num()) != -1) {
csum_length = SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups; /* avoid dup backup w/inplace */
ignore_times++;
if (check_redo && (ndx = get_redo_num()) != -1) {
csum_length = SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups; /* avoid dup backup w/inplace */
ignore_times++;
flist = cur_flist;
cur_flist = flist_for_ndx(ndx);
flist = cur_flist;
cur_flist = flist_for_ndx(ndx);
file = cur_flist->files[ndx - cur_flist->ndx_start];
if (solo_file)
strlcpy(fbuf, solo_file, sizeof fbuf);
else
f_name(file, fbuf);
recv_generator(fbuf, file, ndx, itemizing, code, sock_f_out);
cur_flist->to_redo--;
file = cur_flist->files[ndx - cur_flist->ndx_start];
if (solo_file)
strlcpy(fbuf, solo_file, sizeof fbuf);
else
f_name(file, fbuf);
recv_generator(fbuf, file, ndx, itemizing, code, sock_f_out);
cur_flist->to_redo--;
cur_flist = flist;
cur_flist = flist;
csum_length = SHORT_SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups;
ignore_times--;
}
csum_length = SHORT_SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups;
ignore_times--;
continue;
}
while (cur_flist != first_flist) { /* only possible with inc_recurse */
if (cur_flist == first_flist)
break;
/* We only get here if inc_recurse is enabled. */
if (first_flist->in_progress || first_flist->to_redo)
break;
@@ -1927,7 +2032,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
if (delete_during == 2 || !dir_tweaking) {
/* Skip directory touch-up. */
} else if (first_flist->ndx_start != 0)
} else if (first_flist->parent_ndx >= 0)
touch_up_dirs(dir_flist, first_flist->parent_ndx);
flist_free(first_flist); /* updates first_flist */
@@ -2002,12 +2107,12 @@ void generate_files(int f_out, const char *local_name)
}
#endif
if (inc_recurse && cur_flist->ndx_start) {
if (inc_recurse && cur_flist->parent_ndx >= 0) {
struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx];
f_name(fp, fbuf);
ndx = cur_flist->ndx_start - 1;
recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
if (delete_during && dry_run < 2) {
if (delete_during && dry_run < 2 && !list_only) {
if (BITS_SETnUNSET(fp->flags, FLAG_CONTENT_DIR, FLAG_MISSING_DIR)) {
dev_t dirdev;
if (one_file_system) {
@@ -2025,11 +2130,9 @@ void generate_files(int f_out, const char *local_name)
if (!F_IS_ACTIVE(file))
continue;
#ifdef ICONV_OPTION
if (ic_ndx)
if (unsort_ndx)
ndx = F_NDX(file);
else
#endif
ndx = i + cur_flist->ndx_start;
if (solo_file)

View File

@@ -3,7 +3,7 @@
* `id -G` on Linux, but it's too hard to find a portable equivalent.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as

View File

@@ -1,7 +1,7 @@
/*
* Routines to provide a memory-efficient hashtable.
*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
struct hashtable *hashtable_create(int size, int key64)
{
struct hashtable *tbl;
int node_size = key64 ? sizeof (struct ht_int64_node )
int node_size = key64 ? sizeof (struct ht_int64_node)
: sizeof (struct ht_int32_node);
/* Pick a power of 2 that can hold the requested size. */
@@ -41,6 +41,7 @@ struct hashtable *hashtable_create(int size, int key64)
tbl->size = size;
tbl->entries = 0;
tbl->node_size = node_size;
tbl->key64 = key64;
return tbl;
}
@@ -55,7 +56,7 @@ void hashtable_destroy(struct hashtable *tbl)
* already existing. Returns NULL if not allocating and not found. */
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
{
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
int key64 = tbl->key64;
struct ht_int32_node *node;
uint32 ndx;

65
hlink.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
extern int verbose;
extern int dry_run;
extern int list_only;
extern int am_sender;
extern int inc_recurse;
extern int do_xfers;
@@ -34,11 +35,9 @@ extern int protocol_version;
extern int remove_source_files;
extern int stdout_format_has_i;
extern int maybe_ATTRS_REPORT;
extern int unsort_ndx;
extern char *basis_dir[];
extern struct file_list *cur_flist;
#ifdef ICONV_OPTION
extern int ic_ndx;
#endif
#ifdef SUPPORT_HARD_LINKS
@@ -144,12 +143,10 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
if (gnum != gnum_next)
break;
F_HL_PREV(file) = prev;
/* The linked list must use raw ndx values. */
#ifdef ICONV_OPTION
if (ic_ndx)
/* The linked list uses over-the-wire ndx values. */
if (unsort_ndx)
prev = F_NDX(file);
else
#endif
prev = ndx_list[from] + hlink_flist->ndx_start;
}
if (prev < 0 && !inc_recurse) {
@@ -163,11 +160,9 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
file->flags |= FLAG_HLINK_LAST;
F_HL_PREV(file) = prev;
if (inc_recurse && CVAL(node->data, 0) == 0) {
#ifdef ICONV_OPTION
if (ic_ndx)
if (unsort_ndx)
prev = F_NDX(file);
else
#endif
prev = ndx_list[from] + hlink_flist->ndx_start;
SIVAL(node->data, 1, prev);
}
@@ -180,23 +175,25 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
int i, ndx_count = 0;
int32 *ndx_list;
if (!list_only) {
int i, ndx_count = 0;
int32 *ndx_list;
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
if (protocol_version < 30)
idev_destroy();
}
@@ -223,7 +220,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
if (!make_backup(fname))
return -1;
} else if (robust_unlink(fname)) {
rsyserr(FERROR, errno, "unlink %s failed",
rsyserr(FERROR_XFER, errno, "unlink %s failed",
full_fname(fname));
return -1;
}
@@ -278,13 +275,13 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
if (!prev_name) {
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
/* Is the previous link is not complete yet? */
/* Is the previous link not complete yet? */
if (!(prev_file->flags & FLAG_HLINK_DONE)) {
/* Is the previous link being transferred? */
if (prev_file->flags & FLAG_FILE_SENT) {
/* Add ourselves to the list of files that will be
* updated when the transfer completes, and mark
* ourself as waiting for the transfer. */
/* Add ourselves to the list of files that will
* be updated when the transfer completes, and
* mark ourself as waiting for the transfer. */
F_HL_PREV(file) = F_HL_PREV(prev_file);
F_HL_PREV(prev_file) = ndx;
file->flags |= FLAG_FILE_SENT;
@@ -323,7 +320,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
}
if (link_stat(prev_name, &prev_st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(prev_name));
return -1;
}
@@ -396,10 +393,10 @@ int hard_link_one(struct file_struct *file, const char *fname,
enum logcode code;
if (terse) {
if (!verbose)
return -1;
return 0;
code = FINFO;
} else
code = FERROR;
code = FERROR_XFER;
rsyserr(code, errno, "link %s => %s failed",
full_fname(fname), oldname);
return 0;
@@ -423,7 +420,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
if (stp == NULL && prev_ndx >= 0) {
if (link_stat(fname, &st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return;
}

View File

@@ -1,6 +1,6 @@
/* Inline functions for rsync.
*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

80
io.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2001 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -100,7 +100,7 @@ static char ff_lastchar;
#ifdef ICONV_OPTION
static xbuf iconv_buf = EMPTY_XBUF;
#endif
static int defer_forwarding_messages = 0;
static int defer_forwarding_messages = 0, defer_forwarding_keep = 0;
static int select_timeout = SELECT_TIMEOUT;
static int active_filecnt = 0;
static OFF_T active_bytecnt = 0;
@@ -413,15 +413,17 @@ static void read_msg_fd(void)
readfd(fd, buf, 4);
got_flist_entry_status(FES_NO_SEND, buf);
break;
case MSG_SOCKERR:
case MSG_ERROR_SOCKET:
case MSG_CLIENT:
if (!am_generator)
goto invalid_msg;
if (tag == MSG_SOCKERR)
if (tag == MSG_ERROR_SOCKET)
io_end_multiplex_out();
/* FALL THROUGH */
case MSG_INFO:
case MSG_ERROR:
case MSG_ERROR_XFER:
case MSG_WARNING:
case MSG_LOG:
while (len) {
n = len;
@@ -440,7 +442,7 @@ static void read_msg_fd(void)
no_flush--;
msg_fd_in = fd;
if (!--defer_forwarding_messages)
if (!--defer_forwarding_messages && !no_flush)
msg_flush();
}
@@ -468,46 +470,41 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len,
char buffer[BIGPATHBUFLEN]; /* Oversized for use by iconv code. */
size_t n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
#ifdef ICONV_OPTION
if (convert && ic_send == (iconv_t)-1)
#endif
convert = 0;
/* We need to convert buf before doing anything else so that we
* can include the (converted) byte length in the message header. */
if (convert && ic_send != (iconv_t)-1) {
xbuf outbuf, inbuf;
if (convert || n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
n = 0;
INIT_XBUF(outbuf, buffer + 4, 0, sizeof buffer - 4);
INIT_XBUF(inbuf, (char*)buf, len, -1);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
if (inbuf.len > 0) {
rprintf(FERROR, "overflowed conversion buffer in mplex_write");
exit_cleanup(RERR_UNSUPPORTED);
}
n = len = outbuf.len;
} else
#endif
if (n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
n = 0; /* We'd rather do 2 writes than too much memcpy(). */
else
memcpy(buffer + 4, buf, n);
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
defer_forwarding_keep = 1; /* defer_forwarding_messages++ on return */
writefd_unbuffered(fd, buffer, n+4);
defer_forwarding_keep = 0;
len -= n;
buf += n;
if (len > n)
writefd_unbuffered(fd, buf+n, len-n);
#ifdef ICONV_OPTION
if (convert) {
xbuf outbuf, inbuf;
INIT_CONST_XBUF(outbuf, buffer);
INIT_XBUF(inbuf, (char*)buf, len, -1);
defer_forwarding_messages++;
do {
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
writefd_unbuffered(fd, outbuf.buf, outbuf.len);
} while (inbuf.len);
if (!--defer_forwarding_messages)
msg_flush();
} else
#endif
if (len) {
defer_forwarding_messages++;
writefd_unbuffered(fd, buf, len);
if (!--defer_forwarding_messages)
msg_flush();
}
if (!--defer_forwarding_messages && !no_flush)
msg_flush();
}
int send_msg(enum msgcode code, const char *buf, int len, int convert)
@@ -756,7 +753,7 @@ static int read_timeout(int fd, char *buf, size_t len)
/* Don't write errors on a dead socket. */
if (fd == sock_f_in) {
io_end_multiplex_out();
rsyserr(FSOCKERR, errno, "read error");
rsyserr(FERROR_SOCKET, errno, "read error");
} else
rsyserr(FERROR, errno, "read error");
exit_cleanup(RERR_STREAMIO);
@@ -1062,7 +1059,7 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
int pos = 0;
INIT_CONST_XBUF(outbuf, line);
inbuf.buf = ibuf;
INIT_XBUF(inbuf, ibuf, 0, -1);
while (msg_bytes) {
inbuf.len = msg_bytes > sizeof ibuf
@@ -1111,6 +1108,8 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
break;
case MSG_INFO:
case MSG_ERROR:
case MSG_ERROR_XFER:
case MSG_WARNING:
if (msg_bytes >= sizeof line) {
overflow:
rprintf(FERROR,
@@ -1512,7 +1511,8 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len)
}
no_flush--;
if (!(defer_forwarding_messages -= defer_inc))
defer_inc -= defer_forwarding_keep;
if (!(defer_forwarding_messages -= defer_inc) && !no_flush)
msg_flush();
}

2
io.h
View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007 Wayne Davison
* Copyright (C) 2007-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -1 +0,0 @@
dummy

180
lib/addrinfo.h Normal file
View File

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

508
lib/getaddrinfo.c Normal file
View File

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

View File

@@ -4,7 +4,7 @@
* An implementation of MD4 designed for use in the SMB authentication protocol.
*
* Copyright (C) 1997-1998 Andrew Tridgell
* Copyright (C) 2005-2007 Wayne Davison
* Copyright (C) 2005-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -2,6 +2,7 @@
* Unix SMB/CIFS implementation.
* Based on the Samba ACL support code.
* Copyright (C) Jeremy Allison 2000.
* Copyright (C) 2007-2008 Wayne Davison
*
* The permission functions have been changed to get/set all bits via
* one call. Some functions that rsync doesn't need were also removed.
@@ -1735,6 +1736,13 @@ int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
struct new_acl_entry *entry;
int keep_going;
if (entry_id == SMB_ACL_FIRST_ENTRY)
theacl->count = 0;
else if (entry_id != SMB_ACL_NEXT_ENTRY) {
errno = EINVAL;
return -1;
}
DEBUG(10,("This is the count: %d\n",theacl->count));
/* Check if count was previously set to -1. *
@@ -1804,7 +1812,6 @@ SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
struct acl_entry_link *acl_entry_link_head;
int i;
int rc = 0;
uid_t user_id;
/* AIX has no DEFAULT */
if ( type == SMB_ACL_TYPE_DEFAULT ) {
@@ -2025,7 +2032,6 @@ SMB_ACL_T sys_acl_get_fd(int fd)
struct acl_entry_link *acl_entry_link_head;
int i;
int rc = 0;
uid_t user_id;
/* Get the acl using fstatacl */
@@ -2255,6 +2261,11 @@ SMB_ACL_T sys_acl_init( int count)
{
struct acl_entry_link *theacl = NULL;
if (count < 0) {
errno = EINVAL;
return NULL;
}
DEBUG(10,("Entering sys_acl_init\n"));
theacl = SMB_MALLOC_P(struct acl_entry_link);
@@ -2373,7 +2384,6 @@ int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl
struct acl_entry *acl_entry = NULL;
struct ace_id *ace_id = NULL;
uint id_type;
uint ace_access;
uint user_id;
uint acl_length;
uint rc;
@@ -2551,7 +2561,7 @@ int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
}
#endif
int sys_acl_delete_def_file(const char *name)
int sys_acl_delete_def_file(UNUSED(const char *name))
{
/* AIX has no default ACL */
return 0;
@@ -2694,6 +2704,8 @@ int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits,
rc = mbr_uid_to_uuid(u_g_id, uu);
else
rc = mbr_gid_to_uuid(u_g_id, uu);
if (rc != 0)
return rc;
if (acl_set_tag_type(entry, tag_type) != 0
|| acl_set_qualifier(entry, &uu) != 0

View File

@@ -3,6 +3,7 @@
* Version 2.2.x
* Portable SMB ACL interface
* Copyright (C) Jeremy Allison 2000
* Copyright (C) 2007-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -2,6 +2,7 @@
* Extended attribute support for rsync.
*
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2003-2008 Wayne Davison
* Written by Jay Fenlason.
*
* This program is free software; you can redistribute it and/or modify

View File

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

47
log.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +41,7 @@ extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern int receiver_symlink_times;
extern mode_t orig_umask;
extern char *auth_user;
extern char *stdout_format;
@@ -61,7 +62,7 @@ static int logfile_was_closed;
static FILE *logfile_fp;
struct stats stats;
int log_got_error = 0;
int got_xfer_error = 0;
struct {
int code;
@@ -86,6 +87,7 @@ struct {
{ RERR_PARTIAL , "some files could not be transferred" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
{ RERR_TIMEOUT , "timeout in data send/receive" },
{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
{ RERR_CMD_FAILED , "remote shell failed" },
{ RERR_CMD_KILLED , "remote shell killed" },
{ RERR_CMD_RUN , "remote command could not be run" },
@@ -235,8 +237,8 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
}
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
* certain fatal conditions. */
* it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT. Note: recursion
* can happen with certain fatal conditions. */
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
{
int trailing_CR_or_NL;
@@ -259,7 +261,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
return;
}
if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */
code = FERROR;
if (code == FCLIENT)
@@ -267,7 +269,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
else if (am_daemon || logfile_name) {
static int in_block;
char msg[2048];
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
int priority = code == FINFO || code == FLOG ? LOG_INFO : LOG_WARNING;
if (in_block)
return;
@@ -283,12 +285,19 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
} else if (code == FLOG)
return;
if (quiet && code != FERROR)
if (quiet && code == FINFO)
return;
if (am_server) {
enum msgcode msg = (enum msgcode)code;
if (protocol_version < 30) {
if (msg == MSG_ERROR)
msg = MSG_ERROR_XFER;
else if (msg == MSG_WARNING)
msg = MSG_INFO;
}
/* Pass the message to the non-server side. */
if (send_msg((enum msgcode)code, buf, len, !is_utf8))
if (send_msg(msg, buf, len, !is_utf8))
return;
if (am_daemon) {
/* TODO: can we send the error to the user somehow? */
@@ -297,8 +306,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
}
switch (code) {
case FERROR_XFER:
got_xfer_error = 1;
/* FALL THROUGH */
case FERROR:
log_got_error = 1;
case FWARNING:
f = stderr;
break;
case FINFO:
@@ -342,8 +354,8 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
}
}
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
/* This is the rsync debugging function. Call it with FINFO, FERROR_*,
* FWARNING, FLOG, or FCLIENT. */
void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
@@ -421,10 +433,10 @@ void rflush(enum logcode code)
if (am_daemon || code == FLOG)
return;
if (code == FERROR || am_server)
f = stderr;
else
if (code == FINFO && !am_server)
f = stdout;
else
f = stderr;
fflush(f);
}
@@ -612,7 +624,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
break;
case 'i':
if (iflags & ITEM_DELETED) {
n = "*deleting";
n = "*deleting ";
break;
}
n = c = buf2 + MAXPATHLEN - 32;
@@ -627,7 +639,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
c[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
: !preserve_times || (!receiver_symlink_times && S_ISLNK(file->mode))
? 'T' : 't';
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
@@ -801,7 +814,7 @@ void log_exit(int code, const char *file, int line)
/* VANISHED is not an error, only a warning */
if (code == RERR_VANISHED) {
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
} else {
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",

122
main.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,10 +41,11 @@ extern int remove_source_files;
extern int need_messages_from_generator;
extern int kluge_around_eof;
extern int do_stats;
extern int log_got_error;
extern int got_xfer_error;
extern int module_id;
extern int copy_links;
extern int copy_dirlinks;
extern int copy_unsafe_links;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
@@ -63,10 +64,13 @@ extern int read_batch;
extern int write_batch;
extern int batch_fd;
extern int filesfrom_fd;
extern int connect_timeout;
extern pid_t cleanup_child_pid;
extern unsigned int module_dirlen;
extern struct stats stats;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *dest_option;
extern char *basis_dir[];
extern char *rsync_path;
extern char *shell_cmd;
@@ -79,6 +83,7 @@ extern struct filter_list_struct server_filter_list;
extern iconv_t ic_send;
#endif
uid_t our_uid;
int local_server = 0;
int daemon_over_rsh = 0;
mode_t orig_umask = 0;
@@ -272,9 +277,10 @@ static void output_summary(void)
"sent %s bytes received %s bytes %s bytes/sec\n",
human_num(total_written), human_num(total_read),
human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
rprintf(FINFO, "total size is %s speedup is %.2f\n",
rprintf(FINFO, "total size is %s speedup is %.2f%s\n",
human_num(stats.total_size),
(double)stats.total_size / (total_written+total_read));
(double)stats.total_size / (total_written+total_read),
write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
}
fflush(stdout);
@@ -329,7 +335,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
int i, argc = 0;
char *args[MAX_ARGS];
pid_t ret;
char *dir = NULL;
int dash_l_set = 0;
if (!read_batch && !local_server) {
@@ -505,9 +510,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
ret = piped_child(args, f_in_p, f_out_p);
}
if (dir)
free(dir);
return ret;
oom:
@@ -636,36 +638,41 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
return cp + 1;
}
/* Call this if the destination dir (which is assumed to be in curr_dir)
* does not yet exist and we can't create it due to being in dry-run
* mode. We'll fix dirs that can be relative to the non-existent dir. */
static void fix_basis_dirs(void)
/* This function checks on our alternate-basis directories. If we're in
* dry-run mode and the destination dir does not yet exist, we'll try to
* tweak any dest-relative paths to make them work for a dry-run (the
* destination dir must be in curr_dir[] when this function is called).
* We also warn about any arg that is non-existent or not a directory. */
static void check_alt_basis_dirs(void)
{
char **dir, *new, *slash;
int len;
STRUCT_STAT st;
char **dir_p, *slash = strrchr(curr_dir, '/');
if (dry_run <= 1)
return;
slash = strrchr(curr_dir, '/');
for (dir = basis_dir; *dir; dir++) {
if (**dir == '/')
continue;
len = curr_dir_len + 1 + strlen(*dir) + 1;
if (!(new = new_array(char, len)))
out_of_memory("fix_basis_dirs");
if (slash && strncmp(*dir, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir);
*dir = new;
for (dir_p = basis_dir; *dir_p; dir_p++) {
if (dry_run > 1 && **dir_p != '/') {
int len = curr_dir_len + 1 + strlen(*dir_p) + 1;
char *new = new_array(char, len);
if (!new)
out_of_memory("check_alt_basis_dirs");
if (slash && strncmp(*dir_p, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir_p + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir_p);
*dir_p = new;
}
if (do_stat(*dir_p, &st) < 0) {
rprintf(FWARNING, "%s arg does not exist: %s\n",
dest_option, *dir_p);
} else if (!S_ISDIR(st.st_mode)) {
rprintf(FWARNING, "%s arg is not a dir: %s\n",
dest_option, *dir_p);
}
}
}
@@ -753,7 +760,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
/* The receiving side mustn't obey this, or an existing symlink that
* points to an identical file won't be replaced by the referent. */
copy_links = copy_dirlinks = 0;
copy_links = copy_dirlinks = copy_unsafe_links = 0;
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && !inc_recurse)
@@ -861,7 +868,6 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
int exit_code;
struct file_list *flist;
char *local_name = NULL;
char *dir = NULL;
int save_verbose = verbose;
if (filesfrom_fd >= 0) {
@@ -882,7 +888,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
}
if (argc > 0) {
dir = argv[0];
char *dir = argv[0];
argc--;
argv++;
if (!am_daemon && !push_dir(dir, 0)) {
@@ -923,26 +929,27 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
/* Now that we know what our destination directory turned out to be,
* we can sanitize the --link-/copy-/compare-dest args correctly. */
if (sanitize_paths) {
char **dir;
for (dir = basis_dir; *dir; dir++) {
*dir = sanitize_path(NULL, *dir, NULL, curr_dir_depth, NULL);
}
if (partial_dir) {
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, NULL);
}
char **dir_p;
for (dir_p = basis_dir; *dir_p; dir_p++)
*dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth);
if (partial_dir)
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth);
}
fix_basis_dirs();
check_alt_basis_dirs();
if (server_filter_list.head) {
char **dir;
char **dir_p;
struct filter_list_struct *elp = &server_filter_list;
for (dir = basis_dir; *dir; dir++) {
if (check_filter(elp, *dir, 1) < 0)
for (dir_p = basis_dir; *dir_p; dir_p++) {
char *dir = *dir_p;
if (*dir == '/')
dir += module_dirlen;
if (check_filter(elp, dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
&& check_filter(elp, partial_dir, 1) < 0) {
&& check_filter(elp, partial_dir + module_dirlen, 1) < 0) {
options_rejected:
rprintf(FERROR,
"Your options have been rejected by the server.\n");
@@ -1081,7 +1088,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (flist && flist->used > 0) {
local_name = get_local_name(flist, argv[0]);
fix_basis_dirs();
check_alt_basis_dirs();
exit_code2 = do_recv(f_in, f_out, local_name);
} else {
@@ -1263,6 +1270,12 @@ static int start_client(int argc, char *argv[])
exit_cleanup(RERR_SYNTAX);
}
if (connect_timeout) {
rprintf(FERROR, "The --contimeout option may only be "
"used when connecting to an rsync daemon.\n");
exit_cleanup(RERR_SYNTAX);
}
if (shell_machine) {
p = strrchr(shell_machine,'@');
if (p) {
@@ -1309,7 +1322,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
if (!am_server)
output_summary();
close_all();
if (log_got_error)
if (got_xfer_error)
_exit(RERR_PARTIAL);
_exit(0);
}
@@ -1416,7 +1429,8 @@ int main(int argc,char *argv[])
#endif
starttime = time(NULL);
am_root = (MY_UID() == 0);
our_uid = MY_UID();
am_root = our_uid == 0;
memset(&stats, 0, sizeof(stats));

85
match.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,40 +39,51 @@ static int total_matches;
extern struct stats stats;
#define TABLESIZE (1<<16)
#define TRADITIONAL_TABLESIZE (1<<16)
static uint32 tablesize;
static int32 *hash_table;
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
static int32 build_hash_table(struct sum_struct *s, int32 start)
{
int32 i, end = s->count;
#define BIG_SUM2HASH(sum) ((sum)%tablesize)
if (!hash_table) {
hash_table = new_array(int32, TABLESIZE);
static void build_hash_table(struct sum_struct *s)
{
static uint32 alloc_size;
int32 i;
/* Dynamically calculate the hash table size so that the hash load
* for big files is about 80%. A number greater than the traditional
* size must be odd or s2 will not be able to span the entire set. */
tablesize = (uint32)(s->count/8) * 10 + 11;
if (tablesize < TRADITIONAL_TABLESIZE)
tablesize = TRADITIONAL_TABLESIZE;
if (tablesize > alloc_size || tablesize < alloc_size - 16*1024) {
if (hash_table)
free(hash_table);
hash_table = new_array(int32, tablesize);
if (!hash_table)
out_of_memory("build_hash_table");
alloc_size = tablesize;
}
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
memset(hash_table, 0xFF, tablesize * sizeof hash_table[0]);
if (end - start > TABLESIZE*8/10)
end = start + TABLESIZE*8/10;
for (i = start; i < end; i++) {
uint32 t = SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
if (tablesize == TRADITIONAL_TABLESIZE) {
for (i = 0; i < s->count; i++) {
uint32 t = SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
}
} else {
for (i = 0; i < s->count; i++) {
uint32 t = BIG_SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
}
}
if (verbose > 2) {
rprintf(FINFO, "built hash table for entries %ld - %ld\n",
(long)start, (long)end - 1);
}
return end;
}
@@ -130,8 +141,8 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf, OFF_T len)
{
OFF_T offset, end, reset = 0;
int32 k, want_i, backup, sum_pos = 0;
OFF_T offset, end;
int32 k, want_i, backup;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
int more;
@@ -169,24 +180,21 @@ static void hash_search(int f,struct sum_struct *s,
int done_csum2 = 0;
int32 i;
if (offset >= reset) {
sum_pos = build_hash_table(s, sum_pos);
if (sum_pos == s->count)
reset = len;
else
reset = sum_pos * s->blength;
}
if (verbose > 4) {
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
}
i = hash_table[SUM2HASH2(s1,s2)];
if (i < 0)
goto null_hash;
if (tablesize == TRADITIONAL_TABLESIZE) {
if ((i = hash_table[SUM2HASH2(s1,s2)]) < 0)
goto null_hash;
sum = (s1 & 0xffff) | (s2 << 16);
} else {
sum = (s1 & 0xffff) | (s2 << 16);
if ((i = hash_table[BIG_SUM2HASH(sum)]) < 0)
goto null_hash;
}
sum = (s1 & 0xffff) | (s2 << 16);
hash_hits++;
do {
int32 l;
@@ -354,6 +362,11 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
}
if (len > 0 && s->count > 0) {
build_hash_table(s);
if (verbose > 2)
rprintf(FINFO,"built hash table\n");
hash_search(f, s, buf, len);
if (verbose > 2)

View File

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

48
mkproto.pl Normal file
View File

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

View File

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

108
options.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002-2007 Wayne Davison
* Copyright (C) 2002-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
extern int module_id;
extern int sanitize_paths;
extern int daemon_over_rsh;
extern unsigned int module_dirlen;
extern struct filter_list_struct filter_list;
extern struct filter_list_struct server_filter_list;
@@ -99,6 +100,7 @@ int xfer_dirs = -1;
int am_daemon = 0;
int do_stats = 0;
int do_progress = 0;
int connect_timeout = 0;
int keep_partial = 0;
int safe_symlinks = 0;
int copy_unsafe_links = 0;
@@ -185,8 +187,8 @@ int list_only = 0;
#define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
char *batch_name = NULL;
#ifdef ICONV_OPTION
int need_unsorted_flist = 0;
#ifdef ICONV_OPTION
char *iconv_opt = ICONV_OPTION;
#endif
@@ -200,7 +202,7 @@ static int itemize_changes = 0;
static int refused_delete, refused_archive_part, refused_compress;
static int refused_partial, refused_progress, refused_delete_before;
static int refused_delete_during;
static int refused_inplace;
static int refused_inplace, refused_no_iconv;
static char *max_size_arg, *min_size_arg;
static char tmp_partialdir[] = ".~tmp~";
@@ -216,6 +218,7 @@ static void print_rsync_version(enum logcode f)
char const *got_socketpair = "no ";
char const *have_inplace = "no ";
char const *hardlinks = "no ";
char const *symtimes = "no ";
char const *acls = "no ";
char const *xattrs = "no ";
char const *links = "no ";
@@ -250,6 +253,9 @@ static void print_rsync_version(enum logcode f)
#ifdef ICONV_OPTION
iconv = "";
#endif
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
symtimes = "";
#endif
rprintf(f, "%s version %s protocol version %d%s\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
@@ -263,8 +269,8 @@ static void print_rsync_version(enum logcode f)
(int)(sizeof (int64) * 8));
rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
got_socketpair, hardlinks, links, ipv6, have_inplace);
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv\n",
have_inplace, acls, xattrs, iconv);
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
have_inplace, acls, xattrs, iconv, symtimes);
#ifdef MAINTAINER_MODE
rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
@@ -351,8 +357,8 @@ void usage(enum logcode F)
rprintf(F," --fake-super store/recover privileged attrs using xattrs\n");
#endif
rprintf(F," -S, --sparse handle sparse files efficiently\n");
rprintf(F," -n, --dry-run show what would have been transferred\n");
rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n");
rprintf(F," -n, --dry-run perform a trial run with no changes made\n");
rprintf(F," -W, --whole-file copy files whole (without delta-xfer algorithm)\n");
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
rprintf(F," -B, --block-size=SIZE force a fixed checksum block-size\n");
rprintf(F," -e, --rsh=COMMAND specify the remote shell to use\n");
@@ -377,7 +383,8 @@ void usage(enum logcode F)
rprintf(F," --delay-updates put all updated files into place at transfer's end\n");
rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n");
rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n");
rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n");
rprintf(F," --size-only skip files that match in size\n");
rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n");
@@ -421,7 +428,7 @@ void usage(enum logcode F)
rprintf(F," --read-batch=FILE read a batched update from FILE\n");
rprintf(F," --protocol=NUM force an older protocol version to be used\n");
#ifdef ICONV_OPTION
rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filesnames\n");
rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filenames\n");
#endif
rprintf(F," -4, --ipv4 prefer IPv4\n");
rprintf(F," -6, --ipv6 prefer IPv6\n");
@@ -438,7 +445,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
OPT_NO_D, OPT_APPEND,
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
OPT_SERVER, OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
@@ -521,6 +528,8 @@ static struct poptOption long_options[] = {
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
{"no-one-file-system",'x',POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"no-x", 'x', POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
{"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
{"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
@@ -603,11 +612,13 @@ static struct poptOption long_options[] = {
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
{"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 },
{"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 },
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
#ifdef ICONV_OPTION
{"iconv", 0, POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
{"no-iconv", 0, POPT_ARG_NONE, 0, OPT_NO_ICONV, 0, 0 },
#endif
{"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
{"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
@@ -754,6 +765,8 @@ static void set_refuse_options(char *bp)
refused_progress = op->val;
else if (wildmatch("inplace", op->longName))
refused_inplace = op->val;
else if (wildmatch("no-iconv", op->longName))
refused_no_iconv = op->val;
break;
}
if (!is_wild)
@@ -874,8 +887,11 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
if (ref && *ref)
set_refuse_options(ref);
if (am_daemon)
if (am_daemon) {
set_refuse_options("log-file*");
if (!*lp_charset(module_id))
set_refuse_options("iconv");
}
#ifdef ICONV_OPTION
if (!am_daemon && !protect_args && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
@@ -1001,16 +1017,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
case OPT_INCLUDE_FROM:
arg = poptGetOptArg(pc);
if (sanitize_paths)
arg = sanitize_path(NULL, arg, NULL, 0, NULL);
arg = sanitize_path(NULL, arg, NULL, 0);
if (server_filter_list.head) {
int rej;
char *cp = strdup(arg);
char *dir, *cp = strdup(arg);
if (!cp)
out_of_memory("parse_arguments");
if (!*cp)
goto options_rejected;
clean_fname(cp, 1);
rej = check_filter(&server_filter_list, cp, 0) < 0;
dir = cp + (*cp == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
rej = check_filter(&server_filter_list, dir, 0) < 0;
free(cp);
if (rej)
goto options_rejected;
@@ -1122,6 +1139,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
read_batch = 1;
break;
case OPT_NO_ICONV:
#ifdef ICONV_OPTION
iconv_opt = NULL;
#endif
break;
case OPT_MAX_SIZE:
if ((max_size = parse_size_arg(&max_size_arg, 'b')) <= 0) {
snprintf(err_buf, sizeof err_buf,
@@ -1249,6 +1272,10 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
else
need_unsorted_flist = 1;
}
if (refused_no_iconv && !iconv_opt) {
create_refuse_error(refused_no_iconv);
return 0;
}
#endif
if (protect_args == 1) {
@@ -1301,7 +1328,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
batch_name = NULL;
} else if (dry_run)
write_batch = 0;
}
} else if (write_batch < 0 && dry_run)
write_batch = 0;
if (read_batch && files_from) {
snprintf(err_buf, sizeof err_buf,
"--read-batch cannot be used with --files-from\n");
@@ -1394,26 +1422,30 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
if (sanitize_paths) {
int i;
for (i = argc; i-- > 0; )
argv[i] = sanitize_path(NULL, argv[i], "", 0, NULL);
argv[i] = sanitize_path(NULL, argv[i], "", 0);
if (tmpdir)
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
if (backup_dir)
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
}
if (server_filter_list.head && !am_sender) {
struct filter_list_struct *elp = &server_filter_list;
if (tmpdir) {
char *dir;
if (!*tmpdir)
goto options_rejected;
clean_fname(tmpdir, 1);
if (check_filter(elp, tmpdir, 1) < 0)
dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, dir, 1) < 0)
goto options_rejected;
}
if (backup_dir) {
char *dir;
if (!*backup_dir)
goto options_rejected;
clean_fname(backup_dir, 1);
if (check_filter(elp, backup_dir, 1) < 0)
dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, dir, 1) < 0)
goto options_rejected;
}
}
@@ -1565,7 +1597,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
if (partial_dir) {
if (*partial_dir)
clean_fname(partial_dir, 1);
clean_fname(partial_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (!*partial_dir || strcmp(partial_dir, ".") == 0)
partial_dir = NULL;
if (!partial_dir && refused_partial) {
@@ -1602,12 +1634,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
} else {
if (sanitize_paths)
files_from = sanitize_path(NULL, files_from, NULL, 0, NULL);
files_from = sanitize_path(NULL, files_from, NULL, 0);
if (server_filter_list.head) {
char *dir;
if (!*files_from)
goto options_rejected;
clean_fname(files_from, 1);
if (check_filter(&server_filter_list, files_from, 0) < 0)
dir = files_from + (*files_from == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&server_filter_list, dir, 0) < 0)
goto options_rejected;
}
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
@@ -1749,24 +1783,24 @@ void server_options(char **args, int *argc_p)
argstr[x++] = 'z';
/* We make use of the -e option to let the server know about any
* pre-release protocol version && our allow_inc_recurse status. */
set_allow_inc_recurse();
* pre-release protocol version && some behavior flags. */
argstr[x++] = 'e';
#if SUBPROTOCOL_VERSION != 0
if (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"e%d.%d%s", PROTOCOL_VERSION, SUBPROTOCOL_VERSION,
allow_inc_recurse ? "i" : "");
"%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
} else
#endif
if (allow_inc_recurse) {
argstr[x++] = 'e';
argstr[x++] = '.';
set_allow_inc_recurse();
if (allow_inc_recurse)
argstr[x++] = 'i';
}
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
argstr[x++] = 'L';
#endif
argstr[x] = '\0';
if (x != 1)
args[ac++] = argstr;
args[ac++] = argstr;
#ifdef ICONV_OPTION
if (iconv_opt) {

View File

@@ -1,9 +1,9 @@
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.0pre4
Version: 3.0.0
Release: 1
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz
Source: http://rsync.samba.org/ftp/rsync/rsync-%{version}.tar.gz
URL: http://rsync.samba.org/
Prefix: %{_prefix}
@@ -45,5 +45,5 @@ rm -rf $RPM_BUILD_ROOT
%{_mandir}/man5/rsyncd.conf.5*
%changelog
* Fri Oct 26 2007 Wayne Davison <wayned@samba.org>
Released 3.0.0pre4.
* Sat Mar 01 2008 Wayne Davison <wayned@samba.org>
Released 3.0.0.

View File

@@ -14,16 +14,13 @@ use strict;
use Getopt::Long;
use Date::Format;
# Choose any dir where a pristine rsync has been checked out of CVS.
our $unpacked = $ENV{HOME} . '/release/nightly';
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
our $dest = $ENV{HOME} . '/samba-rsync-ftp/nightly';
our $nightly_symlink = "$dest/rsync-HEAD.tar.gz";
our($cvs_update, $make_tar, $upload, $help_opt);
our($make_tar, $upload, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'cvs-update|c' => \$cvs_update,
'make-tar|t' => \$make_tar,
'upload|u' => \$upload,
'help|h' => \$help_opt,
@@ -32,70 +29,65 @@ our($cvs_update, $make_tar, $upload, $help_opt);
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
our $ztoday = time2str('%d %b %Y', time);
our $today = $ztoday;
our $gen_target = $upload ? 'gensend' : 'gen';
chdir($unpacked) or die $!;
if ($cvs_update) {
print "Updating from cvs...\n";
system 'cvs -q up' and die $!;
}
die "$dest does not exist\n" unless -d $dest;
die "There is no .git dir in the current directory.\n" unless -d '.git';
die "There is no rsync checkout in the current directory.\n" unless -f 'rsyncd.conf.yo';
if ($make_tar) {
print "Generating list of active CVS files...\n";
my($dir, @files);
open(CVS, '-|', 'cvs status 2>&1') or die $!;
while (<CVS>) {
if (/^cvs status: Examining (.*)/) {
if ($1 eq '.') {
$dir = '';
} else {
push(@files, $1);
$dir = $1 . '/';
}
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
push(@files, $dir . $1);
if ($2 ne 'Up-to-date') {
print "*** Not up-to-date: $dir$1\n";
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
system "make $gen_target" and die "make $gen_target failed!\n";
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extra_files = split(' ', $_);
last;
}
}
close CVS;
close IN;
print "Creating $name.tar.gz\n";
system "rsync -a @extra_files $name/";
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
system "support/git-set-file-times --prefix=$name/";
system "fakeroot tar czf $dest/$name.tar.gz $name; rm -rf $name";
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 $!;
unlink($nightly_symlink);
symlink("$name.tar.gz", $nightly_symlink);
}
chdir($nightly) or die $!;
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
my $html_fn = $fn;
$html_fn =~ s/\.yo/.html/;
my $yo_tmp = "$dest/$fn";
(my $html_fn = "$dest/$fn") =~ s/\.yo/.html/;
open(IN, '<', "$unpacked/$fn") or die $!;
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
open(OUT, '>', $fn) or die $!;
open(OUT, '>', $yo_tmp) or die $!;
print OUT $_;
close OUT;
system "yodl2html -o $html_fn $fn";
system 'yodl2html', '-o', $html_fn, $yo_tmp;
unlink($fn);
unlink($yo_tmp);
}
chdir($dest) or die $!;
my $cnt = 0;
open(PIPE, '-|', 'ls -1t rsync-HEAD-*') or die $!;
while (<PIPE>) {
@@ -122,8 +114,7 @@ sub usage
die <<EOT;
Usage: nightly-rsync [OPTIONS]
-c, --cvs-update update $unpacked via CVS.
-t, --make-tar create a new tar file in $nightly
-t, --make-tar create a new tar file in $dest
-u, --upload upload the revised nightly dir to samba.org
-h, --help display this help
EOT

View File

@@ -1,104 +1,81 @@
#!/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.
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
# the git repository in the current directory will be updated, and the local
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
use Cwd;
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $releasedir = $ENV{HOME} . '/release';
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
my $cl_today = time2str('* %a %b %d %Y', time);
my $ztoday = time2str('%d %b %Y', time);
(my $today = $ztoday) =~ s/^0//;
my $break = <<EOT;
==========================================================================
EOT
my $note = <<EOT;
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
EOT
my $curdir = Cwd::cwd;
my $live = shift;
my $skipping = '';
print $break;
if ($live) {
print <<EOT;
== This will release a new version of rsync onto an unsuspecting world. ==
EOT
} else {
print <<EOT;
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
EOT
$dest =~ s#([^/]+$)#tmp/$1#;
$skipping = ' ** SKIPPING **';
}
die "$dest does not exist\n" unless -d $dest;
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
chdir($releasedir) or die $!;
system 'rm -rf rsync';
my(%dirs, @files);
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
while (<CVS>) {
print $_;
next if /\.(cvs)?ignore$/;
if (m#^[UP] rsync/(.*)#) {
my $fn = $1;
my($dir) = $fn =~ m#^(.+)/#;
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
push(@files, $fn);
}
}
chdir('rsync') or die $!;
my($version, $lastversion);
open(IN, '<', 'configure.in') or die $!;
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$version = $lastversion = $1;
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extra_files = split(' ', $_);
last;
}
}
close IN;
if ($lastversion =~ /cvs$/) {
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
($lastversion) = /(\d+\.\d+\.\d+)/;
my $break = <<EOT;
==========================================================================
EOT
print $break, <<EOT, $break, "\n";
== This will release a new version of rsync onto an unsuspecting world. ==
EOT
die "$dest does not exist\n" unless -d $dest;
die "There is no .git dir in the current directory.\n" unless -d '.git';
die "'a' must not exist in the current directory.\n" if -e 'a';
die "'b' must not exist in the current directory.\n" if -e 'b';
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
my $lastversion;
open(IN, '<', 'configure.in') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$lastversion = $1;
last;
}
}
close IN;
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
my($lastrelease) = /(\d+\.\d+\.\d+)/;
print $break, "\nPlease enter the version number of this release: [$version] ";
$lastversion = $lastrelease if $lastversion =~ /dev$/;
my $version = $lastversion;
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
print "Please enter the version number of this release: [$version] ";
chomp($_ = <STDIN>);
if ($_ eq '.') {
$version =~ s/pre\d+//;
} elsif ($_ ne '') {
$version = $_;
}
$version =~ s/[-.]*pre[-.]*/pre/;
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
my $cvstag = "release-$version";
$cvstag =~ s/[.]/-/g;
$cvstag =~ s/pre/-pre/;
$lastversion = $lastrelease unless $version =~ s/[-.]*pre[-.]*/pre/;
print "Enter the previous version to produce a patch against: [$lastversion] ";
chomp($_ = <STDIN>);
@@ -111,49 +88,44 @@ chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
my $diffdir;
my $skipping2;
my $skipping;
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 **';
$skipping = ' ** SKIPPING **';
} elsif ($version =~ /pre/) {
$diffdir = $dest;
$skipping2 = ' ** SKIPPING **';
$skipping = ' ** SKIPPING **';
} else {
$diffdir = "$dest/old-versions";
$skipping2 = '';
$skipping = '';
}
print "\n", $break, <<EOT;
\$version is "$version"
\$lastversion is "$lastversion"
\$cvstag is "$cvstag"
\$dest is "$dest"
\$releasedir is "$releasedir"
\$curdir is "$curdir"
\$diffdir is "$diffdir"
\$release is "$release"
About to:
- make sure that SUBPROTOCOL_VERSION is 0$skipping2
- tweak the version in configure.in, configure, and the spec files
- make sure that configure, config.h.in, and proto.h are updated
- tweak NEWS and OLDNEWS to update the release date$skipping2
- tweak the date in the *.yo files and re-generate the man pages
- make sure that the patches dir has been updated
- page through the "cvs diff" output
- make sure that SUBPROTOCOL_VERSION is 0$skipping
- tweak the version in configure.in and the spec files
- tweak NEWS and OLDNEWS to update the release date$skipping
- tweak the date in the *.yo files and generate the man pages
- generate configure.sh, config.h.in, and proto.h
- page through the differences
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
my $f_opt = /f/ ? ' -f' : '';
print $break;
system "./prepare-source && touch proto.h";
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in configure ) );
glob('*.yo'), qw( configure.in ) );
if ($version !~ /pre/) {
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
}
@@ -187,64 +159,45 @@ foreach my $fn (@tweak_files) {
close OUT;
}
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage rsync.1";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage rsyncd.conf.5";
mkdir('patches/tmp') or die $!;
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
print "\n", $break, $note, $break;
system "patches/verify-patches -n -an$f_opt";
print $break;
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
system "git diff --color | less -p '^diff .*'";
my $srctar_name = "rsync-$version.tar.gz";
my $pattar_name = "rsync-patches-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $srctar_file = "$dest/$srctar_name";
my $pattar_file = "$dest/$pattar_name";
my $diff_file = "$dest/$diff_name";
my $lasttar_file = "$dest/rsync-$lastversion.tar.gz";
print $break, <<EOT;
About to:
- "cvs commit" all changes$skipping
- "cvs tag" this release as $cvstag$skipping
- change the diffs in the patches dir to include generated files
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:
- commit all changes
- tag this release as v$version
- move the old tar/diff files into the appropriate old-* dirs
- hard-link the moved tar/diff files on samba.org$skipping
- create release tar, "$tar_name"
- hard-link the moved tar/diff files on samba.org
- create release tar, "$srctar_name"
- create patches tar, "$pattar_name"
- create release diffs, "$diff_name"
- update README, *NEWS, TODO, and cvs.log
- update patch branches and generate patch/* files
- update README, *NEWS, TODO, and ChangeLog
- update rsync*.html man pages
- gpg-sign the release files$skipping
- gpg-sign the release files
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
chdir($releasedir) or die $!;
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
print "\nSign the tag:";
system "git tag -s -m 'Version $version.' v$version" and exit 1;
print $break;
system "rm -rf rsync-$version";
rename('rsync', "rsync-$version") or die $!;
# Extract some files from the old tar before we do the shuffle.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
@@ -278,53 +231,49 @@ if ($diffdir ne $dest) {
# Optimize our future upload (in the absence of --detect-renamed) by
# using rsync to hard-link the above files on samba.org.
if ($live) {
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
}
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
foreach (@moved_files) {
unlink($_);
}
chdir($releasedir) or die $!;
chdir($curdir) 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";
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "rm -rf a";
rename('b', "rsync-$version");
print "Creating $srctar_file ...\n";
system "git archive --format=tar --prefix=rsync-$version/ v$version | tar xf -";
system "support/git-set-file-times --prefix=rsync-$version/";
system "fakeroot tar czf $srctar_file rsync-$version; rm -rf rsync-$version";
mkdir("rsync-$version", 0755);
mkdir("rsync-$version/patches", 0755);
system "support/patch-update --skip-check --gen=rsync-$version/patches";
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
print "Updating the other files in $dest ...\n";
system "rsync -a rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
system "rsync -a 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 "git log --name-status | gzip -9 >$dest/ChangeLog.gz";
system "yodl2html -o $dest/rsync.html rsync-$version/rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
system "yodl2html -o $dest/rsync.html rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsyncd.conf.yo";
system "rm -rf rsync-*";
if ($live) {
chdir($dest) or die $!;
system "gpg -ba $tar_name; gpg -ba $diff_name";
print $break, <<EOT;
All done. Remember to announce the release on *BOTH*
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
EOT
} else {
print $break, "All done.\n";
chdir($dest) or die $!;
my $cnt = 0;
foreach my $fn ($srctar_name, $pattar_name, $diff_name) {
print ++$cnt, ". Sign file \"$fn\":";
system "gpg -ba $fn";
}
print $break, <<'EOT';
Local changes are done. When you're satisfied, push the git repository
and rsync the release files. Remember to announce the release on *BOTH*
rsync-announce@lists.samba.org and rsync@lists.samba.org (and the web)!
EOT

View File

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

14
pipe.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -133,6 +133,12 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
filesfrom_fd = -1;
chmod_modes = NULL; /* Let the sending side handle this. */
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
@@ -150,12 +156,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
child_main(argc, argv);
}
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rsyserr(FERROR, errno, "Failed to close");

View File

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

View File

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

View File

@@ -1,25 +1,7 @@
gen: configure config.h.in proto.h man
conf: configure.sh config.h.in
configure: configure.in aclocal.m4
autoconf
configure.sh: configure.in aclocal.m4
autoconf -o configure.sh
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
-./tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
-./tweak_manpage rsyncd.conf.5

View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,8 +22,10 @@
#include "rsync.h"
extern struct stats stats;
extern int am_server;
extern int need_unsorted_flist;
extern struct stats stats;
extern struct file_list *cur_flist;
#define PROGRESS_HISTORY_SECS 5
@@ -41,6 +43,7 @@ struct progress_history {
static struct progress_history ph_start;
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
static int newest_hpos, oldest_hpos;
static int current_file_index;
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
{
@@ -104,7 +107,7 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
if (is_last) {
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
stats.num_transferred_files,
stats.num_files - stats.current_file_index - 1,
stats.num_files - current_file_index - 1,
stats.num_files);
} else
strlcpy(eol, "\r", sizeof eol);
@@ -112,6 +115,15 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
human_num(ofs), pct, rate, units, rembuf, eol);
}
void set_current_file_index(struct file_struct *file, int ndx)
{
if (need_unsorted_flist)
current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start;
else
current_file_index = ndx;
current_file_index -= cur_flist->flist_num;
}
void end_progress(OFF_T size)
{
if (!am_server) {

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ extern struct filter_list_struct server_filter_list;
static struct bitbag *delayed_bits = NULL;
static int phase = 0, redoing = 0;
/* We're either updating the basis file or an identical copy: */
static int updating_basis;
static int updating_basis_or_equiv;
/*
* get_tmpname() - create a tmp filename for a given filename
@@ -83,10 +83,10 @@ static int updating_basis;
* As long as it's unique, rsync will work.
*/
int get_tmpname(char *fnametmp, char *fname)
int get_tmpname(char *fnametmp, const char *fname)
{
int maxname, added, length = 0;
char *f;
const char *f;
if (tmpdir) {
/* Note: this can't overflow, so the return value is safe */
@@ -110,7 +110,7 @@ int get_tmpname(char *fnametmp, char *fname)
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
if (maxname < 1) {
rprintf(FERROR, "temporary filename too long: %s\n", fname);
rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
fnametmp[0] = '\0';
return 0;
}
@@ -123,6 +123,43 @@ int get_tmpname(char *fnametmp, char *fname)
return 1;
}
/* Opens a temporary file for writing.
* Success: Writes name into fnametmp, returns fd.
* Failure: Clobbers fnametmp, returns -1.
* Calling cleanup_set() is the caller's job. */
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
{
int fd;
if (!get_tmpname(fnametmp, fname))
return -1;
/* We initially set the perms without the setuid/setgid bits or group
* access to ensure that there is no race condition. They will be
* correctly updated after the right owner and group info is set.
* (Thanks to snabb@epipe.fi for pointing this out.) */
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
#if 0
/* In most cases parent directories will already exist because their
* information should have been previously transferred, but that may
* not be the case with -R */
if (fd == -1 && relative_paths && errno == ENOENT
&& create_directory_path(fnametmp) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
#endif
if (fd == -1) {
rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
full_fname(fnametmp));
return -1;
}
return fd;
}
static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
const char *fname, int fd, OFF_T total_size)
@@ -174,7 +211,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
}
offset = sum.flength;
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
full_fname(fname), (double)j, (double)offset);
exit_cleanup(RERR_FILEIO);
}
@@ -222,14 +259,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_update(map, len);
}
if (updating_basis) {
if (updating_basis_or_equiv) {
if (offset == offset2 && fd != -1) {
OFF_T pos;
if (flush_write_file(fd) < 0)
goto report_write_error;
offset += len;
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"lseek of %s returned %.0f, not %.0f",
full_fname(fname),
(double)pos, (double)offset);
@@ -256,7 +293,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
report_write_error:
rsyserr(FERROR, errno, "write failed on %s",
rsyserr(FERROR_XFER, errno, "write failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
@@ -298,7 +335,7 @@ static void handle_delayed_updates(char *local_name)
/* We don't use robust_rename() here because the
* partial-dir must be on the same drive. */
if (do_rename(partialptr, fname) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"rename failed for %s (from %s)",
full_fname(fname), partialptr);
} else {
@@ -315,10 +352,11 @@ static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
{
while (next_gen_ndx < desired_ndx) {
if (next_gen_ndx >= 0) {
rprintf(FINFO,
struct file_struct *file = cur_flist->files[next_gen_ndx];
rprintf(FERROR_XFER,
"(No batched update for%s \"%s\")\n",
redoing ? " resend of" : "",
f_name(cur_flist->files[next_gen_ndx], NULL));
file->flags & FLAG_FILE_SENT ? " resend of" : "",
f_name(file, NULL));
}
next_gen_ndx = read_int(fd);
if (next_gen_ndx == -1) {
@@ -364,8 +402,6 @@ int recv_files(int f_in, char *local_name)
if (delay_updates)
delayed_bits = bitbag_create(cur_flist->used + 1);
updating_basis = inplace;
while (1) {
cleanup_disable();
@@ -446,9 +482,11 @@ int recv_files(int f_in, char *local_name)
}
}
stats.current_file_index = ndx;
if (!am_server && do_progress)
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.total_transferred_size += F_LENGTH(file);
cleanup_got_literal = 0;
if (server_filter_list.head
@@ -464,7 +502,7 @@ int recv_files(int f_in, char *local_name)
continue;
}
if (write_batch < 0) {
log_item(FINFO, file, &stats, iflags, NULL);
log_item(FCLIENT, file, &stats, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, F_LENGTH(file));
continue;
@@ -498,7 +536,6 @@ int recv_files(int f_in, char *local_name)
fnamecmp = get_backup_name(fname);
break;
case FNAMECMP_FUZZY:
updating_basis = 0;
if (file->dirname) {
pathjoin(fnamecmpbuf, MAXPATHLEN,
file->dirname, xname);
@@ -507,7 +544,6 @@ int recv_files(int f_in, char *local_name)
fnamecmp = xname;
break;
default:
updating_basis = 0;
if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
@@ -520,14 +556,18 @@ int recv_files(int f_in, char *local_name)
break;
}
if (!fnamecmp || (server_filter_list.head
&& check_filter(&server_filter_list, fname, 0) < 0))
&& check_filter(&server_filter_list, fname, 0) < 0)) {
fnamecmp = fname;
fnamecmp_type = FNAMECMP_FNAME;
}
} else {
/* Reminder: --inplace && --partial-dir are never
* enabled at the same time. */
if (inplace && make_backups > 0) {
if (!(fnamecmp = get_backup_name(fname)))
fnamecmp = fname;
else
fnamecmp_type = FNAMECMP_BACKUP;
} else if (partial_dir && partialptr)
fnamecmp = partialptr;
else
@@ -554,11 +594,14 @@ int recv_files(int f_in, char *local_name)
}
}
updating_basis_or_equiv = inplace
&& (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);
if (fd1 == -1) {
st.st_mode = 0;
st.st_size = 0;
} else if (do_fstat(fd1,&st) != 0) {
rsyserr(FERROR, errno, "fstat %s failed",
rsyserr(FERROR_XFER, errno, "fstat %s failed",
full_fname(fnamecmp));
discard_receive_data(f_in, F_LENGTH(file));
close(fd1);
@@ -573,7 +616,7 @@ int recv_files(int f_in, char *local_name)
* and the underlying robust_unlink could cope
* with directories
*/
rprintf(FERROR,"recv_files: %s is a directory\n",
rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
full_fname(fnamecmp));
discard_receive_data(f_in, F_LENGTH(file));
close(fd1);
@@ -607,54 +650,22 @@ int recv_files(int f_in, char *local_name)
if (inplace) {
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
if (fd2 == -1) {
rsyserr(FERROR, errno, "open %s failed",
rsyserr(FERROR_XFER, errno, "open %s failed",
full_fname(fname));
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
} else {
if (!get_tmpname(fnametmp,fname)) {
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
fd2 = open_tmpfile(fnametmp, fname, file);
if (fd2 != -1)
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
}
/* we initially set the perms without the
* setuid/setgid bits to ensure that there is no race
* condition. They are then correctly updated after
* the lchown. Thanks to snabb@epipe.fi for pointing
* this out. We also set it initially without group
* access because of a similar race condition. */
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
/* in most cases parent directories will already exist
* because their information should have been previously
* transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT
&& create_directory_path(fnametmp) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rsyserr(FERROR, errno, "mkstemp %s failed",
full_fname(fnametmp));
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
if (fd2 == -1) {
discard_receive_data(f_in, F_LENGTH(file));
if (fd1 != -1)
close(fd1);
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
continue;
}
/* log the transfer */
@@ -678,26 +689,23 @@ int recv_files(int f_in, char *local_name)
}
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
char *temp_copy_name;
if (partialptr == fname)
partialptr = temp_copy_name = NULL;
else if (*partial_dir == '/')
temp_copy_name = NULL;
else
temp_copy_name = partialptr;
finish_transfer(fname, fnametmp, fnamecmp,
temp_copy_name, file, recv_ok, 1);
if (fnamecmp == partialptr) {
partialptr = NULL;
if (!finish_transfer(fname, fnametmp, fnamecmp,
partialptr, file, recv_ok, 1))
recv_ok = -1;
else if (fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir);
if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
recv_ok = -1;
else if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
recv_ok = 2;
}
} else {
partialptr = NULL;
@@ -706,13 +714,15 @@ int recv_files(int f_in, char *local_name)
cleanup_disable();
if (recv_ok > 0) {
switch (recv_ok) {
case 1:
if (remove_source_files || inc_recurse
|| (preserve_hard_links && F_IS_HLINKED(file)))
send_msg_int(MSG_SUCCESS, ndx);
} else if (!recv_ok) {
enum logcode msgtype = redoing || read_batch ? FERROR : FINFO;
if (msgtype == FERROR || verbose) {
break;
case 0: {
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
if (msgtype == FERROR_XFER || verbose) {
char *errstr, *redostr, *keptstr;
if (!(keep_partial && partialptr) && !inplace)
keptstr = "discarded";
@@ -720,22 +730,30 @@ int recv_files(int f_in, char *local_name)
keptstr = "put into partial-dir";
else
keptstr = "retained";
if (msgtype == FERROR) {
if (msgtype == FERROR_XFER) {
errstr = "ERROR";
redostr = "";
} else {
errstr = "WARNING";
redostr = " (will try again)";
redostr = read_batch ? " (may try again)"
: " (will try again)";
}
rprintf(msgtype,
"%s: %s failed verification -- update %s%s.\n",
errstr, fname, keptstr, redostr);
errstr, local_name ? f_name(file, NULL) : fname,
keptstr, redostr);
}
if (!redoing) {
send_msg_int(MSG_REDO, ndx);
file->flags |= FLAG_FILE_SENT;
} else if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
break;
}
case -1:
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
break;
}
}
if (make_backups < 0)

38
rounding.c Normal file
View File

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

116
rsync.c
View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +41,7 @@ extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int protocol_version;
extern int receiver_symlink_times;
extern int uid_ndx;
extern int gid_ndx;
extern int inc_recurse;
@@ -211,7 +212,7 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
int len, iflags = 0;
struct file_list *flist;
uchar fnamecmp_type = FNAMECMP_FNAME;
int ndx;
int ndx, save_verbose = verbose;
read_loop:
while (1) {
@@ -239,15 +240,17 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
}
/* Send everything read from f_in to msg_fd_out. */
send_msg_int(MSG_FLIST, ndx);
start_flist_forward(f_in);
if (verbose > 3) {
rprintf(FINFO, "[%s] receiving flist for dir %d\n",
who_am_i(), ndx);
}
verbose = 0;
send_msg_int(MSG_FLIST, ndx);
start_flist_forward(f_in);
flist = recv_file_list(f_in);
flist->parent_ndx = ndx;
stop_flist_forward();
verbose = save_verbose;
}
iflags = protocol_version >= 29 ? read_shortint(f_in)
@@ -262,11 +265,13 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
}
if (!(flist = flist_for_ndx(ndx))) {
int start, used;
invalid_ndx:
start = first_flist ? first_flist->ndx_start : 0;
used = first_flist ? first_flist->used : 0;
rprintf(FERROR,
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
ndx, first_flist->ndx_start - 1, first_flist->prev->ndx_end,
iflags, who_am_i());
ndx, start - 1, start + used -1, iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
cur_flist = flist;
@@ -347,7 +352,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
if (dry_run)
return 1;
if (link_stat(fname, &sx2.st, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return 0;
}
@@ -368,16 +373,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
new_mode |= S_ISGID;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
get_acl(fname, sxp);
#endif
#ifdef SUPPORT_XATTRS
if (am_root < 0)
set_stat_xattr(fname, file, new_mode);
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
if (am_root < 0)
set_stat_xattr(fname, file);
#endif
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
@@ -386,12 +394,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
if (ret < 0) {
rsyserr(FERROR, errno, "failed to set times on %s",
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
full_fname(fname));
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
else if (receiver_symlink_times)
file->flags |= FLAG_TIME_FAILED;
}
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
@@ -415,31 +425,28 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
}
}
if (am_root < 0) {
;
} else if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
* unless have the privilege */
rsyserr(FERROR, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
} else
/* a lchown had been done - we have to re-stat if the
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
if (am_root >= 0) {
if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
/* We shouldn't have attempted to change uid
* or gid unless have the privilege. */
rsyserr(FERROR_XFER, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
}
/* A lchown had been done, so we need to re-stat if
* the destination had the setuid or setgid bits set
* (due to the side effect of the chown call). */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
}
}
updated = 1;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
/* It's OK to call set_acl() now, even for a dir, as the generator
* will enable owner-writability using chmod, if necessary.
@@ -455,7 +462,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"failed to set permissions on %s",
full_fname(fname));
goto cleanup;
@@ -500,15 +507,17 @@ RETSIGTYPE sig_int(UNUSED(int val))
}
/* Finish off a file transfer: renaming the file and setting the file's
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
* NULL and the robust_rename() call is forced to copy the temp file, we
* stage the file into the partial-dir and then rename it into place. */
void finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
* attributes (e.g. permissions, ownership, etc.). If the robust_rename()
* call is forced to copy the temp file and partialptr is both non-NULL and
* not an absolute path, we stage the file into the partial-dir and then
* rename it into place. This returns 1 on succcess or 0 on failure. */
int finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
{
int ret;
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
if (inplace) {
if (verbose > 2)
@@ -518,7 +527,7 @@ void finish_transfer(const char *fname, const char *fnametmp,
}
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return;
return 1;
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -527,34 +536,39 @@ void finish_transfer(const char *fname, const char *fnametmp,
/* move tmp file over real file */
if (verbose > 2)
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
ret = robust_rename(fnametmp, fname, partialptr,
ret = robust_rename(fnametmp, fname, temp_copy_name,
file->mode & INITACCESSPERMS);
if (ret < 0) {
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname);
do_unlink(fnametmp);
return;
if (!partialptr || (ret == -2 && temp_copy_name)
|| robust_rename(fnametmp, partialptr, NULL,
file->mode & INITACCESSPERMS) < 0)
do_unlink(fnametmp);
return 0;
}
if (ret == 0) {
/* The file was moved into place (not copied), so it's done. */
return;
return 1;
}
/* The file was copied, so tweak the perms of the copied file. If it
* was copied to partialptr, move it into its final destination. */
fnametmp = partialptr ? partialptr : fname;
fnametmp = temp_copy_name ? temp_copy_name : fname;
do_set_file_attrs:
set_file_attrs(fnametmp, file, NULL, fnamecmp,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
if (partialptr) {
if (temp_copy_name) {
if (do_rename(fnametmp, fname) < 0) {
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
full_fname(fnametmp), fname);
} else
handle_partial_dir(partialptr, PDIR_DELETE);
return 0;
}
handle_partial_dir(temp_copy_name, PDIR_DELETE);
}
return 1;
}
struct file_list *flist_for_ndx(int ndx)
@@ -569,7 +583,7 @@ struct file_list *flist_for_ndx(int ndx)
return NULL;
flist = flist->prev;
}
while (ndx > flist->ndx_end) {
while (ndx >= flist->ndx_start + flist->used) {
if (!(flist = flist->next))
return NULL;
}

47
rsync.h
View File

@@ -2,7 +2,7 @@
* Copyright (C) 1996, 2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,6 +32,9 @@
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
#define URL_PREFIX "rsync://"
#define SYMLINK_PREFIX "/rsyncd-munged/"
#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
#define BACKUP_SUFFIX "~"
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
@@ -74,6 +77,7 @@
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator (checked on all types) */
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
#define FLAG_TIME_FAILED (1<<11)/* generator */
/* These flags are passed to functions but not stored. */
@@ -90,7 +94,7 @@
/* This is used when working on a new protocol version in CVS, and should
* be a new non-zero value for each CVS change that affects the protocol.
* It must ALWAYS be 0 when the protocol goes final! */
#define SUBPROTOCOL_VERSION 12
#define SUBPROTOCOL_VERSION 0
/* We refuse to interoperate with versions that are not in this range.
* Note that we assume we'll work with later versions: the onus is on
@@ -183,18 +187,29 @@
#define SIGNIFICANT_ITEM_FLAGS (~(\
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
#define CFN_KEEP_LEADING_DOT_DIR (1<<0)
#define CFN_KEEP_TRAILING_SLASH (1<<1)
#define CFN_DROP_TRAILING_DOT_DIR (1<<2)
#define CFN_COLLAPSE_DOT_DOT_DIRS (1<<3)
/* Log-message categories. Only FERROR and FINFO get sent over the socket,
* but FLOG and FSOCKERR can be sent over the receiver -> generator pipe.
* FLOG only goes to the log file, not the client; FCLIENT is the opposite. */
enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
/* Log-message categories. FLOG only goes to the log file, not the client;
* FCLIENT is the opposite. */
enum logcode {
FNONE=0, /* never sent */
FERROR_XFER=1, FINFO=2, /* sent over socket for any protocol */
FERROR=3, FWARNING=4, /* sent over socket for protocols >= 30 */
FERROR_SOCKET=5, FLOG=6, /* only sent via receiver -> generator pipe */
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
};
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, MSG_SOCKERR=FSOCKERR, /* sibling logging */
MSG_ERROR_XFER=FERROR_XFER, MSG_INFO=FINFO, /* remote logging */
MSG_ERROR=FERROR, MSG_WARNING=FWARNING, /* protocol-30 remote logging */
MSG_ERROR_SOCKET=FERROR_SOCKET, /* sibling logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
MSG_FLIST=20, /* extra file list over sibling socket */
MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
@@ -327,7 +342,9 @@ enum msgcode {
#include <stdarg.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <syslog.h>
#include <sys/file.h>
@@ -392,13 +409,13 @@ enum msgcode {
#include "lib/pool_alloc.h"
#ifndef HAVE_ID_T
typedef int id_t;
typedef unsigned int id_t;
#endif
#ifndef HAVE_PID_T
typedef int pid_t;
#endif
#ifndef HAVE_MODE_T
typedef int mode_t;
typedef unsigned int mode_t;
#endif
#ifndef HAVE_OFF_T
typedef long off_t;
@@ -524,6 +541,7 @@ struct hashtable {
void *nodes;
int32 size, entries;
uint32 node_size;
int key64;
};
struct ht_int32_node {
@@ -641,7 +659,7 @@ extern int xattrs_ndx;
#define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
#define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
#define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
#define F_NDX(f) REQ_EXTRA(f, ic_ndx)->num
#define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
/* These items are per-entry optional: */
#define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num /* non-dirs */
@@ -656,7 +674,7 @@ extern int xattrs_ndx;
/* This optional item might follow an F_HL_*() item.
* (Note: a device doesn't need to check LEN64_BUMP(f).) */
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + 2 - 1)->unum)
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + DEV_EXTRA_CNT - 1)->unum)
/* The sum is only present on regular files. */
#define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
@@ -707,7 +725,7 @@ struct file_list {
int used, malloced;
int low, high; /* 0-relative index values excluding empties */
int ndx_start; /* the start offset for inc_recurse mode */
int ndx_end; /* the end offset for inc_recurse mode */
int flist_num; /* 1-relative file_list number or 0 */
int parent_ndx; /* dir_flist index of parent directory */
int in_progress, to_redo;
};
@@ -798,7 +816,6 @@ struct stats {
int64 flist_size;
int num_files;
int num_transferred_files;
int current_file_index;
};
struct chmod_mode_struct;
@@ -837,7 +854,7 @@ typedef struct {
#define RL_CONVERT (1<<2)
typedef struct {
char is_dot_dir;
char name_type;
char fname[1]; /* has variable size */
} relnamecache;

124
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(26 Oct 2007)()()
manpage(rsync)(1)(1 Mar 2008)()()
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
manpagesynopsis()
@@ -225,7 +225,7 @@ verb( export RSYNC_CONNECT_PROG='ssh proxyhost nc %H 873'
rsync -av targethost1::module/src/ /dest/
rsync -av rsync:://targethost2/module/src/ /dest/ )
The command specifed above uses ssh to run nc (netcat) on a proxyhost,
The command specified above uses ssh to run nc (netcat) on a proxyhost,
which forwards all data to port 873 (the rsync daemon) on the targethost
(%H).
@@ -328,7 +328,7 @@ to the detailed description below for a complete description. verb(
-u, --update skip files that are newer on the receiver
--inplace update destination files in-place
--append append data onto shorter files
--append-verify --append w/old data in file cheksum
--append-verify --append w/old data in file checksum
-d, --dirs transfer directories without recursing
-l, --links copy symlinks as symlinks
-L, --copy-links transform symlink into referent file/dir
@@ -352,8 +352,8 @@ to the detailed description below for a complete description. verb(
--super receiver attempts super-user activities
--fake-super store/recover privileged attrs using xattrs
-S, --sparse handle sparse files efficiently
-n, --dry-run show what would have been transferred
-W, --whole-file copy files whole (without rsync algorithm)
-n, --dry-run perform a trial run with no changes made
-W, --whole-file copy files whole (w/o delta-xfer algorithm)
-x, --one-file-system don't cross filesystem boundaries
-B, --block-size=SIZE force a fixed checksum block-size
-e, --rsh=COMMAND specify the remote shell to use
@@ -378,7 +378,8 @@ to the detailed description below for a complete description. verb(
--delay-updates put all updated files into place at end
-m, --prune-empty-dirs prune empty directory chains from file-list
--numeric-ids don't map uid/gid values by user/group name
--timeout=TIME set I/O timeout in seconds
--timeout=SECONDS set I/O timeout in seconds
--contimeout=SECONDS set daemon connection timeout in seconds
-I, --ignore-times don't skip files that match size and time
--size-only skip files that match in size
--modify-window=NUM compare mod-times with reduced accuracy
@@ -421,7 +422,7 @@ to the detailed description below for a complete description. verb(
--only-write-batch=FILE like --write-batch but w/o updating dest
--read-batch=FILE read a batched update from FILE
--protocol=NUM force an older protocol version to be used
--iconv=CONVERT_SPEC request charset conversion of filesnames
--iconv=CONVERT_SPEC request charset conversion of filenames
--checksum-seed=NUM set block/file checksum seed (advanced)
-4, --ipv4 prefer IPv4
-6, --ipv6 prefer IPv6
@@ -527,7 +528,7 @@ either a changed size or a changed checksum are selected for transfer.
Note that rsync always verifies that each em(transferred) file was
correctly reconstructed on the receiving side by checking a whole-file
checksum that is generated when as the file is transferred, but that
checksum that is generated as the file is transferred, but that
automatic after-the-transfer verification has nothing to do with this
option's before-the-transfer "Does this file need to be updated?" check.
@@ -801,6 +802,14 @@ directory, and receives the file into the new directory. With
bf(--keep-dirlinks), the receiver keeps the symlink and "file" ends up in
"bar".
One note of caution: if you use bf(--keep-dirlinks), you must trust all
the symlinks in the copy! If it is possible for an untrusted user to
create their own symlink to any directory, the user could then (on a
subsequent copy) replace the symlink with a real directory and affect the
content of whatever directory the symlink references. For backup copies,
you are better off using something like a bind mount instead of a symlink
to modify your receiving hierarchy.
See also bf(--copy-dirlinks) for an analogous option for the sending side.
dit(bf(-H, --hard-links)) This tells rsync to look for hard-linked files in
@@ -808,11 +817,24 @@ the transfer and link together the corresponding files on the receiving
side. Without this option, hard-linked files in the transfer are treated
as though they were separate files.
Note that rsync can only detect hard links if both parts of the link
are in the list of files being sent.
When you are updating a non-empty destination, this option only ensures
that files that are hard-linked together on the source are hard-linked
together on the destination. It does NOT currently endeavor to break
already existing hard links on the destination that do not exist between
the source files. Note, however, that if one or more extra-linked files
have content changes, they will become unlinked when updated (assuming you
are not using the bf(--inplace) option).
Note that rsync can only detect hard links between files that are inside
the transfer set. If rsync updates a file that has extra hard-link
connections to files outside the transfer, that linkage will be broken. If
you are tempted to use the bf(--inplace) option to avoid this breakage, be
very careful that you know how your files are being updated so that you are
certain that no unintended changes happen due to lingering hard links (and
see the bf(--inplace) option for more caveats).
If incremental recursion is active (see bf(--recursive)), rsync may transfer
a missing hard-linked file before it finds that another link for the file
a missing hard-linked file before it finds that another link for that contents
exists elsewhere in the hierarchy. This does not affect the accuracy of
the transfer, just its efficiency. One way to avoid this is to disable
incremental recursion using the bf(--no-inc-recursive) option.
@@ -846,17 +868,17 @@ permissions (while leaving existing files unchanged), make sure that the
bf(--perms) option is off and use bf(--chmod=ugo=rwX) (which ensures that
all non-masked bits get enabled). If you'd care to make this latter
behavior easier to type, you could define a popt alias for it, such as
putting this line in the file ~/.popt (this defines the bf(-s) option,
putting this line in the file ~/.popt (the following defines the bf(-Z) option,
and includes --no-g to use the default group of the destination dir):
quote(tt( rsync alias -s --no-p --no-g --chmod=ugo=rwX))
quote(tt( rsync alias -Z --no-p --no-g --chmod=ugo=rwX))
You could then use this new option in a command such as this one:
quote(tt( rsync -asv src/ dest/))
quote(tt( rsync -avZ src/ dest/))
(Caveat: make sure that bf(-a) does not follow bf(-s), or it will re-enable
the "--no-*" options.)
(Caveat: make sure that bf(-a) does not follow bf(-Z), or it will re-enable
the two "--no-*" options mentioned above.)
The preservation of the destination's setgid bit on newly-created
directories when bf(--perms) is off was added in rsync 2.6.7. Older rsync
@@ -987,7 +1009,7 @@ files we create can always be accessed/changed by the creating user).
This option also handles ACLs (if bf(--acls) was specified) and non-user
extended attributes (if bf(--xattrs) was specified).
This is a good way to backup data withou using a super-user, and to store
This is a good way to backup data without using a super-user, and to store
ACLs from incompatible systems.
The bf(--fake-super) option only affects the side where the option is used.
@@ -997,7 +1019,7 @@ path:
quote(tt( rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
Since there is only one "side" in a local copy, this option affects both
the sending and recieving of files. You'll need to specify a copy using
the sending and receiving of files. You'll need to specify a copy using
"localhost" if you need to avoid this, possibly using the "lsh" shell
script (from the support directory) as a substitute for an actual remote
shell (see bf(--rsh)).
@@ -1014,10 +1036,22 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
filesystem. It doesn't seem to handle seeks over null regions
correctly and ends up corrupting the files.
dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
instead it will just report the actions it would have taken.
dit(bf(-n, --dry-run)) This makes rsync perform a trial run that doesn't
make any changes (and produces mostly the same output as a real run). It
is most commonly used in combination with the bf(-v, --verbose) and/or
bf(-i, --itemize-changes) options to see what an rsync command is going
to do before one actually runs it.
dit(bf(-W, --whole-file)) With this option the delta transfer algorithm
The output of bf(--itemize-changes) is supposed to be exactly the same on a
dry run and a subsequent real run (barring intentional trickery and system
call failures); if it isn't, that's a bug. Other output is the same to the
extent practical, but may differ in some areas. Notably, a dry run does not
send the actual data for file transfers, so bf(--progress) has no effect,
the "bytes sent", "bytes received", "literal data", and "matched data"
statistics are too small, and the "speedup" value is equivalent to a run
where no file transfers are needed.
dit(bf(-W, --whole-file)) With this option the delta-transfer algorithm
is not used and the whole file is sent as-is instead. The transfer may be
faster if this option is used when the bandwidth between the source and
destination machines is higher than the bandwidth to disk (especially when the
@@ -1272,7 +1306,10 @@ exclude certain files from the list of files to be transferred. This is
most useful in combination with a recursive transfer.
You may use as many bf(--filter) options on the command line as you like
to build up the list of files to exclude.
to build up the list of files to exclude. If the filter contains whitespace,
be sure to quote it so that the shell gives the rule to rsync as a single
argument. The text below also mentions that you can use an underscore to
replace the space that separates a rule from its arg.
See the FILTER RULES section for detailed information on this option.
@@ -1385,7 +1422,7 @@ characters are not translated (such as ~, $, ;, &, etc.). Wildcards are
expanded on the remote host by rsync (instead of the shell doing it).
If you use this option with bf(--iconv), the args will also be translated
from the local to the remote character set. The translation happens before
from the local to the remote character-set. The translation happens before
wild-cards are expanded. See also the bf(--files-from) option.
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
@@ -1395,7 +1432,7 @@ file in the same directory as the associated destination file.
This option is most often used when the receiving disk partition does not
have enough free space to hold a copy of the largest file in the transfer.
In this case (i.e. when the scratch directory in on a different disk
In this case (i.e. when the scratch directory is on a different disk
partition), rsync will not be able to rename each received temporary file
over the top of the associated destination file, but instead must copy it
into place. Rsync does this by copying the file over the top of the
@@ -1562,6 +1599,10 @@ dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
timeout in seconds. If no data is transferred for the specified time
then rsync will exit. The default is 0, which means no timeout.
dit(bf(--contimeout)) This option allows you to set the amount of time
that rsync will wait for its connection to an rsync daemon to succeed.
If the timeout is reached, rsync exits with an error.
dit(bf(--address)) By default rsync will bind to the wildcard address when
connecting to an rsync daemon. The bf(--address) option allows you to
specify a specific IP address (or hostname) to bind to. See also this
@@ -1615,6 +1656,8 @@ quote(itemization(
bf(--hard-links)).
it() A bf(.) means that the item is not being updated (though it might
have attributes that are being modified).
it() A bf(*) means that the rest of the itemized-output area contains
a message (e.g. "deleting").
))
The file-types that replace the bf(X) are: bf(f) for a file, a bf(d) for a
@@ -1638,19 +1681,17 @@ quote(itemization(
it() A bf(t) means the modification time is different and is being updated
to the sender's value (requires bf(--times)). An alternate value of bf(T)
means that the modification time will be set to the transfer time, which happens
anytime a symlink is transferred, or when a regular file or device is
transferred without bf(--times).
when a file/symlink/device is updated without bf(--times) and when a
symlink is changed and the receiver can't set its time.
it() A bf(p) means the permissions are different and are being updated to
the sender's value (requires bf(--perms)).
it() An bf(o) means the owner is different and is being updated to the
sender's value (requires bf(--owner) and super-user privileges).
it() A bf(g) means the group is different and is being updated to the
sender's value (requires bf(--group) and the authority to set the group).
it() The bf(u) slot is reserved for reporting update (access) time changes
(a feature that is not yet released).
it() The bf(u) slot is reserved for future use.
it() The bf(a) means that the ACL information changed.
it() The bf(x) slot is reserved for reporting extended attribute changes
(a feature that is not yet released).
it() The bf(x) means that the extended attribute information changed.
))
One other output is possible: when deleting files, the "%i" will output
@@ -1919,6 +1960,8 @@ dit(bf(--password-file)) This option allows you to provide a password in a
file for accessing an rsync daemon. The file must not be world readable.
It should contain just the password as a single line.
This option does not supply a password to a remote shell transport such as
ssh; to learn how to do that, consult the remote shell's documentation.
When accessing an rsync daemon using a remote shell as the transport, this
option only comes into effect after the remote shell finishes its
authentication (i.e. if you have also specified a password in the daemon's
@@ -1990,11 +2033,17 @@ dit(bf(--iconv=CONVERT_SPEC)) Rsync can convert filenames between character
sets using this option. Using a CONVERT_SPEC of "." tells rsync to look up
the default character-set via the locale setting. Alternately, you can
fully specify what conversion to do by giving a local and a remote charset
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591).
Finally, you can specify a CONVERT_SPEC of "-" to turn off any conversion.
separated by a comma in the order bf(--iconv=LOCAL,REMOTE), e.g.
bf(--iconv=utf8,iso88591). This order ensures that the option
will stay the same whether you're pushing or pulling files.
Finally, you can specify either bf(--no-iconv) or a CONVERT_SPEC of "-"
to turn off any conversion.
The default setting of this option is site-specific, and can also be
affected via the RSYNC_ICONV environment variable.
For a list of what charset names your local iconv library supports, you can
run "iconv --list".
If you specify the bf(--protect-args) option (bf(-s)), rsync will translate
the filenames you specify on the command-line that are being sent to the
remote host. See also the bf(--files-from) option.
@@ -2005,6 +2054,11 @@ specifying matching rules that can match on both sides of the transfer.
For instance, you can specify extra include/exclude rules if there are
filename differences on the two sides that need to be accounted for.
When you pass an bf(--iconv) option to an rsync daemon that allows it, the
daemon uses the charset specified in its "charset" configuration parameter
regardless of the remote charset you actually pass. Thus, you may feel free to
specify just the local charset for a daemon transfer (e.g. bf(--iconv=utf8)).
dit(bf(-4, --ipv4) or bf(-6, --ipv6)) Tells rsync to prefer IPv4/IPv6
when creating sockets. This only affects sockets that rsync has direct
control over, such as the outgoing socket when directly contacting an
@@ -2755,6 +2809,7 @@ dit(bf(23)) Partial transfer due to error
dit(bf(24)) Partial transfer due to vanished source files
dit(bf(25)) The --max-delete limit stopped deletions
dit(bf(30)) Timeout in data send/receive
dit(bf(35)) Timeout waiting for daemon connection
enddit()
manpagesection(ENVIRONMENT VARIABLES)
@@ -2774,7 +2829,8 @@ rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
password allows you to run authenticated rsync connections to an rsync
daemon without user intervention. Note that this does not supply a
password to a shell transport such as ssh.
password to a remote shell transport such as ssh; to learn how to do that,
consult the remote shell's documentation.
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
are used to determine the default username sent to an rsync daemon.
If neither is set, the username defaults to "nobody".
@@ -2808,7 +2864,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre4 of rsync.
This man page is current for version 3.0.0 of rsync.
manpagesection(INTERNAL OPTIONS)

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(26 Oct 2007)()()
manpage(rsyncd.conf)(5)(1 Mar 2008)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -113,6 +113,10 @@ After the global options you should define a number of modules, each
module exports a directory tree as a symbolic name. Modules are
exported by specifying a module name in square brackets [module]
followed by the options for that module.
The module name cannot contain a slash or a closing square bracket. If the
name contains whitespace, each internal sequence of whitespace will be
changed into a single space, while leading or trailing whitespace will be
discarded.
startdit()
@@ -129,35 +133,112 @@ to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges,
of not being able to follow symbolic links that are either absolute or outside
of the new root path, and of complicating the preservation of usernames and groups
(see below). When "use chroot" is false, for security reasons,
symlinks may only be relative paths pointing to other files within the root
path, and leading slashes are removed from most absolute paths (options
such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
rooted in the module's "path" dir, just as if chroot was specified).
The default for "use chroot" is true.
of the new root path, and of complicating the preservation of users and groups
by name (see below).
In order to preserve usernames and groupnames, rsync needs to be able to
As an additional safety feature, you can specify a dot-dir in the module's
"path" to indicate the point where the chroot should occur. This allows rsync
to run in a chroot with a non-"/" path for the top of the transfer hierarchy.
Doing this guards against unintended library loading (since those absolute
paths will not be inside the transfer hierarchy unless you have used an unwise
pathname), and lets you setup libraries for the chroot that are outside of the
transfer. For example, specifying "/var/rsync/./module1" will chroot to the
"/var/rsync" directory and set the inside-chroot path to "/module1". If you
had omitted the dot-dir, the chroot would have used the whole path, and the
inside-chroot path would have been "/".
When "use chroot" is false or the inside-chroot path is not "/", rsync will:
(1) munge symlinks by
default for security reasons (see "munge symlinks" for a way to turn this
off, but only if you trust your users), (2) substitute leading slashes in
absolute paths with the module's path (so that options such as
bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
rooted in the module's "path" dir), and (3) trim ".." path elements from
args if rsync believes they would escape the module hierarchy.
The default for "use chroot" is true, and is the safer choice (especially
if the module is not read-only).
When this option is enabled, rsync will not attempt to map users and groups
by name (by default), but instead copy IDs as though bf(--numeric-ids) had
been specified. In order to enable name-mapping, rsync needs to be able to
use the standard library functions for looking up names and IDs (i.e.
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
process in the chroot namespace will need to have access to the resources
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())).
This means the rsync
process in the chroot hierarchy will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
able to copy the IDs, just as if the bf(--numeric-ids) option had been
specified.
/etc/group, but perhaps additional dynamic libraries as well).
Note that you are free to setup user/group information in the chroot area
differently from your normal system. For example, you could abbreviate
the list of users and groups. Also, you can protect this information from
being downloaded/uploaded by adding an exclude rule to the rsyncd.conf file
(e.g. "bf(exclude = /etc/**)"). Note that having the exclusion affect uploads
is a relatively new feature in rsync, so make sure your daemon is
at least 2.6.3 to effect this. Also note that it is safest to exclude a
directory and all its contents combining the rule "/some/dir/" with the
rule "/some/dir/**" just to be sure that rsync will not allow deeper
access to some of the excluded files inside the directory (rsync tries to
do this automatically, but you might as well specify both to be extra
sure).
If you copy the necessary resources into the module's chroot area, you
should protect them through your OS's normal user/group or ACL settings (to
prevent the rsync module's user from being able to change them), and then
hide them from the user's view via "exclude" (see how in the discussion of
that option). At that point it will be safe to enable the mapping of users
and groups by name using the "numeric ids" daemon option (see below).
Note also that you are free to setup custom user/group information in the
chroot area that is different from your normal system. For example, you
could abbreviate the list of users and groups.
dit(bf(numeric ids)) Enabling the "numeric ids" option disables the mapping
of users and groups by name for the current daemon module. This prevents
the daemon from trying to load any user/group-related files or libraries.
Enabling this option makes the transfer behave as if the client had passed
the bf(--numeric-ids) command-line option. By default, this parameter is
enabled for chroot modules and disabled for non-chroot modules.
A chroot-enabled module should not have this option enabled unless you've
taken steps to ensure that the module has the necessary resources it needs
to translate names, and that it is not possible for a user to change those
resources.
dit(bf(munge symlinks)) The "munge symlinks" option tells rsync to modify
all incoming symlinks in a way that makes them unusable but recoverable
(see below). This should help protect your files from user trickery when
your daemon module is writable. The default is disabled when "use chroot"
is on and the inside-chroot path is "/", otherwise it is enabled.
If you disable this option on a daemon that is not read-only, there
are tricks that a user can play with uploaded symlinks to access
daemon-excluded items (if your module has any), and, if "use chroot"
is off, rsync can even be tricked into showing or changing data that
is outside the module's path (as access-permissions allow).
The way rsync disables the use of symlinks is to prefix each one with
the string "/rsyncd-munged/". This prevents the links from being used
as long as that directory does not exist. When this option is enabled,
rsync will refuse to run if that path is a directory or a symlink to
a directory. When using the "munge symlinks" option in a chroot area
that has an inside-chroot path of "/", you should add "/rsyncd-munged/"
to the exclude setting for the module so that
a user can't try to create it.
Note: rsync makes no attempt to verify that any pre-existing symlinks in
the hierarchy are as safe as you want them to be. If you setup an rsync
daemon on a new area or locally add symlinks, you can manually protect your
symlinks from being abused by prefixing "/rsyncd-munged/" to the start of
every symlink's value. There is a perl script in the support directory
of the source code named "munge-symlinks" that can be used to add or remove
this prefix from your symlinks.
When this option is disabled on a writable module and "use chroot" is off
(or the inside-chroot path is not "/"),
incoming symlinks will be modified to drop a leading slash and to remove ".."
path elements that rsync believes will allow a symlink to escape the module's
hierarchy. There are tricky ways to work around this, though, so you had
better trust your users if you choose this combination of options.
dit(bf(charset)) This specifies the name of the character set in which the
module's filenames are stored. If the client uses an bf(--iconv) option,
the daemon will use the value of the "charset" parameter regardless of the
character set the client actually passed. This allows the daemon to
support charset conversion in a chroot module without extra files in the
chroot area, and also ensures that name-translation is done in a consistent
manner. If the "charset" parameter is not set, the bf(--iconv) option is
refused, just as if "iconv" had been specified via "refuse options".
If you wish to force users to always use bf(--iconv) for a particular
module, add "no-iconv" to the "refuse options" parameter. Keep in mind
that this will restrict access to your module to very new rsync clients.
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow.
@@ -256,6 +337,13 @@ from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a daemon.
When you want to exclude a directory and all its contents, it is safest to
use a rule that does both, such as "/some/dir/***" (the three stars tells
rsync to exclude the directory itself and everything inside it). This is
better than just excluding the directory alone with "/some/dir/", as it
helps to guard against attempts to trick rsync into accessing files deeper
in the hierarchy.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the daemon that contains exclude patterns, one per line.
This is only superficially equivalent
@@ -468,9 +556,9 @@ quote(tt( refuse options = c delete))
The reason the above refuses all delete options is that the options imply
bf(--delete), and implied options are refused just like explicit options.
As an additional safety feature, the refusal of "delete" also refuses
bf(remove-sent-files) when the daemon is the sender; if you want the latter
bf(remove-source-files) when the daemon is the sender; if you want the latter
without the former, instead refuse "delete-*" -- that refuses all the
delete modes without affecting bf(--remove-sent-files).
delete modes without affecting bf(--remove-source-files).
When an option is refused, the daemon prints an error message and exits.
To prevent all compression when serving files,
@@ -492,7 +580,7 @@ of the patterns will not be compressed during transfer.
See the bf(--skip-compress) option in the bf(rsync)(1) manpage for the list
of file suffixes that are not compressed by default. Specifying a value
for the bf(dont compress) option changes the default when the daemon is
for the "dont compress" option changes the default when the daemon is
the sender.
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
@@ -562,21 +650,21 @@ A more sophisticated example would be:
verb(
uid = nobody
gid = nobody
use chroot = no
use chroot = yes
max connections = 4
syslog facility = local5
pid file = /var/run/rsyncd.pid
[ftp]
path = /var/ftp/pub
path = /var/ftp/./pub
comment = whole ftp area (approx 6.1 GB)
[sambaftp]
path = /var/ftp/pub/samba
path = /var/ftp/./pub/samba
comment = Samba ftp area (approx 300 MB)
[rsyncftp]
path = /var/ftp/pub/rsync
path = /var/ftp/./pub/rsync
comment = rsync ftp area (approx 6 MB)
[sambawww]
@@ -614,7 +702,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre4 of rsync.
This man page is current for version 3.0.0 of rsync.
manpagesection(CREDITS)

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -229,7 +229,7 @@ void send_files(int f_in, int f_out)
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
recv_xattr_request(file, f_in);
#endif
@@ -265,7 +265,8 @@ void send_files(int f_in, int f_out)
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
stats.current_file_index = ndx;
if (!am_server && do_progress)
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.total_transferred_size += F_LENGTH(file);
@@ -289,13 +290,13 @@ void send_files(int f_in, int f_out)
if (errno == ENOENT) {
enum logcode c = am_daemon
&& protocol_version < 28 ? FERROR
: FINFO;
: FWARNING;
io_error |= IOERR_VANISHED;
rprintf(c, "file has vanished: %s\n",
full_fname(fname));
} else {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"send_files failed to open %s",
full_fname(fname));
}
@@ -349,7 +350,7 @@ void send_files(int f_in, int f_out)
j = unmap_file(mbuf);
if (j) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, j,
rsyserr(FERROR_XFER, j,
"read errors mapping %s",
full_fname(fname));
}

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
extern char *bind_address;
extern int default_af_hint;
extern int connect_timeout;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
@@ -157,6 +158,11 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
return -1;
}
/* connect() timeout handler based on alarm() */
static RETSIGTYPE contimeout_handler(UNUSED(int val))
{
connect_timeout = -1;
}
/**
* Open a socket to a tcp remote host with the specified port .
@@ -261,11 +267,27 @@ int open_socket_out(char *host, int port, const char *bind_addr,
s = -1;
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
if (connect_timeout > 0) {
SIGACTION(SIGALRM, contimeout_handler);
alarm(connect_timeout);
}
while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
if (connect_timeout < 0)
exit_cleanup(RERR_CONTIMEOUT);
if (errno == EINTR)
continue;
close(s);
s = -1;
continue;
break;
}
if (connect_timeout > 0)
alarm(0);
if (s < 0)
continue;
if (proxied
&& establish_proxy_connection(s, host, port,
proxy_user, proxy_pass) != 0) {

18
support/extern-squish Executable file
View File

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

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

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

60
support/munge-symlinks Executable file
View File

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

190
support/patch-update Executable file
View File

@@ -0,0 +1,190 @@
#!/usr/bin/perl -w
# This script is used to turn one or more of the "patch/*" branches
# into one or more diffs in the "patches" directory. Pass the option
# --gen if you want generated files in the diffs. Pass the name of
# one or more diffs if you want to just update a subset of all the
# diffs.
use strict;
use Getopt::Long;
my $patches_dir = 'patches';
my $tmp_dir = "patches.$$";
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'skip-check' => \( my $skip_branch_check ),
'gen:s' => \( my $incl_generated_files ),
'help|h' => \( my $help_opt ),
);
&usage if $help_opt;
if (defined $incl_generated_files) {
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
$incl_generated_files = 1;
}
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
die "No '.git' directory present in the current dir.\n" unless -d '.git';
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
unless ($skip_branch_check) {
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
}
my($starting_branch) = $status =~ /^# On branch (.+)\n/;
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
if (s/^GENFILES=//) {
while (s/\\$//) {
$_ .= <IN>;
}
@extra_files = split(' ', $_);
last;
}
}
close IN;
if ($incl_generated_files) {
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
}
my $last_touch = time;
my(@patches, %local_patch);
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
while (<PIPE>) {
if (m# origin/patch/(.*)#) {
push(@patches, $1);
} elsif (m# patch/(.*)#) {
$local_patch{$1} = 1;
}
}
close PIPE;
my(%parent, %description);
foreach my $patch (@patches) {
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
my $desc = '';
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
while (<PIPE>) {
last if /^@@ /;
}
while (<PIPE>) {
next unless s/^[ +]//;
if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
$parent{$patch} = $1;
}
$desc .= $_;
}
$description{$patch} = $desc;
}
if (@ARGV) {
# Limit the list of patches to actually process based on @ARGV.
@patches = ( );
foreach (@ARGV) {
s{^(patches|patch|origin/patch)/} {};
s{\.diff$} {};
push(@patches, $_);
}
}
my %completed;
foreach my $patch (@patches) {
next if $completed{$patch}++;
update_patch($patch);
}
if ($incl_generated_files) {
system "rm -rf $tmp_dir";
}
sleep 1 if $last_touch == time;
system "git checkout $starting_branch" and exit 1;
exit;
sub update_patch
{
my($patch) = @_;
my $parent = $parent{$patch};
if (defined $parent) {
unless ($completed{$parent}++) {
update_patch($parent);
}
$parent = "patch/$parent";
} else {
$parent = 'master';
}
print "======== $patch ========\n";
sleep 1 if $incl_generated_files && $last_touch == time;
if ($local_patch{$patch}) {
system "git checkout patch/$patch" and exit 1;
} else {
system "git checkout --track -b patch/$patch origin/patch/$patch" and exit 1;
}
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
print OUT $description{$patch}, "\n";
if (system("git merge $parent") != 0) {
print qq|"git merge $parent" incomplete -- please fix.\n|;
$ENV{PS1} = "[$parent] patch/$patch: ";
system $ENV{SHELL} and exit 1;
}
if ($incl_generated_files) {
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
DIFF: while (<PIPE>) {
while (m{^diff --git a/PATCH}) {
while (<PIPE>) {
last if m{^diff --git a/};
}
last DIFF if !defined $_;
}
next if /^index /;
print OUT $_;
}
close PIPE;
if ($incl_generated_files) {
$parent =~ s#.*/##;
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
while (<PIPE>) {
s#^(diff -up) $tmp_dir/[^/]+/(.*?) $tmp_dir/[^/]+/(.*)#$1 a/$2 b/$3#o;
s#^\Q---\E $tmp_dir/[^/]+/([^\t]+)\t.*#--- a/$1#o;
s#^\Q+++\E $tmp_dir/[^/]+/([^\t]+)\t.*#+++ b/$1#o;
print OUT $_;
}
close PIPE;
}
close OUT;
}
exit;
sub usage
{
die <<EOT;
Usage: patch-update [OPTIONS]
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
--skip-check Skip the check that ensures starting with a clean branch.
EOT
}

View File

@@ -4,7 +4,7 @@
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,6 +34,7 @@ extern int am_root;
extern int read_only;
extern int list_only;
extern int preserve_perms;
extern int preserve_executability;
#define RETURN_ERROR_IF(x,e) \
do { \
@@ -167,7 +168,7 @@ int do_chmod(const char *path, mode_t mode)
#endif
} else
code = chmod(path, mode & CHMOD_BITS);
if (code != 0 && preserve_perms)
if (code != 0 && (preserve_perms || preserve_executability))
return code;
return 0;
}
@@ -211,6 +212,7 @@ int do_mkstemp(char *template, mode_t perms)
{
RETURN_ERROR_IF(dry_run, 0);
RETURN_ERROR_IF(read_only, EROFS);
perms |= S_IWUSR;
#if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
{

View File

@@ -3,7 +3,7 @@
* functions, so that module test harnesses can run standalone.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -2,7 +2,7 @@
* Test harness for unsafe_symlink(). Not linked into rsync itself.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@ int read_only = 0;
int list_only = 0;
int verbose = 0;
int preserve_perms = 0;
int preserve_executability = 0;
int
main(int argc, char **argv)

View File

@@ -43,7 +43,7 @@ runtest "BATCH.sh use of --read-batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"'
rm -rf "$todir"
mkdir "$todir" || test_fail "failed to restore empty destination directory"
runtest "daemon recv --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
runtest "daemon recv --write-batch" 'checkit "\"$ignore23\" $RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
# The script would have aborted on error, so getting here means we pass.
exit 0

View File

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

View File

@@ -81,14 +81,14 @@ touch -r "$fromdir/block" "$fromdir/block2"
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++++ block
cD$all_plus block
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -ai "$fromdir/block2" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++++ block2
cD$all_plus block2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
@@ -97,7 +97,7 @@ sleep 1
$RSYNC -Di "$fromdir/block3" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD..T...... block3
cD..T.$dots block3
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -105,15 +105,15 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t...... ./
cD..t...... block
cD block2
cD+++++++++ block3
hD+++++++++ block2.5 => block3
cD+++++++++ char
cD+++++++++ char2
cD+++++++++ char3
cS+++++++++ fifo
.d..t.$dots ./
cD..t.$dots block
cD$allspace block2
cD$all_plus block3
hD$all_plus block2.5 => block3
cD$all_plus char
cD$all_plus char2
cD$all_plus char3
cS$all_plus fifo
EOT
if test ! -r "$fromdir/block2.5"; then
sed -e '/block2\.5/d' <"$chkfile" >"$chkfile.new"
@@ -132,15 +132,15 @@ if test -b "$fromdir/block2.5"; then
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd ./
hD block
hD block2
hD block2.5
hD block3
hD char
hD char2
hD char3
hS fifo
cd$allspace ./
hD$allspace block
hD$allspace block2
hD$allspace block2.5
hD$allspace block3
hD$allspace char
hD$allspace char2
hD$allspace char3
hS$allspace fifo
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
fi

View File

@@ -26,7 +26,8 @@ ln -s ../bar/baz/rsync "$fromdir/foo/sym"
umask 022
ln "$fromdir/foo/config1" "$fromdir/foo/extra"
# Check if the OS can hard-link symlinks or not
# Check if the OS can hard-link symlinks or not.
# (Note: the link we check MUST NOT point to a valid file!)
ln -s no-such-dir "$to2dir"
if ln "$to2dir" "$to2dir.test" 2>/dev/null; then
L=hL
@@ -35,18 +36,32 @@ else
fi
rm -f "$to2dir" "$to2dir.test"
# Check if rsync can preserve time on symlinks
case "$RSYNC" in
*protocol=2*)
T=.T
;;
*)
if $RSYNC --version | grep ", symtimes" >/dev/null; then
T=.t
else
T=.T
fi
;;
esac
$RSYNC -iplr "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++++ ./
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
cd$all_plus ./
cd$all_plus bar/
cd$all_plus bar/baz/
>f$all_plus bar/baz/rsync
cd$all_plus foo/
>f$all_plus foo/config1
>f$all_plus foo/config2
>f$all_plus foo/extra
cL$all_plus foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
@@ -58,10 +73,10 @@ 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
>f..T.$dots bar/baz/rsync
>f..T.$dots foo/config1
>f.sTp$dots foo/config2
hf..T.$dots foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
@@ -78,11 +93,11 @@ 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
.f..tp$dots bar/baz/rsync
.d..t.$dots foo/
.f..t.$dots foo/config1
>fcstp$dots foo/config2
cL.$T.$dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -107,15 +122,15 @@ $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
.d$allspace ./
.d$allspace bar/
.d$allspace bar/baz/
.f...p$dots bar/baz/rsync
.d$allspace foo/
.f$allspace foo/config1
>f..t.$dots foo/config2
hf$allspace foo/extra
.L$allspace foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
@@ -134,32 +149,47 @@ touch "$todir/foo/config2"
$RSYNC -iplrtH "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
.f...p..... foo/config1
>f..t...... foo/config2
.f...p$dots foo/config1
>f..t.$dots foo/config2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
$RSYNC -ivvplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
case `tail -1 "$outfile"` in
cL..t*)
sym_dots="..t.$dots"
L_sym_dots="cL$sym_dots"
is_uptodate='-> ../bar/baz/rsync'
echo "cL$sym_dots foo/sym $is_uptodate" >"$chkfile.extra"
L=cL
;;
*)
sym_dots="$allspace"
L_sym_dots=".L$allspace"
is_uptodate='is uptodate'
touch "$chkfile.extra"
;;
esac
cat <<EOT >"$chkfile"
cd ./
cd bar/
cd bar/baz/
cf bar/baz/rsync
cd foo/
cf foo/config1
cf foo/config2
hf foo/extra => foo/config1
cL foo/sym -> ../bar/baz/rsync
cd$allspace ./
cd$allspace bar/
cd$allspace bar/baz/
cf$allspace bar/baz/rsync
cd$allspace foo/
cf$allspace foo/config1
cf$allspace foo/config2
hf$allspace foo/extra => foo/config1
cL$sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
hf foo/extra => foo/config1
cat - "$chkfile.extra" <<EOT >"$chkfile"
hf$allspace foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
@@ -176,7 +206,7 @@ foo/ is uptodate
foo/config1 is uptodate
foo/config2 is uptodate
foo/extra => foo/config1
foo/sym is uptodate
foo/sym $is_uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 10 failed"
@@ -185,29 +215,29 @@ $RSYNC -ivvplrtH --link-dest="$todir" "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
cd ./
cd bar/
cd bar/baz/
hf bar/baz/rsync
cd foo/
hf foo/config1
hf foo/config2
hf foo/extra => foo/config1
$L foo/sym -> ../bar/baz/rsync
cd$allspace ./
cd$allspace bar/
cd$allspace bar/baz/
hf$allspace bar/baz/rsync
cd$allspace foo/
hf$allspace foo/config1
hf$allspace foo/config2
hf$allspace foo/extra => foo/config1
$L$sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --dry-run --link-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --link-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 13 failed"
@@ -224,7 +254,7 @@ foo/ is uptodate
foo/config1 is uptodate
foo/config2 is uptodate
foo/extra is uptodate
foo/sym is uptodate
foo/sym $is_uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
@@ -233,22 +263,22 @@ $RSYNC -ivvplrtH --compare-dest="$todir" "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
cd ./
cd bar/
cd bar/baz/
.f bar/baz/rsync
cd foo/
.f foo/config1
.f foo/config2
.f foo/extra
.L foo/sym -> ../bar/baz/rsync
cd$allspace ./
cd$allspace bar/
cd$allspace bar/baz/
.f$allspace bar/baz/rsync
cd$allspace foo/
.f$allspace foo/config1
.f$allspace foo/config2
.f$allspace foo/extra
$L_sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --compare-dest="$todir" "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 16 failed"
@@ -265,7 +295,7 @@ foo/ is uptodate
foo/config1 is uptodate
foo/config2 is uptodate
foo/extra is uptodate
foo/sym is uptodate
foo/sym $is_uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 17 failed"

View File

@@ -23,6 +23,11 @@ fromdir="$tmpdir/from"
todir="$tmpdir/to"
chkdir="$tmpdir/chk"
# For itemized output:
all_plus='+++++++++'
allspace=' '
dots='.....' # trailing dots after changes
# Berkley's nice.
PATH="$PATH:/usr/ucb"
@@ -234,6 +239,7 @@ build_rsyncd_conf() {
pid file = $pidfile
use chroot = no
munge symlinks = no
hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
log file = $logfile
log format = %i %h [%a] %m (%u) %l %f%L
@@ -255,6 +261,25 @@ gid = 0
path = $scratchdir
read only = no
EOF
# Build a helper script to ignore exit code 23
ignore23="$scratchdir/ignore23"
echo "building help script $ignore23"
cat >"$ignore23" <<'EOT'
if "${@}"; then
exit
fi
ret=$?
if test $ret = 23; then
exit
fi
exit $ret
EOT
chmod +x "$ignore23"
}

View File

@@ -34,18 +34,19 @@ case "`xattr 2>&1`" in
;;
esac
makepath "$fromdir/foo"
makepath "$fromdir/foo/bar"
echo now >"$fromdir/file0"
echo something >"$fromdir/file1"
echo else >"$fromdir/file2"
echo deep >"$fromdir/foo/file3"
echo normal >"$fromdir/file4"
echo deeper >"$fromdir/foo/bar/file5"
makepath "$chkdir/foo"
echo wow >"$chkdir/file1"
cp -p "$fromdir/foo/file3" "$chkdir/foo"
files='foo file0 file1 file2 foo/file3 file4'
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
cd "$fromdir"
@@ -61,10 +62,10 @@ xset user.foo foo file2
xset user.bar bar file2
xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
xset user.foo 'new foo' foo/file3
xset user.bar 'new bar' foo/file3
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3
xset user.foo 'new foo' foo/file3 foo/bar/file5
xset user.bar 'new bar' foo/file3 foo/bar/file5
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3 foo/bar/file5
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3 foo/bar/file5
xset user.short 'old short' "$chkdir/file1"
xset user.extra 'remove me' "$chkdir/file1"

3
tls.c
View File

@@ -2,7 +2,7 @@
* Trivial ls for comparing two directories after running an rsync.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -46,6 +46,7 @@ int am_root = 0;
int read_only = 1;
int list_only = 0;
int preserve_perms = 0;
int preserve_executability = 0;
#ifdef SUPPORT_XATTRS

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@@ -26,6 +26,7 @@ int am_root = 0;
int read_only = 1;
int list_only = 0;
int preserve_perms = 0;
int preserve_executability = 0;
int
main(int argc, char **argv)

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004-2007 Wayne Davison
* Copyright (C) 2004-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,7 +43,7 @@ extern int numeric_ids;
struct idlist {
struct idlist *next;
char *name;
const char *name;
id_t id, id2;
uint16 flags;
};
@@ -51,7 +51,7 @@ struct idlist {
static struct idlist *uidlist;
static struct idlist *gidlist;
static struct idlist *add_to_list(struct idlist **root, id_t id, char *name,
static struct idlist *add_to_list(struct idlist **root, id_t id, const char *name,
id_t id2, uint16 flags)
{
struct idlist *node = new(struct idlist);
@@ -67,7 +67,7 @@ static struct idlist *add_to_list(struct idlist **root, id_t id, char *name,
}
/* turn a uid into a user name */
static char *uid_to_name(uid_t uid)
static const char *uid_to_name(uid_t uid)
{
struct passwd *pass = getpwuid(uid);
if (pass)
@@ -76,7 +76,7 @@ static char *uid_to_name(uid_t uid)
}
/* turn a gid into a group name */
static char *gid_to_name(gid_t gid)
static const char *gid_to_name(gid_t gid)
{
struct group *grp = getgrgid(gid);
if (grp)
@@ -84,7 +84,7 @@ static char *gid_to_name(gid_t gid)
return NULL;
}
static uid_t map_uid(uid_t id, char *name)
static uid_t map_uid(uid_t id, const char *name)
{
uid_t uid;
if (id != 0 && name_to_uid(name, &uid))
@@ -92,7 +92,7 @@ static uid_t map_uid(uid_t id, char *name)
return id;
}
static gid_t map_gid(gid_t id, char *name)
static gid_t map_gid(gid_t id, const char *name)
{
gid_t gid;
if (id != 0 && name_to_gid(name, &gid))
@@ -160,7 +160,7 @@ static int is_in_group(gid_t gid)
}
/* Add a uid to the list of uids. Only called on receiving side. */
static struct idlist *recv_add_uid(uid_t id, char *name)
static struct idlist *recv_add_uid(uid_t id, const char *name)
{
uid_t id2 = name ? map_uid(id, name) : id;
struct idlist *node;
@@ -176,7 +176,7 @@ static struct idlist *recv_add_uid(uid_t id, char *name)
}
/* Add a gid to the list of gids. Only called on receiving side. */
static struct idlist *recv_add_gid(gid_t id, char *name)
static struct idlist *recv_add_gid(gid_t id, const char *name)
{
gid_t id2 = name ? map_gid(id, name) : id;
struct idlist *node;
@@ -237,7 +237,7 @@ gid_t match_gid(gid_t gid, uint16 *flags_ptr)
}
/* Add a uid to the list of uids. Only called on sending side. */
char *add_uid(uid_t uid)
const char *add_uid(uid_t uid)
{
struct idlist *list;
struct idlist *node;
@@ -255,7 +255,7 @@ char *add_uid(uid_t uid)
}
/* Add a gid to the list of gids. Only called on sending side. */
char *add_gid(gid_t gid)
const char *add_gid(gid_t gid)
{
struct idlist *list;
struct idlist *node;
@@ -316,6 +316,10 @@ uid_t recv_user_name(int f, uid_t uid)
if (!name)
out_of_memory("recv_user_name");
read_sbuf(f, name, len);
if (numeric_ids < 0) {
free(name);
name = NULL;
}
node = recv_add_uid(uid, name); /* node keeps name's memory */
return node->id2;
}
@@ -328,6 +332,10 @@ gid_t recv_group_name(int f, gid_t gid, uint16 *flags_ptr)
if (!name)
out_of_memory("recv_group_name");
read_sbuf(f, name, len);
if (numeric_ids < 0) {
free(name);
name = NULL;
}
node = recv_add_gid(gid, name); /* node keeps name's memory */
if (flags_ptr && node->flags & FLAG_SKIP_GROUP)
*flags_ptr |= FLAG_SKIP_GROUP;
@@ -341,13 +349,13 @@ void recv_id_list(int f, struct file_list *flist)
id_t id;
int i;
if ((preserve_uid || preserve_acls) && !numeric_ids) {
if ((preserve_uid || preserve_acls) && numeric_ids <= 0) {
/* read the uid list */
while ((id = read_varint30(f)) != 0)
recv_user_name(f, id);
}
if ((preserve_gid || preserve_acls) && !numeric_ids) {
if ((preserve_gid || preserve_acls) && numeric_ids <= 0) {
/* read the gid list */
while ((id = read_varint30(f)) != 0)
recv_group_name(f, id, NULL);

144
util.c
View File

@@ -4,7 +4,7 @@
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -147,12 +147,13 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
t[1].tv_usec = 0;
# ifdef HAVE_LUTIMES
if (S_ISLNK(mode)) {
lutimes(fname, t);
return 0; /* ignore errors */
if (lutimes(fname, t) < 0)
return errno == ENOSYS ? 1 : -1;
return 0;
}
# endif
return utimes(fname, t);
#elif defined HAVE_UTIMBUF
#elif defined HAVE_STRUCT_UTIMBUF
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
@@ -261,38 +262,41 @@ static int safe_read(int desc, char *ptr, size_t len)
return n_chars;
}
/** Copy a file.
/* Copy a file. If ofd < 0, copy_file unlinks and opens the "dest" file.
* Otherwise, it just writes to and closes the provided file descriptor.
*
* This is used in conjunction with the --temp-dir, --backup, and
* --copy-dest options. */
int copy_file(const char *source, const char *dest, mode_t mode, int create_bak_dir)
int copy_file(const char *source, const char *dest, int ofd,
mode_t mode, int create_bak_dir)
{
int ifd;
int ofd;
char buf[1024 * 8];
int len; /* Number of bytes read into `buf'. */
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
rsyserr(FERROR, errno, "open %s", full_fname(source));
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
return -1;
}
if (robust_unlink(dest) && errno != ENOENT) {
rsyserr(FERROR, errno, "unlink %s", full_fname(dest));
return -1;
}
if (ofd < 0) {
if (robust_unlink(dest) && errno != ENOENT) {
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
return -1;
}
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
rsyserr(FERROR, errno, "open %s", full_fname(dest));
close(ifd);
return -1;
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest));
close(ifd);
return -1;
}
}
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) {
rsyserr(FERROR, errno, "write %s", full_fname(dest));
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
close(ifd);
close(ofd);
return -1;
@@ -300,19 +304,19 @@ int copy_file(const char *source, const char *dest, mode_t mode, int create_bak_
}
if (len < 0) {
rsyserr(FERROR, errno, "read %s", full_fname(source));
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
close(ifd);
close(ofd);
return -1;
}
if (close(ifd) < 0) {
rsyserr(FINFO, errno, "close failed on %s",
rsyserr(FWARNING, errno, "close failed on %s",
full_fname(source));
}
if (close(ofd) < 0) {
rsyserr(FERROR, errno, "close failed on %s",
rsyserr(FERROR_XFER, errno, "close failed on %s",
full_fname(dest));
return -1;
}
@@ -368,7 +372,7 @@ int robust_unlink(const char *fname)
} while ((rc = access(path, 0)) == 0 && counter != start);
if (verbose > 0) {
rprintf(FINFO,"renaming %s to %s because of text busy\n",
rprintf(FWARNING, "renaming %s to %s because of text busy\n",
fname, path);
}
@@ -407,7 +411,7 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
return -1;
to = partialptr;
}
if (copy_file(from, to, mode, 0) != 0)
if (copy_file(from, to, -1, mode, 0) != 0)
return -2;
do_unlink(from);
return 1;
@@ -462,31 +466,27 @@ void kill_all(int sig)
}
/** Turn a user name into a uid */
int name_to_uid(const char *name, uid_t *uid)
int name_to_uid(const char *name, uid_t *uid_p)
{
struct passwd *pass;
if (!name || !*name)
return 0;
pass = getpwnam(name);
if (pass) {
*uid = pass->pw_uid;
return 1;
}
return 0;
if (!(pass = getpwnam(name)))
return 0;
*uid_p = pass->pw_uid;
return 1;
}
/** Turn a group name into a gid */
int name_to_gid(const char *name, gid_t *gid)
int name_to_gid(const char *name, gid_t *gid_p)
{
struct group *grp;
if (!name || !*name)
return 0;
grp = getgrnam(name);
if (grp) {
*gid = grp->gr_gid;
return 1;
}
return 0;
if (!(grp = getgrnam(name)))
return 0;
*gid_p = grp->gr_gid;
return 1;
}
/** Lock a byte range in a open file */
@@ -546,7 +546,7 @@ void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
s = ".";
if (sanitize_paths)
s = sanitize_path(NULL, s, "", 0, NULL);
s = sanitize_path(NULL, s, "", 0);
else
s = strdup(s);
if (!s)
@@ -687,11 +687,14 @@ int count_dir_elements(const char *p)
return cnt;
}
/* Turns multiple adjacent slashes into a single slash, gets rid of "./"
* elements (but not a trailing dot dir), removes a trailing slash, and
* optionally collapses ".." elements (except for those at the start of the
* string). If the resulting name would be empty, change it into a ".". */
unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
/* Turns multiple adjacent slashes into a single slash, drops interior "."
* elements, drops an intial "./" unless CFN_KEEP_LEADING_DOT_DIR is flagged,
* will even drop a trailing '.' after a '/' if CFN_DROP_TRAILING_DOT_DIR is
* flagged, removes a trailing slash (perhaps after removing the aforementioned
* dot) unless CFN_KEEP_TRAILING_SLASH is flagged, will even collapse ".."
* elements (except at the start of the string) if CFN_COLLAPSE_DOT_DOT_DIRS
* is flagged. If the resulting name would be empty, we return ".". */
unsigned int clean_fname(char *name, int flags)
{
char *limit = name - 1, *t = name, *f = name;
int anchored;
@@ -701,6 +704,10 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
if ((anchored = *f == '/') != 0)
*t++ = *f++;
else if (flags & CFN_KEEP_LEADING_DOT_DIR && *f == '.' && f[1] == '/') {
*t++ = *f++;
*t++ = *f++;
}
while (*f) {
/* discard extra slashes */
if (*f == '/') {
@@ -708,14 +715,16 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
continue;
}
if (*f == '.') {
/* discard "." dirs (but NOT a trailing '.'!) */
/* discard interior "." dirs */
if (f[1] == '/') {
f += 2;
continue;
}
if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR)
break;
/* collapse ".." dirs */
if (collapse_dot_dot
&& f[1] == '.' && (f[2] == '/' || !f[2])) {
if (flags & CFN_COLLAPSE_DOT_DOT_DIRS
&& f[1] == '.' && (f[2] == '/' || !f[2])) {
char *s = t - 1;
if (s == name && anchored) {
f += 2;
@@ -733,7 +742,7 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
while (*f && (*t++ = *f++) != '/') {}
}
if (t > name+anchored && t[-1] == '/')
if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
t--;
if (t == name)
*t++ = '.';
@@ -754,8 +763,7 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
* Specify NULL to get the default of "module_dir".
*
* The depth var is a count of how many '..'s to allow at the start of the
* path. If symlink is set, combine its value with the "p" value to get
* the target path, and **return NULL if any '..'s try to escape**.
* path.
*
* We also clean the path in a manner similar to clean_fname() but with a
* few differences:
@@ -765,17 +773,11 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
* ALWAYS collapses ".." elements (except for those at the start of the
* string up to "depth" deep). If the resulting name would be empty,
* change it into a ".". */
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
const char *symlink)
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
{
char *start, *sanp, *save_dest = dest;
char *start, *sanp;
int rlen = 0, leave_one_dotdir = relative_paths;
if (symlink && *symlink == '/') {
p = symlink;
symlink = "";
}
if (dest != p) {
int plen = strlen(p);
if (*p == '/') {
@@ -798,18 +800,7 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
}
start = sanp = dest + rlen;
while (1) {
if (*p == '\0') {
if (!symlink || !*symlink)
break;
while (sanp != start && sanp[-1] != '/') {
/* strip last element */
sanp--;
}
/* Append a relative symlink */
p = symlink;
symlink = "";
}
while (*p) {
/* discard leading or extra slashes */
if (*p == '/') {
p++;
@@ -831,11 +822,6 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
/* ".." component followed by slash or end */
if (depth <= 0 || sanp != start) {
if (symlink && sanp == start) {
if (!save_dest)
free(dest);
return NULL;
}
p += 2;
if (sanp != start) {
/* back up sanp one level */
@@ -902,13 +888,16 @@ int push_dir(const char *dir, int set_path_only)
curr_dir_len += len;
}
curr_dir_len = clean_fname(curr_dir, 1);
curr_dir_len = clean_fname(curr_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (sanitize_paths) {
if (module_dirlen > curr_dir_len)
module_dirlen = curr_dir_len;
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
}
if (verbose >= 5 && !set_path_only)
rprintf(FINFO, "[%s] push_dir(%s)\n", who_am_i(), curr_dir);
return 1;
}
@@ -927,6 +916,9 @@ int pop_dir(const char *dir)
if (sanitize_paths)
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
if (verbose >= 5)
rprintf(FINFO, "[%s] pop_dir(%s)\n", who_am_i(), curr_dir);
return 1;
}

View File

@@ -1,7 +1,7 @@
/*
* Test suite for the wildmatch code.
*
* Copyright (C) 2003-2007 Wayne Davison
* Copyright (C) 2003-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

216
xattrs.c
View File

@@ -3,7 +3,7 @@
* Written by Jay Fenlason, vaguely based on the ACLs patch.
*
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2006, 2007 Wayne Davison
* Copyright (C) 2006-2008 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,7 +47,6 @@ extern int checksum_seed;
#define XSTATE_ABBREV 0
#define XSTATE_DONE 1
#define XSTATE_TODO 2
#define XSTATE_LOCAL 3
#define USER_PREFIX "user."
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
@@ -70,6 +69,7 @@ extern int checksum_seed;
typedef struct {
char *datum, *name;
size_t datum_len, name_len;
int num;
} rsync_xa;
static size_t namebuf_len = 0;
@@ -111,6 +111,7 @@ static int rsync_xal_compare_names(const void *x1, const void *x2)
static ssize_t get_xattr_names(const char *fname)
{
ssize_t list_len;
double arg;
if (!namebuf) {
namebuf_len = 1024;
@@ -119,23 +120,26 @@ static ssize_t get_xattr_names(const char *fname)
out_of_memory("get_xattr_names");
}
/* The length returned includes all the '\0' terminators. */
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
if (list_len > (ssize_t)namebuf_len) {
list_len = -1;
errno = ERANGE;
}
if (list_len >= 0)
return list_len;
if (errno == ENOTSUP)
return 0;
if (errno == ERANGE) {
while (1) {
/* The length returned includes all the '\0' terminators. */
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
if (list_len >= 0) {
if ((size_t)list_len <= namebuf_len)
break;
} else if (errno == ENOTSUP)
return 0;
else if (errno != ERANGE) {
arg = (double)namebuf_len;
got_error:
rsyserr(FERROR_XFER, errno,
"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
fname, arg);
return -1;
}
list_len = sys_llistxattr(fname, NULL, 0);
if (list_len < 0) {
rsyserr(FERROR, errno,
"get_xattr_names: llistxattr(\"%s\",0) failed",
fname);
return -1;
arg = 0;
goto got_error;
}
if (namebuf_len)
free(namebuf);
@@ -143,15 +147,9 @@ static ssize_t get_xattr_names(const char *fname)
namebuf = new_array(char, namebuf_len);
if (!namebuf)
out_of_memory("get_xattr_names");
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
if (list_len >= 0)
return list_len;
}
rsyserr(FERROR, errno,
"get_xattr_names: llistxattr(\"%s\",%ld) failed",
fname, (long)namebuf_len);
return -1;
return list_len;
}
/* On entry, the *len_ptr parameter contains the size of the extra space we
@@ -161,32 +159,35 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
int no_missing_error)
{
size_t datum_len = sys_lgetxattr(fname, name, NULL, 0);
size_t extra_len = *len_ptr;
char *ptr;
*len_ptr = datum_len;
if (datum_len == (size_t)-1) {
if (errno == ENOTSUP || no_missing_error)
return NULL;
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
fname, name);
return NULL;
}
if (datum_len + *len_ptr < datum_len /* checks for overflow */
|| !(ptr = new_array(char, datum_len + *len_ptr)))
if (!datum_len && !extra_len)
extra_len = 1; /* request non-zero amount of memory */
if (datum_len + extra_len < datum_len /* checks for overflow */
|| !(ptr = new_array(char, datum_len + extra_len)))
out_of_memory("get_xattr_data");
*len_ptr = datum_len;
if (datum_len) {
size_t len = sys_lgetxattr(fname, name, ptr, datum_len);
if (len != datum_len) {
if (len == (size_t)-1) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
" failed", fname, name, (long)datum_len);
} else {
rprintf(FERROR,
rprintf(FERROR_XFER,
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
" returned %ld\n", fname, name,
(long)datum_len, (long)len);
@@ -207,14 +208,14 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
#ifdef HAVE_LINUX_XATTRS
int user_only = am_sender ? 0 : !am_root;
#endif
rsync_xa *rxa;
int count;
/* This puts the name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(fname)) < 0)
return -1;
for (name = namebuf; list_len > 0; name += name_len) {
rsync_xa *rxas;
name_len = strlen(name) + 1;
list_len -= name_len;
@@ -227,9 +228,12 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
#endif
/* No rsync.%FOO attributes are copied w/o 2 -X options. */
if (preserve_xattrs < 2 && name_len > RPRE_LEN
&& name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX))
continue;
if (name_len > RPRE_LEN && name[RPRE_LEN] == '%'
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
if ((am_sender && preserve_xattrs < 2)
|| (am_root < 0 && strcmp(name, XSTAT_ATTR) == 0))
continue;
}
datum_len = name_len; /* Pass extra size to get_xattr_data() */
if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -250,22 +254,26 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
name_offset = datum_len;
#ifdef HAVE_LINUX_XATTRS
if (am_root < 0 && name_len > RPRE_LEN
if (am_root < 0 && name_len > RPRE_LEN && name[RPRE_LEN] != '%'
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
name += RPRE_LEN;
name_len -= RPRE_LEN;
}
#endif
rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
rxas->name = ptr + name_offset;
memcpy(rxas->name, name, name_len);
rxas->datum = ptr;
rxas->name_len = name_len;
rxas->datum_len = datum_len;
rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
rxa->name = ptr + name_offset;
memcpy(rxa->name, name, name_len);
rxa->datum = ptr;
rxa->name_len = name_len;
rxa->datum_len = datum_len;
}
if (xalp->count > 1)
qsort(xalp->items, xalp->count, sizeof (rsync_xa), rsync_xal_compare_names);
count = xalp->count;
rxa = xalp->items;
if (count > 1)
qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names);
for (rxa += count-1; count; count--, rxa--)
rxa->num = count;
return 0;
}
@@ -453,18 +461,19 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
{
item_list *lst = rsync_xal_l.items;
int j, cnt, prior_req = -1;
int cnt, prior_req = 0;
rsync_xa *rxa;
lst += F_XATTR(file);
cnt = lst->count;
for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) {
for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) {
if (rxa->datum_len <= MAX_FULL_DATUM)
continue;
switch (rxa->datum[0]) {
case XSTATE_LOCAL:
/* Items set locally will get cached by receiver. */
rxa->datum[0] = XSTATE_DONE;
case XSTATE_ABBREV:
/* Items left abbreviated matched the sender's checksum, so
* the receiver will cache the local data for future use. */
if (am_generator)
rxa->datum[0] = XSTATE_DONE;
continue;
case XSTATE_TODO:
break;
@@ -475,16 +484,19 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
/* Flag that we handled this abbreviated item. */
rxa->datum[0] = XSTATE_DONE;
write_varint(f_out, j - prior_req);
prior_req = j;
write_varint(f_out, rxa->num - prior_req);
prior_req = rxa->num;
if (fname) {
size_t len = 0;
char *ptr;
/* Re-read the long datum. */
if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0)))
if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) {
rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname);
write_varint(f_out, 0);
continue;
}
write_varint(f_out, len); /* length might have changed! */
write_buf(f_out, ptr, len);
@@ -495,37 +507,16 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
write_byte(f_out, 0); /* end the list */
}
/* Any items set locally by the generator that the receiver doesn't
* get told about get changed back to XSTATE_ABBREV. */
void xattr_clear_locals(struct file_struct *file)
{
item_list *lst = rsync_xal_l.items;
rsync_xa *rxa;
int cnt;
if (F_XATTR(file) < 0)
return;
lst += F_XATTR(file);
cnt = lst->count;
for (rxa = lst->items; cnt--; rxa++) {
if (rxa->datum_len <= MAX_FULL_DATUM)
continue;
if (rxa->datum[0] == XSTATE_LOCAL)
rxa->datum[0] = XSTATE_ABBREV;
}
}
/* When called by the sender, read the request from the generator and mark
* any needed xattrs with a flag that lets us know they need to be sent to
* the receiver. When called by the receiver, reads the sent data and
* stores it in place of its checksum. */
void recv_xattr_request(struct file_struct *file, int f_in)
int recv_xattr_request(struct file_struct *file, int f_in)
{
item_list *lst = rsync_xal_l.items;
char *old_datum, *name;
rsync_xa *rxa;
int rel_pos, cnt;
int rel_pos, cnt, num, got_xattr_data = 0;
if (F_XATTR(file) < 0) {
rprintf(FERROR, "recv_xattr_request: internal data error!\n");
@@ -535,13 +526,20 @@ void recv_xattr_request(struct file_struct *file, int f_in)
cnt = lst->count;
rxa = lst->items;
rxa -= 1;
num = 0;
while ((rel_pos = read_varint(f_in)) != 0) {
rxa += rel_pos;
cnt -= rel_pos;
if (cnt < 0 || rxa->datum_len <= MAX_FULL_DATUM
|| rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "recv_xattr_request: internal abbrev error!\n");
num += rel_pos;
while (cnt && rxa->num < num) {
rxa++;
cnt--;
}
if (!cnt || rxa->num != num) {
rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",
who_am_i(), num, f_name(file, NULL));
exit_cleanup(RERR_STREAMIO);
}
if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i());
exit_cleanup(RERR_STREAMIO);
}
@@ -563,7 +561,10 @@ void recv_xattr_request(struct file_struct *file, int f_in)
rxa->name = name;
free(old_datum);
read_buf(f_in, rxa->datum, rxa->datum_len);
got_xattr_data = 1;
}
return got_xattr_data;
}
/* ------------------------------------------------------------------------- */
@@ -572,7 +573,7 @@ void recv_xattr_request(struct file_struct *file, int f_in)
void receive_xattr(struct file_struct *file, int f)
{
static item_list temp_xattr = EMPTY_ITEM_LIST;
int count;
int count, num;
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
@@ -591,7 +592,7 @@ void receive_xattr(struct file_struct *file, int f)
temp_xattr.count = 0;
}
while (count--) {
for (num = 1; num <= count; num++) {
char *ptr, *name;
rsync_xa *rxa;
size_t name_len = read_varint(f);
@@ -615,14 +616,14 @@ void receive_xattr(struct file_struct *file, int f)
}
#ifdef HAVE_LINUX_XATTRS
/* Non-root can only save the user namespace. */
if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
if (!am_root) {
free(ptr);
continue;
}
name -= RPRE_LEN;
name_len += RPRE_LEN;
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
if (!am_root) {
free(ptr);
continue;
}
name -= RPRE_LEN;
name_len += RPRE_LEN;
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
}
#else
/* This OS only has a user namespace, so we either
@@ -651,6 +652,7 @@ void receive_xattr(struct file_struct *file, int f)
rxa->datum = ptr;
rxa->name_len = name_len;
rxa->datum_len = datum_len;
rxa->num = num;
}
ndx = rsync_xal_l.count; /* pre-incremented count */
@@ -719,7 +721,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
if (fname == fnamecmp)
; /* Value is already set when identical */
else if (sys_lsetxattr(fname, name, ptr, len) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
fname, name);
ret = -1;
@@ -727,8 +729,6 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
sxp->st.st_mtime = (time_t)-1;
if (am_generator) { /* generator items stay abbreviated */
if (rxas[i].datum[0] == XSTATE_ABBREV)
rxas[i].datum[0] = XSTATE_LOCAL;
free(ptr);
continue;
}
@@ -742,7 +742,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
}
if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
fname, name);
ret = -1;
@@ -762,6 +762,9 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
: !HAS_PREFIX(name, USER_PREFIX))
continue;
#endif
if (am_root < 0 && name_len > RPRE_LEN
&& name[RPRE_LEN] == '%' && strcmp(name, XSTAT_ATTR) == 0)
continue;
for (i = 0; i < xalp->count; i++) {
if (strcmp(name, rxas[i].name) == 0)
@@ -769,7 +772,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
}
if (i == xalp->count) {
if (sys_lremovexattr(fname, name) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed",
fname, name);
ret = -1;
@@ -804,6 +807,7 @@ int set_xattr(const char *fname, const struct file_struct *file,
char *get_xattr_acl(const char *fname, int is_access_acl, size_t *len_p)
{
const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
*len_p = 0; /* no extra data alloc needed from get_xattr_data() */
return get_xattr_data(fname, name, len_p, 1);
}
@@ -811,7 +815,7 @@ int set_xattr_acl(const char *fname, int is_access_acl, const char *buf, size_t
{
const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
if (sys_lsetxattr(fname, name, buf, buf_len) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"set_xattr_acl: lsetxattr(\"%s\",\"%s\") failed",
fname, name);
return -1;
@@ -856,7 +860,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst
xst->st_gid = 0;
return 0;
}
rsyserr(FERROR, errno, "failed to read xattr %s for %s",
rsyserr(FERROR_XFER, errno, "failed to read xattr %s for %s",
XSTAT_ATTR, full_fname(fname));
return -1;
}
@@ -877,7 +881,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst
return 0;
}
int set_stat_xattr(const char *fname, struct file_struct *file)
int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
{
STRUCT_STAT fst, xst;
dev_t rdev;
@@ -887,19 +891,19 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
return 0;
if (read_only || list_only) {
rsyserr(FERROR, EROFS, "failed to write xattr %s for %s",
rsyserr(FERROR_XFER, EROFS, "failed to write xattr %s for %s",
XSTAT_ATTR, full_fname(fname));
return -1;
}
if (x_lstat(fname, &fst, &xst) < 0) {
rsyserr(FERROR, errno, "failed to re-stat %s",
rsyserr(FERROR_XFER, errno, "failed to re-stat %s",
full_fname(fname));
return -1;
}
fst.st_mode &= (_S_IFMT | CHMOD_BITS);
fmode = file->mode & (_S_IFMT | CHMOD_BITS);
fmode = new_mode & (_S_IFMT | CHMOD_BITS);
if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) {
uint32 *devp = F_RDEV_P(file);
@@ -919,7 +923,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
&& fst.st_uid == F_OWNER(file) && fst.st_gid == F_GROUP(file)) {
/* xst.st_mode will be 0 if there's no current stat xattr */
if (xst.st_mode && sys_lremovexattr(fname, XSTAT_ATTR) < 0) {
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"delete of stat xattr failed for %s",
full_fname(fname));
return -1;
@@ -937,7 +941,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
if (sys_lsetxattr(fname, XSTAT_ATTR, buf, len) < 0) {
if (errno == EPERM && S_ISLNK(fst.st_mode))
return 0;
rsyserr(FERROR, errno,
rsyserr(FERROR_XFER, errno,
"failed to write xattr %s for %s",
XSTAT_ATTR, full_fname(fname));
return -1;

View File

@@ -1 +0,0 @@
dummy