Compare commits

...

379 Commits

Author SHA1 Message Date
Wayne Davison
8ba802f3b4 Preparing for release of 3.0.2 2008-04-08 08:16:05 -07:00
Wayne Davison
e53f49d1af Call patch-update in its new location. 2008-04-08 08:15:39 -07:00
Wayne Davison
0917f581bc Roll over the NEWS files for the next release. 2008-04-08 08:03:20 -07:00
Wayne Davison
1fe2a3533f Fixed a potential overflow issue with realloc() that Sebastian Krahmer
pointed out.
2008-04-08 08:01:43 -07:00
Wayne Davison
237e9a178f Have the spec file put more useful stuff into the doc dir. 2008-04-05 22:46:48 -07:00
Wayne Davison
0668bfe077 Moving some files from support into packaging. 2008-04-05 22:45:12 -07:00
Wayne Davison
214af6ad83 Comment out the Source1 tar file by default in the spec file. 2008-04-04 00:27:14 -07:00
Wayne Davison
2551c47eb7 Fixed the code that removes old file versions for a final release. 2008-04-04 00:05:44 -07:00
Wayne Davison
83d22fd7f9 Bump the repository version to 3.0.2dev. 2008-04-04 00:04:58 -07:00
Wayne Davison
325c243210 Preparing for release of 3.0.1 2008-04-03 22:37:01 -07:00
Wayne Davison
4e90cfbfed A few more spec-file tweaks. 2008-04-01 20:00:08 -07:00
Wayne Davison
6fd2c27f38 Define a "srcdir" in the spec file and use it in the URLs for the
source files so that they use the unchanging src or src-preview
subdirectory location for the file.
2008-04-01 12:55:27 -07:00
Wayne Davison
19173d224a Tweaked rsync.spec to use "rsync" in place of "%{name}" in a few
places (which allows for easier creation of adjunct RPMs).
2008-03-31 14:10:07 -07:00
Wayne Davison
5b83829669 A simple change to change_pathname() to ensure that the error output
mentions the right path when dir == NULL.
2008-03-31 07:46:47 -07:00
Wayne Davison
8cd3c6dccf Preparing for release of 3.0.1pre3 2008-03-30 23:29:43 -07:00
Wayne Davison
29a89172f7 Improved the chdir() code:
- Renamed push_dir() to change_dir() and revised it a little so that it
  can chdir() to a relative path without an intervening chdir() back to
  the staring path.
- Renamed push_pathname() to change_pathname() and revised it to take
  different args and to only call path_is_daemon_excluded() on a new
  path (not a revisit of a file's already-checked path).
- Fixed change_pathname() to set the right pathname value when a chdir()
  call fails.
- Set orig_dir once outside of the change_pathname() function.
- Got rid of pop_dir().
2008-03-30 15:44:46 -07:00
Wayne Davison
2089375179 Some argc-based actions in parse_arguments() shouldn't happen on
the server side.
2008-03-30 08:05:50 -07:00
Wayne Davison
f8949e7647 Fixed a path-exclusion glitch when checking more than one arg. 2008-03-30 08:05:42 -07:00
Wayne Davison
84ecaa0eca Improved the code that protects a '.' dir from exclusion.
This fixed a glitch in the daemon-exclusion code that allowed
an exclude rule such as ".*" or "*/" to affect a '.' dir.
2008-03-29 23:06:18 -07:00
Wayne Davison
3f2d8d683a Extended a test to ensure that hard-linked distant files continues
to work in incremental-recursion mode.
2008-03-28 10:40:17 -07:00
Wayne Davison
fd2598022c Allow the file-list sending code to set XMIT_SAME_UID/XMIT_SAME_GID
when owner/group info isn't being preserved.  This helps to ensure
that the lower 8 bits of the xflags aren't 0, and is what older
rsync versions did.
2008-03-28 10:40:10 -07:00
Wayne Davison
b05c58cce6 Dump an extraneous empty line. 2008-03-28 10:30:11 -07:00
Wayne Davison
05805cd6b7 Preparing for release of 3.0.1pre2 2008-03-26 17:12:07 -07:00
Wayne Davison
a165be754b Mention two more NEWS items. 2008-03-26 17:04:29 -07:00
Wayne Davison
af3172c148 Ensure that a per-dir merge file is also loaded from implied directories
in the sender (was working in incremental mode).
2008-03-26 16:49:12 -07:00
Wayne Davison
487cb52615 Fixed the discovery of a prior finished hard-link when the entry
is old enough that it is no longer in the flist data.
2008-03-26 16:12:39 -07:00
Wayne Davison
9793bbb364 Improved a length check in parse_merge_name(). 2008-03-26 14:01:52 -07:00
Wayne Davison
f6f74b93ef Ensure that a per-dir merge file is also loaded from implied directories
in the generator (for protocol 30, at least).
2008-03-26 14:01:26 -07:00
Wayne Davison
7568ff448a Fixed the way rsync handles iconv-conversion problems in the file-list:
- If the sender cannot convert a name, the discarding of the entry now
  occurs soon enough to avoid affecting the sender's list (which was
  causing the file-list on the receiving side to be out of sync).
- If the receiver cannot convert a name, its transformation of the name
  into an empty name (which indicates that the entry should be skipped)
  is no longer thwarted by the clean_fname() call (which was changing
  the name into a ".").
2008-03-25 10:46:06 -07:00
Wayne Davison
56158b7e04 Preparing for release of 3.0.1pre1 2008-03-24 21:15:51 -07:00
Wayne Davison
798a9e4e74 Some more improvements for the packaging/release-rsync script:
- Check early if the version tag already exists, so it aborts right
  away if the release script can't do its work.
- Update the files in the "patches" dir while merging the master branch
  into the patch branches (done before creating the release patches for
  the rsync-patches tar file).
- Allow the user to ask to visit each patch when updating them.
- Pause after initial patch updating so that any extra patch changes
  can be done before the creating of the tar files.
- Ask for the GPG signing passphrase once for all signing commands.
2008-03-24 21:15:30 -07:00
Wayne Davison
c202b4fa96 Some improvements for support/patch-update:
- Added a --shell option which starts a sub-shell on each patch branch.
- Don't allow the user to exit a sub-shell if the branch is not clean.
- If the sub-shell exited with a non-zero exit status, prompt to see if
  the user wanted to abort rather than assuming that.
- Wait to start the new patch-file output until after the shell runs.
- Always return to the starting branch on exit.
2008-03-24 20:30:09 -07:00
Wayne Davison
1df02d13d3 Don't send daemon-config filter-action messages back to the user. 2008-03-24 10:14:59 -07:00
Wayne Davison
73cb6738b3 Improved --dirs/--no-dirs/--list-only option handling:
- Moved setting of list_only and xfer_dirs from main.c to options.c.
- Fixed the ability of the user to force --no-dirs.
- Added the --old-dirs/--old-d option to make it easier to interact
  in list-only mode with an older rsync.
- Suggest the use of --old-d instead of "-r --exclude='/*/*'".
2008-03-24 09:54:04 -07:00
Wayne Davison
ba8672dfab Added a couple more NEWS items. 2008-03-23 10:06:53 -07:00
Wayne Davison
a5e0bf3579 Properly handle a new patch-branch that is only available locally. 2008-03-23 09:53:15 -07:00
Wayne Davison
99ba99c74c Changed the way version numbering of pre-releases will be done in
the RPM spec file so that they order prior to the final release.
2008-03-23 00:10:12 -07:00
Wayne Davison
469ff84e29 More NEWS updates and improvements. 2008-03-22 22:33:04 -07:00
Wayne Davison
b5daf5300f Made the filename arg-parsing code skip args that have excluded path
components, returning the same errors that would occur if the path
elements didn't actually exist.  The glob_match() code was also
changed to no longer truncate an arg with an excluded path element
(it just omits excluded items from glob matching).
2008-03-22 15:33:18 -07:00
Wayne Davison
f5aeb6ff9b Added XFLG_DIR2WILD3 flag that the daemon uses to transform any
config-file dir/ exclude rule into a dir/*** rule.
2008-03-22 14:02:34 -07:00
Wayne Davison
4c74d44dab A couple fixes in add_rule() for XFLG_ABS_IF_SLASH:
- Remove the trailing slash earlier, so that it doesn't
  affect the XFLG_ABS_IF_SLASH check.
- Count the slashes earlier so that the XFLG_ABS_IF_SLASH
  can use it instead of using a strchr() all that could
  scan past the end of the input.
2008-03-22 12:30:43 -07:00
Wayne Davison
4a86fbcda0 Change ex_len to pre_len in add_rule(). 2008-03-22 12:21:41 -07:00
Wayne Davison
bc267e0f57 Improved ENSURE_MEMSPACE() macro and use it in more places in glob code. 2008-03-22 08:13:04 -07:00
Wayne Davison
fc05137846 Mention the most recent changes in the NEWS. 2008-03-21 17:50:01 -07:00
Wayne Davison
c085ece623 Some RPM spec file improvements:
- Added installation of new /etc/xinetd.d/rsync config file.
- Added commented-out lines to demonstrate how to use rsync-patches.
2008-03-21 17:11:20 -07:00
Wayne Davison
91f625cee0 Make glob_expand() return an indicator if the glob had no matches. 2008-03-21 15:00:28 -07:00
Wayne Davison
27b067f87b Changed d_name() to be a static inline function. 2008-03-21 07:26:25 -07:00
Wayne Davison
987a546756 A couple improvements to the new arg-globbing code:
- Put all the state variables into a single struct.
- Reuse the buffer memory for each glob_expand() call until a final
  call with a NULL pointer tells us to free it.
2008-03-21 07:22:34 -07:00
Wayne Davison
4d30f17671 Changed the arg-globbing routine to use a custom arg-globbing algorithm
that does not include any daemon-excluded items in the matches.  It is
also not subverted by the presence of one or more dot-dir elements in
an arg.
2008-03-20 23:30:09 -07:00
Wayne Davison
d48810ba5b Some improvements to the file-name cleaning code:
- Removed the CFN_KEEP_LEADING_DOT_DIR flag for clean_fname().
- Explicitly add an implied dot-dir to the transfer rather than keeping
  a leading a "./" prefix as a part of a relative pathname.
- Added the CFN_KEEP_DOT_DIRS flag for clean_fname().
- Added the SP_KEEP_DOT_DIRS flag for sanitize_path().
- Call clean_fname() a couple more times.
2008-03-20 22:39:29 -07:00
Wayne Davison
819bfe4599 Changed the name of the server_filter_list to be
daemon_filter_list, for improved clarity.
2008-03-20 10:42:43 -07:00
Wayne Davison
d2f6e19262 Fixed a bug in the truncating of daemon-excluded paths. 2008-03-20 10:35:53 -07:00
Wayne Davison
e889e0c43b A couple more support/rrsync tweaks:
- Die if the --server option is not first on the command-line.
- Don't allow the --daemon option by default.
2008-03-19 16:44:11 -07:00
Wayne Davison
6e0bf4d840 Some more minor changes for the skip/missing/dry_run code. 2008-03-19 08:59:44 -07:00
Matt McCutchen
83a8ca7b14 Unsnarl missing_below/dry_run logic.
The generator can skip a directory's contents altogether due to
--ignore-non-existing, a daemon exclude, or a mkdir failure.  On a
--dry-run, the generator can also note the missingness of a directory
while still scanning its contents.  These two scenarios were conflated
using a single set of missing_below/missing_dir variables in combination
with transient increments in dry_run; this caused at least three bugs.

Now recv_generator has separate variables for the two scenarios, called
skip_dir and dry_missing_dir, respectively.  For simplicity, we take the
F_DEPTH instead of having separate *_below variables.  We mark both
kinds of missing dirs with FLAG_MISSING_DIR.  (dry_run > 1) iff the
*root* of the destination does not exist; it is no longer incremented
for missing subdirs.  I added tests for the three fixed bugs in
missing.test.
2008-03-19 07:45:58 -07:00
Matt McCutchen
100200d0d2 Fix a poorly placed sentence in rsyncd.conf.yo. 2008-03-18 15:28:36 -04:00
Wayne Davison
f28bf7f401 My modified version of Matt's improvements to the sections on
the various filter parameters.
2008-03-18 11:41:00 -07:00
Wayne Davison
e0fd68f5ce Improved arg-path checking so that wildcards can't be used to
avoid a daemon-exclude.
2008-03-18 10:57:54 -07:00
Wayne Davison
cc12c488aa Use the missing_below code to make the daemon-exclusions
work better.
2008-03-18 10:10:13 -07:00
Wayne Davison
99c3e591b2 Reject a daemon-excluded destination. 2008-03-18 09:44:42 -07:00
Wayne Davison
1aefb7ef73 Output a non-existent-file error for server-excluded files instead of
silently ignoring them.
2008-03-18 09:16:24 -07:00
Matt McCutchen
d7b6774d82 More typo fixes. 2008-03-17 15:32:07 -04:00
Wayne Davison
d4c5cb2b01 A couple more changes for dealing with "checker" warnings. 2008-03-17 10:50:11 -07:00
Matt McCutchen
df476bfcff Fix typo in rsyncd.conf man page. 2008-03-17 11:30:08 -04:00
Wayne Davison
aa0e6b9977 Attempting to silence some more "checker" warnings. 2008-03-17 07:35:19 -07:00
Wayne Davison
1ba6468f1b Mention all the latest changes in the NEWS file. 2008-03-16 22:43:35 -07:00
Wayne Davison
f490102454 If we're not compiling one or more major options (ACLs, xattrs, & iconv),
try to turn off unused-parameter compiler warnings.
2008-03-16 21:51:07 -07:00
Wayne Davison
18f3cb6957 Changed stat() call to do_stat(). 2008-03-16 21:44:33 -07:00
Wayne Davison
7abcfd85b7 Moved declaration of "int i" outside the ifdef in send_protected_args(). 2008-03-16 20:39:16 -07:00
Wayne Davison
6de417d9d4 If the system's popt.h file is not found, use our provided popt code. 2008-03-16 20:35:18 -07:00
Wayne Davison
ffe8feb265 Added "const" to a couple more char * args. 2008-03-16 19:50:35 -07:00
Wayne Davison
c9b62cf375 Fixed hard-linking when some of the files can get skipped. This adds
the FLAG_SKIP_HLINK flag, which gets set on any hard-linked file that
the user wants to skip (e.g. via --ignore-existing, --append, etc.).
The code in hlink.c now deals with the skipped files instead of
triggering an assert() error.
2008-03-16 19:47:35 -07:00
Wayne Davison
7bc595785e Made the FLAG_MOUNT_DIR bit only honored on a directory. 2008-03-16 17:52:31 -07:00
Wayne Davison
022dec7aba Moved the --append check so that files that don't need to be transferred
still get their non-content attributes updated, and combining --append
with --hard-links will not prevent the discovery of unchanged files.
2008-03-16 17:50:28 -07:00
Wayne Davison
ddaef70ced Make the --ignore-existing option not overwrite a regular file with
a dir/symlink/device/special-file, just like it already refuses to
overwrite a non-regular file with a regular file.
2008-03-16 17:17:38 -07:00
Wayne Davison
2357a51e09 A daemon no longer tries to refuse the iconv option when it is not enabled. 2008-03-16 12:11:19 -07:00
Wayne Davison
24ded29ff6 Fixed a hang when using --remove-source-files in dry-run mode. 2008-03-16 06:56:26 -07:00
Wayne Davison
ddff23a7f9 Added missing $(CPPFLAGS) from the building of rounding.h. 2008-03-15 14:09:20 -07:00
Wayne Davison
53936ef935 Fixed the use of --protect-args (-s) with a daemon. 2008-03-15 11:56:18 -07:00
Wayne Davison
7f9bf6b710 Generate a helpful message when we get an option-error from a daemon
while requesting a file-listing and we suspect that the remote rsync
is complaining about the -d option.
2008-03-15 11:24:38 -07:00
Wayne Davison
cfdb27b0c1 Another optimization of "bp" adding when creating a file_struct. 2008-03-15 07:27:33 -07:00
Wayne Davison
fc3ca11040 Got rid of some useless uses of the -t option. 2008-03-15 07:26:46 -07:00
Wayne Davison
d6c9c3319b - Fixed a crash bug when backing up files with ACLs enabled and we
create a directory in the backup-path area.
- Fixed a bug where make_file() was setting F_PATHNAME() on the
  receiving side.
- A non-pool (temp-memory) file structure now stores the size of
  its extra_cnt value in the F_DEPTH() int so that unmake_file()
  can always be sure of how to free() the memory.
- The ACL-preserving code no longer allocates 4 more bytes per
  file entry than it needs.
- Got rid of a useless adding of the symlink length to "bp".
2008-03-15 00:44:53 -07:00
Wayne Davison
8afaef4219 Have configure check to see if /usr/include/popt/popt.h is around
(rather than /usr/include/popt.h), and use the included popt lib
if it is (to avoid a potential conflict due to our use of -I.).
2008-03-14 22:55:59 -07:00
Wayne Davison
11faa893ca (Matt) More itemize clarifications. 2008-03-13 17:45:13 -07:00
Wayne Davison
600b56b316 Clarify that the change/checksum itemize flag can be missing
when talking to older rsync versions.
2008-03-12 16:51:13 -07:00
Wayne Davison
ee39281d14 Fixed the 'T' itemized output for a symlink the right way this time. 2008-03-11 17:35:49 -07:00
Wayne Davison
0607c30700 - One more fix for the 'T' itemized output for a symlink when we're
the client on the receiving side of a protocol-29 connection.
2008-03-11 07:26:37 -07:00
Wayne Davison
492ad04277 (Matt) Add missing --no-y option. 2008-03-10 21:40:04 -07:00
Wayne Davison
1ed9018e69 Fixed some itemized logging failures:
- If a symlink/device/special-file changes its value without any
  attribute changes, the itemized event no longer gets dropped.
- We put a 'c' into the checksum/change field now to indicate when
  a symlink/device/special-file changes its value without changing
  its type.  This lets us properly interpret the --copy-links output
  to know which items are getting copied without changes and which
  are getting created with new content.
- Fixed the 'T' itemized output for a symlink when rsync tries to
  set the right time but fails due to lack of OS/disk support.
2008-03-10 21:39:01 -07:00
Wayne Davison
ff0e15804f Fixed the itemizing of perms with -E. 2008-03-09 19:50:51 -07:00
Wayne Davison
894e6299c1 Some popt improvements:
- Fixed a bug in short-opt parsing when an abutting arg has an '='.
- Allow a short-opt to be separated from its arg by an '='.
- Avoid an IBM-checker warning about an impossible case in a switch
  and a warning about a potential NULL-pointer dereference.
- Fixed a memory leak.
2008-03-08 11:02:40 -08:00
Wayne Davison
c080190365 Fixed the latest xattrs tests on OS X. 2008-03-07 17:13:38 -08:00
Wayne Davison
26f0e56587 Restore a long-attribute test that was temporarily disabled. 2008-03-07 16:45:26 -08:00
Wayne Davison
b4e6aac985 Fixed a syntax problem for non-HAVE_LINUX_ATTRS systems. 2008-03-07 16:41:09 -08:00
Wayne Davison
7c21776e54 Handle the very latest spot for the nightly dir. 2008-03-07 16:25:05 -08:00
Wayne Davison
d724dd186e Fixed the interaction of --fake-super with --link-dest & --xattrs.
Fixed the munging of non-user namespace xattrs w/--fake-super.
Fixed the sorting of received xattrs when name-munging occurs.
Added xattr tests to verify that these things stay fixed.
2008-03-07 16:23:21 -08:00
Wayne Davison
cbbd8e2e8b The --fake-super option conflicts with -XX (which copies internal
rsync xattrs literally).
2008-03-07 15:23:39 -08:00
Wayne Davison
af6241f7ad Simplify the description of what we're doing. 2008-03-06 09:40:46 -08:00
Wayne Davison
852e763b89 Added even more no-OPTION overrides. 2008-03-06 09:38:48 -08:00
Wayne Davison
0f71592015 Made the description of ignored symlink errors more accurate. 2008-03-06 09:37:26 -08:00
Wayne Davison
e63d3a29e2 Updated nightly-rsync and release-rsync to handle the new
ftp directory layout.
2008-03-05 00:22:55 -08:00
Wayne Davison
38cef641a5 Updated rrsync to deal with the latest 3.0.0's use of the -e option.
Added a couple more long options that might get passed.
2008-03-04 22:51:56 -08:00
Wayne Davison
6226396c4a Don't call utimes() on a dir that doesn't need its mtime changed. 2008-03-04 22:48:01 -08:00
Wayne Davison
89b47d43de - Made the itemize test check for CAN_HARDLINK_SYMLINK define instead
of running its own test using ln.
- Made the merge test call checkit with absolute paths so that some
  folk's cd command won't foul things up with extra output.
2008-03-04 21:46:27 -08:00
Wayne Davison
d1c06c2180 Fixing a problem with a NULL config_file pointer when accessing
a single-use daemon without no --config option specified.  Added
a test to ensure that this doesn't break in the future.
2008-03-03 18:33:11 -08:00
Wayne Davison
800a4485f3 Improved the error-checking when tweaking the files for a new release. 2008-03-03 12:33:15 -08:00
Wayne Davison
fede378577 Updated copyright year in --version output and improved the release
script to look for year changes in options.c and to get the version
defaults totally right in the prompts.
2008-03-03 11:19:48 -08:00
Wayne Davison
3bc207b9dd Fixed a thinko and a typo in the --append option. 2008-03-03 07:16:38 -08:00
Wayne Davison
ebac031925 Show the last compile error if we failed to create rounding.h. 2008-03-01 21:00:41 -08:00
Wayne Davison
3cbe640d3c Tweak the files to start work on the next release.
The work-in-progress version is 3.0.1dev.
2008-03-01 20:35:18 -08:00
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
Wayne Davison
6a85ee9623 Preparing for release of 3.0.0pre4 2007-10-27 05:09:06 +00:00
Wayne Davison
5851ac2dfe Fixed a problem with build_hash_table() getting called too
often when overwriting a shorter file.
2007-10-27 04:41:18 +00:00
Wayne Davison
e844a4a8a8 When listing a bare module name w/o -r, make sure we list the
contents of the module's root directory.
2007-10-27 02:19:49 +00:00
Wayne Davison
1d8638ce86 Preparing for release of 3.0.0pre3 2007-10-27 00:00:21 +00:00
Wayne Davison
4c17cdcb64 Chunk a really large file to avoid sender-side hash-table
overload.
2007-10-26 22:11:19 +00:00
Wayne Davison
c291d05759 Fixed problem with anchored filter and an absolute
source path with --relative.
2007-10-26 16:53:02 +00:00
Wayne Davison
9520ce4b65 Mention .git/ exclude. 2007-10-25 02:05:43 +00:00
Wayne Davison
0485b451ea Added .git/ to "CVS" excludes. 2007-10-25 02:05:05 +00:00
Wayne Davison
4efa11680a We need to provide iconvbufs() anytime ICONV_CONST is defined. 2007-10-25 01:40:17 +00:00
Wayne Davison
2f39f112c1 A few more improvements. 2007-10-21 22:30:49 +00:00
Wayne Davison
0438c59fd0 Improved a description. 2007-10-21 21:53:20 +00:00
Wayne Davison
1aa343e89c Make last fix even better. 2007-10-21 21:52:25 +00:00
Wayne Davison
5ed353a881 Avoid dropping a hard-linked itemized output with -ii. 2007-10-21 16:50:31 +00:00
Wayne Davison
c126e66ebd Got rid of a couple compiler warnings when SUPPORT_HARD_LINKS is not
defined.
2007-10-20 06:19:01 +00:00
Wayne Davison
97bcf138be Improved a couple entries. 2007-10-18 19:47:41 +00:00
Wayne Davison
37ce167996 We can't decrement the in_progress value for a hard-linked file until
the generator gets a chance to finish the hard links.
2007-10-18 14:04:42 +00:00
Wayne Davison
88a7426843 Typedef any missing types. 2007-10-17 14:15:22 +00:00
Wayne Davison
a1f7c8e250 Add checking for id_t, and changed some of the type checking to use
the newer, recommended method.  (Couldn't switch uid_t and gid_t.)
2007-10-17 14:15:18 +00:00
Wayne Davison
52d9a554d1 Changed a word in an error message. 2007-10-16 22:42:10 +00:00
Wayne Davison
aabb50d4e3 Tweaked set_allow_inc_recurse() a bit more. 2007-10-16 18:33:47 +00:00
Wayne Davison
03646b4910 The start of some updated "thanks". 2007-10-16 16:19:40 +00:00
Wayne Davison
11b02d927f Adding Wesley Terpstra's lchmod()-equivalent that uses setattrlist(). 2007-10-16 16:00:41 +00:00
Wayne Davison
5cefa088e2 We now report symlink mode changes if HAVE_SETATTRLIST is defined. 2007-10-16 16:00:34 +00:00
Wayne Davison
2e4e03f196 Added checks for setattrlist and sys/attr.h. 2007-10-16 16:00:31 +00:00
Wayne Davison
ea4e8cf8a1 Call set_allow_inc_recurse() for situations that don't call server_options(). 2007-10-16 15:10:17 +00:00
Wayne Davison
95def6d957 - Send an 'i' in the -e arg to the server if we can support inc_recurse.
- Got rid of some unneeded blocking_io value twiddling.
- Send --use-qsort to the server if it was specified.
2007-10-16 15:10:12 +00:00
Wayne Davison
9970bed4d9 - Moved the arg-checking relating into set_allow_inc_recurse() and
call it when the server is in setup_protocol().  The function sets
  allow_inc_recurse to 0 if some options won't allow us to support
  an incremental-recursive transfer.
- The server now checks for an 'i' in the -e option from the client
  and zeros out allow_inc_recurse if not found.
- The server reports its inc_recurse determination back to the client.
- The client sets inc_recurse based on the value it gets from the server.
2007-10-16 15:10:09 +00:00
Wayne Davison
494d049ce1 Incremented the SUBPROTOCOL_VERSION. 2007-10-16 15:10:05 +00:00
Wayne Davison
6a385e3b7e We don't need to send --no-i-r anymore. 2007-10-16 04:08:25 +00:00
Wayne Davison
71456d301f Write out the inc_recurse flag into a protocol-30 batch file. 2007-10-16 04:08:21 +00:00
Wayne Davison
dbd697b578 - Send a flag from the client to the server to indicate if the protocol
is going to run in inc_recurse mode or not.
- Verify that the options we received (as a server or as a batch-reader)
  are compatible with the requested inc_recurse mode.
2007-10-16 04:08:18 +00:00
Wayne Davison
5ca70927be Incremented the SUBPROTOCOL_VERSION. 2007-10-16 04:08:14 +00:00
Wayne Davison
2e52ba36cb Added braces to an empty "if" (to avoid any complaints from a compiler
that likes to point out an "if (...)" with a semicolon after it).
2007-10-15 00:16:12 +00:00
Wayne Davison
fd78520dca If there's no lchmod(), don't itemize permission differences for
symlinks.
2007-10-15 00:13:59 +00:00
Wayne Davison
3f655ca08d If the user told us to use a password file and we used it, there's
no need to comment if a RSYNC_PASSWORD environment variable is set.
2007-10-14 21:20:31 +00:00
Wayne Davison
76edd33498 Fixed a typo in a comment. 2007-10-14 18:55:49 +00:00
Wayne Davison
e5f35681e6 Forward MSG_IO_ERROR to the generator so that it can disable deletions. 2007-10-13 05:23:34 +00:00
Wayne Davison
32b9011ae9 Improvements surrounding --list-only and --dirs. 2007-10-13 04:32:53 +00:00
Wayne Davison
fdad5aad3f Get the version # right in the changelog. 2007-10-12 14:08:19 +00:00
Wayne Davison
90ac152deb Modify the changelog section in the .spec file for each release. 2007-10-12 14:04:29 +00:00
Wayne Davison
e9df0a6242 Fixed the day of the week. 2007-10-12 14:04:00 +00:00
Wayne Davison
4cf94b8a01 Improved the summary, the description, and the changelog. 2007-10-12 13:57:37 +00:00
Wayne Davison
a6fa5bdef3 Improved the initial description summary. 2007-10-12 13:57:15 +00:00
Wayne Davison
8f61dfdbd4 One more tweak to the synopsis. 2007-10-12 01:21:02 +00:00
Wayne Davison
ddf8c2b0b2 Improvements suggested by Matt's improved manpage. 2007-10-12 01:12:05 +00:00
98 changed files with 5479 additions and 2758 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,27 @@ 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) $(CPPFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >rounding.out 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 \
cat rounding.out 1>&2; \
echo "Failed to create rounding.h!" 1>&2; \
exit 1; \
fi
@rm -f rounding.out
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
@@ -99,22 +111,59 @@ TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
gen:
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 +173,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 +211,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)

230
NEWS
View File

@@ -1,232 +1,18 @@
NEWS for rsync 3.0.0 (UNRELEASED)
Protocol: 30 (changed)
Changes since 2.6.9:
NOTABLE CHANGES IN BEHAVIOR:
- The handling of implied directories when using --relative has changed to
send them as directories (e.g. no implied dir is ever sent as a symlink).
This avoids unexpected behavior and should not adversely affect most
people. If you're one of those rare people who relied upon having 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.)
- Requesting a remote file list 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.
NEWS for rsync 3.0.2 (8 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.1:
BUG FIXES:
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
- Made the output of all file types consistent when using a --*-dest
option. Prior versions used to output too many creation events for
matching items.
- The code that waits for a child pid now handles being interrupted by a
signal. This fixes a problem with the pre-xfer exec function not being
able to get the exit status from the script.
- A negated filter rule (with a '!' modifier) no longer loses the negation
when sending the filter rules to the remote rsync.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
would output superfluous directory information for a non-daemon rsync.
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
files (which includes local copies). Version 2.6.9 would complete the
copy, but exit with an error when the receiver output its memory stats.
- If --password-file is used on a non-daemon transfer, rsync now complains
and exits. This should help users figure out that they can't use this
option to control a remote shell's password prompt.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- The --append option no longer updates a file that has the same size.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- 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 does not delete the pidfile
for the running daemon -- if the pidfile exists, the extra program 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).
- Fixed a potential buffer overflow in the xattr code.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
to another 3.x version. This starts the transfer going more quickly
(before all the files have been found), and requires much less memory.
See the --recursive option in the manpage for some restrictions.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.
- 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 have an
empty hostname, as seen here: :file1 ::module/file2. This means that
local use of brace expansion now works: rsync -av host:path/{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
to the remote-shell command. This protects them from space-splitting,
and only interprets basic wildcard special shell characters (*?[).
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.
- 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, patched versions of rsync, apply the acls.diff file from the patches
dir.)
- Added the --xattrs (-X) option to preserver extended attributes. This is
an improved version of the prior patch that was available. (If you need
to have backward compatibility with old, patched versions of rsync, apply
the xattrs.diff file from the patches dir.)
- 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.
There is also an analogous "fake super" option 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
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.
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress.
- 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 --max-delete option now outputs a warning if it skipped any file
deletions, including a count of how many deletions were skipped. (Older
versions just silently stopped deleting things.)
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
about extraneous files without deleting anything. If you're not sure
what version the client is, you can use the less-obvious --max-delete=-1,
as both old and new versions will treat that as the same request (though
older versions don't warn).
- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).
- The filter rules now support a perishable ("p") modifier that marks rules
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- 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).
- Protocol 30 now uses MD5 checksums instead of MD4.
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --append-verify option, which works like the older --append
option (verifying the existing data in the destination file). For
compatibility with older rsync versions, any use of --append that is
talking protocol 29 or older will revert to the --append-verify method.
- 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.
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.
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Fixed a build problem with older (2.x) versions of gcc.
- Added some isType() functions that make dealing with signed characters
easier without forcing variables via casts.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Added missing prototypes for compatibility functions from the lib dir.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Made the sending of some numbers more efficient for protocol 30.
- Make sure that a daemon process doesn't mind if the client was weird and
omitted the --server option.
- 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.
- None.
DEVELOPER RELATED:
- Rsync is now licensed under the GPLv3 or later.
- The RPM spec file was improved to install more useful files.
- 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,
and another file system 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
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).
- A few developer-oriented scripts were moved from the support dir
to the packaging dir.

485
OLDNEWS
View File

@@ -1,3 +1,484 @@
NEWS for rsync 3.0.1 (3 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.0:
NOTABLE CHANGES IN BEHAVIOR:
- Added the 'c'-flag to the itemizing of non-regular files so that the
itemized output doesn't get hidden if there were no attribute changes,
and also so that the itemizing of a --copy-links run will distinguish
between copying an identical non-regular file and the creation of a
revised version with a new value (e.g. a changed symlink referent, a
new device number, etc.).
BUG FIXES:
- Fixed a crash bug when a single-use rsync daemon (via remote shell) was
run without specifying a --config=FILE option.
- Fixed a crash when backing up a directory that has a default ACL.
- Fixed a bug in the handling of xattr values that could cause rsync to
not think that a file's extended attributes are up-to-date.
- Fixed the working of --fake-super with --link-dest and --xattrs.
- Fixed a hang when combining --dry-run with --remove-source-files.
- Fixed a bug with --iconv's handling of files that cannot be converted:
a failed name can no longer cause a transfer failure.
- Fixed the building of the rounding.h file on systems that need custom
CPPFLAGS to be used. Also improved the error reporting if the building
of rounding.h fails.
- Fixed the use of the --protect-args (-s) option when talking to a daemon.
- Fixed the --ignore-existing option's protection of files on the receiver
that are non-regular files on the sender (e.g. if a symlink or a dir on
the sender is trying to replace a file on the receiver). The reverse
protection (protecting a dir/symlink/device from being replaced by a
file) was already working.
- Fixed an assert failure if --hard-links is combined with an option that
can skip a file in a set of hard-linked files (i.e. --ignore-existing,
--append, etc.), without skipping all the files in the set.
- Avoid setting the modify time on a directory that already has the right
modify time set. This avoids tweaking the dir's ctime.
- Improved the daemon-exclude handling to do a better job of applying the
exclude rules to path entries. It also sends the user an error just as
if the files were actually missing (instead of silently ignoring the
user's args), and avoids sending the user the filter-action messages
for these non-user-initiated rules.
- Fixed some glitches with the dry-run code's missing-directory
handling, including a problem when combined with --fuzzy.
- Fixed some glitches with the skipped-directory handling.
- Fixed the 'T'-flag itemizing of symlinks when --time isn't preserved.
- Fixed a glitch in the itemizing of permissions with the -E option.
- The --append option's restricting of transfers to those that add data no
longer prevents the updating of non-content changes to otherwise up-to-
date files (i.e. those with the same content but differing permissions,
ownership, xattrs, etc.).
- Don't allow --fake-super to be specified with -XX (double --xattrs)
because the options conflict. If a daemon has "fake super" enabled,
it automatically downgrades a -XX request to -X.
- Fixed a couple bugs in the parsing of daemon-config excludes that could
make a floating exclude rule get treated as matching an absolute path.
- A daemon doesn't try to auto-refuse the "iconv" option if iconv-support
wasn't compiled in to the daemon (avoiding a warning in the logs).
- Fixed the inclusion of per-dir merge files from implied dirs.
- Fixed the support/rrsync script to work with the latest options that
rsync sends (including its flag-specifying use of -e to the server).
ENHANCEMENTS:
- Added the --old-dirs (--old-d) option to make it easier for a user to
ask for file-listings with older rsync versions (this is easier than
having to type "-r --exclude='/*/*'" manually).
- When getting an error while asking an older rsync daemon for a file
listing, rsync will try to notice if the error is a rejection of the
--dirs (-d) option and let the user know how to work around the issue.
- Added a few more --no-OPTION overrides.
- Improved the documentation of the --append option.
- Improved the documentation of the filter/exclude/include daemon
parameters.
INTERNAL:
- Fixed a couple minor bugs in the included popt library (ones which I
sent to the official popt project for inclusion in the 1.14 release).
- Fixed a stat() call that should have been do_stat() so that the proper
normal/64-bit stat() function gets called. (Was in an area that should
not have caused problems, though.)
- Changed the file-glob code to do a directory scan without using the
"glob" and "glob.h". This lets us do the globbing with less memory
churn, and also avoid adding daemon-excluded items to the returned
args.
DEVELOPER RELATED:
- The configure script tries to get the user's compiler to not warn about
unused function parameters if the build is not including one or more of
the ACL/xattrs/iconv features.
- The configure script now has better checks for figuring out if the
included popt code should be used or not.
- Fixed two testsuite glitches: avoid a failure if someone's "cd" command
outputs the current directory when cd-ing to a relative path, and made
the itemized test query how rsync was built to determine if it should
expect hard-linked symlinks or not.
- Updated the testsuite to verify that various bug fixes remain fixed.
- The RPM spec file was updated to have: (1) comments for how to use the
rsync-patch tar file, and (2) an /etc/xinetd.d/rsync file.
- Updated the build scripts to work with a revised FTP directory
structure.
NEWS for rsync 3.0.0 (1 Mar 2008)
Protocol: 30 (changed)
Changes since 2.6.9:
NOTABLE CHANGES IN BEHAVIOR:
- The handling of implied directories when using --relative has changed to
send them as directories (e.g. no implied dir is ever sent as a symlink).
This avoids unexpected behavior and should not adversely affect most
people. If you're one of those rare individuals who relied upon having
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-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.
- Made the output of all file types consistent when using a --*-dest
option. Prior versions would output too many creation events for
matching items.
- The code that waits for a child pid now handles being interrupted by a
signal. This fixes a problem with the pre-xfer exec function not being
able to get the exit status from the script.
- A negated filter rule (i.e. with a '!' modifier) no longer loses the
negation when sending the filter rules to the remote rsync.
- Fixed a problem with the --out-format (aka --log-format) option %f: it
no longer outputs superfluous directory info for a non-daemon rsync.
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
files (which includes local copies). Version 2.6.9 would complete the
copy, but exit with an error when the receiver output its memory stats.
- If --password-file is used on a non-daemon transfer, rsync now complains
and exits. This should help users figure out that they can't use this
option to control a remote shell's password prompt.
- Make sure that directory permissions of a newly-created destination
directory are handled right when --perms is left off.
- The itemized output of a newly-created destination directory is now
output as a creation event, not a change event.
- Improved --hard-link so that more corner cases are handled correctly
when combined with options such as --link-dest and/or --ignore-existing.
- The --append option no longer updates a file that has the same size.
- Fixed a bug when combining --backup and --backup-dir with --inplace:
any missing backup directories are now created.
- Fixed a bug when using --backup and --inplace with --whole-file or
--read-batch: backup files are actually created now.
- 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
to another 3.x version. This starts the transfer going more quickly
(before all the files have been found), and requires much less memory.
See the --recursive option in the manpage for some restrictions.
- Lowered memory use in the non-incremental-recursion algorithm for typical
option values (usually saving from 21-29 bytes per file).
- The default --delete algorithm is now --delete-during when talking to a
3.x rsync. This is a faster scan than using --delete-before (which is
the default when talking to older rsync versions), and is compatible with
the new incremental recursion mode.
- 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). 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
to the remote-shell command. This protects them from space-splitting,
and only interprets basic wildcard special shell characters (*?[).
- Added the --delete-delay option, which is a more efficient way to delete
files at the end of the transfer without needing a separate delete pass.
- 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
dir.
- 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
rsync, apply the xattrs.diff file from the patches dir.
- 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" 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
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 (-z).
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
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
versions just silently stopped deleting things.)
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
about extraneous files without deleting anything. If you're not sure
what version the client is, you can use the less-obvious --max-delete=-1,
as both old and new versions will treat that as the same request (though
older versions don't warn).
- The --hard-link option now uses less memory on both the sending and
receiving side for all protocol versions. For protocol 30, the use of a
hashtable on the sending side allows us to more efficiently convey to the
receiver what files are linked together. This reduces the amount of data
sent over the socket by a considerable margin (rather than adding more
data), and limits the in-memory storage of the device+inode information
to just the sending side for the new protocol 30, or to the receiving
side when speaking an older protocol (note that older rsync versions kept
the device+inode information on both sides).
- The filter rules now support a perishable ("p") modifier that marks rules
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 ENOSYS error setting the time on a symlink, we don't
complain about it anymore (for those systems that even support the
setting of the modify-time on a symlink).
- Protocol 30 now uses MD5 checksums instead of MD4.
- Changed the --append option to not checksum the existing data in the
destination file, which speeds up file appending.
- Added the --append-verify option, which works like the older --append
option (verifying the existing data in the destination file). For
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.
- 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 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
easier without forcing variables via casts.
- Changed strcat/strcpy/sprintf function calls to use safer versions.
- Upgraded the included popt version to 1.10.2 and improved its use of
string-handling functions.
- Added missing prototypes for compatibility functions from the lib dir.
- Configure determines if iconv() has a const arg, allowing us to avoid a
compiler warning.
- Made the sending of some numbers more efficient for protocol 30.
- 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 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 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 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.
NEWS for rsync 2.6.9 (6 Nov 2006)
Protocol: 29 (unchanged)
Changes since 2.6.8:
@@ -2244,7 +2725,9 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
?? ??? 2007 3.0.0 11 Nov 2006 30
08 Apr 2008 3.0.2 30
03 Apr 2008 3.0.1 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,34 +163,31 @@ 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(FERROR, "falling back to RSYNC_PASSWORD environment variable.\n");
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
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) {
rprintf(FERROR,"continuing without password file\n");
if (envpw)
rprintf(FERROR, "using RSYNC_PASSWORD environment variable.\n");
close(fd);
rprintf(FWARNING, "continuing without password file\n");
if (envpw)
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
if (envpw)
rprintf(FERROR, "RSYNC_PASSWORD environment variable ignored\n");
n = read(fd, buffer, sizeof buffer - 1);
close(fd);
if (n > 0) {

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
@@ -22,7 +22,9 @@
#include "rsync.h"
#include "ifuncs.h"
extern int quiet;
extern int verbose;
extern int dry_run;
extern int output_motd;
extern int list_only;
extern int am_sender;
@@ -30,15 +32,19 @@ extern int am_server;
extern int am_daemon;
extern int am_root;
extern int rsync_port;
extern int protect_args;
extern int ignore_errors;
extern int preserve_xattrs;
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;
@@ -50,16 +56,22 @@ extern char *logfile_format;
extern char *files_from;
extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
extern struct filter_list_struct daemon_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 +123,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);
@@ -192,21 +208,31 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int
int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char *argv[])
{
int i;
int i, modlen;
char line[BIGPATHBUFLEN];
char *sargs[MAX_ARGS];
int sargc = 0;
char *p, *path = *argv;
char *p, *modname;
if (argc == 0 && !am_sender)
list_only |= 1;
assert(argc > 0 && *argv != NULL);
if (*path == '/') {
if (**argv == '/') {
rprintf(FERROR,
"ERROR: The remote path must start with a module name\n");
return -1;
}
if (!(p = strchr(*argv, '/')))
modlen = strlen(*argv);
else
modlen = p - *argv;
if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */
out_of_memory("start_inband_exchange");
strlcpy(modname, *argv, modlen + 1);
modname[modlen] = '/';
modname[modlen+1] = '\0';
if (!user)
user = getenv("USER");
if (!user)
@@ -232,7 +258,12 @@ 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);
}
sargs[sargc++] = *argv++;
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
else
sargs[sargc++] = *argv;
argv++;
argc--;
}
@@ -241,10 +272,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
if (verbose > 1)
print_child_argv("sending daemon args:", sargs);
p = strchr(path, '/');
if (p) *p = '\0';
io_printf(f_out, "%s\n", path);
if (p) *p = '/';
io_printf(f_out, "%.*s\n", modlen, modname);
/* Old servers may just drop the connection here,
rather than sending a proper EXIT command. Yuck. */
@@ -288,6 +316,8 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
if (rl_nulls) {
for (i = 0; i < sargc; i++) {
if (!sargs[i]) /* stop at --protect-args NULL */
break;
write_sbuf(f_out, sargs[i]);
write_byte(f_out, 0);
}
@@ -298,25 +328,38 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
write_sbuf(f_out, "\n");
}
if (protect_args)
send_protected_args(f_out, sargs);
if (protocol_version < 23) {
if (protocol_version == 22 || !am_sender)
io_start_multiplex_in();
}
free(modname);
return 0;
}
static char *finish_pre_exec(pid_t pid, int fd, char *request,
int argc, char *argv[])
char **early_argv, char **argv)
{
int j, status = -1;
int j = 0, status = -1;
if (!request)
request = "(NONE)";
write_buf(fd, request, strlen(request)+1);
for (j = 0; j < argc; j++)
if (early_argv) {
for ( ; *early_argv; early_argv++)
write_buf(fd, *early_argv, strlen(*early_argv)+1);
j = 1; /* Skip arg0 name in argv. */
}
for ( ; argv[j]; j++) {
write_buf(fd, argv[j], strlen(argv[j])+1);
if (argv[j][0] == '.' && argv[j][1] == '\0')
break;
}
write_byte(fd, 0);
close(fd);
@@ -338,8 +381,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)
@@ -352,8 +399,8 @@ 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;
int argc;
char **argv, **orig_argv, **orig_early_argv, *chroot_path = NULL;
char line[BIGPATHBUFLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
@@ -364,6 +411,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);
@@ -446,43 +500,57 @@ 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);
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);
push_dir(line, 1); /* Restore curr_dir. */
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0';
p += 2;
} else if ((p = strdup("/")) == NULL) /* MEMORY LEAK */
out_of_memory("rsync_module");
}
if (use_chroot || (module_dirlen = strlen(module_dir)) == 1) {
/* We do a change_dir() that doesn't actually call chdir()
* just to make a relative path absolute. */
strlcpy(line, curr_dir, sizeof line);
if (!change_dir(module_dir, CD_SKIP_CHDIR))
goto chdir_failed;
if (strcmp(curr_dir, module_dir) != 0
&& (module_dir = strdup(curr_dir)) == NULL)
out_of_memory("rsync_module");
change_dir(line, CD_SKIP_CHDIR); /* Restore curr_dir. */
if (use_chroot) {
chroot_path = module_dir;
module_dir = p; /* p is "/" or our inside-chroot path */
}
module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
if (module_dirlen == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
set_filter_dir(module_dir, module_dirlen);
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH);
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
p = lp_include_from(i);
parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
parse_filter_file(&daemon_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
parse_rule(&server_filter_list, p,
parse_rule(&daemon_filter_list, p,
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
parse_filter_file(&server_filter_list, p, 0,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
parse_filter_file(&daemon_filter_list, p, 0,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
log_init(1);
@@ -490,8 +558,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)
@@ -591,15 +668,17 @@ 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 (!change_dir(module_dir, CD_NORMAL))
goto chdir_failed;
if (module_dirlen)
sanitize_paths = 1;
} else {
if (!push_dir(module_dir, 0)) {
if (!change_dir(module_dir, CD_NORMAL)) {
chdir_failed:
rsyserr(FLOG, errno, "chdir %s failed\n", module_dir);
io_printf(f_out, "@ERROR: chdir failed\n");
@@ -608,6 +687,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 (do_stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
SYMLINK_PREFIX);
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
@@ -655,22 +746,40 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
io_printf(f_out, "@RSYNCD: OK\n");
opt_cnt = read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
orig_argv = argv;
verbose = 0; /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv);
if (protect_args && ret) {
orig_early_argv = orig_argv;
protect_args = 2;
read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request);
orig_argv = argv;
ret = parse_arguments(&argc, (const char ***) &argv);
} else
orig_early_argv = NULL;
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
opt_cnt, argv);
orig_early_argv, orig_argv);
}
verbose = 0; /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv, 0);
if (orig_early_argv)
free(orig_early_argv);
am_server = 1; /* Don't let someone try to be tricky. */
quiet = 0;
if (lp_ignore_errors(module_id))
ignore_errors = 1;
if (write_batch < 0)
dry_run = 1;
if (lp_fake_super(i))
if (lp_fake_super(i)) {
if (preserve_xattrs > 1)
preserve_xattrs = 1;
am_root = -1;
else if (am_root < 0) /* Treat --fake-super from client as --super. */
} else if (am_root < 0) /* Treat --fake-super from client as --super. */
am_root = 2;
if (filesfrom_fd == 0)
@@ -733,6 +842,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));
@@ -770,6 +896,17 @@ static void send_listing(int fd)
io_printf(fd,"@RSYNCD: EXIT\n");
}
static int load_config(int globals_only)
{
if (!config_file) {
if (am_server && am_root <= 0)
config_file = RSYNCD_USERCONF;
else
config_file = RSYNCD_SYSCONF;
}
return lp_load(config_file, globals_only);
}
/* this is called when a connection is established to a client
and we want to start talking. The setup of the system is done from
here */
@@ -785,7 +922,7 @@ int start_daemon(int f_in, int f_out)
* might cause log-file output to occur. This ensures that the
* "log file" param gets honored for the 2 non-forked use-cases
* (when rsync is run by init and run by a remote shell). */
if (!lp_load(config_file, 0))
if (!load_config(0))
exit_cleanup(RERR_SYNTAX);
addr = client_addr(f_in);
@@ -894,13 +1031,6 @@ static void become_daemon(void)
int daemon_main(void)
{
if (!config_file) {
if (am_server && am_root <= 0)
config_file = RSYNCD_USERCONF;
else
config_file = RSYNCD_SYSCONF;
}
if (is_a_socket(STDIN_FILENO)) {
int i;
@@ -915,7 +1045,7 @@ int daemon_main(void)
return start_daemon(STDIN_FILENO, STDIN_FILENO);
}
if (!lp_load(config_file, 1)) {
if (!load_config(1)) {
fprintf(stderr, "Failed to parse config file: %s\n", config_file);
exit_cleanup(RERR_SYNTAX);
}

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)
@@ -102,6 +109,21 @@ static void check_sub_protocol(void)
protocol_version--;
}
void set_allow_inc_recurse(void)
{
client_info = shell_cmd ? shell_cmd : "";
if (!recurse || use_qsort)
allow_inc_recurse = 0;
else if (!am_sender
&& (delete_before || delete_after
|| delay_updates || prune_empty_dirs))
allow_inc_recurse = 0;
else if (am_server && !local_server
&& (strchr(client_info, 'i') == NULL))
allow_inc_recurse = 0;
}
void setup_protocol(int f_out,int f_in)
{
if (am_sender)
@@ -117,6 +139,9 @@ void setup_protocol(int f_out,int f_in)
if (preserve_xattrs)
xattrs_ndx = ++file_extra_cnt;
if (am_server)
set_allow_inc_recurse();
if (remote_protocol == 0) {
if (am_server && !local_server)
check_sub_protocol();
@@ -156,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)
@@ -216,17 +243,42 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
} else if (protocol_version >= 30) {
if (recurse && allow_inc_recurse
&& !delete_before && !delete_after && !delay_updates
&& !use_qsort && !prune_empty_dirs)
inc_recurse = 1;
int compat_flags;
if (am_server) {
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
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,
"Incompatible options specified for inc-recursive %s.\n",
read_batch ? "batch file" : "connection");
exit_cleanup(RERR_SYNTAX);
}
need_messages_from_generator = 1;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
} else if (!am_sender) {
receiver_symlink_times = 1;
#endif
}
#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.0pre2
RSYNC_VERSION=3.0.2
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)]),
@@ -306,8 +311,10 @@ AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
sys/un.h sys/attr.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h \
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
popt.h popt/popt.h)
AC_HEADER_MAJOR
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
@@ -353,10 +360,7 @@ AC_C_LONG_DOUBLE
AC_TYPE_SIGNAL
AC_TYPE_UID_T
AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_PID_T
AC_CHECK_TYPES([mode_t,off_t,size_t,pid_t,id_t])
AC_TYPE_GETGROUPS
AC_CHECK_MEMBERS([struct stat.st_rdev])
@@ -438,6 +442,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],
@@ -451,7 +459,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.
@@ -462,13 +470,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],
@@ -497,15 +503,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?]) ],
[],
@@ -515,8 +512,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
@@ -531,10 +527,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)
#
@@ -557,11 +550,16 @@ AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask)
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
@@ -658,6 +656,15 @@ fi
if test x"$with_included_popt" != x"yes"; then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
fi
if test x"$ac_cv_header_popt_popt_h" = x"yes"; then
# If the system has /usr/include/popt/popt.h, we enable the
# included popt because an attempt to "#include <popt/popt.h>"
# would use our included header file anyway (due to -I.), and
# might conflict with the system popt.
with_included_popt=yes
elif test x"$ac_cv_header_popt_h" != x"yes"; then
with_included_popt=yes
fi
AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"; then
@@ -692,13 +699,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,[
@@ -827,8 +834,8 @@ 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)
#################################################
# check for ACL support
@@ -910,10 +917,6 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
esac
fi
AC_CHECK_HEADERS(attr/xattr.h)
AC_CHECK_HEADERS(sys/xattr.h)
AC_CHECK_HEADERS(sys/extattr.h)
#################################################
# check for extended attribute support
AC_MSG_CHECKING(whether to support extended attributes)
@@ -955,6 +958,23 @@ else
esac
fi
if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"$enable_iconv" = x"no"; then
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wno-unused-parameter"
AC_COMPILE_IFELSE([ ], [rsync_warn_flag=yes], [rsync_warn_flag=no])
AC_MSG_RESULT([$rsync_warn_flag])
if test x"$rsync_warn_flag" = x"no"; then
CFLAGS="$OLD_CFLAGS"
fi
fi
case "$CC" in
' checker'*|checker*)
AC_DEFINE(FORCE_FD_ZERO_MEMSET, 1, [Used to make "checker" understand that FD_ZERO() clears memory.])
;;
esac
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT

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:

116
exclude.c
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;
@@ -44,7 +43,7 @@ extern unsigned int module_dirlen;
struct filter_list_struct filter_list = { 0, 0, "" };
struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" };
struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
struct filter_list_struct daemon_filter_list = { 0, 0, " [daemon]" };
/* Need room enough for ":MODS " prefix plus some room to grow. */
#define MAX_RULE_PREFIX (16)
@@ -53,6 +52,8 @@ struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
#define MODIFIERS_INCL_EXCL "/!Crsp"
#define MODIFIERS_HIDE_PROTECT "/!p"
#define SLASH_WILD3_SUFFIX "/***"
/* The dirbuf is set by push_local_filters() to the current subdirectory
* relative to curr_dir that is being processed. The path always has a
* trailing slash appended, and the variable dirbuf_len contains the length
@@ -120,7 +121,7 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
{
struct filter_struct *ret;
const char *cp;
unsigned int ex_len;
unsigned int pre_len, suf_len, slash_cnt = 0;
if (verbose > 2) {
rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n",
@@ -146,22 +147,51 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
if (!(ret = new0(struct filter_struct)))
out_of_memory("add_rule");
if (pat_len > 1 && pat[pat_len-1] == '/') {
pat_len--;
mflags |= MATCHFLG_DIRECTORY;
}
for (cp = pat; cp < pat + pat_len; cp++) {
if (*cp == '/')
slash_cnt++;
}
if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
&& ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
|| (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) {
|| (xflags & XFLG_ABS_IF_SLASH && slash_cnt))) {
mflags |= MATCHFLG_ABS_PATH;
if (*pat == '/')
ex_len = dirbuf_len - module_dirlen - 1;
pre_len = dirbuf_len - module_dirlen - 1;
else
ex_len = 0;
pre_len = 0;
} else
ex_len = 0;
if (!(ret->pattern = new_array(char, ex_len + pat_len + 1)))
pre_len = 0;
/* The daemon wants dir-exclude rules to get an appended "/" + "***". */
if (xflags & XFLG_DIR2WILD3
&& BITS_SETnUNSET(mflags, MATCHFLG_DIRECTORY, MATCHFLG_INCLUDE)) {
mflags &= ~MATCHFLG_DIRECTORY;
suf_len = sizeof SLASH_WILD3_SUFFIX - 1;
} else
suf_len = 0;
if (!(ret->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
out_of_memory("add_rule");
if (ex_len)
memcpy(ret->pattern, dirbuf + module_dirlen, ex_len);
strlcpy(ret->pattern + ex_len, pat, pat_len + 1);
pat_len += ex_len;
if (pre_len) {
memcpy(ret->pattern, dirbuf + module_dirlen, pre_len);
for (cp = ret->pattern; cp < ret->pattern + pre_len; cp++) {
if (*cp == '/')
slash_cnt++;
}
}
strlcpy(ret->pattern + pre_len, pat, pat_len + 1);
pat_len += pre_len;
if (suf_len) {
memcpy(ret->pattern + pat_len, SLASH_WILD3_SUFFIX, suf_len+1);
pat_len += suf_len;
slash_cnt++;
}
if (strpbrk(ret->pattern, "*[?")) {
mflags |= MATCHFLG_WILD;
@@ -179,11 +209,6 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
}
}
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
ret->pattern[pat_len-1] = 0;
mflags |= MATCHFLG_DIRECTORY;
}
if (mflags & MATCHFLG_PERDIR_MERGE) {
struct filter_list_struct *lp;
unsigned int len;
@@ -227,10 +252,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
out_of_memory("add_rule");
}
mergelist_parents[mergelist_cnt++] = ret;
} else {
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
ret->u.slash_cnt++;
}
} else
ret->u.slash_cnt = slash_cnt;
ret->match_flags = mflags;
@@ -296,7 +319,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, SP_DEFAULT)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
return NULL;
@@ -304,18 +327,19 @@ 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. */
if (fn != buf) {
if (dirbuf_len + fn_len >= MAXPATHLEN) {
int d_len = dirbuf_len - prefix_skip;
if (d_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
return NULL;
}
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);
memcpy(buf, dirbuf + prefix_skip, d_len);
memcpy(buf + d_len, fn, fn_len + 1);
fn_len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
}
if (len_ptr)
@@ -337,7 +361,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 +397,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';
@@ -518,15 +542,14 @@ void change_local_filter_dir(const char *dname, int dlen, int dir_depth)
filt_array[cur_depth] = push_local_filters(dname, dlen);
}
static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
static int rule_matches(const char *fname, struct filter_struct *ex, int name_is_dir)
{
int slash_handling, str_cnt = 0, anchored_match = 0;
int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
char *p, *pattern = ex->pattern;
const char *strings[16]; /* more than enough */
const char *name = fname + (*fname == '/');
if (*name == '/')
name++;
if (!*name)
return 0;
@@ -536,13 +559,13 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
* just match the name portion of the path. */
if ((p = strrchr(name,'/')) != NULL)
name = p+1;
} else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
} else if (ex->match_flags & MATCHFLG_ABS_PATH && *fname != '/'
&& curr_dir_len > module_dirlen + 1) {
/* If we're matching against an absolute-path pattern,
* we need to prepend our full path info. */
strings[str_cnt++] = curr_dir + module_dirlen + 1;
strings[str_cnt++] = "/";
} else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') {
} else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *fname != '/') {
/* Allow "**"+"/" to match at the start of the string. */
strings[str_cnt++] = "/";
}
@@ -598,7 +621,7 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
}
static void report_filter_result(char const *name,
static void report_filter_result(enum logcode code, char const *name,
struct filter_struct const *ent,
int name_is_dir, const char *type)
{
@@ -610,7 +633,7 @@ static void report_filter_result(char const *name,
static char *actions[2][2]
= { {"show", "hid"}, {"risk", "protect"} };
const char *w = who_am_i();
rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n",
rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
name_is_dir ? "directory" : "file", name, ent->pattern,
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
@@ -622,7 +645,8 @@ static void report_filter_result(char const *name,
* Return -1 if file "name" is defined to be excluded by the specified
* exclude list, 1 if it is included, and 0 if it was not matched.
*/
int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
int check_filter(struct filter_list_struct *listp, enum logcode code,
const char *name, int name_is_dir)
{
struct filter_struct *ent;
@@ -630,22 +654,22 @@ int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
continue;
if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
int rc = check_filter(ent->u.mergelist, name,
int rc = check_filter(ent->u.mergelist, code, name,
name_is_dir);
if (rc)
return rc;
continue;
}
if (ent->match_flags & MATCHFLG_CVS_IGNORE) {
int rc = check_filter(&cvs_filter_list, name,
int rc = check_filter(&cvs_filter_list, code, name,
name_is_dir);
if (rc)
return rc;
continue;
}
if (rule_matches(name, ent, name_is_dir)) {
report_filter_result(name, ent, name_is_dir,
listp->debug_type);
report_filter_result(code, name, ent, name_is_dir,
listp->debug_type);
return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1;
}
}
@@ -900,7 +924,7 @@ static char default_cvsignore[] =
" *.a *.olb *.o *.obj *.so *.exe"
" *.Z *.elc *.ln core"
/* The rest we added to suit ourself. */
" .svn/ .bzr/";
" .svn/ .git/ .bzr/";
static void get_cvs_excludes(uint32 mflags)
{
@@ -1011,10 +1035,10 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
return;
if (*fname != '-' || fname[1] || am_server) {
if (server_filter_list.head) {
if (daemon_filter_list.head) {
strlcpy(line, fname, sizeof line);
clean_fname(line, 1);
if (check_filter(&server_filter_list, line, 0) < 0)
clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&daemon_filter_list, FLOG, line, 0) < 0)
fp = NULL;
else
fp = fopen(line, "rb");

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

791
flist.c
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
* `id -G` on Linux, but it's too hard to find a portable equivalent.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003-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;

160
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
@@ -126,12 +125,16 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
prev = -1;
} else if (CVAL(node->data, 0) == 0) {
struct file_list *flist;
struct file_struct *fp;
prev = IVAL(node->data, 1);
flist = flist_for_ndx(prev);
assert(flist != NULL);
fp = flist->files[prev - flist->ndx_start];
fp->flags &= ~FLAG_HLINK_LAST;
if (flist)
flist->files[prev - flist->ndx_start]->flags &= ~FLAG_HLINK_LAST;
else {
/* We skipped all prior files in this
* group, so mark this as a "first". */
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
}
} else
prev = -1;
} else {
@@ -144,12 +147,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 +164,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 +179,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 +224,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;
}
@@ -243,21 +244,42 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
}
/* Figure out if a prior entry is still there or if we just have a
* cached name for it. Never called with a FLAG_HLINK_FIRST entry. */
static char *check_prior(int prev_ndx, int gnum, struct file_list **flist_p)
* cached name for it. */
static char *check_prior(struct file_struct *file, int gnum,
int *prev_ndx_p, struct file_list **flist_p)
{
struct file_list *flist = flist_for_ndx(prev_ndx);
struct file_struct *fp;
struct ht_int32_node *node;
int prev_ndx = F_HL_PREV(file);
if (flist) {
*flist_p = flist;
return NULL;
while (1) {
struct file_list *flist;
if (prev_ndx < 0
|| (flist = flist_for_ndx(prev_ndx)) == NULL)
break;
fp = flist->files[prev_ndx - flist->ndx_start];
if (!(fp->flags & FLAG_SKIP_HLINK)) {
*prev_ndx_p = prev_ndx;
*flist_p = flist;
return NULL;
}
F_HL_PREV(file) = prev_ndx = F_HL_PREV(fp);
}
node = hashtable_find(prior_hlinks, gnum, 0);
assert(node != NULL && node->data);
assert(CVAL(node->data, 0) != 0);
return node->data;
if ((node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
assert(node->data != NULL);
if (CVAL(node->data, 0) != 0) {
*prev_ndx_p = -1;
*flist_p = NULL;
return node->data;
}
/* The prior file must have been skipped. */
F_HL_PREV(file) = -1;
}
*prev_ndx_p = -1;
*flist_p = NULL;
return NULL;
}
/* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns:
@@ -271,20 +293,28 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
char *realname, *prev_name;
struct file_list *flist;
int gnum = inc_recurse ? F_HL_GNUM(file) : -1;
int prev_ndx = F_HL_PREV(file);
int prev_ndx;
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
prev_name = realname = check_prior(file, gnum, &prev_ndx, &flist);
if (!prev_name) {
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
struct file_struct *prev_file;
/* Is the previous link is not complete yet? */
if (!flist) {
/* The previous file was skipped, so this one is
* treated as if it were the first in its group. */
return 0;
}
prev_file = flist->files[prev_ndx - flist->ndx_start];
/* 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;
@@ -297,8 +327,8 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
/* There is a finished file to link with! */
if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
/* The previous previous is FIRST when prev is not. */
prev_ndx = F_HL_PREV(prev_file);
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
prev_name = realname = check_prior(prev_file, gnum, &prev_ndx, &flist);
assert(prev_name != NULL || flist != NULL);
/* Update our previous pointer to point to the FIRST. */
F_HL_PREV(file) = prev_ndx;
}
@@ -323,7 +353,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;
}
@@ -345,7 +375,8 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|| prev_st.st_ino != alt_sx.st.st_ino)
continue;
statret = 1;
if (verbose < 2 || !stdout_format_has_i) {
if (stdout_format_has_i == 0
|| (verbose < 2 && stdout_format_has_i < 2)) {
itemizing = 0;
code = FNONE;
if (verbose > 1 && maybe_ATTRS_REPORT)
@@ -395,10 +426,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;
@@ -422,7 +453,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;
}
@@ -476,4 +507,25 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
out_of_memory("finish_hard_link");
}
}
int skip_hard_link(struct file_struct *file, struct file_list **flist_p)
{
struct file_list *flist;
int prev_ndx;
file->flags |= FLAG_SKIP_HLINK;
if (!(file->flags & FLAG_HLINK_LAST))
return -1;
check_prior(file, F_HL_GNUM(file), &prev_ndx, &flist);
if (prev_ndx >= 0) {
file = flist->files[prev_ndx - flist->ndx_start];
if (file->flags & (FLAG_HLINK_DONE|FLAG_FILE_SENT))
return -1;
file->flags |= FLAG_HLINK_LAST;
*flist_p = flist;
}
return prev_ndx;
}
#endif

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
@@ -57,6 +57,16 @@ from_wire_mode(int mode)
return mode;
}
static inline char *
d_name(struct dirent *di)
{
#ifdef HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;
#endif
}
static inline int
isDigit(const char *ptr)
{

149
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
@@ -45,6 +45,7 @@ extern int inc_recurse;
extern int io_error;
extern int eol_nulls;
extern int flist_eof;
extern int list_only;
extern int read_batch;
extern int csum_length;
extern int protect_args;
@@ -100,10 +101,11 @@ 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;
static int first_message = 1;
static char int_byte_extra[64] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (00 - 3F)/4 */
@@ -112,6 +114,9 @@ static char int_byte_extra[64] = {
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, /* (C0 - FF)/4 */
};
#define REMOTE_OPTION_ERROR "rsync: on remote machine: -"
#define REMOTE_OPTION_ERROR2 ": unknown option"
enum festatus { FES_SUCCESS, FES_REDO, FES_NO_SEND };
static void readfd(int fd, char *buffer, size_t N);
@@ -181,7 +186,6 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
struct file_list *flist = flist_for_ndx(ndx);
assert(flist != NULL);
assert(ndx >= flist->ndx_start);
if (remove_source_files) {
active_filecnt--;
@@ -197,8 +201,10 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
send_msg(MSG_SUCCESS, buf, 4, 0);
if (preserve_hard_links) {
struct file_struct *file = flist->files[ndx - flist->ndx_start];
if (F_IS_HLINKED(file))
if (F_IS_HLINKED(file)) {
flist_ndx_push(&hlink_list, ndx);
flist->in_progress++;
}
}
break;
case FES_REDO:
@@ -320,6 +326,36 @@ static void msg_flush(void)
}
}
static void check_for_d_option_error(const char *msg)
{
static char rsync263_opts[] = "BCDHIKLPRSTWabceghlnopqrtuvxz";
char *colon;
int saw_d = 0;
if (*msg != 'r'
|| strncmp(msg, REMOTE_OPTION_ERROR, sizeof REMOTE_OPTION_ERROR - 1) != 0)
return;
msg += sizeof REMOTE_OPTION_ERROR - 1;
if (*msg == '-' || (colon = strchr(msg, ':')) == NULL
|| strncmp(colon, REMOTE_OPTION_ERROR2, sizeof REMOTE_OPTION_ERROR2 - 1) != 0)
return;
for ( ; *msg != ':'; msg++) {
if (*msg == 'd')
saw_d = 1;
else if (*msg == 'e')
break;
else if (strchr(rsync263_opts, *msg) == NULL)
return;
}
if (saw_d) {
rprintf(FWARNING,
"*** Try using \"--old-d\" if remote rsync is <= 2.6.3 ***\n");
}
}
/* Read a message from the MSG_* fd and handle it. This is called either
* during the early stages of being a local sender (up through the sending
* of the file list) or when we're the generator (to fetch the messages
@@ -388,6 +424,12 @@ static void read_msg_fd(void)
goto invalid_msg;
flist_eof = 1;
break;
case MSG_IO_ERROR:
if (len != 4)
goto invalid_msg;
readfd(fd, buf, len);
io_error |= IVAL(buf, 0);
break;
case MSG_DELETED:
if (len >= (int)sizeof buf || !am_generator)
goto invalid_msg;
@@ -406,15 +448,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;
@@ -433,7 +477,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();
}
@@ -461,46 +505,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)
@@ -749,7 +788,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);
@@ -834,8 +873,8 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags)
return s - buf;
}
int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
char ***argv_p, int *argc_p, char **request_p)
void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
char ***argv_p, int *argc_p, char **request_p)
{
int maxargs = MAX_ARGS;
int dot_pos = 0;
@@ -849,14 +888,14 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
if (!(argv = new_array(char *, maxargs)))
out_of_memory("read_args");
if (mod_name)
if (mod_name && !protect_args)
argv[argc++] = "rsyncd";
while (1) {
if (read_line(f_in, buf, bufsiz, rl_flags) == 0)
break;
if (argc == maxargs) {
if (argc == maxargs-1) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("read_args");
@@ -879,11 +918,12 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
dot_pos = argc;
}
}
argv[argc] = NULL;
glob_expand(NULL, NULL, NULL, NULL);
*argc_p = argc;
*argv_p = argv;
return dot_pos ? dot_pos : argc;
}
int io_start_buffering_out(int f_out)
@@ -1041,6 +1081,7 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
if (msg_bytes != 4)
goto invalid_msg;
read_loop(fd, line, msg_bytes);
send_msg_int(MSG_IO_ERROR, IVAL(line, 0));
io_error |= IVAL(line, 0);
break;
case MSG_DELETED:
@@ -1054,7 +1095,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
@@ -1103,6 +1144,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,
@@ -1112,6 +1155,13 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
}
read_loop(fd, line, msg_bytes);
rwrite((enum logcode)tag, line, msg_bytes, 1);
if (first_message) {
if (list_only && !am_sender && tag == 1) {
line[msg_bytes] = '\0';
check_for_d_option_error(line);
}
first_message = 0;
}
break;
default:
rprintf(FERROR, "unexpected tag %d [%s]\n",
@@ -1504,7 +1554,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();
}
@@ -1854,6 +1905,8 @@ void start_write_batch(int fd)
* actual communication so far depends on whether a daemon
* is involved. */
write_int(batch_fd, protocol_version);
if (protocol_version >= 30)
write_byte(batch_fd, inc_recurse);
write_int(batch_fd, checksum_seed);
if (am_sender)

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

67
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;
@@ -620,14 +632,21 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
: !(iflags & ITEM_TRANSFER) ? '.'
: !local_server && *op == 's' ? '<' : '>';
c[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: IS_DEVICE(file->mode) ? 'D'
: S_ISLNK(file->mode) ? 'L' : 'f';
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';
if (S_ISLNK(file->mode)) {
c[1] = 'L';
c[3] = '.';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || !receiver_symlink_times
|| (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't';
} else {
c[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: IS_DEVICE(file->mode) ? 'D' : 'f';
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times ? 'T' : 't';
}
c[2] = !(iflags & ITEM_REPORT_CHANGE) ? '.' : 'c';
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
@@ -801,7 +820,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",

233
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;
@@ -74,11 +78,9 @@ extern char *batch_name;
extern char *password_file;
extern char curr_dir[MAXPATHLEN];
extern struct file_list *first_flist;
extern struct filter_list_struct server_filter_list;
#ifdef ICONV_OPTION
extern iconv_t ic_send;
#endif
extern struct filter_list_struct daemon_filter_list;
uid_t our_uid;
int local_server = 0;
int daemon_over_rsh = 0;
mode_t orig_umask = 0;
@@ -272,9 +274,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);
@@ -328,8 +331,7 @@ 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;
pid_t pid;
int dash_l_set = 0;
if (!read_batch && !local_server) {
@@ -339,7 +341,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
cmd = rsh_env;
if (!cmd)
cmd = RSYNC_RSH;
cmd = strdup(cmd);
cmd = strdup(cmd); /* MEMORY LEAK */
if (!cmd)
goto oom;
@@ -440,6 +442,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
if (read_batch) {
int from_gen_pipe[2];
set_allow_inc_recurse();
if (fd_pair(from_gen_pipe) < 0) {
rsyserr(FERROR, errno, "pipe");
exit_cleanup(RERR_IPC);
@@ -447,7 +450,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
batch_gen_fd = from_gen_pipe[0];
*f_out_p = from_gen_pipe[1];
*f_in_p = batch_fd;
ret = -1; /* no child pid */
pid = (pid_t)-1; /* no child pid */
#ifdef ICONV_CONST
setup_iconv();
#endif
@@ -456,57 +459,21 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
* it on, but only if we're not batch processing. */
if (whole_file < 0 && !write_batch)
whole_file = 1;
ret = local_child(argc, args, f_in_p, f_out_p, child_main);
set_allow_inc_recurse();
pid = local_child(argc, args, f_in_p, f_out_p, child_main);
#ifdef ICONV_CONST
setup_iconv();
#endif
} else {
pid = piped_child(args, f_in_p, f_out_p);
#ifdef ICONV_CONST
setup_iconv();
#endif
if (protect_args) {
int fd;
#ifdef ICONV_OPTION
int convert = ic_send != (iconv_t)-1;
xbuf outbuf, inbuf;
if (convert)
alloc_xbuf(&outbuf, 1024);
#endif
ret = piped_child(args, f_in_p, f_out_p);
for (i = 0; args[i]; i++) {} /* find first NULL */
args[i] = "rsync"; /* set a new arg0 */
if (verbose > 1)
print_child_argv("protected args:", args + i + 1);
fd = *f_out_p;
do {
#ifdef ICONV_OPTION
if (convert) {
INIT_XBUF_STRLEN(inbuf, args[i]);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
outbuf.buf[outbuf.len] = '\0';
write_buf(fd, outbuf.buf, outbuf.len + 1);
outbuf.len = 0;
} else
#endif
write_buf(fd, args[i], strlen(args[i]) + 1);
} while (args[++i]);
write_byte(fd, 0);
#ifdef ICONV_OPTION
if (convert)
free(outbuf.buf);
#endif
} else
ret = piped_child(args, f_in_p, f_out_p);
if (protect_args)
send_protected_args(*f_out_p, args);
}
if (dir)
free(dir);
return ret;
return pid;
oom:
out_of_memory("do_cmd");
@@ -540,12 +507,20 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (!dest_path || list_only)
return NULL;
if (daemon_filter_list.head
&& (check_filter(&daemon_filter_list, FLOG, dest_path, 0 != 0) < 0
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1 != 0) < 0)) {
rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
dest_path);
exit_cleanup(RERR_FILESELECT);
}
/* See what currently exists at the destination. */
if ((statret = do_stat(dest_path, &st)) == 0) {
/* If the destination is a dir, enter it and use mode 1. */
if (S_ISDIR(st.st_mode)) {
if (!push_dir(dest_path, 0)) {
rsyserr(FERROR, errno, "push_dir#1 %s failed",
if (!change_dir(dest_path, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#1 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
@@ -604,8 +579,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
dry_run++;
}
if (!push_dir(dest_path, dry_run > 1)) {
rsyserr(FERROR, errno, "push_dir#2 %s failed",
if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#2 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
@@ -624,8 +599,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
dest_path = "/";
*cp = '\0';
if (!push_dir(dest_path, 0)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
if (!change_dir(dest_path, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#3 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
@@ -634,36 +609,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);
}
}
}
@@ -712,8 +692,8 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
}
if (!relative_paths) {
if (!push_dir(dir, 0)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
if (!change_dir(dir, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#3 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
@@ -721,7 +701,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
argc--;
argv++;
if (argc == 0 && (recurse || list_only)) {
if (argc == 0 && (recurse || xfer_dirs || list_only)) {
argc = 1;
argv--;
argv[0] = ".";
@@ -751,7 +731,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)
@@ -859,7 +839,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) {
@@ -880,11 +859,11 @@ 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)) {
rsyserr(FERROR, errno, "push_dir#4 %s failed",
if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#4 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
@@ -921,26 +900,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, SP_DEFAULT);
if (partial_dir)
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, SP_DEFAULT);
}
fix_basis_dirs();
check_alt_basis_dirs();
if (server_filter_list.head) {
char **dir;
struct filter_list_struct *elp = &server_filter_list;
if (daemon_filter_list.head) {
char **dir_p;
struct filter_list_struct *elp = &daemon_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, FLOG, dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
&& check_filter(elp, partial_dir, 1) < 0) {
&& check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
options_rejected:
rprintf(FERROR,
"Your options have been rejected by the server.\n");
@@ -1058,11 +1038,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_start_multiplex_out();
}
if (argc == 0) {
list_only |= 1;
xfer_dirs |= 1;
}
send_filter_list(read_batch ? -1 : f_out);
if (filesfrom_fd >= 0) {
@@ -1079,7 +1054,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 {
@@ -1173,8 +1148,6 @@ static int start_client(int argc, char *argv[])
static char *dotarg[1] = { "." };
p = dotarg[0];
remote_argv = dotarg;
list_only |= 1;
xfer_dirs |= 1;
}
remote_argc = 1;
@@ -1246,10 +1219,6 @@ static int start_client(int argc, char *argv[])
}
remote_argv[i] = arg;
}
if (argc == 0) {
list_only |= 1;
xfer_dirs |= 1;
}
}
if (daemon_over_rsh < 0)
@@ -1261,6 +1230,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) {
@@ -1307,7 +1282,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);
}
@@ -1414,7 +1389,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));
@@ -1431,7 +1407,7 @@ int main(int argc,char *argv[])
setlocale(LC_CTYPE, "");
#endif
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
if (!parse_arguments(&argc, (const char ***) &argv)) {
/* FIXME: We ought to call the same error-handling
* code here, rather than relying on getopt. */
option_error();
@@ -1452,11 +1428,11 @@ int main(int argc,char *argv[])
SIGACTION(SIGXFSZ, SIG_IGN);
#endif
/* Initialize push_dir here because on some old systems getcwd
/* Initialize change_dir() here because on some old systems getcwd
* (implemented by forking "pwd" and reading its output) doesn't
* work when there are other child processes. Also, on all systems
* that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL, 0);
change_dir(NULL, CD_NORMAL);
init_flist();
@@ -1480,7 +1456,6 @@ int main(int argc,char *argv[])
read_stream_flags(batch_fd);
else
write_stream_flags(batch_fd);
}
if (write_batch < 0)
dry_run = 1;
@@ -1496,7 +1471,7 @@ int main(int argc,char *argv[])
char buf[MAXPATHLEN];
protect_args = 2;
read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
if (!parse_arguments(&argc, (const char ***) &argv)) {
option_error();
exit_cleanup(RERR_SYNTAX);
}

52
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,29 +39,50 @@ 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)
#define BIG_SUM2HASH(sum) ((sum)%tablesize)
static void build_hash_table(struct sum_struct *s)
{
static uint32 alloc_size;
int32 i;
if (!hash_table) {
hash_table = new_array(int32, TABLESIZE);
/* 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]);
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;
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;
}
}
}
@@ -164,11 +185,16 @@ static void hash_search(int f,struct sum_struct *s,
(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;

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

208
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
@@ -25,10 +25,12 @@
#include "zlib/zlib.h"
extern int module_id;
extern int local_server;
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;
extern struct filter_list_struct daemon_filter_list;
int make_backups = 0;
@@ -99,6 +101,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 +188,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 +203,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 +219,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,10 +254,13 @@ 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);
rprintf(f, "Copyright (C) 1996-2007 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "Copyright (C) 1996-2008 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "Web site: http://rsync.samba.org/\n");
rprintf(f, "Capabilities:\n");
rprintf(f, " %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
@@ -263,8 +270,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 +358,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 +384,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 +429,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 +446,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[] = {
@@ -467,6 +475,8 @@ static struct poptOption long_options[] = {
{"dirs", 'd', POPT_ARG_VAL, &xfer_dirs, 2, 0, 0 },
{"no-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 0, 0, 0 },
{"no-d", 0, POPT_ARG_VAL, &xfer_dirs, 0, 0, 0 },
{"old-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 },
{"old-d", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 },
{"perms", 'p', POPT_ARG_VAL, &preserve_perms, 1, 0, 0 },
{"no-perms", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
{"no-p", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
@@ -521,14 +531,19 @@ 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 },
{"ignore-existing", 0, POPT_ARG_NONE, &ignore_existing, 0, 0, 0 },
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
{"min-size", 0, POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
{"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
{"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
{"sparse", 'S', POPT_ARG_VAL, &sparse_files, 1, 0, 0 },
{"no-sparse", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
{"no-S", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
{"inplace", 0, POPT_ARG_VAL, &inplace, 1, 0, 0 },
{"no-inplace", 0, POPT_ARG_VAL, &inplace, 0, 0, 0 },
{"append", 0, POPT_ARG_NONE, 0, OPT_APPEND, 0, 0 },
{"append-verify", 0, POPT_ARG_VAL, &append_mode, 2, 0, 0 },
{"no-append", 0, POPT_ARG_VAL, &append_mode, 0, 0, 0 },
@@ -541,8 +556,10 @@ static struct poptOption long_options[] = {
{"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 },
{"remove-sent-files",0, POPT_ARG_VAL, &remove_source_files, 2, 0, 0 }, /* deprecated */
{"remove-source-files",0,POPT_ARG_VAL, &remove_source_files, 1, 0, 0 },
{"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
{"force", 0, POPT_ARG_VAL, &force_delete, 1, 0, 0 },
{"no-force", 0, POPT_ARG_VAL, &force_delete, 0, 0, 0 },
{"ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 1, 0, 0 },
{"no-ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 0, 0, 0 },
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
{0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
{"filter", 'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
@@ -561,11 +578,13 @@ static struct poptOption long_options[] = {
{"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
{"fuzzy", 'y', POPT_ARG_NONE, &fuzzy_basis, 0, 0, 0 },
{"fuzzy", 'y', POPT_ARG_VAL, &fuzzy_basis, 1, 0, 0 },
{"no-fuzzy", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 },
{"no-y", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 },
{"compress", 'z', POPT_ARG_NONE, 0, 'z', 0, 0 },
{"no-compress", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 },
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
{"no-z", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 },
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
{"compress-level", 0, POPT_ARG_INT, &def_compress_level, 'z', 0, 0 },
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
{"progress", 0, POPT_ARG_VAL, &do_progress, 1, 0, 0 },
@@ -575,7 +594,9 @@ static struct poptOption long_options[] = {
{"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
{"delay-updates", 0, POPT_ARG_VAL, &delay_updates, 1, 0, 0 },
{"no-delay-updates", 0, POPT_ARG_VAL, &delay_updates, 0, 0, 0 },
{"prune-empty-dirs",'m', POPT_ARG_NONE, &prune_empty_dirs, 0, 0, 0 },
{"prune-empty-dirs",'m', POPT_ARG_VAL, &prune_empty_dirs, 1, 0, 0 },
{"no-prune-empty-dirs",0,POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 },
{"no-m", 0, POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 },
{"log-file", 0, POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
{"log-file-format", 0, POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
{"out-format", 0, POPT_ARG_STRING, &stdout_format, 0, 0, 0 },
@@ -603,15 +624,20 @@ 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 },
{"no-contimeout", 0, POPT_ARG_VAL, &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 },
{"8-bit-output", '8', POPT_ARG_NONE, &allow_8bit_chars, 0, 0, 0 },
{"8-bit-output", '8', POPT_ARG_VAL, &allow_8bit_chars, 1, 0, 0 },
{"no-8-bit-output", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
{"no-8", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
{"qsort", 0, POPT_ARG_NONE, &use_qsort, 0, 0, 0 },
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
@@ -754,6 +780,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)
@@ -864,7 +892,7 @@ static void create_refuse_error(int which)
*
* @retval 0 on error, with err_buf containing an explanation
**/
int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
int parse_arguments(int *argc_p, const char ***argv_p)
{
static poptContext pc;
char *ref = lp_refuse_options(module_id);
@@ -874,8 +902,13 @@ 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*");
#ifdef ICONV_OPTION
if (!*lp_charset(module_id))
set_refuse_options("iconv");
#endif
}
#ifdef ICONV_OPTION
if (!am_daemon && !protect_args && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
@@ -1001,16 +1034,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);
if (server_filter_list.head) {
arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
if (daemon_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(&daemon_filter_list, FLOG, dir, 0) < 0;
free(cp);
if (rej)
goto options_rejected;
@@ -1063,8 +1097,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
break;
case 'q':
if (frommain)
quiet++;
quiet++;
break;
case 'x':
@@ -1122,6 +1155,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,
@@ -1236,7 +1275,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
}
if (human_readable && argc == 2) {
if (human_readable && argc == 2 && !am_server) {
/* Allow the old meaning of 'h' (--help) on its own. */
usage(FINFO);
exit_cleanup(0);
@@ -1249,14 +1288,17 @@ 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) {
if (!frommain)
protect_args = 0;
else if (am_server)
return 1;
}
if (protect_args == 1 && am_server)
return 1;
*argv_p = argv = poptGetArgs(pc);
*argc_p = argc = count_args(argv);
#ifndef SUPPORT_LINKS
if (preserve_links && !am_sender) {
@@ -1276,7 +1318,13 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
}
#endif
#ifndef SUPPORT_XATTRS
#ifdef SUPPORT_XATTRS
if (am_root < 0 && preserve_xattrs > 1) {
snprintf(err_buf, sizeof err_buf,
"--fake-super conflicts with -XX\n");
return 0;
}
#else
if (am_root < 0) {
snprintf(err_buf, sizeof err_buf,
"--fake-super requires an rsync with extended attributes enabled\n");
@@ -1301,7 +1349,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");
@@ -1338,8 +1387,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
xfer_dirs = 1;
}
if (xfer_dirs < 1)
xfer_dirs = recurse || list_only;
if (argc < 2 && !read_batch && !am_server)
list_only |= 1;
if (xfer_dirs >= 4) {
parse_rule(&filter_list, "- /*/*", 0, 0);
recurse = xfer_dirs = 1;
} else if (recurse)
xfer_dirs = 1;
else if (xfer_dirs < 0)
xfer_dirs = list_only ? 1 : 0;
if (relative_paths < 0)
relative_paths = files_from? 1 : 0;
@@ -1388,32 +1445,33 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
need_messages_from_generator = 1;
}
*argv_p = argv = poptGetArgs(pc);
*argc_p = argc = count_args(argv);
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, SP_KEEP_DOT_DIRS);
if (tmpdir)
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
if (backup_dir)
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
}
if (server_filter_list.head && !am_sender) {
struct filter_list_struct *elp = &server_filter_list;
if (daemon_filter_list.head && !am_sender) {
struct filter_list_struct *elp = &daemon_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, FLOG, 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, FLOG, dir, 1) < 0)
goto options_rejected;
}
}
@@ -1565,7 +1623,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 +1660,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);
if (server_filter_list.head) {
files_from = sanitize_path(NULL, files_from, NULL, 0, SP_DEFAULT);
if (daemon_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(&daemon_filter_list, FLOG, dir, 0) < 0)
goto options_rejected;
}
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
@@ -1644,12 +1704,8 @@ void server_options(char **args, int *argc_p)
static char argstr[64];
int ac = *argc_p;
char *arg;
int i, x;
if (blocking_io == -1)
blocking_io = 0;
/* This should always remain first on the server's command-line. */
args[ac++] = "--server";
@@ -1681,8 +1737,8 @@ void server_options(char **args, int *argc_p)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if ((list_only && !recurse) || xfer_dirs > 1
|| (xfer_dirs && !recurse && delete_mode && am_sender))
if ((xfer_dirs >= 2 && xfer_dirs < 4)
|| (xfer_dirs && !recurse && (list_only || (delete_mode && am_sender))))
argstr[x++] = 'd';
if (am_sender) {
if (keep_dirlinks)
@@ -1752,19 +1808,25 @@ void server_options(char **args, int *argc_p)
if (do_compression)
argstr[x++] = 'z';
/* We make use of the -e option to let the server know about any
* pre-release protocol version && some behavior flags. */
argstr[x++] = 'e';
#if SUBPROTOCOL_VERSION != 0
/* If we're speaking a pre-release version of a protocol, we tell
* the server about this by (ab)using the -e option. */
if (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"e%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
}
"%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
} else
#endif
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) {
@@ -1779,7 +1841,7 @@ void server_options(char **args, int *argc_p)
}
#endif
if (protect_args) /* initial args break here */
if (protect_args && !local_server) /* unprotected args stop here */
args[ac++] = NULL;
if (list_only > 1)
@@ -1925,8 +1987,8 @@ void server_options(char **args, int *argc_p)
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (!allow_inc_recurse)
args[ac++] = "--no-i-r";
if (use_qsort)
args[ac++] = "--use-qsort";
if (am_sender) {
if (ignore_existing)

6
packaging/bin/gpg Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh -e
# This script gets git to run gpg with a --passphrase-file option.
PATH=`echo $PATH | sed 's/^[^:]*://'`
gpg --batch --passphrase-file=$GPG_PASSFILE "${@}"

View File

@@ -4,13 +4,19 @@
# is included in the rrsync script.
use strict;
our(%short_no_arg, %short_with_num, %long_opt);
our %short_no_arg;
our %short_with_num;
our %long_opt = (
'no-i-r' => 0,
'fake-super' => 0,
'log-file' => 3,
);
our $last_long_opt;
open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
while (<IN>) {
if (/\Qargstr[x++]\E = '(.)'/) {
if (/\Qargstr[x++]\E = '([^.ie])'/) {
$short_no_arg{$1} = 1;
undef $last_long_opt;
} elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {

18
packaging/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;
}
}

View File

@@ -1,9 +1,12 @@
Summary: A program for synchronizing files over a network.
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.0pre2
Version: 3.0.2
%define fullversion %{version}
Release: 1
%define srcdir src
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz
Source0: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
#Source1: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-patches-%{fullversion}.tar.gz
URL: http://rsync.samba.org/
Prefix: %{_prefix}
@@ -11,18 +14,32 @@ BuildRoot: /var/tmp/%{name}-root
License: GPL
%description
Rsync uses a reliable algorithm to bring remote and host files into
sync very quickly. Rsync is fast because it just sends the differences
in the files over the network instead of sending the complete
files. Rsync is often used as a very powerful mirroring process or
just as a more capable replacement for the rcp command. A technical
report which describes the rsync algorithm is included in this
package.
Rsync is a fast and extraordinarily versatile file copying tool. It can
copy locally, to/from another host over any remote shell, or to/from a
remote rsync daemon. It offers a large number of options that control
every aspect of its behavior and permit very flexible specification of the
set of files to be copied. It is famous for its delta-transfer algorithm,
which reduces the amount of data sent over the network by sending only the
differences between the source files and the existing files in the
destination. Rsync is widely used for backups and mirroring and as an
improved copy command for everyday use.
%prep
%setup -q
# Choose one -- setup source only, or setup source + rsync-patches:
%setup -q -n rsync-%{fullversion}
#%setup -q -b1 -n rsync-%{fullversion}
# If you you used "%setup -q -b1", choose the patches you wish to apply:
#patch -p1 <patches/acls.diff
#patch -p1 <patches/xattrs.diff
#patch -p1 <patches/remote-option.diff
#patch -p1 <patches/db.diff
# Avoid extra perl dependencies for scripts going into doc dir.
chmod -x support/*
%build
#./prepare-source
%configure
make
@@ -32,57 +49,26 @@ rm -rf $RPM_BUILD_ROOT
%makeinstall
mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d
install -m 644 packaging/lsb/rsync.xinetd $RPM_BUILD_ROOT/etc/xinetd.d/rsync
#install -p -m 755 support/rsyncdb $RPM_BUILD_ROOT/usr/bin/rsyncdb
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc COPYING README tech_report.tex
%{_prefix}/bin/rsync
%doc COPYING NEWS OLDNEWS README support/ tech_report.tex
%config(noreplace) /etc/xinetd.d/rsync
%{_prefix}/bin/rsync*
%{_mandir}/man1/rsync.1*
%{_mandir}/man5/rsyncd.conf.5*
%changelog
* Thu Jan 30 2003 Horst von Brand <vonbrand@inf.utfsm.cl>
Fixed "Sept" date in %changelog here
Use %{_mandir} to point to manpages
Support for compressed manpages (* at end catches them in %files)
Add doc/README-SGML and doc/rsync.sgml to %doc
* Tue Apr 08 2008 Wayne Davison <wayned@samba.org>
Released 3.0.2.
* Mon Sep 11 2000 John H Terpstra <jht@turbolinux.com>
Changed target paths to be Linux Standards Base compliant
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
quoted RPM_OPT_FLAGS for the sake of robustness
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
Upgraded to Rsync 2.0.6
-new feature anonymous rsync
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
Upgrade to rsync version 1.7.2.
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
Changes from 1.6.3-2 packaging: added latex and dvips commands
to create tech_report.ps.
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
showing no packager nor signature but giving
"Source RPM: rsync-1.6.3-1.src.rpm".
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
to '%build', removed '%prefix'.
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
previous package(s).)
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
Added installation of /etc/xinetd.d/rsync file and some commented-out
lines that demonstrate how to use the rsync-patches tar file.

View File

@@ -0,0 +1,13 @@
# default: off
# description: The rsync server is a good addition to an ftp server, as it
# allows crc checksumming etc.
service rsync
{
disable = yes
socket_type = stream
wait = no
user = root
server = /usr/bin/rsync
server_args = --daemon
log_on_failure += USERID
}

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";
# Where the local copy of /home/ftp/pub/rsync/dev/nightly should be updated.
our $dest = $ENV{HOME} . '/samba-rsync-ftp/dev/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>) {
@@ -112,7 +104,7 @@ if ($upload) {
if (defined $ENV{RSYNC_PARTIAL_DIR}) {
$opt = " -f 'R $ENV{RSYNC_PARTIAL_DIR}'";
}
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/dev/nightly";
}
exit;
@@ -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

213
packaging/patch-update Executable file
View File

@@ -0,0 +1,213 @@
#!/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 ),
'shell|s' => \( my $launch_shell ),
'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';
my($status, $is_clean, $starting_branch) = &check_git_status;
if (!$skip_branch_check && !$is_clean) {
die "The checkout is not clean:\n", $status;
}
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/(.*)#) {
$patches{$1} = 1;
} elsif (m# patch/(.*)#) {
$patches{$1} = $local_patch{$1} = 1;
}
}
close PIPE;
my @patches = sort keys %patches;
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}++;
last unless 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 return 0;
} else {
system "git checkout --track -b patch/$patch origin/patch/$patch" and return 0;
}
my $ok = system("git merge $parent") == 0;
if (!$ok || $launch_shell) {
print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
$ENV{PS1} = "[$parent] patch/$patch: ";
while (1) {
if (system($ENV{SHELL}) != 0) {
print "Abort? [n/y] ";
$_ = <STDIN>;
next unless /^y/i;
return 0;
}
($status, $is_clean) = &check_git_status;
last if $is_clean;
print $status;
}
}
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
print OUT $description{$patch}, "\n";
if ($incl_generated_files) {
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/";
}
$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;
1;
}
exit;
sub check_git_status
{
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
my($starting_branch) = $status =~ /^# On branch (.+)\n/;
($status, $is_clean, $starting_branch);
}
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

@@ -1,182 +1,202 @@
#!/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 Term::ReadKey;
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $releasedir = $ENV{HOME} . '/release';
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
my $passfile = $ENV{HOME} . '/.rsyncpass';
my $path = $ENV{PATH};
my $ztoday = time2str('%d %b %Y', time);
my $today = $ztoday;
$today =~ s/^0//;
my $now = time;
my $cl_today = time2str('* %a %b %d %Y', $now);
my $year = time2str('%Y', $now);
my $ztoday = time2str('%d %b %Y', $now);
(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);
}
END {
unlink($passfile);
}
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 $confversion;
open(IN, '<', 'configure.in') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$confversion = $1;
last;
}
}
close IN;
die "Unable to find RSYNC_VERSION in configure.in\n" unless defined $confversion;
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
close IN;
my($lastversion) = /(\d+\.\d+\.\d+)/;
print $break, "\nPlease enter the version number of this release: [$version] ";
my $version = $confversion;
$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/;
die "Invalid version: `$version'\n" unless $version =~ /^[\d.]+(pre\d+)?$/;
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
if (`git tag -l v$version` ne '') {
print "Tag v$version already exists.\n\nDelete tag or quit? [q/del] ";
$_ = <STDIN>;
exit 1 unless /^del/i;
system "git tag -d v$version";
}
my $cvstag = "release-$version";
$cvstag =~ s/[.]/-/g;
$cvstag =~ s/pre/-pre/;
if ($version =~ s/[-.]*pre[-.]*/pre/ && $confversion !~ /dev$/) {
$lastversion = $confversion;
}
print "Enter the previous version to produce a patch against: [$lastversion] ";
chomp($_ = <STDIN>);
$lastversion = $_ if $_ ne '';
$lastversion =~ s/[-.]*pre[-.]*/pre/;
my $release = 1;
my $pre = $version =~ /(pre\d+)/ ? $1 : '';
my $release = $pre ? '0.1' : '1';
print "Please enter the RPM release number of this release: [$release] ";
chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
$release .= ".$pre" if $pre;
my $diffdir;
my $skipping2;
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
if ($lastversion =~ /pre/) {
if ($version !~ /pre/) {
if (!$pre) {
die "You should not diff a release version against a pre-release version.\n";
}
$diffdir = "$dest/old-previews";
$skipping2 = ' ** SKIPPING **';
} elsif ($version =~ /pre/) {
$diffdir = $dest;
$skipping2 = ' ** SKIPPING **';
$srcdir = $srcdiffdir = $lastsrcdir = 'src-previews';
$skipping = ' ** SKIPPING **';
} elsif ($pre) {
$srcdir = $srcdiffdir = 'src-previews';
$lastsrcdir = 'src';
$skipping = ' ** SKIPPING **';
} else {
$diffdir = "$dest/old-versions";
$skipping2 = '';
$srcdir = $lastsrcdir = 'src';
$srcdiffdir = 'src-diffs';
$skipping = '';
}
print "\n", $break, <<EOT;
\$version is "$version"
\$lastversion is "$lastversion"
\$cvstag is "$cvstag"
\$dest is "$dest"
\$releasedir is "$releasedir"
\$diffdir is "$diffdir"
\$curdir is "$curdir"
\$srcdir is "$srcdir"
\$srcdiffdir is "$srcdiffdir"
\$lastsrcdir is "$lastsrcdir"
\$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 manpages
- 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 $finalversion = $version) =~ s/pre\d+//;
my %specvars = ( 'Version:' => $finalversion, 'Release:' => $release,
'%define fullversion' => "\%{version}$pre", 'Released' => "$version.",
'%define srcdir' => $srcdir );
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'), glob('*.yo'),
qw( configure.in rsync.h NEWS OLDNEWS options.c ) );
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in configure ) );
if ($version !~ /pre/) {
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
}
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
if ($fn =~ /configure/) {
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m;
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m
or die "Unable to update RSYNC_VERSION in $fn\n";
} elsif ($fn =~ /\.spec/) {
s/^(Version:) .*/$1 $version/m;
s/^(Release:) .*/$1 $release/m;
while (my($str, $val) = each %specvars) {
s/^\Q$str\E .*/$str $val/m
or die "Unable to update $str in $fn\n";
}
s/^\* \w\w\w \w\w\w \d\d \d\d\d\d (.*)/$cl_today $1/m
or die "Unable to update ChangeLog header in $fn\n";
} elsif ($fn =~ /\.yo/) {
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
} elsif ($fn eq 'NEWS') {
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
or die "Couldn't update NEWS file with release date!\n";
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m
or die "Unable to update date in manpage() header in $fn\n";
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m
or die "Unable to update current version info in $fn\n";
} elsif ($fn eq 'rsync.h') {
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/;
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/
or die "Unable to find SUBPROTOCOL_VERSION define in $fn\n";
next if $pre;
} elsif ($fn eq 'NEWS') {
s/^(NEWS for rsync \Q$finalversion\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
or die "The first line of $fn is not in the right format. It must be:\n"
. "NEWS for rsync $finalversion (UNRELEASED)\n";
next if $pre;
} elsif ($fn eq 'OLDNEWS') {
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m
or die "Couldn't update OLDNEWS file with release date!\n";
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$finalversion\E)/\t$ztoday$1/m
or die "Unable to find \"?? ??? $year\t$finalversion\" line in $fn\n";
next if $pre;
} elsif ($fn eq 'options.c') {
if (s/(Copyright \(C\) 2002-)(\d+)( Wayne Davison)/$1$year$3/
&& $2 ne $year) {
die "Copyright comments need to be updated to $year in all files!\n";
}
# Adjust the year in the --version output.
s/(rprintf\(f, "Copyright \(C\) 1996-)(\d+)/$1$year/
or die "Unable to find Copyright string in --version output of $fn\n";
next if $2 eq $year;
} else {
die "Unrecognized file in \@tweak_files: $fn\n";
}
@@ -185,144 +205,141 @@ 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/$srcdir/$srctar_name";
my $pattar_file = "$dest/$srcdir/$pattar_name";
my $diff_file = "$dest/$srcdiffdir/$diff_name";
my $news_file = "$dest/$srcdir/rsync-$version-NEWS";
my $lasttar_file = "$dest/$lastsrcdir/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
- commit all version changes
- merge the master branch into the patch/* branches
- update the files in the "patches" dir and OPTIONALLY
(if you type 'y') to launch a shell for each patch
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
print "<Press Enter OR 'y' to continue> ";
my $ans = <STDIN>;
if ($live) {
system "cvs commit -m 'Preparing for release of $version'";
system "cvs tag -F $cvstag .";
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
print "Updating files in \"patches\" dir ...\n";
system "packaging/patch-update";
if ($ans =~ /^y/i) {
print "\nVisiting all \"patch/*\" branches ...\n";
system "packaging/patch-update --shell";
}
if (!/skip/i) {
print "\n", $break, $note, $break;
system "patches/verify-patches -pun -an";
}
my $tar_name = "rsync-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $tar_file = "$dest/$tar_name";
my $diff_file = "$dest/$diff_name";
print $break, <<EOT;
About to do the following in the samba-rsync-ftp dir:
- move the old tar/diff files into the appropriate old-* dirs
- hard-link the moved tar/diff files on samba.org$skipping
- create release tar, "$tar_name"
About to:
- create signed tag for this release: v$version
- create release diffs, "$diff_name"
- update README, *NEWS, TODO, and cvs.log
- update rsync*.html man pages
- gpg-sign the release files$skipping
- create release tar, "$srctar_name"
- generate rsync-$version/patches/* files
- create patches tar, "$pattar_name"
- update top-level README, *NEWS, TODO, and ChangeLog
- update top-level rsync*.html manpages
- gpg-sign the release files
- update hard-linked top-level release files$skipping
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
chdir($releasedir) or die $!;
my $passphrase;
while (1) {
ReadMode('noecho');
print "\nEnter your GPG pass-phrase: ";
chomp($passphrase = <STDIN>);
ReadMode(0);
print "\n";
print $break;
system "rm -rf rsync-$version";
rename('rsync', "rsync-$version") or die $!;
# Briefly create a temp file with the passphrase for git's tagging use.
my $oldmask = umask 077;
unlink($passfile);
open(OUT, '>', $passfile) or die $!;
print OUT $passphrase, "\n";
close OUT;
umask $oldmask;
$ENV{'GPG_PASSFILE'} = $passfile;
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
chdir($dest) or die $!;
print "Shuffling old files ...\n";
# We need to run this regardless of $lastversion's "pre"ness.
my @moved_files;
foreach my $fn (glob('rsync*pre*.tar.gz*'), glob('rsync*pre*-NEWS')) {
link($fn, "old-previews/$fn") or die $!;
push(@moved_files, $fn);
}
if ($version !~ /pre/) {
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
next if $fn =~ /^rsync.*pre/;
link($fn, "old-versions/$fn") or die $!;
push(@moved_files, $fn);
}
foreach my $fn (glob('rsync*pre*.diffs.gz*')) {
unlink($fn);
}
foreach my $fn (glob('rsync*.diffs.gz*')) {
link($fn, "old-patches/$fn") or die $!;
push(@moved_files, $fn);
}
}
# 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";
}
foreach (@moved_files) {
unlink($_);
}
chdir($releasedir) or die $!;
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
$ENV{PATH} = "packaging/bin:$path";
$_ = `git tag -s -m 'Version $version.' v$version 2>&1`;
$ENV{PATH} = $path;
unlink($passfile);
print $_;
next if /bad passphrase/;
last unless /failed/;
exit 1;
}
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;
# Extract the generated files from the old tar.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
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";
print "Updating files in \"rsync-$version/patches\" dir ...\n";
mkdir("rsync-$version", 0755);
mkdir("rsync-$version/patches", 0755);
system "packaging/patch-update --skip-check --gen=rsync-$version/patches";
print "Creating $pattar_file ...\n";
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";
unlink("$dest/rsync-$version-NEWS");
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
system "rsync -a README NEWS OLDNEWS TODO $dest";
unlink($news_file);
link("$dest/NEWS", $news_file);
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";
foreach my $fn ($srctar_file, $pattar_file, $diff_file) {
unlink("$fn.asc");
open(GPG, '|-', "gpg --batch --passphrase-fd=0 -ba $fn") or die $!;
print GPG $passphrase, "\n";
close GPG;
}
if (!$pre) {
system "rm $dest/rsync-*.gz $dest/rsync-*.asc $dest/rsync-*-NEWS $dest/src-previews/rsync-*diffs.gz*";
foreach my $fn ($srctar_file, "$srctar_file.asc",
$pattar_file, "$pattar_file.asc",
$diff_file, "$diff_file.asc", $news_file) {
(my $top_fn = $fn) =~ s#/src(-\w+)?/#/#;
link($fn, $top_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

@@ -809,16 +809,20 @@ int poptGetNextOpt(poptContext con)
*oe++ = '\0';
/* XXX longArg is mapped back to persistent storage. */
longArg = origOptString + (oe - localOptString);
}
} else
oe = NULL;
opt = findOption(con->options, optString, '\0', &cb, &cbData,
singleDash);
if (!opt && !singleDash)
return POPT_ERROR_BADOPT;
if (!opt && oe)
oe[-1] = '='; /* restore overwritten '=' */
}
if (!opt) {
con->os->nextCharArg = origOptString + 1;
longArg = NULL;
} else {
if (con->os == con->optionStack &&
opt->argInfo & POPT_ARGFLAG_STRIP)
@@ -856,7 +860,7 @@ int poptGetNextOpt(poptContext con)
origOptString++;
if (*origOptString != '\0')
con->os->nextCharArg = origOptString;
con->os->nextCharArg = origOptString + (*origOptString == '=');
}
/*@=branchstate@*/

View File

@@ -121,7 +121,7 @@ getArgDescrip(const struct poptOption * opt,
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_NONE: return POPT_("NONE");
/*case POPT_ARG_NONE: return POPT_("NONE");*/ /* impossible */
#ifdef DYING
case POPT_ARG_VAL: return POPT_("VAL");
#else
@@ -767,6 +767,9 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
int len = 0;
if (s == NULL)
return 0;
/*@-boundswrite@*/
if (opt != NULL)
for (; (opt->longName || opt->shortName || opt->arg); opt++) {

View File

@@ -163,8 +163,10 @@ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int fl
p++;
linelen = strlen(p);
if (linelen >= maxlinelen-1)
if (linelen >= maxlinelen-1) {
free(argstr);
return POPT_ERROR_OVERFLOW; /* XXX line too long */
}
if (*p == '\0' || *p == '\n') continue; /* line is empty */
if (*p == '#') continue; /* comment line */

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
@@ -55,12 +55,12 @@ extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct server_filter_list;
extern struct filter_list_struct daemon_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,13 +482,15 @@ 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
&& check_filter(&server_filter_list, fname, 0) < 0) {
if (daemon_filter_list.head
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) {
rprintf(FERROR, "attempt to hack rsync failed.\n");
exit_cleanup(RERR_PROTOCOL);
}
@@ -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",
@@ -519,15 +555,19 @@ int recv_files(int f_in, char *local_name)
fnamecmp = fnamecmpbuf;
break;
}
if (!fnamecmp || (server_filter_list.head
&& check_filter(&server_filter_list, fname, 0) < 0))
if (!fnamecmp || (daemon_filter_list.head
&& check_filter(&daemon_filter_list, FLOG, 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;
}

158
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
@@ -134,8 +134,6 @@ void setup_iconv(void)
# endif
}
# ifdef ICONV_OPTION
/* This function converts the characters in the "in" xbuf into characters
* in the "out" xbuf. The "len" of the "in" xbuf is used starting from its
* "pos". The "size" of the "out" xbuf restricts how many characters can be
@@ -205,16 +203,51 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
return errno ? -1 : 0;
}
# endif
#endif
void send_protected_args(int fd, char *args[])
{
int i;
#ifdef ICONV_OPTION
int convert = ic_send != (iconv_t)-1;
xbuf outbuf, inbuf;
if (convert)
alloc_xbuf(&outbuf, 1024);
#endif
for (i = 0; args[i]; i++) {} /* find first NULL */
args[i] = "rsync"; /* set a new arg0 */
if (verbose > 1)
print_child_argv("protected args:", args + i + 1);
do {
#ifdef ICONV_OPTION
if (convert) {
INIT_XBUF_STRLEN(inbuf, args[i]);
iconvbufs(ic_send, &inbuf, &outbuf,
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
outbuf.buf[outbuf.len] = '\0';
write_buf(fd, outbuf.buf, outbuf.len + 1);
outbuf.len = 0;
} else
#endif
write_buf(fd, args[i], strlen(args[i]) + 1);
} while (args[++i]);
write_byte(fd, 0);
#ifdef ICONV_OPTION
if (convert)
free(outbuf.buf);
#endif
}
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
char *buf, int *len_ptr)
{
int len, iflags = 0;
struct file_list *flist;
uchar fnamecmp_type = FNAMECMP_FNAME;
int ndx;
int ndx, save_verbose = verbose;
read_loop:
while (1) {
@@ -242,15 +275,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)
@@ -265,11 +300,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;
@@ -350,7 +387,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;
}
@@ -371,16 +408,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))
@@ -389,21 +429,23 @@ 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
file->flags |= FLAG_TIME_FAILED;
}
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
if (S_ISLNK(sxp->st.st_mode))
if (S_ISLNK(sxp->st.st_mode)) {
;
else
} else
#endif
if (change_uid || change_gid) {
if (verbose > 2) {
@@ -418,31 +460,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.
@@ -458,7 +497,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;
@@ -503,15 +542,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)
@@ -521,7 +562,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,
@@ -530,34 +571,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)
@@ -572,7 +618,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;
}

90
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
@@ -64,7 +67,8 @@
#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
#define FLAG_DIR_CREATED (1<<1) /* generator */
#define FLAG_CONTENT_DIR (1<<2) /* sender/receiver/generator */
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator */
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator (dirs only) */
#define FLAG_SKIP_HLINK (1<<3) /* receiver/generator (w/FLAG_HLINKED) */
#define FLAG_DUPLICATE (1<<4) /* sender */
#define FLAG_MISSING_DIR (1<<4) /* generator */
#define FLAG_HLINKED (1<<5) /* receiver/generator (checked on all types) */
@@ -74,10 +78,12 @@
#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. */
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
#define FLAG_DOTDIR_NAME (1<<17)/* sender */
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
@@ -90,7 +96,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 10
#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
@@ -122,7 +128,7 @@
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (256*1024)
#define IO_BUFFER_SIZE (4092)
#define MAX_BLOCK_SIZE ((int32)1 << 29)
#define MAX_BLOCK_SIZE ((int32)1 << 17)
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
#define IOERR_VANISHED (1<<1)
@@ -140,8 +146,9 @@
#define XFLG_FATAL_ERRORS (1<<0)
#define XFLG_OLD_PREFIXES (1<<1)
#define XFLG_ANCHORED2ABS (1<<2)
#define XFLG_ABS_IF_SLASH (1<<3)
#define XFLG_ANCHORED2ABS (1<<2) /* leading slash indicates absolute */
#define XFLG_ABS_IF_SLASH (1<<3) /* leading or interior slash is absolute */
#define XFLG_DIR2WILD3 (1<<4) /* dir/ match gets trailing *** added */
#define ATTRS_REPORT (1<<0)
#define ATTRS_SKIP_MTIME (1<<1)
@@ -162,8 +169,9 @@
/* For use by the itemize_changes code */
#define ITEM_REPORT_ATIME (1<<0)
#define ITEM_REPORT_CHECKSUM (1<<1)
#define ITEM_REPORT_SIZE (1<<2)
#define ITEM_REPORT_CHANGE (1<<1)
#define ITEM_REPORT_SIZE (1<<2) /* regular files only */
#define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
#define ITEM_REPORT_TIME (1<<3)
#define ITEM_REPORT_PERMS (1<<4)
#define ITEM_REPORT_OWNER (1<<5)
@@ -183,18 +191,35 @@
#define SIGNIFICANT_ITEM_FLAGS (~(\
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
#define CFN_KEEP_DOT_DIRS (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 };
#define SP_DEFAULT 0
#define SP_KEEP_DOT_DIRS (1<<0)
#define CD_NORMAL 0
#define CD_SKIP_CHDIR 1
/* 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 */
@@ -316,10 +341,6 @@ enum msgcode {
#endif
#endif
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
/* these are needed for the uid/gid mapping code */
#include <pwd.h>
#include <grp.h>
@@ -327,7 +348,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>
@@ -391,6 +414,22 @@ enum msgcode {
#include "lib/pool_alloc.h"
#ifndef HAVE_ID_T
typedef unsigned int id_t;
#endif
#ifndef HAVE_PID_T
typedef int pid_t;
#endif
#ifndef HAVE_MODE_T
typedef unsigned int mode_t;
#endif
#ifndef HAVE_OFF_T
typedef long off_t;
#endif
#ifndef HAVE_SIZE_T
typedef unsigned int size_t;
#endif
#define BOOL int
#ifndef uchar
@@ -508,6 +547,7 @@ struct hashtable {
void *nodes;
int32 size, entries;
uint32 node_size;
int key64;
};
struct ht_int32_node {
@@ -625,7 +665,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 */
@@ -640,7 +680,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) \
@@ -691,7 +731,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;
};
@@ -782,7 +822,6 @@ struct stats {
int64 flist_size;
int num_files;
int num_transferred_files;
int current_file_index;
};
struct chmod_mode_struct;
@@ -821,7 +860,7 @@ typedef struct {
#define RL_CONVERT (1<<2)
typedef struct {
char is_dot_dir;
char name_type;
char fname[1]; /* has variable size */
} relnamecache;
@@ -1072,6 +1111,11 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#define MY_GID() getgid()
#endif
#ifdef FORCE_FD_ZERO_MEMSET
#undef FD_ZERO
#define FD_ZERO(fdsetp) memset(fdsetp, 0, sizeof (fd_set))
#endif
extern int verbose;
#ifndef HAVE_INET_NTOP

249
rsync.yo
View File

@@ -1,41 +1,40 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(11 Oct 2007)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpage(rsync)(1)(8 Apr 2008)()()
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
manpagesynopsis()
rsync [OPTION]... SRC [SRC]... DEST
verb(Local: rsync [OPTION...] SRC... [DEST]
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
Access via remote shell:
Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
Access via rsync daemon:
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST)
rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST
rsync [OPTION]... SRC
rsync [OPTION]... [USER@]HOST:SRC [DEST]
rsync [OPTION]... [USER@]HOST::SRC [DEST]
rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
Usages with just one SRC arg and no DEST arg will list the source files
instead of copying.
manpagedescription()
Rsync is a program that behaves in much the same way that rcp does,
but has many more options and uses the rsync remote-update protocol to
greatly speed up file transfers when the destination file is being
updated.
Rsync is a fast and extraordinarily versatile file copying tool. It can
copy locally, to/from another host over any remote shell, or to/from a
remote rsync daemon. It offers a large number of options that control
every aspect of its behavior and permit very flexible specification of the
set of files to be copied. It is famous for its delta-transfer algorithm,
which reduces the amount of data sent over the network by sending only the
differences between the source files and the existing files in the
destination. Rsync is widely used for backups and mirroring and as an
improved copy command for everyday use.
The rsync remote-update protocol allows rsync to transfer just the
differences between two sets of files across the network connection, using
an efficient checksum-search algorithm described in the technical
report that accompanies this package.
Rsync finds files that need to be transferred using a "quick check" algorithm
that looks for files that have changed in size or in last-modified time (by
default). Any changes in the other preserved attributes (as requested by
options) are made on the destination file directly when the quick check
indicates that the file's data does not need to be updated.
Rsync finds files that need to be transferred using a "quick check"
algorithm (by default) that looks for files that have changed in size or
in last-modified time. Any changes in the other preserved attributes (as
requested by options) are made on the destination file directly when the
quick check indicates that the file's data does not need to be updated.
Some of the additional features of rsync are:
@@ -226,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).
@@ -329,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
@@ -353,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
@@ -379,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
@@ -422,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
@@ -528,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.
@@ -723,9 +723,12 @@ receiving user.
dit(bf(--append)) This causes rsync to update a file by appending data onto
the end of the file, which presumes that the data that already exists on
the receiving side is identical with the start of the file on the sending
side. Any files that are the same size or shorter on the receiving size
are skipped. Files that do not yet exist on the receiving side are also
sent, since they are considered to have 0 length. Implies bf(--inplace),
side. If a file needs to be transferred and its size on the receiver is
the same or longer than the size on the sender, the file is skipped. This
does not interfere with the updating of a file's non-content attributes
(e.g. permissions, ownership, etc.) when the file does not need to be
transferred, nor does it affect the updating of any non-regular files.
Implies bf(--inplace),
but does not conflict with bf(--sparse) (since it is always extending a
file's length).
@@ -748,6 +751,16 @@ bf(--recursive) option, rsync will skip all directories it encounters (and
output a message to that effect for each one). If you specify both
bf(--dirs) and bf(--recursive), bf(--recursive) takes precedence.
The bf(--dirs) option is implied by the bf(--files-from) option
or the bf(--list-only) option (including an implied
bf(--list-only) usage) if bf(--recursive) wasn't specified (so that
directories are seen in the listing). Specify bf(--no-dirs) (or bf(--no-d))
if you want to turn this off.
There is also a backward-compatibility helper option, bf(--old-dirs) (or
bf(--old-d)) that tells rsync to use a hack of "-r --exclude='/*/*'" to get
an older rsync to list a single directory without recursing.
dit(bf(-l, --links)) When symlinks are encountered, recreate the
symlink on the destination.
@@ -796,6 +809,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
@@ -803,11 +824,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.
@@ -841,17 +875,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
@@ -982,7 +1016,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.
@@ -992,7 +1026,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)).
@@ -1009,10 +1043,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
@@ -1074,9 +1120,9 @@ Prior to rsync 2.6.7, this option would have no effect unless bf(--recursive)
was enabled. Beginning with 2.6.7, deletions will also occur when bf(--dirs)
(bf(-d)) is enabled, but only for directories whose contents are being copied.
This option can be dangerous if used incorrectly! It is a very good idea
to run first using the bf(--dry-run) option (bf(-n)) to see what files would be
deleted to make sure important files aren't listed.
This option can be dangerous if used incorrectly! It is a very good idea to
first try a run using the bf(--dry-run) option (bf(-n)) to see what files are
going to be deleted.
If the sending side detects any I/O errors, then the deletion of any
files at the destination will be automatically disabled. This is to
@@ -1238,8 +1284,8 @@ The exclude list is initialized to exclude the following items (these
initial items are marked as perishable -- see the FILTER RULES section):
quote(quote(tt(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej
.del-* *.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .bzr/)))
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej .del-*
*.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .git/ .bzr/)))
then, files listed in a $HOME/.cvsignore are added to the list and any
files listed in the CVSIGNORE environment variable (all cvsignore names
@@ -1267,7 +1313,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.
@@ -1380,7 +1429,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
@@ -1390,7 +1439,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
@@ -1557,6 +1606,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
@@ -1610,6 +1663,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
@@ -1626,26 +1681,29 @@ a "?" (this can happen when talking to an older rsync).
The attribute that is associated with each letter is as follows:
quote(itemization(
it() A bf(c) means the checksum of the file is different and will be
updated by the file transfer (requires bf(--checksum)).
it() A bf(s) means the size of the file is different and will be updated
it() A bf(c) means either that a regular file has a different checksum
(requires bf(--checksum)) or that a symlink, device, or special file has
a changed value.
Note that if you are sending files to an rsync prior to 3.0.1, this
change flag will be present only for checksum-differing regular files.
it() A bf(s) means the size of a regular file is different and will be updated
by the file transfer.
it() A bf(t) means the modification time is different and is being updated
to the 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.
(Note: when using an rsync 3.0.0 client, you might see the bf(s) flag combined
with bf(t) instead of the proper bf(T) flag for this time-setting failure.)
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
@@ -1914,6 +1972,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
@@ -1923,16 +1983,22 @@ dit(bf(--list-only)) This option will cause the source files to be listed
instead of transferred. This option is inferred if there is a single source
arg and no destination specified, so its main uses are: (1) to turn a copy
command that includes a
destination arg into a file-listing command, (2) to be able to specify more
than one local source arg (note: be sure to include the destination), or
(3) to avoid the automatically added "bf(-r --exclude='/*/*')" options that
rsync usually uses as a compatibility kluge when generating a non-recursive
listing. Caution: keep in mind that a source arg with a wild-card is expanded
by the shell into multiple args, so it is never safe to try to list such an arg
destination arg into a file-listing command, or (2) to be able to specify
more than one source arg (note: be sure to include the destination).
Caution: keep in mind that a source arg with a wild-card is expanded by the
shell into multiple args, so it is never safe to try to list such an arg
without using this option. For example:
verb( rsync -av --list-only foo* dest/)
Compatibility note: when requesting a remote listing of files from an rsync
that is version 2.6.3 or older, you may encounter an error if you ask for a
non-recursive listing. This is because a file listing implies the bf(--dirs)
option w/o bf(--recursive), and older rsyncs don't have that option. To
avoid this problem, either specify the bf(--no-dirs) option (if you don't
need to expand a directory's content), or turn on recursion and exclude
the content of subdirectories: bf(-r --exclude='/*/*').
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
transfer rate in kilobytes per second. This option is most effective when
using rsync with large files (several megabytes and up). Due to the nature
@@ -1979,11 +2045,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.
@@ -1994,6 +2066,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
@@ -2744,6 +2821,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)
@@ -2763,7 +2841,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".
@@ -2797,7 +2876,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre2 of rsync.
This man page is current for version 3.0.2 of rsync.
manpagesection(INTERNAL OPTIONS)
@@ -2823,23 +2902,25 @@ The primary ftp site for rsync is
url(ftp://rsync.samba.org/pub/rsync)(ftp://rsync.samba.org/pub/rsync).
We would be delighted to hear from you if you like this program.
Please contact the mailing-list at rsync@lists.samba.org.
This program uses the excellent zlib compression library written by
Jean-loup Gailly and Mark Adler.
manpagesection(THANKS)
Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
and David Bell for helpful suggestions, patches and testing of rsync.
I've probably missed some people, my apologies if I have.
Especial thanks go out to: John Van Essen, Matt McCutchen, Wesley W. Terpstra,
David Dykstra, Jos Backus, Sebastian Krahmer, Martin Pool, and our
gone-but-not-forgotten compadre, J.W. Schultz.
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer,
Martin Pool, Wayne Davison, J.W. Schultz.
Thanks also to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
and David Bell. I've probably missed some people, my apologies if I have.
manpageauthor()
rsync was originally written by Andrew Tridgell and Paul Mackerras.
Many people have later contributed to it.
Many people have later contributed to it. It is currently maintained
by Wayne Davison.
Mailing lists for support and development are available at
url(http://lists.samba.org)(lists.samba.org)

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(11 Oct 2007)()()
manpage(rsyncd.conf)(5)(8 Apr 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.
@@ -233,49 +314,54 @@ daemon side to behave as if the bf(--fake-user) command-line option had
been specified. This allows the full attributes of a file to be stored
without having to have the daemon actually running as root.
dit(bf(filter)) The "filter" option allows you to specify a space-separated
list of filter rules that the daemon will not allow to be read or written.
This is only superficially equivalent to the client specifying these
patterns with the bf(--filter) option. Only one "filter" option may be
specified, but it may contain as many rules as you like, including
merge-file rules. Note that per-directory merge-file rules do not provide
as much protection as global rules, but they can be used to make bf(--delete)
work better when a client downloads the daemon's files (if the per-dir
merge files are included in the transfer).
dit(bf(filter)) The daemon has its own filter chain that determines what files
it will let the client access. This chain is not sent to the client and is
independent of any filters the client may have specified. Files excluded by
the daemon filter chain (bf(daemon-excluded) files) are treated as non-existent
if the client tries to pull them, are skipped with an error message if the
client tries to push them (triggering exit code 23), and are never deleted from
the module. You can use daemon filters to prevent clients from downloading or
tampering with private administrative files, such as files you may add to
support uid/gid name translations.
dit(bf(exclude)) The "exclude" option allows you to specify a
space-separated list of patterns that the daemon will not allow to be read
or written. This is only superficially equivalent to the client
specifying these patterns with the bf(--exclude) option. Only one "exclude"
option may be specified, but you can use "-" and "+" before patterns to
specify exclude/include.
The daemon filter chain is built from the "filter", "include from", "include",
"exclude from", and "exclude" parameters, in that order of priority. Anchored
patterns are anchored at the root of the module. To prevent access to an
entire subtree, for example, "/secret", you em(must) exclude everything in the
subtree; the easiest way to do this is with a triple-star pattern like
"/secret/***".
Because this exclude list is not passed to the client it only applies on
the daemon: that is, it excludes files received by a client when receiving
from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a daemon.
The "filter" parameter takes a space-separated list of daemon filter rules,
though it is smart enough to know not to split a token at an internal space in
a rule (e.g. "- /foo - /bar" is parsed as two rules). You may specify one or
more merge-file rules using the normal syntax. Only one "filter" parameter can
apply to a given module in the config file, so put all the rules you want in a
single parameter. Note that per-directory merge-file rules do not provide as
much protection as global rules, but they can be used to make bf(--delete) work
better during a client download operation if the per-dir merge files are
included in the transfer and the client requests that they be used.
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
to the client specifying the bf(--exclude-from) option with an equivalent file.
See the "exclude" option above.
dit(bf(exclude)) The "exclude" parameter takes a space-separated list of daemon
exclude patterns. As with the client bf(--exclude) option, patterns can be
qualified with "- " or "+ " to explicitly indicate exclude/include. Only one
"exclude" parameter can apply to a given module. See the "filter" parameter
for a description of how excluded files affect the daemon.
dit(bf(include)) The "include" option allows you to specify a
space-separated list of patterns which rsync should not exclude. This is
only superficially equivalent to the client specifying these patterns with
the bf(--include) option because it applies only on the daemon. This is
useful as it allows you to build up quite complex exclude/include rules.
Only one "include" option may be specified, but you can use "+" and "-"
before patterns to switch include/exclude. See the "exclude" option
above.
dit(bf(include)) Use an "include" to override the effects of the "exclude"
parameter. Only one "include" parameter can apply to a given module. See the
"filter" parameter for a description of how excluded files affect the daemon.
dit(bf(include from)) The "include from" option specifies a filename
on the daemon that contains include patterns, one per line. This is
only superficially equivalent to the client specifying the
bf(--include-from) option with a equivalent file.
See the "exclude" option above.
dit(bf(exclude from)) The "exclude from" parameter specifies the name of a file
on the daemon that contains daemon exclude patterns, one per line. Only one
"exclude from" parameter can apply to a given module; if you have multiple
exclude-from files, you can specify them as a merge file in the "filter"
parameter. See the "filter" parameter for a description of how excluded files
affect the daemon.
dit(bf(include from)) Analogue of "exclude from" for a file of daemon include
patterns. Only one "include from" parameter can apply to a given module. See
the "filter" parameter for a description of how excluded files affect the
daemon.
dit(bf(incoming chmod)) This option allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
@@ -368,7 +454,7 @@ tt( fe80::%link1/ffff:ffff:ffff:ffff::)nl()
)
You can also combine "hosts allow" with a separate "hosts deny"
option. If both options are specified then the "hosts allow" option s
option. If both options are specified then the "hosts allow" option is
checked first and a match results in the client being able to
connect. The "hosts deny" option is then checked and a match means
that the host is rejected. If the host does not match either the
@@ -468,9 +554,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 +578,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 +648,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 +700,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre2 of rsync.
This man page is current for version 3.0.2 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
@@ -135,7 +135,7 @@ void successful_send(int ndx)
}
file = flist->files[ndx - flist->ndx_start];
if (!push_pathname(F_PATHNAME(file), -1))
if (!change_pathname(file, NULL, 0))
return;
f_name(file, fname);
@@ -221,7 +221,7 @@ void send_files(int f_in, int f_out)
} else {
path = slash = "";
}
if (!push_pathname(F_PATHNAME(file), -1))
if (!change_pathname(file, NULL, 0))
continue;
f_name(file, fname);
@@ -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) {

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
}

View File

@@ -39,6 +39,7 @@ die "$0: Restricted directory does not exist!\n" if $subdir ne '/' && !-d $subdi
my $command = $ENV{SSH_ORIGINAL_COMMAND};
die "$0: Not invoked via sshd\n$Usage" unless defined $command;
die "$0: SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ s/^rsync\s+//;
die "$0: --server option is not first\n" unless $command =~ /^--server\s/;
our $am_sender = $command =~ /^--server\s+--sender\s/; # Restrictive on purpose!
die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
@@ -65,7 +66,7 @@ our %long_opt = (
'compress-level' => 1,
'copy-dest' => 2,
'copy-unsafe-links' => 0,
'daemon' => 0,
'daemon' => -1,
'delay-updates' => 0,
'delete' => 0,
'delete-after' => 0,
@@ -74,6 +75,7 @@ our %long_opt = (
'delete-during' => 0,
'delete-excluded' => 0,
'existing' => 0,
'fake-super' => 0,
'files-from' => 3,
'force' => 0,
'from0' => 0,
@@ -84,6 +86,7 @@ our %long_opt = (
'inplace' => 0,
'link-dest' => 2,
'list-only' => 0,
'log-file' => 3,
'log-format' => 1,
'max-delete' => 1,
'max-size' => 1,
@@ -110,6 +113,7 @@ our %long_opt = (
'super' => 0,
'temp-dir' => 2,
'timeout' => 1,
'use-qsort' => 0,
);
### END of options data produced by the cull_options script. ###
@@ -139,7 +143,7 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
if ($_ eq '.') {
$in_options = 0;
} else {
next if /^-$short_no_arg+(e\d+\.\d+)?$/o || /^-$short_with_num\d+$/o;
next if /^-$short_no_arg+(e\d*\.\w*)?$/o || /^-$short_with_num\d+$/o;
my($opt,$arg) = /^--([^=]+)(?:=(.*))?$/;
my $disabled;

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
@@ -25,12 +25,16 @@
#if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef HAVE_SYS_ATTR_H
#include <sys/attr.h>
#endif
extern int dry_run;
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 { \
@@ -151,13 +155,21 @@ int do_chmod(const char *path, mode_t mode)
if (S_ISLNK(mode)) {
#ifdef HAVE_LCHMOD
code = lchmod(path, mode & CHMOD_BITS);
#elif defined HAVE_SETATTRLIST
struct attrlist attrList;
uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
memset(&attrList, 0, sizeof attrList);
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.commonattr = ATTR_CMN_ACCESSMASK;
code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
#else
code = 1;
#endif
} else
code = chmod(path, mode & CHMOD_BITS);
if (code != 0 && preserve_perms)
return code;
code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
if (code != 0 && (preserve_perms || preserve_executability))
return code;
return 0;
}
#endif
@@ -200,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)
{
@@ -269,12 +282,3 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
return lseek(fd, offset, whence);
#endif
}
char *d_name(struct dirent *di)
{
#ifdef HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;
#endif
}

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
@@ -29,7 +29,7 @@ int module_dirlen = 0;
mode_t orig_umask = 002;
char *partial_dir;
char *module_dir;
struct filter_list_struct server_filter_list;
struct filter_list_struct daemon_filter_list;
void rprintf(UNUSED(enum logcode code), const char *format, ...)
{
@@ -56,8 +56,8 @@ struct filter_list_struct server_filter_list;
exit(code);
}
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(char *name),
UNUSED(int name_is_dir))
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(enum logcode code),
UNUSED(const char *name), UNUSED(int name_is_dir))
{
/* This function doesn't really get called in this test context, so
* just return 0. */

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

@@ -24,8 +24,29 @@
. "$suitedir/rsync.fns"
SSH="$scratchdir/pretend-ssh"
cat >"$SSH" <<'EOT'
while : ; do
case "$1" in
-*) shift ;;
localhost) shift; break ;;
*) exit 1 ;;
esac
done
eval "${@}"
EOT
chmod +x "$SSH"
build_rsyncd_conf
cd "$scratchdir"
ln -s test-rsyncd.conf rsyncd.conf
$RSYNC -ve $SSH --rsync-path="$RSYNC" localhost::
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG

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
cDc.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 ./
cDc.t.$dots block
cDc...$dots 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

@@ -38,9 +38,20 @@ echo "extra extra" >>"$todir/name1"
checkit "$RSYNC -aHivv --no-whole-file '$fromdir/' '$todir/'" "$fromdir" "$todir"
# Add a new link in a new subdirectory to test that we don't try to link
# the files before the directory gets created.
mkdir "$fromdir/subdir"
ln "$name1" "$fromdir/subdir/new-file"
# the files before the directory gets created. We also create a bunch of
# extra files to ensure that an incremental-recursion transfer works across
# distant files.
makepath "$fromdir/subdir/down/deep"
files=''
for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z; do
for y in 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z; do
files="$files $x$y"
done
done
(cd "$fromdir/subdir"; touch $files)
ln "$name1" "$fromdir/subdir/down/deep/new-file"
rm "$todir/text"
checkit "$RSYNC -aHivv '$fromdir/' '$todir/'" "$fromdir" "$todir"

View File

@@ -25,28 +25,42 @@ umask 0
ln -s ../bar/baz/rsync "$fromdir/foo/sym"
umask 022
ln "$fromdir/foo/config1" "$fromdir/foo/extra"
rm -f "$to2dir"
# Check if the OS can hard-link symlinks or not
ln -s no-such-dir "$to2dir"
if ln "$to2dir" "$to2dir.test" 2>/dev/null; then
# Check if rsync is set to hard-link symlinks.
confile=`echo "$scratchdir" | sed 's;/testtmp/itemize$;/config.h;'`
if egrep '^#define CAN_HARDLINK_SYMLINK 1' "$confile" >/dev/null; then
L=hL
else
L=cL
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 +72,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 +92,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
cLc$T.$dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -107,15 +121,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 +148,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
cLc.t*)
sym_dots="c.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 +205,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 +214,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 +253,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 +262,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 +294,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

@@ -51,7 +51,7 @@ $RSYNC -av --existing -f 'exclude,! */' from2/ from3/
$RSYNC -av --existing -f 'exclude,! */' from1/ chk/
$RSYNC -av --existing -f 'exclude,! */' from3/ chk/
checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" chk to
checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" "$chkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

27
testsuite/missing.test Normal file
View File

@@ -0,0 +1,27 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test three bugs fixed by my redoing of the missing_below logic.
. $srcdir/testsuite/rsync.fns
makepath "$fromdir/subdir" "$todir"
echo data >"$fromdir/subdir/file"
echo data >"$todir/other"
# Test 1: Too much "not creating new..." output on a dry run
$RSYNC -n -r --ignore-non-existing -vv "$fromdir/" "$todir/" | tee "$scratchdir/out"
if grep 'not creating new.*subdir/file' "$scratchdir/out" >/dev/null; then
test_fail 'test 1 failed'
fi
# Test 2: Attempt to make a fuzzy dirlist for a dir not created on a dry run
$RSYNC -n -r -R --no-implied-dirs -y "$fromdir/./subdir/file" "$todir/" \
|| test_fail 'test 2 failed'
# Test 3: --delete-after pass skipped when last dir is dry-missing
$RSYNC -n -r --delete-after -i "$fromdir/" "$todir/" | tee "$scratchdir/out"
grep '^\*deleting * other' "$scratchdir/out" >/dev/null \
|| test_fail 'test 3 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

@@ -20,6 +20,7 @@ case "`xattr 2>&1`" in
xls() {
xattr -l "${@}"
}
RUSR='rsync.nonuser'
;;
*)
xset() {
@@ -31,21 +32,23 @@ case "`xattr 2>&1`" in
xls() {
getfattr -d "${@}"
}
RUSR='user.rsync'
;;
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,28 +64,28 @@ 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 $RUSR.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"
xset user.foo 'old foo' "$chkdir/foo/file3"
xset user.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
xset $RUSR.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
xls $files >"$scratchdir/xattrs.txt"
# OK, let's try a simple xattr copy.
checkit "$RSYNC -avX . '$chkdir/'" "$fromdir" "$chkdir"
checkit "$RSYNC -avX --super . '$chkdir/'" "$fromdir" "$chkdir"
cd "$chkdir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
checkit "$RSYNC -aiX --copy-dest=../chk . ../to" "$fromdir" "$todir"
checkit "$RSYNC -aiX --super --copy-dest=../chk . ../to" "$fromdir" "$todir"
cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
@@ -94,10 +97,17 @@ xls $files >"$scratchdir/xattrs.txt"
rm -rf "$todir"
checkit "$RSYNC -aiX --link-dest=../chk . ../to" "$chkdir" "$todir"
checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
sed -n -e '/\.\/file1$/d' -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff"
if [ -s "$scratchdir/ls-diff" ]; then
echo "Missing hard links on:"
cat "$scratchdir/ls-diff"
exit 1
fi
# The script would have aborted on error, so getting here means we've won.
exit 0

5
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
@@ -35,7 +35,7 @@
* change. */
#include "rsync.h"
#include "popt.h"
#include <popt.h>
#include "lib/sysxattrs.h"
#define PROGRAM "tls"
@@ -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);

441
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
@@ -33,7 +33,7 @@ extern char *module_dir;
extern unsigned int module_dirlen;
extern mode_t orig_umask;
extern char *partial_dir;
extern struct filter_list_struct server_filter_list;
extern struct filter_list_struct daemon_filter_list;
int sanitize_paths = 0;
@@ -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 */
@@ -503,82 +503,172 @@ int lock_range(int fd, int offset, int len)
return fcntl(fd,F_SETLK,&lock) == 0;
}
static int filter_server_path(char *arg)
{
char *s;
#define ENSURE_MEMSPACE(buf, type, sz, req) \
if ((req) > sz && !(buf = realloc_array(buf, type, sz = MAX(sz * 2, req)))) \
out_of_memory("glob_expand")
if (server_filter_list.head) {
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
*s = '\0';
if (check_filter(&server_filter_list, arg, 1) < 0) {
/* We must leave arg truncated! */
return 1;
}
*s++ = '/';
static inline void call_glob_match(const char *name, int len, int from_glob,
char *arg, int abpos, int fbpos);
static struct glob_data {
char *arg_buf, *filt_buf, **argv;
int absize, fbsize, maxargs, argc;
} glob;
static void glob_match(char *arg, int abpos, int fbpos)
{
int len;
char *slash;
while (*arg == '.' && arg[1] == '/') {
if (fbpos < 0) {
ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, glob.absize);
memcpy(glob.filt_buf, glob.arg_buf, abpos + 1);
fbpos = abpos;
}
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + 3);
glob.arg_buf[abpos++] = *arg++;
glob.arg_buf[abpos++] = *arg++;
glob.arg_buf[abpos] = '\0';
}
return 0;
if ((slash = strchr(arg, '/')) != NULL) {
*slash = '\0';
len = slash - arg;
} else
len = strlen(arg);
if (strpbrk(arg, "*?[")) {
struct dirent *di;
DIR *d;
if (!(d = opendir(abpos ? glob.arg_buf : ".")))
return;
while ((di = readdir(d)) != NULL) {
char *dname = d_name(di);
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
continue;
if (!wildmatch(arg, dname))
continue;
call_glob_match(dname, strlen(dname), 1,
slash ? arg + len + 1 : NULL,
abpos, fbpos);
}
closedir(d);
} else {
call_glob_match(arg, len, 0,
slash ? arg + len + 1 : NULL,
abpos, fbpos);
}
if (slash)
*slash = '/';
}
void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
static inline void call_glob_match(const char *name, int len, int from_glob,
char *arg, int abpos, int fbpos)
{
char **argv = *argv_ptr;
int argc = *argc_ptr;
int maxargs = *maxargs_ptr;
#if !defined HAVE_GLOB || !defined HAVE_GLOB_H
if (argc == maxargs) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("glob_expand");
*argv_ptr = argv;
*maxargs_ptr = maxargs;
}
if (!*s)
s = ".";
s = argv[argc++] = strdup(s);
filter_server_path(s);
#else
glob_t globbuf;
char *use_buf;
if (maxargs <= argc)
return;
if (!*s)
s = ".";
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + len + 2);
memcpy(glob.arg_buf + abpos, name, len);
abpos += len;
glob.arg_buf[abpos] = '\0';
if (fbpos >= 0) {
ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, fbpos + len + 2);
memcpy(glob.filt_buf + fbpos, name, len);
fbpos += len;
glob.filt_buf[fbpos] = '\0';
use_buf = glob.filt_buf;
} else
use_buf = glob.arg_buf;
if (from_glob || arg) {
STRUCT_STAT st;
int is_dir;
if (do_stat(glob.arg_buf, &st) != 0)
return;
is_dir = S_ISDIR(st.st_mode) != 0;
if (arg && !is_dir)
return;
if (daemon_filter_list.head
&& check_filter(&daemon_filter_list, FLOG, use_buf, is_dir) < 0)
return;
}
if (arg) {
glob.arg_buf[abpos++] = '/';
glob.arg_buf[abpos] = '\0';
if (fbpos >= 0) {
glob.filt_buf[fbpos++] = '/';
glob.filt_buf[fbpos] = '\0';
}
glob_match(arg, abpos, fbpos);
} else {
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
if (!(glob.argv[glob.argc++] = strdup(glob.arg_buf)))
out_of_memory("glob_match");
}
}
/* This routine performs wild-card expansion of the pathname in "arg". Any
* daemon-excluded files/dirs will not be matched by the wildcards. Returns 0
* if a wild-card string is the only returned item (due to matching nothing). */
int glob_expand(const char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
{
int ret, save_argc;
char *s;
if (!arg) {
if (glob.filt_buf)
free(glob.filt_buf);
free(glob.arg_buf);
memset(&glob, 0, sizeof glob);
return -1;
}
if (sanitize_paths)
s = sanitize_path(NULL, s, "", 0, NULL);
else
s = strdup(s);
if (!s)
out_of_memory("glob_expand");
memset(&globbuf, 0, sizeof globbuf);
if (!filter_server_path(s))
glob(s, 0, NULL, &globbuf);
if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) {
maxargs += globbuf.gl_pathc + MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
out_of_memory("glob_expand");
*argv_ptr = argv;
*maxargs_ptr = maxargs;
}
if (globbuf.gl_pathc == 0)
argv[argc++] = s;
s = sanitize_path(NULL, arg, "", 0, SP_KEEP_DOT_DIRS);
else {
int i;
free(s);
for (i = 0; i < (int)globbuf.gl_pathc; i++) {
if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
out_of_memory("glob_expand");
}
s = strdup(arg);
if (!s)
out_of_memory("glob_expand");
clean_fname(s, CFN_KEEP_DOT_DIRS
| CFN_KEEP_TRAILING_SLASH
| CFN_COLLAPSE_DOT_DOT_DIRS);
}
globfree(&globbuf);
#endif
*argc_ptr = argc;
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, MAXPATHLEN);
*glob.arg_buf = '\0';
glob.argc = save_argc = *argc_p;
glob.argv = *argv_p;
glob.maxargs = *maxargs_p;
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, 100);
glob_match(s, 0, -1);
/* The arg didn't match anything, so add the failed arg to the list. */
if (glob.argc == save_argc) {
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
glob.argv[glob.argc++] = s;
ret = 0;
} else {
free(s);
ret = 1;
}
*maxargs_p = glob.maxargs;
*argv_p = glob.argv;
*argc_p = glob.argc;
return ret;
}
/* This routine is only used in daemon mode. */
void glob_expand_module(char *base1, char *arg, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
void glob_expand_module(char *base1, char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
{
char *p, *s;
char *base = base1;
@@ -600,7 +690,7 @@ void glob_expand_module(char *base1, char *arg, char ***argv_ptr, int *argc_ptr,
for (s = arg; *s; s = p + base_len) {
if ((p = strstr(s, base)) != NULL)
*p = '\0'; /* split it at this point */
glob_expand(s, argv_ptr, argc_ptr, maxargs_ptr);
glob_expand(s, argv_p, argc_p, maxargs_p);
if (!p)
break;
}
@@ -687,11 +777,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 all leading or
* interior "." elements unless CFN_KEEP_DOT_DIRS is flagged. Will also 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, and will also collapse ".." elements
* (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged. If the
* resulting name would be empty, returns ".". */
unsigned int clean_fname(char *name, int flags)
{
char *limit = name - 1, *t = name, *f = name;
int anchored;
@@ -701,6 +794,10 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
if ((anchored = *f == '/') != 0)
*t++ = *f++;
else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {
*t++ = *f++;
*t++ = *f++;
}
while (*f) {
/* discard extra slashes */
if (*f == '/') {
@@ -708,14 +805,16 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
continue;
}
if (*f == '.') {
/* discard "." dirs (but NOT a trailing '.'!) */
if (f[1] == '/') {
/* discard interior "." dirs */
if (f[1] == '/' && !(flags & CFN_KEEP_DOT_DIRS)) {
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 +832,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 +853,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:
@@ -766,15 +864,10 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
* 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)
int flags)
{
char *start, *sanp, *save_dest = dest;
int rlen = 0, leave_one_dotdir = relative_paths;
if (symlink && *symlink == '/') {
p = symlink;
symlink = "";
}
char *start, *sanp;
int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
if (dest != p) {
int plen = strlen(p);
@@ -797,32 +890,22 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
}
}
if (drop_dot_dirs) {
while (*p == '.' && p[1] == '/')
p += 2;
}
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 = "";
}
/* This loop iterates once per filename component in p, pointing at
* the start of the name (past any prior slash) for each iteration. */
while (*p) {
/* discard leading or extra slashes */
if (*p == '/') {
p++;
continue;
}
/* this loop iterates once per filename component in p.
* both p (and sanp if the original had a slash) should
* always be left pointing after a slash
*/
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
if (leave_one_dotdir && p[1])
leave_one_dotdir = 0;
else {
if (drop_dot_dirs) {
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
p++;
continue;
@@ -831,19 +914,12 @@ 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 */
--sanp; /* now pointing at slash */
while (sanp > start && sanp[-1] != '/') {
/* skip back up to slash */
while (sanp > start && sanp[-1] != '/')
sanp--;
}
}
continue;
}
@@ -867,7 +943,7 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
/* Like chdir(), but it keeps track of the current directory (in the
* global "curr_dir"), and ensures that the path size doesn't overflow.
* Also cleans the path using the clean_fname() function. */
int push_dir(const char *dir, int set_path_only)
int change_dir(const char *dir, int set_path_only)
{
static int initialised;
unsigned int len;
@@ -885,47 +961,37 @@ int push_dir(const char *dir, int set_path_only)
if (len == 1 && *dir == '.')
return 1;
if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir) {
errno = ENAMETOOLONG;
return 0;
}
if (!set_path_only && chdir(dir))
return 0;
if (*dir == '/') {
if (len >= sizeof curr_dir) {
errno = ENAMETOOLONG;
return 0;
}
if (!set_path_only && chdir(dir))
return 0;
memcpy(curr_dir, dir, len + 1);
curr_dir_len = len;
} else {
curr_dir[curr_dir_len++] = '/';
memcpy(curr_dir + curr_dir_len, dir, len + 1);
curr_dir_len += len;
if (curr_dir_len + 1 + len >= sizeof curr_dir) {
errno = ENAMETOOLONG;
return 0;
}
curr_dir[curr_dir_len] = '/';
memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
if (!set_path_only && chdir(curr_dir)) {
curr_dir[curr_dir_len] = '\0';
return 0;
}
}
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);
}
return 1;
}
/**
* Reverse a push_dir() call. You must pass in an absolute path
* that was copied from a prior value of "curr_dir".
**/
int pop_dir(const char *dir)
{
if (chdir(dir))
return 0;
curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
if (curr_dir_len >= sizeof curr_dir)
curr_dir_len = sizeof curr_dir - 1;
if (sanitize_paths)
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
if (verbose >= 5 && !set_path_only)
rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir);
return 1;
}
@@ -985,13 +1051,13 @@ char *partial_dir_fname(const char *fname)
fn = fname;
if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
return NULL;
if (server_filter_list.head) {
if (daemon_filter_list.head) {
t = strrchr(partial_fname, '/');
*t = '\0';
if (check_filter(&server_filter_list, partial_fname, 1) < 0)
if (check_filter(&daemon_filter_list, FLOG, partial_fname, 1) < 0)
return NULL;
*t = '/';
if (check_filter(&server_filter_list, partial_fname, 0) < 0)
if (check_filter(&daemon_filter_list, FLOG, partial_fname, 0) < 0)
return NULL;
}
@@ -1263,7 +1329,7 @@ void *_new_array(unsigned long num, unsigned int size, int use_calloc)
return use_calloc ? calloc(num, size) : malloc(num * size);
}
void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
void *_realloc_array(void *ptr, unsigned int size, size_t num)
{
if (num >= MALLOC_MAX/size)
return NULL;
@@ -1484,7 +1550,10 @@ void *expand_item_list(item_list *lp, size_t item_size,
new_size += incr;
else
new_size *= 2;
new_ptr = realloc_array(lp->items, char, new_size * item_size);
if (new_size < lp->malloced)
overflow_exit("expand_item_list");
/* Using _realloc_array() lets us pass the size, not a type. */
new_ptr = _realloc_array(lp->items, item_size, new_size);
if (verbose >= 4) {
rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n",
who_am_i(), desc, (double)new_size * item_size,

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

285
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)
@@ -63,13 +62,17 @@ extern int checksum_seed;
#endif
#define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1)
#define XSTAT_ATTR RSYNC_PREFIX "%stat"
#define XACC_ACL_ATTR RSYNC_PREFIX "%aacl"
#define XDEF_ACL_ATTR RSYNC_PREFIX "%dacl"
#define XSTAT_SUFFIX "stat"
#define XSTAT_ATTR RSYNC_PREFIX "%" XSTAT_SUFFIX
#define XACC_ACL_SUFFIX "aacl"
#define XACC_ACL_ATTR RSYNC_PREFIX "%" XACC_ACL_SUFFIX
#define XDEF_ACL_SUFFIX "dacl"
#define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX
typedef struct {
char *datum, *name;
size_t datum_len, name_len;
int num;
} rsync_xa;
static size_t namebuf_len = 0;
@@ -111,6 +114,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 +123,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 +150,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 +162,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 +211,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 +231,15 @@ 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+RPRE_LEN+1, XSTAT_SUFFIX) == 0
|| strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
|| strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
continue;
}
datum_len = name_len; /* Pass extra size to get_xattr_data() */
if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -249,23 +259,19 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
} else
name_offset = datum_len;
#ifdef HAVE_LINUX_XATTRS
if (am_root < 0 && name_len > 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;
}
@@ -344,25 +350,32 @@ int send_xattr(stat_x *sxp, int f)
int count = sxp->xattr->count;
write_varint(f, count);
for (rxa = sxp->xattr->items; count--; rxa++) {
size_t name_len = rxa->name_len;
const char *name = rxa->name;
/* Strip the rsync prefix from disguised namespaces. */
if (name_len > RPRE_LEN
#ifdef HAVE_LINUX_XATTRS
write_varint(f, rxa->name_len);
write_varint(f, rxa->datum_len);
write_buf(f, rxa->name, rxa->name_len);
#else
/* We strip the rsync prefix from disguised namespaces
* and put everything else in the user namespace. */
if (HAS_PREFIX(rxa->name, RSYNC_PREFIX)
&& rxa->name[RPRE_LEN] != '%') {
write_varint(f, rxa->name_len - RPRE_LEN);
write_varint(f, rxa->datum_len);
write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN);
} else {
write_varint(f, rxa->name_len + UPRE_LEN);
write_varint(f, rxa->datum_len);
write_buf(f, USER_PREFIX, UPRE_LEN);
write_buf(f, rxa->name, rxa->name_len);
&& am_root < 0
#endif
&& name[RPRE_LEN] != '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
name += RPRE_LEN;
name_len -= RPRE_LEN;
}
#ifndef HAVE_LINUX_XATTRS
else {
/* Put everything else in the user namespace. */
name_len += UPRE_LEN;
}
#endif
write_varint(f, name_len);
write_varint(f, rxa->datum_len);
#ifndef HAVE_LINUX_XATTRS
if (name_len > rxa->name_len) {
write_buf(f, USER_PREFIX, UPRE_LEN);
name_len -= UPRE_LEN;
}
#endif
write_buf(f, name, name_len);
if (rxa->datum_len > MAX_FULL_DATUM)
write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
else
@@ -453,18 +466,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 +489,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 +512,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 +531,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 +566,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 +578,12 @@ 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;
#ifdef HAVE_LINUX_XATTRS
int need_sort = 0;
#else
int need_sort = 1;
#endif
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
@@ -591,7 +602,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 +626,15 @@ 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);
need_sort = 1;
}
#else
/* This OS only has a user namespace, so we either
@@ -651,8 +663,12 @@ 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;
}
if (need_sort && count > 1)
qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
ndx = rsync_xal_l.count; /* pre-incremented count */
rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
@@ -682,7 +698,8 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
ssize_t list_len;
size_t i, len;
char *name, *ptr, sum[MAX_DIGEST_LEN];
int name_len, ret = 0;
size_t name_len;
int ret = 0;
/* This puts the current name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(fname)) < 0)
@@ -719,7 +736,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 +744,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 +757,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 +777,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 +787,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 +822,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 +830,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 +875,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 +896,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 +906,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 +938,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 +956,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