Compare commits

...

104 Commits

Author SHA1 Message Date
Wayne Davison
d596d389fe Preparing for release of 3.0.4 2008-09-06 09:32:26 -07:00
Wayne Davison
bc2337717e A few more improvements and a mention of the latest fix. 2008-09-06 08:03:52 -07:00
Wayne Davison
3df40f044a Changed some "rsync" commands into proper "$RSYNC" commands. 2008-09-03 12:14:13 -07:00
Wayne Davison
d11a5b80c1 Made human_num() and human_dnum() able to output negative numbers. 2008-09-01 13:25:41 -07:00
Wayne Davison
deea1f70bd Got rid of the check_for_io_err code, as it could cause a hang.
The io_error issue will be fixed in a better way in 3.1.0.
2008-08-31 09:51:29 -07:00
Wayne Davison
a91e678324 Some minor improvements to the flushing code to try to make it
even more solid.
2008-08-24 13:39:44 -07:00
Wayne Davison
25a22d8501 Make the !flist_eof assumption explicit before the check_for_io_err
code calls wait_for_receiver().
2008-08-24 12:33:22 -07:00
Wayne Davison
fac9e234ae Added /support/savetransfer to .gitignore. 2008-08-17 09:28:06 -07:00
Wayne Davison
f3d87ee972 An improved RERR_PARTIAL message. 2008-08-17 09:25:34 -07:00
Wayne Davison
9bed85542c Changed flist_for_ndx() to optionally die with an error
if the index isn't found.
2008-08-14 07:32:18 -07:00
Wayne Davison
5b979530a7 Made an error of readlink_stat() use the right function name. 2008-08-10 07:31:45 -07:00
Wayne Davison
7ec8baaa7e Make sure that the hlink node->data allocation doesn't fail. 2008-08-08 07:47:31 -07:00
Wayne Davison
8c2c008984 Improved a couple NEWS items. 2008-08-05 18:43:51 -07:00
Wayne Davison
719a29e1cf Preparing for release of 3.0.4pre2 2008-08-02 14:06:31 -07:00
Wayne Davison
4a95d61251 Tweaked the symlink iconv buffer size and fixed a comment. 2008-08-02 13:45:15 -07:00
Wayne Davison
fc088e30c8 When using --iconv, if a server-side receiver can't convert a filename,
it now outputs the name back to the client without mangling the charset.
2008-08-02 10:25:17 -07:00
Wayne Davison
aef51b4c68 Refer to the symlink's contents as "symlink data", not "symlink name". 2008-08-02 10:18:10 -07:00
Wayne Davison
7790ee3684 Added logic to the receiving side to ensure that the --delete-during
code will not delete in a directory prior to receiving an I/O error
for that directory (or not receiving it, as the case may be).
2008-08-02 09:03:49 -07:00
Wayne Davison
ed12c8eb21 Skip new symlink conversion step if the remote rsync is not
new enough to do symlink content conversions.
2008-08-02 07:04:54 -07:00
Wayne Davison
91dd3d0d48 The --iconv option now converts the content of a symlink too. 2008-08-01 19:20:41 -07:00
Wayne Davison
95d1d2a9a4 Fixed a problem with checking for the '.' dir in the first file
list that is transferred.  This fixes a glitch where a failed
--iconv conversion on the receiving side could prevent deletions
from happening in the root-dir of the transfer.
2008-08-01 19:00:21 -07:00
Wayne Davison
a808346dbe Fixed a couple minor problems in util.c:
- Make sure that handle_partial_dir() never returns a truncated fname.
- Make robust_rename() return that it failed to do a cross-device
  copy if the partial-dir could not be created.
2008-08-01 18:00:18 -07:00
Wayne Davison
fa181223d8 Properly handle a failure to create a partial directory, which is
especially important for --delay-updates, particularly when
--remove-source-files was also specified.
2008-08-01 18:00:09 -07:00
Wayne Davison
9ed569486f Output an FERROR* for a general io_error, and an FWARNING for other
io_error flags.
2008-07-31 07:57:55 -07:00
Wayne Davison
2fa069d85f Mention a missing sender-side hash improvment that went out in 3.0.0. 2008-07-30 08:33:35 -07:00
Wayne Davison
a25aed50e6 Make hard-linking work when a device has an st_dev of 0. 2008-07-29 18:08:51 -07:00
Wayne Davison
302e4346c2 Mention some mount options that can interfere with --link-dest. 2008-07-28 18:24:25 -07:00
Wayne Davison
8e5eafccdf Back-porting some manpage improvements. 2008-07-28 17:07:38 -07:00
Wayne Davison
e88b92bade Preparing for release of 3.0.4pre1 2008-07-24 17:03:26 -07:00
Wayne Davison
f8722dba56 Fixed the --fake-super test in the xattrs testsuite when there are
root-level xattrs on the files (e.g. selinux values).
2008-07-24 07:57:57 -07:00
Wayne Davison
ee03cb99d9 Fixed the timeout/flush loop-check logic to work properly with
incremental recursion.
2008-07-23 23:37:11 -07:00
Wayne Davison
92d706a274 Don't interrupt the make if a generated build file didn't really change. 2008-07-23 23:28:57 -07:00
Wayne Davison
581c830c56 A couple xattr fixes for --fake-super. 2008-07-23 23:12:39 -07:00
Wayne Davison
9e58ef45f3 If the user specifies --protocol=29, rsync will avoid sending an -e
option to the server (which is only useful for protocols 30 and above
anyway).  This gives the user an easy way to talk to a restricted
server that has overly restrictive option-checking.
2008-07-23 23:09:15 -07:00
Wayne Davison
05bd05a7a1 Pass --branch option to patch-update script. 2008-07-23 17:13:29 -07:00
Wayne Davison
89b6b4ce4b We only need to deal with local patch branches now. 2008-07-23 14:32:58 -07:00
Wayne Davison
68cdc3b791 Fixed a potential alignment issue in the IRIX ACL code when allocating
the initial struct acl object.  Also, cast mallocs to avoid warnings.
2008-07-22 21:35:21 -07:00
Wayne Davison
209371b891 Fixed a bug in match_hard_links() where an empty directory would try
to allocate 0 bytes of memory (which can fail on some OSes).
2008-07-22 21:34:20 -07:00
Wayne Davison
6fd2662982 Allow a release from a non-master branch. 2008-07-22 09:11:34 -07:00
Wayne Davison
1fdf0302c0 Start the 3.0.4 branch. 2008-07-22 09:11:22 -07:00
Wayne Davison
db8f3f7350 Preparing for release of 3.0.3 2008-06-29 20:15:37 -07:00
Wayne Davison
85fd80ce10 Mention the addition of the deny-rsync script, and tweak some comments. 2008-06-28 10:12:57 -07:00
Wayne Davison
a24d64bfaa Fixed a problem with a file descriptor being left open in the
generator when handling an empty file.
2008-06-26 08:14:11 -07:00
Wayne Davison
33cc92a63a Some deny-rsync fixes:
- Fixed messages longer than 63 chars.
- Don't require the presence of a "bc" program.
- Append a newline to the message to make the script easier to call.
- Make extra sure the message outputs without escape interpretation.
- Stick around long enough for a client to reliably get the message.
2008-06-23 23:10:12 -07:00
Matt McCutchen
5e7f63f0bf The deny-rsync script from bug 3945. 2008-06-23 23:04:21 -07:00
Wayne Davison
8bd77e7098 Fixed the sending of large files with older rsync versions by
handling the old block-size limit for protocols < 29.
2008-06-23 09:17:55 -07:00
Wayne Davison
13074c982b Preparing for release of 3.0.3pre3 2008-06-22 19:03:46 -07:00
Matt McCutchen
2171b9395b The sender now sets IOERR_GENERAL in more skipped-file instances. 2008-06-22 19:00:51 -07:00
Wayne Davison
20bb1eb7ae Mention more fixes in the NEWS. 2008-06-22 18:45:07 -07:00
Wayne Davison
7ee7bcd4e9 Improved the build rules for rsync.1 and rsyncd.conf.5 when building
in a separate build directory from the source.
2008-06-22 18:26:15 -07:00
Wayne Davison
844810d609 Avoid problems with timestamp rounding that cp -p and touch -r may do. 2008-06-17 15:59:47 -07:00
Wayne Davison
67347196b1 Fix the problem with setting xattrs on a directory that has an
identical match found in a --link-dest/--copy-dest hierarchy.
2008-06-12 23:08:43 -07:00
Wayne Davison
e424e26128 Cast the datum_len value to a long for rprintf(). 2008-06-12 06:59:51 -07:00
Wayne Davison
ca7d17e41d Handle a solo_file of a directory for --delete-during. 2008-06-09 07:42:03 -07:00
Wayne Davison
6283e9ef43 A couple more xattr improvements:
- Made the XSTATE_* defines avoid using 0.
- Call !XATTR_ABBREV() in recv_xattr_request().
- Improved the "internal abbrev" error message.
- Fixed the potential for a directory time glitch in xattrs.diff.
2008-06-08 21:14:46 -07:00
Wayne Davison
7462c6ac39 Fixed an "Internal abbrev error" when dealing with an xattr value
that is unchanged on an early file, and changed on a later file.
Added 2 new test cases to ensure this stays fixed.
2008-06-08 20:40:11 -07:00
Wayne Davison
f31850966f Improved the progress_is_active code to not overwrite the progress
output in more circumstances.
2008-06-04 09:01:02 -07:00
Wayne Davison
4ecf3e0671 Improved handling of a system that doesn't have a 64-bit offset type. 2008-06-04 08:15:51 -07:00
Wayne Davison
60a986f504 Improved the proto.h target so that a build in a different dir from the
srcdir will ensure that the builddir has a copy of the proto.h file when
the Makefile found it to be out of date.  This prevents the repeated
building of all the targets when the srcdir's proto.h file is accurate,
but older than the newest .c file.
2008-06-04 07:13:22 -07:00
Wayne Davison
0e9c3564c6 Improved the daemon testing, including adding a test to ensure that
daemon excludes can't exclude a dot dir.
2008-05-31 14:52:24 -07:00
Wayne Davison
164cb66add Fixed the destination path check so that it cannot exclude a
dot dir.
2008-05-31 14:51:38 -07:00
Wayne Davison
0d9eba0312 Have send_file_list() check is_excluded() (but only on non-dot-dirs)
and then call send_file_name() with NO_FILTERS.  This gets rid of
the need for a FLAG_DOTDIR_NAME flag (used only by make_file()).
2008-05-31 14:41:20 -07:00
Wayne Davison
d1f66d8d79 If an arg is excluded, don't include its implied dirs. 2008-05-31 11:29:24 -07:00
Wayne Davison
cc911409d6 Make sure the generator doesn't try to send a negative checksum count to
the sender (which would cause it to die with a cryptic error).  Instead,
warn the user when the file's size is too large for checksum processing.
2008-05-31 10:13:28 -07:00
Wayne Davison
a64f19e24b Fixed the backing up of a device or socket. 2008-05-22 16:44:01 -07:00
Wayne Davison
4337eeb754 A cuple more fixes for --xattrs combined with --backup, this time to
handle when --link-dest is also used.
2008-05-22 07:32:11 -07:00
Wayne Davison
928da42359 Fixed the "src" symlink in each testtmp subdir. 2008-05-18 07:00:48 -07:00
Wayne Davison
e717fa4d37 Fix some path problems when the build dir is not the
source dir.
2008-05-17 15:07:24 -07:00
Wayne Davison
cc56eb2acc Preparing for release of 3.0.3pre2 2008-05-17 10:02:19 -07:00
Wayne Davison
88e05f8489 Fixed an "else" in the device-making part of keep_backup(). 2008-05-17 09:57:08 -07:00
Wayne Davison
9ec8583ef5 Mention the latest fixes in the NEWS. 2008-05-17 09:45:13 -07:00
Wayne Davison
e9489cd6cb Fixed several issues with preserving xattrs when using --backup. 2008-05-17 09:35:46 -07:00
Wayne Davison
f1ca7c4429 Preserve the right errno value when trying adjunct functions during
robust backup, copy, and renaming activities.
2008-05-17 08:25:22 -07:00
Wayne Davison
adc4ebdd76 Improved the docs for --inplace and made the mentions of
rsync's delta-transfer algorithm more consistent.
2008-05-09 23:49:41 -07:00
Wayne Davison
9a30c0cc3c Preparing for release of 3.0.3pre1 2008-05-07 22:12:57 -07:00
Wayne Davison
47f43c023b The test of HAVE_LUTIMES accidentally omitted the 'L'. 2008-05-07 22:11:17 -07:00
Wayne Davison
5b385336b9 Added options to tls.c to allow us to ask for mtime and ownership info
on symlinks.  The testsuite will now pass these options to tls if rsync
is configured to affect such attributes on symlinks.
2008-05-06 10:39:19 -07:00
Wayne Davison
c3a2d95cfa Adding missing entry for 3.0.3 protocol-history list. 2008-05-01 16:14:39 -07:00
Wayne Davison
6b19df680a Mention all the latest changes in the NEWS. 2008-04-28 21:29:30 -07:00
Wayne Davison
fdf74bede0 - Changed prev_name into a buffer so that there is no chance that its
contents can be overwritten by other calls to f_name().
- Changed an hlink assert into a check that provides more debug info.
2008-04-28 21:17:36 -07:00
Wayne Davison
876ad10ccc Fixed a crash if a non-incremental-recursion transfer has a
skipped file in a set of hard-links.
2008-04-27 18:45:13 -07:00
Wayne Davison
34a2b39165 Reorder the filenames to touch to try to avoid a weird error on Solaris
5.8.  Also, use lsh in one of the runs in order to try a hard-link run
that uses a (pretend) remote shell.
2008-04-18 19:55:08 -07:00
Wayne Davison
276cc45571 Added a --no-cd option to support/lsh so that the script can be used by
the testsuite.  Improved the home-directory-changing code and added an
error message when "localhost" is not the hostname specified.  Use the
updated script in the testsuite instead of creating a pretend-ssh script
in a couple spots.
2008-04-18 19:41:57 -07:00
Wayne Davison
311676ed21 Fixed a problem with how the daemon filters deal with
a destination directory with a trailing slash.
2008-04-16 09:32:22 -07:00
Wayne Davison
4616867b0d Don't allow '.' dir to be excluded by the daemon's filter rules. 2008-04-16 09:30:28 -07:00
Wayne Davison
8a5ae84efd A few $last_touch tweaks. 2008-04-16 09:11:15 -07:00
Wayne Davison
59d2cd5a7f When running in --progress mode with a progress message active, the
client now outputs a newline prior to an error message, which avoids
overwriting the active file's last progress line.
2008-04-15 08:50:14 -07:00
Wayne Davison
1c3e6e8b26 Moved the setting of the socket options before the connect(). 2008-04-15 08:34:17 -07:00
Wayne Davison
f2681d42ff Fixed the %M escape, which was munging the wrong spaces. 2008-04-15 08:32:41 -07:00
Wayne Davison
774d1c367b Use overflow_exit() for overflows, not out_of_memory(). 2008-04-15 08:27:38 -07:00
Wayne Davison
1b8e0e876b Consistently call the daemon parameters "parameters", not "options",
which allows us to distinguish them from rsync's command-line options.
2008-04-15 08:26:00 -07:00
Wayne Davison
1502f4f58f Updated the README and the NEWS file. 2008-04-15 08:12:56 -07:00
Wayne Davison
6db1db5488 Fix a file-globbing bug in the daemon when chroot is on. 2008-04-11 22:32:38 -07:00
Wayne Davison
09ad90537d If the daemon test is run as root, use a --config option. 2008-04-11 21:57:17 -07:00
Wayne Davison
da9aefa6b4 Prepare repository for more development. 2008-04-11 21:55:43 -07:00
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
51 changed files with 1505 additions and 697 deletions

4
.gitignore vendored
View File

@@ -3,10 +3,13 @@
dummy
ID
Makefile
Makefile.old
configure.sh
configure.sh.old
config.cache
config.h
config.h.in
config.h.in.old
config.log
config.status
/proto.h
@@ -32,6 +35,7 @@ config.status
/rounding.h
/doc/rsync.pdf
/doc/rsync.ps
/support/savetransfer
/testsuite/chown-fake.test
/testsuite/devices-fake.test
/patches

View File

@@ -66,8 +66,8 @@ install: all
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
-mkdir -p ${DESTDIR}${mandir}/man1
-mkdir -p ${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
if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
install-strip:
$(MAKE) INSTALL_STRIP='-s' install
@@ -126,11 +126,23 @@ conf:
conf_stop: configure.sh config.h.in
configure.sh config.h.in: configure.in aclocal.m4
@if test -f configure.sh; then cp -p configure.sh configure.sh.old; else touch configure.sh.old; fi
@if test -f config.h.in; then cp -p config.h.in config.h.in.old; else touch config.h.in.old; fi
autoconf -o configure.sh
autoheader && touch config.h.in
@echo 'Configure files changed -- perhaps run:'
@echo ' make reconfigure'
@exit 1
@if diff configure.sh configure.sh.old >/dev/null 2>&1; then \
echo "configure.sh is unchanged."; \
rm configure.sh.old; \
fi
@if diff config.h.in config.h.in.old >/dev/null 2>&1; then \
echo "config.h.in is unchanged."; \
rm config.h.in.old; \
fi
@if test -f configure.sh.old -o -f config.h.in.old; then \
echo 'Configure files changed -- perhaps run:'; \
echo ' make reconfigure'; \
exit 1; \
fi
reconfigure: configure.sh
./config.status --recheck
@@ -139,19 +151,27 @@ reconfigure: configure.sh
make_stop: Makefile
Makefile: Makefile.in config.status
@if test -f Makefile; then cp -p Makefile Makefile.old; else touch Makefile.old; fi
@./config.status
@echo "Makefile updated -- rerun your make command."
@exit 1
@if diff Makefile Makefile.old >/dev/null 2>&1; then \
echo "Makefile is unchanged."; \
rm Makefile.old; \
else \
echo "Makefile updated -- rerun your make command."; \
exit 1; \
fi
proto: proto.h-tstamp
proto.h: proto.h-tstamp
@echo ' ' >/dev/null
@if test -f proto.h; then :; else cp -p $(srcdir)/proto.h .; fi
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
@if test -f rsync.1; then :; else cp -p $(srcdir)/rsync.1 .; fi
@if test -f rsyncd.conf.5; then :; else cp -p $(srcdir)/rsyncd.conf.5 .; fi
rsync.1: rsync.yo
yodl2man -o rsync.1 $(srcdir)/rsync.yo
@@ -163,7 +183,7 @@ rsyncd.conf.5: rsyncd.conf.yo
clean: cleantests
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h
rounding rounding.h *.old
cleantests:
rm -rf ./testtmp*

154
NEWS
View File

@@ -1,136 +1,64 @@
NEWS for rsync 3.0.1 (3 Apr 2008)
NEWS for rsync 3.0.4 (6 Sep 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.).
Changes since 3.0.3:
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 bug in the hard-linking code where it would sometimes try to
allocate 0 bytes of memory (which fails on some OSes, such as AIX).
- Fixed a crash when backing up a directory that has a default ACL.
- Fixed the hard-linking of files from a device that has a device number
of 0 (which seems to be a common device number on NetBSD).
- 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 handling of a --partial-dir that cannot be created. This
particularly impacts the --delay-updates option (since the files cannot
be delayed without a partial-dir), and was potentially destructive if
the --remove-source-files was also specified.
- Fixed the working of --fake-super with --link-dest and --xattrs.
- Fixed a couple issues in the --fake-super handling of xattrs when the
destination files have root-level attributes (e.g. selinux values) that
a non-root copy can't affect.
- Fixed a hang when combining --dry-run with --remove-source-files.
- Improved the keep-alive check in the generator to fire consistently in
incremental-recursion mode when --timeout is enabled.
- Fixed a bug with --iconv's handling of files that cannot be converted:
a failed name can no longer cause a transfer failure.
- The --iconv option now converts the content of a symlink too, instead
of leaving it in the wrong character-set (requires 3.0.4 on both sides
of the transfer).
- 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.
- When using --iconv, if a filename fails to convert on the receiving side,
this no longer makes deletions in the root-dir of the transfer fail
silently (the user now gets a warning about deletions being disabled
due to IO error as long as --ignore-errors was not specified).
- Fixed the use of the --protect-args (-s) option when talking to a daemon.
- When using --iconv, if a server-side receiver can't convert a filename,
the error message sent back to the client no longer mangles the name
with the wrong charset conversion.
- 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 a potential alignment issue in the IRIX ACL code when allocating
the initial "struct acl" object. Also, cast mallocs to avoid warnings.
- 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.
- Changed some errors that were going to stdout to go to stderr.
- 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).
- Made human_num() and human_dnum() able to output a negative number
(rather than outputting a cryptic string of punctuation).
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).
- Rsync will avoid sending an -e option to the server if an older protocol
is requested (and thus the option would not be useful). This lets the
user specify the --protocol=29 option to access an overly-restrictive
server that is rejecting the protocol-30 use of -e to the server.
- 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.
- Improved the message output for an RERR_PARTIAL exit.
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 Makefile will not halt for just a timestamp change on the Makefile
or the configure files, only for actual changes in content.
- The configure script now has better checks for figuring out if the
included popt code should be used or not.
- Changed some commands in the testsuite's xattrs.test that called "rsync"
instead of "$RSYNC".
- 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.
- Enhanced the release scripts to be able to handle a branch release and
to do even more consistency checks on the files.

257
OLDNEWS
View File

@@ -1,3 +1,252 @@
NEWS for rsync 3.0.3 (29 Jun 2008)
Protocol: 30 (unchanged)
Changes since 3.0.2:
BUG FIXES:
- Fixed a wildcard matching problem in the daemon when a module has
"use chroot" enabled.
- Fixed a crash bug in the hard-link code.
- Fixed the sending of xattr directory information when the code finds a
--link-dest or --copy-dest directory with unchanged xattrs -- the
destination directory now gets these unchanged xattrs properly applied.
- Fixed an xattr-sending glitch that could cause an "Internal abbrev"
error.
- Fixed the combination of --xattrs and --backup.
- The generator no longer allows a '.' dir to be excluded by a daemon-
exclude rule.
- Fixed deletion handling when copying a single, empty directory (with no
files) to a differently named, non-existent directory.
- Fixed the conversion of spaces into dashes in the %M log escape.
- Fixed several places in the code that were not returning the right
errno when a function failed.
- Fixed the backing up of a device or special file into a backup dir.
- Moved the setting of the socket options prior to the connect().
- If rsync exits in the middle of a --progress output, it now outputs a
newline to help prevent the progress line from being overwritten.
- Fixed a problem with how a destination path with a trailing slash or
a trailing dot-dir was compared against the daemon excludes.
- Fixed the sending of large (size > 16GB) files when talking to an older
rsync (protocols < 30): we now use a compatible block size limit.
- If a file's length is so huge that we overflow a checksum buffer count
(i.e. several hundred TB), warn the user and avoid sending an invalid
checksum struct over the wire.
- If a source arg is excluded, --relative no longer adds the excluded
arg's implied dirs to the transfer. This fix also made the exclude
check happen in the better place in the sending code.
- Use the overflow_exit() function for overflows, not out_of_memory().
- Improved the code to better handle a system that has only 32-bit file
offsets.
ENHANCEMENTS:
- The rsyncd.conf manpage now consistently refers to the parameters in
the daemon config file as "parameters".
- The description of the --inplace option was improved.
EXTRAS:
- Added a new script in the support directory, deny-rsync, which allows
an admin to (temporarily) replace the rsync command with a script that
sends an error message to the remote client via the rsync protocol.
DEVELOPER RELATED:
- Fixed a testcase failure if the tests are run as root and made some
compatibility improvements.
- Improved the daemon tests, including checking module comments, the
listing of files, and the ensuring that daemon excludes can't affect
a dot-dir arg.
- Improved some build rules for those that build in a separate directory
from the source, including better install rules for the man pages, and
the fixing of a proto.h-tstamp rule that could make the binaries get
rebuild without cause.
- Improved the testsuite to work around a problem with some utilities
(e.g. cp -p & touch -r) rounding sub-second timestamps.
- Ensure that the early patches don't cause any generated-file hunks to
bleed-over into patches that follow.
NEWS for rsync 3.0.2 (8 Apr 2008)
Protocol: 30 (unchanged)
Changes since 3.0.1:
BUG FIXES:
- Fixed a potential buffer overflow in the xattr code.
ENHANCEMENTS:
- None.
DEVELOPER RELATED:
- The RPM spec file was improved to install more useful files.
- A few developer-oriented scripts were moved from the support dir
to the packaging dir.
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:
@@ -132,6 +381,11 @@ Changes since 2.6.9:
- Fixed rsync's ability to remove files that are not writable by the file's
owner when rsync is running as the same user.
- When transferring large files, the sender's hashtable of checksums is
kept at a more reasonable state of fullness (no more than 80% full) so
that the scanning of the hashtable will not bog down as the number of
blocks increases.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
@@ -2587,6 +2841,9 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
06 Sep 2008 3.0.4 30
29 Jun 2008 3.0.3 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

123
README
View File

@@ -1,122 +1,135 @@
WHAT IS RSYNC?
--------------
rsync is a replacement for scp/rcp that has many more features.
Rsync is a fast and extraordinarily versatile file copying tool for
both remote and local files.
rsync uses the "rsync algorithm" which provides a very fast method for
bringing remote files into sync. It does this by sending just the
Rsync uses a delta-transfer algorithm which provides a very fast method
for bringing remote files into sync. It does this by sending just the
differences in the files across the link, without requiring that both
sets of files are present at one of the ends of the link beforehand.
At first glance this may seem impossible because the calculation of
diffs between two files normally requires local access to both
files.
sets of files are present at one of the ends of the link beforehand. At
first glance this may seem impossible because the calculation of diffs
between two files normally requires local access to both files.
A technical report describing the rsync algorithm is included with
this package.
A technical report describing the rsync algorithm is included with this
package.
USAGE
-----
Basically you use rsync just like rcp, but rsync has many additional
options. To get a complete list of supported options type
Basically you use rsync just like scp, but rsync has many additional
options. To get a complete list of supported options type:
rsync --help
rsync --help
and see the manual for more information.
See the manpage for more detailed information.
SETUP
-----
Rsync normally uses ssh or rsh for communication. It does not need to
be setuid and requires no special privileges for installation. You
must, however, have a working ssh or rsh system. Using ssh is
recommended for its security features.
Rsync normally uses ssh or rsh for communication with remote systems.
It does not need to be setuid and requires no special privileges for
installation. You must, however, have a working ssh or rsh system.
Using ssh is recommended for its security features.
Alternatively, rsync can run in `daemon' mode, listening on a socket.
This is generally used for public file distribution, although
authentication and access control are available.
To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type
"make".
To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type "make".
Note that on some systems you will have to force configure not to use
gcc because gcc may not support some features (such as 64 bit file
offsets) that your system may support. Set the environment variable CC
offsets) that your system may support. Set the environment variable CC
to the name of your native compiler before running configure in this
case.
case.
Once built put a copy of rsync in your search path on the local and
remote systems (or use "make install"). That's it!
remote systems (or use "make install"). That's it!
RSYNC DAEMONS
-------------
rsync can also talk to "rsync daemons" which can provide anonymous or
authenticated rsync. See the rsyncd.conf(5) man page for details on how
to setup an rsync daemon. See the rsync(1) man page for info on how to
Rsync can also talk to "rsync daemons" which can provide anonymous or
authenticated rsync. See the rsyncd.conf(5) man page for details on how
to setup an rsync daemon. See the rsync(1) man page for info on how to
connect to an rsync daemon.
MAILING LIST
------------
WEB SITE
--------
There is a mailing list for the discussion of rsync and its
applications. It is open to anyone to join. I will announce new
versions on this list.
The main rsync web site is here:
To join the mailing list see the web page at http://lists.samba.org/
http://rsync.samba.org/
To send mail to everyone on the list send it to rsync@lists.samba.org
You'll find a FAQ list, downloads, resources, HTML versions of the
manpages, etc.
MAILING LISTS
-------------
There is a mailing list for the discussion of rsync and its applications
that is open to anyone to join. New releases are announced on this
list, and there is also an announcement-only mailing list for those that
want official announcements. See the mailing-list page for full
details:
http://rsync.samba.org/lists.html
BUG REPORTS
-----------
If you have web access then please look at
To visit this web page for full the details on bug reporting:
http://rsync.samba.org/
http://rsync.samba.org/bugzilla.html
That page contains links to the current bug list, and information on
how to report a bug well. You might also like to try searching the
internet for the error message you've received, or looking in the
mailing list archives at
That page contains links to the current bug list, and information on how
to report a bug well. You might also like to try searching the Internet
for the error message you've received, or looking in the mailing list
archives at:
http://mail-archive.com/rsync@lists.samba.org/
http://mail-archive.com/rsync@lists.samba.org/
To send a bug report, follow the instructions on the bug-tracking
page of the web site.
If you don't have web access, email your bug report to
rsync@lists.samba.org.
Alternately, email your bug report to rsync@lists.samba.org .
CVS TREE
--------
GIT REPOSITORY
--------------
If you want to get the very latest version of rsync direct from the
source code repository then you can use anonymous cvs. You will need a
recent version of cvs then use the following commands:
source code repository then you can use git:
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login
Password: cvs
git clone git://git.samba.org/rsync.git
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co rsync
See the download page for full details on all the ways to grab the
source, including nightly tar files, web-browsing of the git repository,
etc.:
Look at the cvs documentation for more details.
http://rsync.samba.org/download.html
COPYRIGHT
---------
rsync was originally written by Andrew Tridgell and has been improved
by many developers around the world. rsync may be used, modified and
redistributed only under the terms of the GNU General Public License,
found in the file COPYING in this distribution, or at
Rsync was originally written by Andrew Tridgell and is currently
maintained by Wayne Davison. It has been improved by many developers
from around the world.
http://www.fsf.org/licenses/gpl.html
Rsync may be used, modified and redistributed only under the terms of
the GNU General Public License, found in the file COPYING in this
distribution, or at:
http://www.fsf.org/licenses/gpl.html
AVAILABILITY

View File

@@ -180,10 +180,19 @@ int make_bak_dir(const char *fullpath)
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(const char *src, char *dst)
{
if (robust_rename(src, dst, NULL, 0755) < 0
&& (errno != ENOENT || make_bak_dir(dst) < 0
|| robust_rename(src, dst, NULL, 0755) < 0))
return -1;
if (robust_rename(src, dst, NULL, 0755) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(dst) == 0) {
if (robust_rename(src, dst, NULL, 0755) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
errno = save_errno;
return -1;
}
}
return 0;
}
@@ -195,6 +204,7 @@ static int keep_backup(const char *fname)
stat_x sx;
struct file_struct *file;
char *buf;
int save_preserve_xattrs = preserve_xattrs;
int kept = 0;
int ret_code;
@@ -234,15 +244,23 @@ static int keep_backup(const char *fname)
/* Check to see if this is a device file, or link */
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
uint32 *devp = F_RDEV_P(file);
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
int save_errno;
do_unlink(buf);
if (do_mknod(buf, file->mode, rdev) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mknod(buf, file->mode, rdev) < 0)) {
rsyserr(FERROR, errno, "mknod %s failed",
full_fname(buf));
} else if (verbose > 2) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0) {
save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "mknod %s failed",
full_fname(buf));
}
} else
save_errno = 0;
if (verbose > 2 && save_errno == 0) {
rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
fname);
}
@@ -252,11 +270,18 @@ static int keep_backup(const char *fname)
if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */
if (do_mkdir(buf, file->mode) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mkdir(buf, file->mode) < 0)) {
rsyserr(FINFO, errno, "mkdir %s failed",
full_fname(buf));
if (do_mkdir(buf, file->mode) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_mkdir(buf, file->mode) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FINFO, save_errno, "mkdir %s failed",
full_fname(buf));
}
}
ret_code = do_rmdir(fname);
@@ -278,11 +303,18 @@ static int keep_backup(const char *fname)
kept = 1;
} else {
do_unlink(buf);
if (do_symlink(sl, buf) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_symlink(sl, buf) < 0)) {
rsyserr(FERROR, errno, "link %s -> \"%s\"",
full_fname(buf), sl);
if (do_symlink(sl, buf) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_symlink(sl, buf) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
full_fname(buf), sl);
}
}
do_unlink(fname);
kept = 1;
@@ -308,7 +340,9 @@ static int keep_backup(const char *fname)
robust_unlink(fname); /* Just in case... */
}
}
preserve_xattrs = 0;
set_file_attrs(buf, file, NULL, fname, 0);
preserve_xattrs = save_preserve_xattrs;
unmake_file(file);
if (verbose > 1) {

View File

@@ -121,8 +121,6 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
if (fd == -1)
exit_cleanup(RERR_SOCKETIO);
set_socket_options(fd, sockopts);
#ifdef ICONV_CONST
setup_iconv();
#endif
@@ -931,10 +929,6 @@ int start_daemon(int f_in, int f_out)
if (!am_server) {
set_socket_options(f_in, "SO_KEEPALIVE");
if (sockopts)
set_socket_options(f_in, sockopts);
else
set_socket_options(f_in, lp_socket_options());
set_nonblocking(f_in);
}

View File

@@ -57,12 +57,14 @@ extern struct filter_list_struct filter_list;
extern int need_unsorted_flist;
#ifdef ICONV_OPTION
extern iconv_t ic_send, ic_recv;
extern char *iconv_opt;
#endif
/* These index values are for the file-list's extra-attribute array. */
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
int sender_symlink_iconv = 0; /* sender should convert symlink content */
#ifdef ICONV_OPTION
int filesfrom_convert = 0;
@@ -70,6 +72,7 @@ int filesfrom_convert = 0;
#define CF_INC_RECURSE (1<<0)
#define CF_SYMLINK_TIMES (1<<1)
#define CF_SYMLINK_ICONV (1<<2)
static const char *client_info;
@@ -248,6 +251,9 @@ void setup_protocol(int f_out,int f_in)
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
#ifdef ICONV_OPTION
compat_flags |= CF_SYMLINK_ICONV;
#endif
write_byte(f_out, compat_flags);
} else
@@ -262,6 +268,11 @@ void setup_protocol(int f_out,int f_in)
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
else
receiver_symlink_times = 1;
#endif
#ifdef ICONV_OPTION
sender_symlink_iconv = iconv_opt && (am_server
? strchr(client_info, 's') != NULL
: !!(compat_flags & CF_SYMLINK_ICONV));
#endif
if (inc_recurse && !allow_inc_recurse) {
/* This should only be able to happen in a batch. */

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=3.0.1
RSYNC_VERSION=3.0.4
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])

View File

@@ -476,7 +476,7 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
XFLG_ANCHORED2ABS);
} else {
io_error |= IOERR_GENERAL;
rprintf(FINFO,
rprintf(FERROR,
"cannot add local filter rules in long-named directory: %s\n",
full_fname(dirbuf));
}

200
flist.c
View File

@@ -67,6 +67,7 @@ extern int protocol_version;
extern int sanitize_paths;
extern int munge_symlinks;
extern int need_unsorted_flist;
extern int sender_symlink_iconv;
extern int unsort_ndx;
extern struct stats stats;
extern char *filesfrom_host;
@@ -375,7 +376,7 @@ int change_pathname(struct file_struct *file, const char *dir, int dirlen)
if (!change_dir(dir, CD_NORMAL)) {
chdir_error:
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "change_dir %s failed", full_fname(dir));
rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
if (dir != orig_dir)
change_dir(orig_dir, CD_NORMAL);
pathname = NULL;
@@ -386,7 +387,11 @@ int change_pathname(struct file_struct *file, const char *dir, int dirlen)
return 1;
}
static void send_file_entry(int f, const char *fname, struct file_struct *file, int ndx, int first_ndx)
static void send_file_entry(int f, const char *fname, struct file_struct *file,
#ifdef SUPPORT_LINKS
const char *symlink_name, int symlink_len,
#endif
int ndx, int first_ndx)
{
static time_t modtime;
static mode_t mode;
@@ -575,11 +580,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
}
#ifdef SUPPORT_LINKS
if (preserve_links && S_ISLNK(mode)) {
const char *sl = F_SYMLINK(file);
int len = strlen(sl);
write_varint30(f, len);
write_buf(f, sl, len);
if (symlink_len) {
write_varint30(f, symlink_len);
write_buf(f, symlink_name, symlink_len);
}
#endif
@@ -638,7 +641,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
int alloc_len, basename_len, linkname_len;
int extra_len = file_extra_cnt * EXTRA_LEN;
int first_hlink_ndx = -1;
OFF_T file_length;
int64 file_length;
const char *basename;
struct file_struct *file;
alloc_pool_t *pool;
@@ -675,12 +678,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
io_error |= IOERR_GENERAL;
rprintf(FINFO,
rprintf(FERROR_UTF8,
"[%s] cannot convert filename: %s (%s)\n",
who_am_i(), lastname, strerror(errno));
outbuf.len = 0;
}
outbuf.buf[outbuf.len] = '\0';
thisname[outbuf.len] = '\0';
}
#endif
@@ -811,6 +814,13 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
linkname_len - 1);
overflow_exit("recv_file_entry");
}
#ifdef ICONV_OPTION
/* We don't know how much extra room we need to convert
* the as-yet-unread symlink data, so let's hope that a
* double-size buffer is plenty. */
if (sender_symlink_iconv)
linkname_len *= 2;
#endif
if (munge_symlinks)
linkname_len += SYMLINK_PREFIX_LEN;
}
@@ -837,8 +847,14 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (always_checksum && S_ISREG(mode))
extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
#if SIZEOF_INT64 >= 8
if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
extra_len += EXTRA_LEN;
#endif
if (file_length < 0) {
rprintf(FERROR, "Offset underflow: file-length is negative\n");
exit_cleanup(RERR_UNSUPPORTED);
}
if (inc_recurse && S_ISDIR(mode)) {
if (one_file_system) {
@@ -871,10 +887,17 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
#endif
file->modtime = (time_t)modtime;
file->len32 = (uint32)file_length;
#if SIZEOF_INT64 >= 8
if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) {
#if SIZEOF_CAPITAL_OFF_T < 8
rprintf(FERROR, "Offset overflow: attempted 64-bit file-length\n");
exit_cleanup(RERR_UNSUPPORTED);
#else
file->flags |= FLAG_LENGTH64;
OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
#endif
}
#endif
file->mode = mode;
if (preserve_uid)
F_OWNER(file) = uid;
@@ -932,14 +955,40 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (first_hlink_ndx >= flist->ndx_start) {
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
memcpy(bp, F_SYMLINK(first), linkname_len);
} else if (munge_symlinks) {
strlcpy(bp, SYMLINK_PREFIX, linkname_len);
bp += SYMLINK_PREFIX_LEN;
linkname_len -= SYMLINK_PREFIX_LEN;
read_sbuf(f, bp, linkname_len - 1);
} else {
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths)
if (munge_symlinks) {
strlcpy(bp, SYMLINK_PREFIX, linkname_len);
bp += SYMLINK_PREFIX_LEN;
linkname_len -= SYMLINK_PREFIX_LEN;
}
#ifdef ICONV_OPTION
if (sender_symlink_iconv) {
xbuf outbuf, inbuf;
alloc_len = linkname_len;
linkname_len /= 2;
/* Read the symlink data into the end of our double-sized
* buffer and then convert it into the right spot. */
INIT_XBUF(inbuf, bp + alloc_len - linkname_len,
linkname_len - 1, (size_t)-1);
read_sbuf(f, inbuf.buf, inbuf.len);
INIT_XBUF(outbuf, bp, 0, alloc_len);
if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
io_error |= IOERR_GENERAL;
rprintf(FERROR_XFER,
"[%s] cannot convert symlink data for: %s (%s)\n",
who_am_i(), full_fname(thisname), strerror(errno));
bp = (char*)file->basename;
*bp++ = '\0';
outbuf.len = 0;
}
bp[outbuf.len] = '\0';
} else
#endif
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths && !munge_symlinks && *bp)
sanitize_path(bp, bp, "", lastdir_depth, SP_DEFAULT);
}
}
@@ -1009,7 +1058,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
* and performing extensive checks against global options.
*
* Returns a pointer to the new file struct, or NULL if there was an error
* or this file should be excluded. */
* or this file should be excluded.
*
* Note: Any error (here or in send_file_name) that results in the omission of
* an existent source file from the file list should set
* "io_error |= IOERR_GENERAL" to avoid deletion of the file from the
* destination if --delete is on. */
struct file_struct *make_file(const char *fname, struct file_list *flist,
STRUCT_STAT *stp, int flags, int filter_level)
{
@@ -1023,11 +1077,11 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
const char *basename;
alloc_pool_t *pool;
STRUCT_STAT st;
int excl_ret;
char *bp;
if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
rprintf(FINFO, "skipping overly long name: %s\n", fname);
io_error |= IOERR_GENERAL;
rprintf(FERROR_XFER, "skipping overly long name: %s\n", fname);
return NULL;
}
clean_fname(thisname, 0);
@@ -1072,13 +1126,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
}
} else {
io_error |= IOERR_GENERAL;
rsyserr(FERROR_XFER, save_errno, "readlink %s failed",
rsyserr(FERROR_XFER, save_errno, "readlink_stat(%s) failed",
full_fname(thisname));
}
return NULL;
}
/* backup.c calls us with filter_level set to NO_FILTERS. */
if (filter_level == NO_FILTERS)
goto skip_filters;
@@ -1106,17 +1159,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
} else
flags &= ~FLAG_CONTENT_DIR;
if (S_ISDIR(st.st_mode)) {
if (flags & FLAG_DOTDIR_NAME) {
/* A "." fname (or "/." fname in relative mode) is
* never excluded. No other trailing-dotdir names
* are possible. */
excl_ret = 0;
} else
excl_ret = is_excluded(thisname, 1, filter_level);
} else
excl_ret = is_excluded(thisname, 0, filter_level);
if (excl_ret) {
if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
if (ignore_perishable)
non_perishable_cnt++;
return NULL;
@@ -1175,8 +1218,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
linkname_len = 0;
#endif
#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode))
extra_len += EXTRA_LEN;
#endif
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
@@ -1204,8 +1249,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
if (protocol_version >= 28
? (!S_ISDIR(st.st_mode) && st.st_nlink > 1)
: S_ISREG(st.st_mode)) {
tmp_dev = st.st_dev;
tmp_ino = st.st_ino;
tmp_dev = (int64)st.st_dev + 1;
tmp_ino = (int64)st.st_ino;
} else
tmp_dev = 0;
}
@@ -1221,10 +1266,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
file->flags = flags;
file->modtime = st.st_mtime;
file->len32 = (uint32)st.st_size;
#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) {
file->flags |= FLAG_LENGTH64;
OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
}
#endif
file->mode = st.st_mode;
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
F_OWNER(file) = st.st_uid;
@@ -1299,10 +1346,27 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
if (f >= 0) {
char fbuf[MAXPATHLEN];
#ifdef SUPPORT_LINKS
const char *symlink_name;
int symlink_len;
#ifdef ICONV_OPTION
char symlink_buf[MAXPATHLEN];
#endif
#endif
#if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
stat_x sx;
#endif
#ifdef SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
symlink_name = F_SYMLINK(file);
symlink_len = strlen(symlink_name);
} else {
symlink_name = NULL;
symlink_len = 0;
}
#endif
#ifdef ICONV_OPTION
if (ic_send != (iconv_t)-1) {
xbuf outbuf, inbuf;
@@ -1315,19 +1379,38 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
goto convert_error;
outbuf.size += 2;
outbuf.buf[outbuf.len++] = '/';
fbuf[outbuf.len++] = '/';
}
INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
convert_error:
io_error |= IOERR_GENERAL;
rprintf(FINFO,
rprintf(FERROR_XFER,
"[%s] cannot convert filename: %s (%s)\n",
who_am_i(), f_name(file, fbuf), strerror(errno));
return NULL;
}
outbuf.buf[outbuf.len] = '\0';
fbuf[outbuf.len] = '\0';
#ifdef SUPPORT_LINKS
if (symlink_len && sender_symlink_iconv) {
INIT_XBUF(inbuf, (char*)symlink_name, symlink_len, (size_t)-1);
INIT_CONST_XBUF(outbuf, symlink_buf);
if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
io_error |= IOERR_GENERAL;
f_name(file, fbuf);
rprintf(FERROR_XFER,
"[%s] cannot convert symlink data for: %s (%s)\n",
who_am_i(), full_fname(fbuf), strerror(errno));
return NULL;
}
symlink_buf[outbuf.len] = '\0';
symlink_name = symlink_buf;
symlink_len = outbuf.len;
}
#endif
} else
#endif
f_name(file, fbuf);
@@ -1336,19 +1419,27 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
if (preserve_acls && !S_ISLNK(file->mode)) {
sx.st.st_mode = file->mode;
sx.acc_acl = sx.def_acl = NULL;
if (get_acl(fname, &sx) < 0)
if (get_acl(fname, &sx) < 0) {
io_error |= IOERR_GENERAL;
return NULL;
}
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
sx.xattr = NULL;
if (get_xattr(fname, &sx) < 0)
if (get_xattr(fname, &sx) < 0) {
io_error |= IOERR_GENERAL;
return NULL;
}
}
#endif
send_file_entry(f, fbuf, file, flist->used, flist->ndx_start);
send_file_entry(f, fbuf, file,
#ifdef SUPPORT_LINKS
symlink_name, symlink_len,
#endif
flist->used, flist->ndx_start);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
@@ -1543,14 +1634,14 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
continue;
if (strlcpy(p, dname, remainder) >= remainder) {
io_error |= IOERR_GENERAL;
rprintf(FINFO,
rprintf(FERROR_XFER,
"cannot send long-named file %s\n",
full_fname(fbuf));
continue;
}
if (dname[0] == '\0') {
io_error |= IOERR_GENERAL;
rprintf(FINFO,
rprintf(FERROR_XFER,
"cannot send file with empty name in %s\n",
full_fname(fbuf));
continue;
@@ -1853,7 +1944,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
int64 start_write;
int use_ff_fd = 0;
int disable_buffering;
int arg_flags, flags = recurse ? FLAG_CONTENT_DIR : 0;
int flags = recurse ? FLAG_CONTENT_DIR : 0;
int reading_remotely = filesfrom_host != NULL;
int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS)
#ifdef ICONV_OPTION
@@ -2035,6 +2126,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
continue;
}
/* A dot-dir should not be excluded! */
if (name_type != DOTDIR_NAME
&& is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS))
continue;
if (S_ISDIR(st.st_mode) && !xfer_dirs) {
rprintf(FINFO, "skipping directory %s\n", fbuf);
continue;
@@ -2060,13 +2156,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (one_file_system)
filesystem_dev = st.st_dev;
arg_flags = name_type == DOTDIR_NAME ? FLAG_DOTDIR_NAME : 0;
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
struct file_struct *file;
arg_flags |= FLAG_TOP_DIR | FLAG_CONTENT_DIR;
file = send_file_name(f, flist, fbuf, &st,
arg_flags | flags, ALL_FILTERS);
FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
NO_FILTERS);
if (!file)
continue;
if (inc_recurse) {
@@ -2080,7 +2174,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
} else
send_if_directory(f, flist, file, fbuf, len, flags);
} else
send_file_name(f, flist, fbuf, &st, arg_flags | flags, ALL_FILTERS);
send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
}
gettimeofday(&end_tv, NULL);
@@ -2146,7 +2240,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (inc_recurse) {
send_dir_depth = 1;
add_dirs_to_tree(-1, flist, dir_count);
if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
if (!file_total || strcmp(flist->sorted[flist->low]->basename, ".") != 0)
flist->parent_ndx = -1;
flist_done_allocating(flist);
if (send_dir_ndx < 0) {
@@ -2214,8 +2308,8 @@ struct file_list *recv_file_list(int f)
maybe_emit_filelist_progress(flist->used);
if (verbose > 2) {
rprintf(FINFO, "recv_file_name(%s)\n",
f_name(file, NULL));
char *name = f_name(file, NULL);
rprintf(FINFO, "recv_file_name(%s)\n", NS(name));
}
}
file_total += flist->used;
@@ -2270,7 +2364,7 @@ struct file_list *recv_file_list(int f)
else
io_error |= read_int(f);
} else if (inc_recurse && flist->ndx_start == 1) {
if (!file_total || strcmp(flist->sorted[0]->basename, ".") != 0)
if (!file_total || strcmp(flist->sorted[flist->low]->basename, ".") != 0)
flist->parent_ndx = -1;
}

View File

@@ -108,7 +108,7 @@ static int deletion_count = 0; /* used to implement --max-delete */
static int deldelay_size = 0, deldelay_cnt = 0;
static char *deldelay_buf = NULL;
static int deldelay_fd = -1;
static int lull_mod;
static int loopchk_limit;
static int dir_tweaking;
static int symlink_timeset_failed_flags;
static int need_retouch_dir_times;
@@ -697,8 +697,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
if (iflags & ITEM_XNAME_FOLLOWS)
write_vstring(sock_f_out, xname, strlen(xname));
#ifdef SUPPORT_XATTRS
if (iflags & ITEM_REPORT_XATTR && !dry_run)
send_xattr_request(NULL, file, sock_f_out);
if (preserve_xattrs && !dry_run
&& iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {
send_xattr_request(NULL, file,
iflags & ITEM_REPORT_XATTR ? sock_f_out : -1);
}
#endif
} else if (ndx >= 0) {
enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;
@@ -753,18 +756,19 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
{
int32 blength;
int s2length;
int64 l;
if (block_size)
blength = block_size;
else if (len <= BLOCK_SIZE * BLOCK_SIZE)
blength = BLOCK_SIZE;
else {
int32 max_blength = protocol_version < 30 ? OLD_MAX_BLOCK_SIZE : MAX_BLOCK_SIZE;
int32 c;
int64 l;
int cnt;
for (c = 1, l = len, cnt = 0; l >>= 2; c <<= 1, cnt++) {}
if (cnt >= 31 || c >= MAX_BLOCK_SIZE)
blength = MAX_BLOCK_SIZE;
if (c < 0 || c >= max_blength)
blength = max_blength;
else {
blength = 0;
do {
@@ -783,7 +787,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
s2length = SUM_LENGTH;
} else {
int32 c;
int64 l;
int b = BLOCKSUM_BIAS;
for (l = len; l >>= 1; b += 2) {}
for (c = blength; (c >>= 1) && b; b--) {}
@@ -797,7 +800,10 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
sum->blength = blength;
sum->s2length = s2length;
sum->remainder = (int32)(len % blength);
sum->count = (int32)(len / blength) + (sum->remainder != 0);
sum->count = (int32)(l = (len / blength) + (sum->remainder != 0));
if ((int64)sum->count != l)
sum->count = -1;
if (sum->count && verbose > 2) {
rprintf(FINFO,
@@ -813,7 +819,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
*
* Generate approximately one checksum every block_len bytes.
*/
static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
static int generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
{
int32 i;
struct map_struct *mapbuf;
@@ -821,10 +827,12 @@ static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
OFF_T offset = 0;
sum_sizes_sqroot(&sum, len);
if (sum.count < 0)
return -1;
write_sum_head(f_out, &sum);
if (append_mode > 0 && f_copy < 0)
return;
return 0;
if (len > 0)
mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength);
@@ -861,6 +869,8 @@ static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
if (mapbuf)
unmap_file(mapbuf);
return 0;
}
@@ -922,6 +932,7 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru
{
char buf[MAXPATHLEN];
const char *copy_to, *partialptr;
int save_preserve_xattrs = preserve_xattrs;
int ok, fd_w;
if (inplace) {
@@ -946,7 +957,9 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru
return -1;
}
partialptr = partial_dir ? partial_dir_fname(dest) : NULL;
preserve_xattrs = 0; /* xattrs were copied with file */
ok = finish_transfer(dest, copy_to, src, partialptr, file, 1, 0);
preserve_xattrs = save_preserve_xattrs;
cleanup_disable();
return ok ? 0 : -1;
}
@@ -1284,7 +1297,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
skip_dir = NULL;
}
if (daemon_filter_list.head) {
if (daemon_filter_list.head && (*fname != '.' || fname[1])) {
if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {
if (is_dir < 0)
return;
@@ -1432,6 +1445,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (j == -2) {
itemizing = 0;
code = FNONE;
statret = 1;
} else if (j >= 0)
statret = 1;
}
@@ -1454,6 +1468,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
goto cleanup;
}
}
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && statret == 1)
copy_xattrs(fnamecmpbuf, fname);
#endif
if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
&& verbose && code != FNONE && f_out != -1)
rprintf(code, "%s/\n", fname);
@@ -1868,15 +1886,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
close(fd);
goto cleanup;
}
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0
&& (errno != ENOENT || make_bak_dir(backupptr) < 0
|| (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) {
rsyserr(FERROR_XFER, errno, "open %s",
full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
close(fd);
goto cleanup;
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(backupptr) == 0) {
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
close(fd);
goto cleanup;
}
}
fnamecmp_type = FNAMECMP_BACKUP;
}
@@ -1931,16 +1955,32 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (statret != 0 || whole_file)
write_sum_head(f_out, NULL);
else {
generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy);
else if (sx.st.st_size <= 0) {
write_sum_head(f_out, NULL);
close(fd);
} else {
if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) {
rprintf(FWARNING,
"WARNING: file is too large for checksum sending: %s\n",
fnamecmp);
write_sum_head(f_out, NULL);
}
close(fd);
}
cleanup:
if (back_file) {
int save_preserve_xattrs = preserve_xattrs;
if (f_copy >= 0)
close(f_copy);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
copy_xattrs(fname, backupptr);
preserve_xattrs = 0;
}
#endif
set_file_attrs(backupptr, back_file, NULL, NULL, 0);
preserve_xattrs = save_preserve_xattrs;
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
fname, backupptr);
@@ -2018,10 +2058,13 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
&& cmp_time(st.st_mtime, file->modtime) != 0)
set_modtime(fname, file->modtime, file->mode);
}
if (allowed_lull && !(counter % lull_mod))
maybe_send_keepalive();
else if (!(counter & 0xFF))
maybe_flush_socket(0);
if (counter >= loopchk_limit) {
if (allowed_lull)
maybe_send_keepalive();
else
maybe_flush_socket(0);
counter = 0;
}
}
}
@@ -2035,8 +2078,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
while (1) {
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
flist = flist_for_ndx(ndx);
assert(flist != NULL);
flist = flist_for_ndx(ndx, "check_for_finished_files.1");
file = flist->files[ndx - flist->ndx_start];
assert(file->flags & FLAG_HLINKED);
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
@@ -2059,7 +2101,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
ignore_times++;
flist = cur_flist;
cur_flist = flist_for_ndx(ndx);
cur_flist = flist_for_ndx(ndx, "check_for_finished_files.2");
file = cur_flist->files[ndx - cur_flist->ndx_start];
if (solo_file)
@@ -2108,7 +2150,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
void generate_files(int f_out, const char *local_name)
{
int i, ndx;
int i, ndx, next_loopchk = 0;
char fbuf[MAXPATHLEN];
int itemizing;
enum logcode code;
@@ -2134,7 +2176,7 @@ void generate_files(int f_out, const char *local_name)
solo_file = local_name;
dir_tweaking = !(list_only || solo_file || dry_run);
need_retouch_dir_times = preserve_times > 1;
lull_mod = allowed_lull * 5;
loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
symlink_timeset_failed_flags = ITEM_REPORT_TIME
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;
@@ -2179,7 +2221,10 @@ void generate_files(int f_out, const char *local_name)
if (inc_recurse && cur_flist->parent_ndx >= 0) {
struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx];
f_name(fp, fbuf);
if (solo_file)
strlcpy(fbuf, solo_file, sizeof fbuf);
else
f_name(fp, fbuf);
ndx = cur_flist->ndx_start - 1;
recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
if (delete_during && dry_run < 2 && !list_only
@@ -2215,10 +2260,13 @@ void generate_files(int f_out, const char *local_name)
check_for_finished_files(itemizing, code, 0);
if (allowed_lull && !(i % lull_mod))
maybe_send_keepalive();
else if (!(i & 0xFF))
maybe_flush_socket(0);
if (i + cur_flist->ndx_start >= next_loopchk) {
if (allowed_lull)
maybe_send_keepalive();
else
maybe_flush_socket(0);
next_loopchk += loopchk_limit;
}
}
if (!inc_recurse) {
@@ -2286,7 +2334,7 @@ void generate_files(int f_out, const char *local_name)
touch_up_dirs(dir_flist, -1);
if (max_delete >= 0 && deletion_count > max_delete) {
rprintf(FINFO,
rprintf(FWARNING,
"Deletions stopped due to --max-delete limit (%d skipped)\n",
deletion_count - max_delete);
io_error |= IOERR_DEL_LIMIT;

View File

@@ -104,7 +104,9 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
a = b = c = 0xdeadbeef + (8 << 2);
#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
#if SIZEOF_INT64 >= 8
b += (uint32)(key >> 32);
#endif
a += (uint32)key;
c ^= b; c -= rot(b, 14);
a ^= c; a -= rot(c, 11);

20
hlink.c
View File

@@ -119,14 +119,15 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
if (inc_recurse) {
node = hashtable_find(prior_hlinks, gnum, 1);
if (!node->data) {
node->data = new_array0(char, 5);
if (!(node->data = new_array0(char, 5)))
out_of_memory("match_gnums");
assert(gnum >= hlink_flist->ndx_start);
file->flags |= FLAG_HLINK_FIRST;
prev = -1;
} else if (CVAL(node->data, 0) == 0) {
struct file_list *flist;
prev = IVAL(node->data, 1);
flist = flist_for_ndx(prev);
flist = flist_for_ndx(prev, NULL);
if (flist)
flist->files[prev - flist->ndx_start]->flags &= ~FLAG_HLINK_LAST;
else {
@@ -179,7 +180,7 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
if (!list_only) {
if (!list_only && flist->used) {
int i, ndx_count = 0;
int32 *ndx_list;
@@ -255,7 +256,7 @@ static char *check_prior(struct file_struct *file, int gnum,
while (1) {
struct file_list *flist;
if (prev_ndx < 0
|| (flist = flist_for_ndx(prev_ndx)) == NULL)
|| (flist = flist_for_ndx(prev_ndx, NULL)) == NULL)
break;
fp = flist->files[prev_ndx - flist->ndx_start];
if (!(fp->flags & FLAG_SKIP_HLINK)) {
@@ -266,7 +267,8 @@ static char *check_prior(struct file_struct *file, int gnum,
F_HL_PREV(file) = prev_ndx = F_HL_PREV(fp);
}
if ((node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
if (inc_recurse
&& (node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
assert(node->data != NULL);
if (CVAL(node->data, 0) != 0) {
*prev_ndx_p = -1;
@@ -446,7 +448,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
{
stat_x prev_sx;
STRUCT_STAT st;
char alt_name[MAXPATHLEN], *prev_name;
char prev_name[MAXPATHLEN], alt_name[MAXPATHLEN];
const char *our_name;
struct file_list *flist;
int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
@@ -476,14 +478,12 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
while ((ndx = prev_ndx) >= 0) {
int val;
flist = flist_for_ndx(ndx);
assert(flist != NULL);
flist = flist_for_ndx(ndx, "finish_hard_link");
file = flist->files[ndx - flist->ndx_start];
file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE;
prev_ndx = F_HL_PREV(file);
F_HL_PREV(file) = fin_ndx;
prev_name = f_name(file, NULL);
prev_statret = link_stat(prev_name, &prev_sx.st, 0);
prev_statret = link_stat(f_name(file, prev_name), &prev_sx.st, 0);
val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx,
our_name, stp, fname, itemizing, code);
flist->in_progress--;

96
io.c
View File

@@ -101,7 +101,7 @@ static char ff_lastchar;
#ifdef ICONV_OPTION
static xbuf iconv_buf = EMPTY_XBUF;
#endif
static int defer_forwarding_messages = 0, defer_forwarding_keep = 0;
static int defer_forwarding_messages = 0, keep_defer_forwarding = 0;
static int select_timeout = SELECT_TIMEOUT;
static int active_filecnt = 0;
static OFF_T active_bytecnt = 0;
@@ -183,9 +183,7 @@ static int flist_ndx_pop(struct flist_ndx_list *lp)
static void got_flist_entry_status(enum festatus status, const char *buf)
{
int ndx = IVAL(buf, 0);
struct file_list *flist = flist_for_ndx(ndx);
assert(flist != NULL);
struct file_list *flist = flist_for_ndx(ndx, "got_flist_entry_status");
if (remove_source_files) {
active_filecnt--;
@@ -296,33 +294,32 @@ static void msg_list_add(struct msg_list *lst, int code, const char *buf, int le
lst->tail = m;
}
static inline int flush_a_msg(int fd)
{
struct msg_list_item *m = msg_queue.head;
int len = IVAL(m->buf, 0) & 0xFFFFFF;
int tag = *((uchar*)m->buf+3) - MPLEX_BASE;
if (!(msg_queue.head = m->next))
msg_queue.tail = NULL;
defer_forwarding_messages++;
mplex_write(fd, tag, m->buf + 4, len, m->convert);
defer_forwarding_messages--;
free(m);
return len;
}
static void msg_flush(void)
{
if (am_generator) {
while (msg_queue.head && io_multiplexing_out) {
struct msg_list_item *m = msg_queue.head;
int len = IVAL(m->buf, 0) & 0xFFFFFF;
int tag = *((uchar*)m->buf+3) - MPLEX_BASE;
if (!(msg_queue.head = m->next))
msg_queue.tail = NULL;
stats.total_written += len + 4;
defer_forwarding_messages++;
mplex_write(sock_f_out, tag, m->buf + 4, len, m->convert);
defer_forwarding_messages--;
free(m);
}
while (msg_queue.head && io_multiplexing_out)
stats.total_written += flush_a_msg(sock_f_out) + 4;
} else {
while (msg_queue.head) {
struct msg_list_item *m = msg_queue.head;
int len = IVAL(m->buf, 0) & 0xFFFFFF;
int tag = *((uchar*)m->buf+3) - MPLEX_BASE;
if (!(msg_queue.head = m->next))
msg_queue.tail = NULL;
defer_forwarding_messages++;
mplex_write(msg_fd_out, tag, m->buf + 4, len, m->convert);
defer_forwarding_messages--;
free(m);
}
while (msg_queue.head)
(void)flush_a_msg(msg_fd_out);
}
}
@@ -449,6 +446,7 @@ static void read_msg_fd(void)
got_flist_entry_status(FES_NO_SEND, buf);
break;
case MSG_ERROR_SOCKET:
case MSG_ERROR_UTF8:
case MSG_CLIENT:
if (!am_generator)
goto invalid_msg;
@@ -531,9 +529,9 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len,
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
defer_forwarding_keep = 1; /* defer_forwarding_messages++ on return */
keep_defer_forwarding++; /* defer_forwarding_messages++ on return */
writefd_unbuffered(fd, buffer, n+4);
defer_forwarding_keep = 0;
keep_defer_forwarding--;
if (len > n)
writefd_unbuffered(fd, buf+n, len-n);
@@ -568,10 +566,9 @@ void send_msg_int(enum msgcode code, int num)
void wait_for_receiver(void)
{
if (iobuf_out_cnt)
io_flush(NORMAL_FLUSH);
else
read_msg_fd();
if (io_flush(NORMAL_FLUSH))
return;
read_msg_fd();
}
int get_redo_num(void)
@@ -1354,6 +1351,7 @@ int read_vstring(int f, char *buf, int bufsize)
* called by both the sender and the receiver. */
void read_sum_head(int f, struct sum_struct *sum)
{
int32 max_blength = protocol_version < 30 ? OLD_MAX_BLOCK_SIZE : MAX_BLOCK_SIZE;
sum->count = read_int(f);
if (sum->count < 0) {
rprintf(FERROR, "Invalid checksum count %ld [%s]\n",
@@ -1361,7 +1359,7 @@ void read_sum_head(int f, struct sum_struct *sum)
exit_cleanup(RERR_PROTOCOL);
}
sum->blength = read_int(f);
if (sum->blength < 0 || sum->blength > MAX_BLOCK_SIZE) {
if (sum->blength < 0 || sum->blength > max_blength) {
rprintf(FERROR, "Invalid block length %ld [%s]\n",
(long)sum->blength, who_am_i());
exit_cleanup(RERR_PROTOCOL);
@@ -1554,24 +1552,34 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len)
}
no_flush--;
defer_inc -= defer_forwarding_keep;
if (keep_defer_forwarding)
defer_inc--;
if (!(defer_forwarding_messages -= defer_inc) && !no_flush)
msg_flush();
}
void io_flush(int flush_it_all)
int io_flush(int flush_it_all)
{
if (!iobuf_out_cnt || no_flush)
return;
int flushed_something = 0;
if (io_multiplexing_out)
mplex_write(sock_f_out, MSG_DATA, iobuf_out, iobuf_out_cnt, 0);
else
writefd_unbuffered(iobuf_f_out, iobuf_out, iobuf_out_cnt);
iobuf_out_cnt = 0;
if (no_flush)
return 0;
if (flush_it_all && !defer_forwarding_messages)
if (iobuf_out_cnt) {
if (io_multiplexing_out)
mplex_write(sock_f_out, MSG_DATA, iobuf_out, iobuf_out_cnt, 0);
else
writefd_unbuffered(iobuf_f_out, iobuf_out, iobuf_out_cnt);
iobuf_out_cnt = 0;
flushed_something = 1;
}
if (flush_it_all && !defer_forwarding_messages && msg_queue.head) {
msg_flush();
flushed_something = 1;
}
return flushed_something;
}
static void writefd(int fd, const char *buf, size_t len)

View File

@@ -551,7 +551,7 @@ SMB_ACL_T sys_acl_init(int count)
* acl[] array, this actually allocates an ACL with room
* for (count+1) entries
*/
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof (struct acl))) == NULL) {
errno = ENOMEM;
return NULL;
}
@@ -1007,7 +1007,7 @@ SMB_ACL_T sys_acl_init(int count)
* acl[] array, this actually allocates an ACL with room
* for (count+1) entries
*/
if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + count * sizeof(struct acl))) == NULL) {
errno = ENOMEM;
return NULL;
}
@@ -1638,14 +1638,14 @@ SMB_ACL_T sys_acl_init(int count)
return NULL;
}
if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof a[0] + sizeof (struct acl))) == NULL) {
errno = ENOMEM;
return NULL;
}
a->next = -1;
a->freeaclp = False;
a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
a->aclp = (struct acl *)((char *)a + sizeof a[0]);
a->aclp->acl_cnt = 0;
return a;

16
log.c
View File

@@ -37,6 +37,7 @@ extern int protocol_version;
extern int preserve_times;
extern int uid_ndx;
extern int gid_ndx;
extern int progress_is_active;
extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
@@ -84,7 +85,7 @@ struct {
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
{ RERR_WAITCHILD , "waitpid() failed" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files could not be transferred" },
{ RERR_PARTIAL , "some files/attrs were not transferred (see previous errors)" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
{ RERR_TIMEOUT , "timeout in data send/receive" },
{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
@@ -256,13 +257,17 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
if (am_server && msg_fd_out >= 0) {
assert(!is_utf8);
/* Pass the message to our sibling. */
/* Pass the message to our sibling in native charset. */
send_msg((enum msgcode)code, buf, len, 0);
return;
}
if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */
code = FERROR;
else if (code == FERROR_UTF8) {
is_utf8 = 1;
code = FERROR;
}
if (code == FCLIENT)
code = FINFO;
@@ -320,6 +325,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
exit_cleanup(RERR_MESSAGEIO);
}
if (progress_is_active && !am_server) {
fputc('\n', f);
progress_is_active = 0;
}
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;
@@ -517,7 +527,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
break;
case 'M':
n = c = timestring(file->modtime);
while ((c = strchr(p, ' ')) != NULL)
while ((c = strchr(c, ' ')) != NULL)
*c = '-';
break;
case 'B':

21
main.c
View File

@@ -507,12 +507,21 @@ 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);
if (daemon_filter_list.head) {
char *slash = strrchr(dest_path, '/');
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
*slash = '\0';
else
slash = NULL;
if ((*dest_path != '.' || dest_path[1] != '\0')
&& (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
dest_path);
exit_cleanup(RERR_FILESELECT);
}
if (slash)
*slash = '/';
}
/* See what currently exists at the destination. */

View File

@@ -1808,22 +1808,36 @@ 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 (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"%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';
/* Checking the pre-negotiated value allows --protocol=29 override. */
if (protocol_version >= 30) {
/* 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 (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"%d.%d",
PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
} else
#endif
argstr[x++] = '.';
if (allow_inc_recurse)
argstr[x++] = 'i';
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
argstr[x++] = 'L';
#endif
#ifdef ICONV_OPTION
argstr[x++] = 's';
#endif
}
if (x >= (int)sizeof argstr) { /* Not possible... */
rprintf(FERROR, "argstr overflow in server_options().\n");
exit_cleanup(RERR_MALLOC);
}
argstr[x] = '\0';
args[ac++] = argstr;
@@ -2008,7 +2022,6 @@ void server_options(char **args, int *argc_p)
* and it may be an older version that doesn't know this
* option, so don't send it if client is the sender.
*/
int i;
for (i = 0; i < basis_dir_cnt; i++) {
args[ac++] = dest_option;
args[ac++] = basis_dir[i];
@@ -2048,6 +2061,11 @@ void server_options(char **args, int *argc_p)
else if (remove_source_files)
args[ac++] = "--remove-sent-files";
if (ac > MAX_SERVER_ARGS) { /* Not possible... */
rprintf(FERROR, "argc overflow in server_options().\n");
exit_cleanup(RERR_MALLOC);
}
*argc_p = ac;
return;

View File

@@ -1,12 +1,12 @@
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.1
Version: 3.0.4
%define fullversion %{version}
Release: 1
%define srcdir src
Group: Applications/Internet
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
#Source1: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-patches-%{fullversion}.tar.gz
URL: http://rsync.samba.org/
Prefix: %{_prefix}
@@ -35,6 +35,9 @@ improved copy command for everyday use.
#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
@@ -56,15 +59,15 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc COPYING README tech_report.tex
%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 Apr 03 2008 Wayne Davison <wayned@samba.org>
Released 3.0.1.
* Sat Sep 06 2008 Wayne Davison <wayned@samba.org>
Released 3.0.4.
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
Added installation of /etc/xinetd.d/rsync file and some commented-out

View File

@@ -13,6 +13,7 @@ my $tmp_dir = "patches.$$";
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'branch|b=s' => \( my $master_branch = 'master' ),
'skip-check' => \( my $skip_branch_check ),
'shell|s' => \( my $launch_shell ),
'gen:s' => \( my $incl_generated_files ),
@@ -51,17 +52,15 @@ if ($incl_generated_files) {
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;
our $last_touch = time;
my(%patches, %local_patch);
my %patches;
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
while (<PIPE>) {
if (m# origin/patch/(.*)#) {
if (m# patch/(.*)#) {
$patches{$1} = 1;
} elsif (m# patch/(.*)#) {
$patches{$1} = $local_patch{$1} = 1;
}
}
close PIPE;
@@ -70,19 +69,23 @@ my @patches = sort keys %patches;
my(%parent, %description);
foreach my $patch (@patches) {
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
my $branch = "patch/$patch";
my $desc = '';
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
open(PIPE, '-|', 'git', 'diff', '-U1000', "$master_branch...$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;
my $parent = $parent{$patch} = $1;
if (!$patches{$parent}) {
die "Parent of $patch is not a local branch: $parent\n";
}
}
$desc .= $_;
}
close PIPE;
$description{$patch} = $desc;
}
@@ -90,8 +93,11 @@ if (@ARGV) {
# Limit the list of patches to actually process based on @ARGV.
@patches = ( );
foreach (@ARGV) {
s{^(patches|patch|origin/patch)/} {};
s{^patch(es)?/} {};
s{\.diff$} {};
if (!$patches{$_}) {
die "Local branch not available for patch: $_\n";
}
push(@patches, $_);
}
}
@@ -106,7 +112,7 @@ if ($incl_generated_files) {
system "rm -rf $tmp_dir";
}
sleep 1 if $last_touch == time;
sleep 1 while $last_touch >= time;
system "git checkout $starting_branch" and exit 1;
exit;
@@ -123,17 +129,13 @@ sub update_patch
}
$parent = "patch/$parent";
} else {
$parent = 'master';
$parent = $master_branch;
}
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;
}
sleep 1 while $incl_generated_files && $last_touch >= time;
system "git checkout patch/$patch" and return 0;
my $ok = system("git merge $parent") == 0;
if (!$ok || $launch_shell) {
@@ -156,7 +158,7 @@ sub update_patch
print OUT $description{$patch}, "\n";
if ($incl_generated_files) {
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/";
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
@@ -174,8 +176,13 @@ sub update_patch
close PIPE;
if ($incl_generated_files) {
$parent =~ s#.*/##;
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
my $parent_dir;
if ($parent eq $master_branch) {
$parent_dir = 'master';
} else {
($parent_dir) = $parent =~ m{([^/]+)$};
}
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent_dir", "$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;

View File

@@ -7,6 +7,7 @@ use strict;
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
use Cwd;
use Getopt::Long;
use Term::ReadKey;
use Date::Format;
@@ -14,6 +15,13 @@ my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $passfile = $ENV{HOME} . '/.rsyncpass';
my $path = $ENV{PATH};
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'branch|b=s' => \( my $master_branch = 'master' ),
'help|h' => \( my $help_opt ),
);
&usage if $help_opt;
my $now = time;
my $cl_today = time2str('* %a %b %d %Y', $now);
my $year = time2str('%Y', $now);
@@ -56,7 +64,7 @@ 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/;
die "The checkout is not on the $master_branch branch.\n" unless $status =~ /^# On branch $master_branch\n/;
my $confversion;
open(IN, '<', 'configure.in') or die $!;
@@ -221,7 +229,7 @@ print $break, <<EOT;
About to:
- commit all version changes
- merge the master branch into the patch/* branches
- merge the $master_branch 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
@@ -232,11 +240,11 @@ my $ans = <STDIN>;
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
print "Updating files in \"patches\" dir ...\n";
system "support/patch-update";
system "packaging/patch-update --branch=$master_branch";
if ($ans =~ /^y/i) {
print "\nVisiting all \"patch/*\" branches ...\n";
system "support/patch-update --shell";
system "packaging/patch-update --branch=$master_branch --shell";
}
print $break, <<EOT;
@@ -305,7 +313,7 @@ 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 "support/patch-update --skip-check --gen=rsync-$version/patches";
system "packaging/patch-update --skip-check --branch=$master_branch --gen=rsync-$version/patches";
print "Creating $pattar_file ...\n";
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
@@ -327,7 +335,7 @@ foreach my $fn ($srctar_file, $pattar_file, $diff_file) {
}
if (!$pre) {
system "rm $dest/rsync-*{.tar.gz,.asc,-NEWS} $dest/src-preview/rsync-*diffs.gz";
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",
@@ -343,3 +351,15 @@ 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
exit;
sub usage
{
die <<EOT;
Usage: release-rsync [OPTIONS]
-b, --branch=BRANCH The branch to release (default: master)
-h, --help Display this help message
EOT
}

View File

@@ -40,6 +40,8 @@ struct progress_history {
OFF_T ofs;
};
int progress_is_active = 0;
static struct progress_history ph_start;
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
static int newest_hpos, oldest_hpos;
@@ -111,8 +113,11 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
stats.num_files);
} else
strlcpy(eol, "\r", sizeof eol);
progress_is_active = 0;
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %s%s",
human_num(ofs), pct, rate, units, rembuf, eol);
if (!is_last)
progress_is_active = 1;
}
void set_current_file_index(struct file_struct *file, int ndx)

View File

@@ -698,23 +698,30 @@ int recv_files(int f_in, char *local_name)
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
} else if (keep_partial && partialptr) {
if (!handle_partial_dir(partialptr, PDIR_CREATE)) {
rprintf(FERROR,
"Unable to create partial-dir for %s -- discarding %s.\n",
local_name ? local_name : f_name(file, NULL),
recv_ok ? "completed file" : "partial file");
do_unlink(fnametmp);
recv_ok = -1;
} else 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;
} else
partialptr = NULL;
} else
do_unlink(fnametmp);
}
cleanup_disable();
switch (recv_ok) {
case 2:
break;
case 1:
if (remove_source_files || inc_recurse
|| (preserve_hard_links && F_IS_HLINKED(file)))

65
rsync.c
View File

@@ -257,8 +257,17 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
break;
if (ndx == NDX_DONE)
return ndx;
if (!inc_recurse || am_sender)
goto invalid_ndx;
if (!inc_recurse || am_sender) {
int last;
if (first_flist)
last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
else
last = -1;
rprintf(FERROR,
"Invalid file index: %d (%d - %d) [%s]\n",
ndx, NDX_DONE, last, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
if (ndx == NDX_FLIST_EOF) {
flist_eof = 1;
send_msg(MSG_FLIST_EOF, "", 0, 0);
@@ -268,9 +277,10 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
if (ndx < 0 || ndx >= dir_flist->used) {
ndx = NDX_FLIST_OFFSET - ndx;
rprintf(FERROR,
"[%s] Invalid dir index: %d (%d - %d)\n",
who_am_i(), ndx, NDX_FLIST_OFFSET,
NDX_FLIST_OFFSET - dir_flist->used + 1);
"Invalid dir index: %d (%d - %d) [%s]\n",
ndx, NDX_FLIST_OFFSET,
NDX_FLIST_OFFSET - dir_flist->used + 1,
who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
@@ -299,17 +309,7 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
goto read_loop;
}
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, start - 1, start + used -1, iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
cur_flist = flist;
cur_flist = flist_for_ndx(ndx, "read_ndx_and_attrs");
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
@@ -561,8 +561,12 @@ int finish_transfer(const char *fname, const char *fnametmp,
goto do_set_file_attrs;
}
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return 1;
if (make_backups > 0 && overwriting_basis) {
if (!make_backup(fname))
return 1;
if (fnamecmp == fname)
fnamecmp = get_backup_name(fname);
}
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -606,23 +610,40 @@ int finish_transfer(const char *fname, const char *fnametmp,
return 1;
}
struct file_list *flist_for_ndx(int ndx)
struct file_list *flist_for_ndx(int ndx, const char *fatal_error_loc)
{
struct file_list *flist = cur_flist;
if (!flist && !(flist = first_flist))
return NULL;
goto not_found;
while (ndx < flist->ndx_start-1) {
if (flist == first_flist)
return NULL;
goto not_found;
flist = flist->prev;
}
while (ndx >= flist->ndx_start + flist->used) {
if (!(flist = flist->next))
return NULL;
goto not_found;
}
return flist;
not_found:
if (fatal_error_loc) {
int first, last;
if (first_flist) {
first = first_flist->ndx_start - 1;
last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
} else {
first = 0;
last = -1;
}
rprintf(FERROR,
"File-list index %d not in %d - %d (%s) [%s]\n",
ndx, first, last, fatal_error_loc, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
return NULL;
}
const char *who_am_i(void)

View File

@@ -83,7 +83,6 @@
/* 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))
@@ -130,6 +129,9 @@
#define IO_BUFFER_SIZE (4092)
#define MAX_BLOCK_SIZE ((int32)1 << 17)
/* For compatibility with older rsyncs */
#define OLD_MAX_BLOCK_SIZE ((int32)1 << 29)
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
#define IOERR_VANISHED (1<<1)
#define IOERR_DEL_LIMIT (1<<2)
@@ -209,6 +211,7 @@ enum logcode {
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 */
FERROR_UTF8=8, /* only sent via receiver -> generator pipe */
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
};
@@ -219,6 +222,7 @@ enum msgcode {
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_ERROR_UTF8=FERROR_UTF8, /* 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 */
@@ -498,10 +502,12 @@ typedef unsigned int size_t;
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
#define OFF_T off_t
#define STRUCT_STAT struct stat
#define SIZEOF_CAPITAL_OFF_T SIZEOF_OFF_T
#else
#define OFF_T off64_t
#define STRUCT_STAT struct stat64
#define USE_STAT64_FUNCS 1
#define SIZEOF_CAPITAL_OFF_T SIZEOF_OFF64_T
#endif
/* CAVEAT: on some systems, int64 will really be a 32-bit integer IFF

114
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(3 Apr 2008)()()
manpage(rsync)(1)(6 Sep 2008)()()
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
manpagesynopsis()
@@ -464,9 +464,9 @@ dit(bf(--version)) print the rsync version number and exit.
dit(bf(-v, --verbose)) This option increases the amount of information you
are given during the transfer. By default, rsync works silently. A
single bf(-v) will give you information about what files are being
transferred and a brief summary at the end. Two bf(-v) flags will give you
transferred and a brief summary at the end. Two bf(-v) options will give you
information on what files are being skipped and slightly more
information at the end. More than two bf(-v) flags should only be used if
information at the end. More than two bf(-v) options should only be used if
you are debugging rsync.
Note that the names of the transferred files that are output are done using
@@ -480,7 +480,7 @@ any way. See the bf(--out-format) option for more details.
dit(bf(-q, --quiet)) This option decreases the amount of information you
are given during the transfer, notably suppressing information messages
from the remote server. This flag is useful when invoking rsync from
from the remote server. This option is useful when invoking rsync from
cron.
dit(bf(--no-motd)) This option affects the information that is output
@@ -697,13 +697,25 @@ date is on the objects. In other words, if the source has a directory
where the destination has a file, the transfer would occur regardless of
the timestamps.
dit(bf(--inplace)) This causes rsync not to create a new copy of the file
and then move it into place. Instead rsync will overwrite the existing
file, meaning that the rsync algorithm can't accomplish the full amount of
network reduction it might be able to otherwise (since it does not yet try
to sort data matches). One exception to this is if you combine the option
with bf(--backup), since rsync is smart enough to use the backup file as the
basis file for the transfer.
dit(bf(--inplace)) This option changes how rsync transfers a file when the
file's data needs to be updated: instead of the default method of creating
a new copy of the file and moving it into place when it is complete, rsync
instead writes the updated data directly to the destination file.
This has several effects: (1) in-use binaries cannot be updated (either the
OS will prevent this from happening, or binaries that attempt to swap-in
their data will misbehave or crash), (2) the file's data will be in an
inconsistent state during the transfer, (3) a file's data may be left in an
inconsistent state after the transfer if the transfer is interrupted or if
an update fails, (4) a file that does not have write permissions can not be
updated, and (5) the efficiency of rsync's delta-transfer algorithm may be
reduced if some data in the destination file is overwritten before it can
be copied to a position later in the file (one exception to this is if you
combine this option with bf(--backup), since rsync is smart enough to use
the backup file as the basis file for the transfer).
WARNING: you should not use this option to update files that are being
accessed by others, so be careful when choosing to use this for a copy.
This option is useful for transfer of large files with block-based changes
or appended data, and also on systems that are disk bound, not network
@@ -714,12 +726,6 @@ the file), but conflicts with bf(--partial-dir) and bf(--delay-updates).
Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest)
and bf(--link-dest).
WARNING: The file's data will be in an inconsistent state during the
transfer (and possibly afterward if the transfer gets interrupted), so you
should not use this option to update files that are in use. Also note that
rsync will be unable to update a file in-place that is not writable by the
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
@@ -986,7 +992,7 @@ with the files and update them on the remote system. Note that if this
option is not used, the optimization that excludes files that have not been
modified cannot be effective; in other words, a missing bf(-t) or bf(-a) will
cause the next transfer to behave as if it used bf(-I), causing all files to be
updated (though the rsync algorithm will make the update fairly efficient
updated (though rsync's delta-transfer algorithm will make the update fairly efficient
if the files haven't actually changed, you're much better off using bf(-t)).
dit(bf(-O, --omit-dir-times)) This tells rsync to omit directories when
@@ -1058,7 +1064,7 @@ 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
dit(bf(-W, --whole-file)) With this option rsync's 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
@@ -1111,7 +1117,7 @@ directories that are being synchronized. You must have asked rsync to
send the whole directory (e.g. "dir" or "dir/") without using a wildcard
for the directory's contents (e.g. "dir/*") since the wildcard is expanded
by the shell and rsync thus gets a request to transfer individual files, not
the files' parent directory. Files that are excluded from transfer are
the files' parent directory. Files that are excluded from the transfer are
also excluded from being deleted unless you use the bf(--delete-excluded)
option or mark the rules as only matching on the sending side (see the
include/exclude modifiers in the FILTER RULES section).
@@ -1133,7 +1139,7 @@ destination. You can override this with the bf(--ignore-errors) option.
The bf(--delete) option may be combined with one of the --delete-WHEN options
without conflict, as well as bf(--delete-excluded). However, if none of the
--delete-WHEN options are specified, rsync will choose the
bf(--delete-during) algorithm when talking to an rsync 3.0.0 or newer, and
bf(--delete-during) algorithm when talking to rsync 3.0.0 or newer, and
the bf(--delete-before) algorithm when talking to an older rsync. See also
bf(--delete-delay) and bf(--delete-after).
@@ -1150,19 +1156,26 @@ algorithm that requires rsync to scan all the files in the transfer into
memory at once (see bf(--recursive)).
dit(bf(--delete-during, --del)) Request that the file-deletions on the
receiving side be done incrementally as the transfer happens. This is
a faster method than choosing the before- or after-transfer algorithm,
but it is only supported beginning with rsync version 2.6.4.
receiving side be done incrementally as the transfer happens. The
per-directory delete scan is done right before each directory is checked
for updates, so it behaves like a more efficient bf(--delete-before),
including doing the deletions prior to any per-directory filter files
being updated. This option was first added in rsync version 2.6.4.
See bf(--delete) (which is implied) for more details on file-deletion.
dit(bf(--delete-delay)) Request that the file-deletions on the receiving
side be computed during the transfer, and then removed after the transfer
completes. If the number of removed files overflows an internal buffer, a
side be computed during the transfer (like bf(--delete-during)), and then
removed after the transfer completes. This is useful when combined with
bf(--delay-updates) and/or bf(--fuzzy), and is more efficient than using
bf(--delete-after) (but can behave differently, since bf(--delete-after)
computes the deletions in a separate pass after all updates are done).
If the number of removed files overflows an internal buffer, a
temporary file will be created on the receiving side to hold the names (it
is removed while open, so you shouldn't see it during the transfer). If
the creation of the temporary file fails, rsync will try to fall back to
using bf(--delete-after) (which it cannot do if bf(--recursive) is doing an
incremental scan).
See bf(--delete) (which is implied) for more details on file-deletion.
dit(bf(--delete-after)) Request that the file-deletions on the receiving
side be done after the transfer has completed. This is useful if you
@@ -1225,7 +1238,7 @@ transferring small, junk files.
See the bf(--max-size) option for a description of SIZE.
dit(bf(-B, --block-size=BLOCKSIZE)) This forces the block size used in
the rsync algorithm to a fixed value. It is normally selected based on
rsync's delta-transfer algorithm to a fixed value. It is normally selected based on
the size of each file being updated. See the technical report for details.
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
@@ -1516,6 +1529,11 @@ An example:
quote(tt( rsync -av --link-dest=$PWD/prior_dir host:src_dir/ new_dir/))
If file's aren't linking, double-check their attributes. Also check if some
attributes are getting forced outside of rsync's control, such a mount option
that squishes root to a single user, or mounts a removable drive with generic
ownership (such as OS X's "Ignore ownership on this volume" option).
Beginning in version 2.6.4, multiple bf(--link-dest) directories may be
provided, which will cause rsync to search the list in the order specified
for an exact match.
@@ -1712,22 +1730,22 @@ you are talking to a recent enough rsync that it logs deletions instead of
outputting them as a verbose message).
dit(bf(--out-format=FORMAT)) This allows you to specify exactly what the
rsync client outputs to the user on a per-update basis. The format is a text
string containing embedded single-character escape sequences prefixed with
a percent (%) character. For a list of the possible escape characters, see
the "log format" setting in the rsyncd.conf manpage.
rsync client outputs to the user on a per-update basis. The format is a
text string containing embedded single-character escape sequences prefixed
with a percent (%) character. A default format of "%n%L" is assumed if
bf(-v) is specified (which reports the name
of the file and, if the item is a link, where it points). For a full list
of the possible escape characters, see the "log format" setting in the
rsyncd.conf manpage.
Specifying this option will mention each file, dir, etc. that gets updated
in a significant way (a transferred file, a recreated symlink/device, or a
touched directory). In addition, if the itemize-changes escape (%i) is
included in the string, the logging of names increases to mention any
item that is changed in any way (as long as the receiving side is at least
2.6.4). See the bf(--itemize-changes) option for a description of the
output of "%i".
The bf(--verbose) option implies a format of "%n%L", but you can use
bf(--out-format) without bf(--verbose) if you like, or you can override
the format of its per-file output using this option.
Specifying the bf(--out-format) option
will mention each file, dir, etc. that gets updated in a significant
way (a transferred file, a recreated symlink/device, or a touched
directory). In addition, if the itemize-changes escape (%i) is included in
the string (e.g. if the bf(--itemize-changes) option was used), the logging
of names increases to mention any item that is changed in any way (as long
as the receiving side is at least 2.6.4). See the bf(--itemize-changes)
option for a description of the output of "%i".
Rsync will output the out-format string prior to a file's transfer unless
one of the transfer-statistic escapes is requested, in which case the
@@ -1759,14 +1777,14 @@ For a list of the possible escape characters, see the "log format" setting
in the rsyncd.conf manpage.
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
on the file transfer, allowing you to tell how effective the rsync
on the file transfer, allowing you to tell how effective rsync's delta-transfer
algorithm is for your data.
The current statistics are as follows: quote(itemization(
it() bf(Number of files) is the count of all "files" (in the generic
sense), which includes directories, symlinks, etc.
it() bf(Number of files transferred) is the count of normal files that
were updated via the rsync algorithm, which does not include created
were updated via rsync's delta-transfer algorithm, which does not include created
dirs, symlinks, etc.
it() bf(Total file size) is the total sum of all file sizes in the transfer.
This does not count any size for directories or special files, but does
@@ -1827,7 +1845,7 @@ after it has served its purpose.
Note that if bf(--whole-file) is specified (or implied), any partial-dir
file that is found for a file that is being updated will simply be removed
(since
rsync is sending files without using the delta transfer algorithm).
rsync is sending files without using rsync's delta-transfer algorithm).
Rsync will create the em(DIR) if it is missing (just the last dir -- not
the whole path). This makes it easy to use a relative path (such as
@@ -1945,7 +1963,7 @@ sender's file, which is being reconstructed at a rate of 110.64 kilobytes
per second, and the transfer will finish in 4 seconds if the current rate
is maintained until the end.
These statistics can be misleading if the delta transfer algorithm is
These statistics can be misleading if rsync's delta-transfer algorithm is
in use. For example, if the sender's file consists of the basis file
followed by additional data, the reported rate will probably drop
dramatically when the receiver gets to the literal data, and the transfer
@@ -2087,7 +2105,7 @@ by the server and defaults to the current code(time()). This option
is used to set a specific checksum seed, which is useful for
applications that want repeatable block and file checksums, or
in the case where the user wants a more random checksum seed.
Note that setting NUM to 0 causes rsync to use the default of code(time())
Setting NUM to 0 causes rsync to use the default of code(time())
for checksum seed.
enddit()
@@ -2876,7 +2894,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.1 of rsync.
This man page is current for version 3.0.4 of rsync.
manpagesection(INTERNAL OPTIONS)

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(3 Apr 2008)()()
manpage(rsyncd.conf)(5)(6 Sep 2008)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -69,7 +69,7 @@ Note that you should bf(not) send the rsync daemon a HUP signal to force
it to reread the tt(rsyncd.conf) file. The file is re-read on each client
connection.
manpagesection(GLOBAL OPTIONS)
manpagesection(GLOBAL PARAMETERS)
The first parameters in the file (before a [module] header) are the
global parameters.
@@ -79,12 +79,12 @@ config file in which case the supplied value will override the
default for that parameter.
startdit()
dit(bf(motd file)) The "motd file" option allows you to specify a
dit(bf(motd file)) This parameter allows you to specify a
"message of the day" to display to clients on each connect. This
usually contains site information and any legal notices. The default
is no motd file.
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
dit(bf(pid file)) This parameter tells the rsync daemon to write
its process ID to that file. If the file already exists, the rsync
daemon will abort rather than overwrite the file.
@@ -96,23 +96,22 @@ dit(bf(address)) You can override the default IP address the daemon
will listen on by specifying this value. This is ignored if the daemon is
being run by inetd, and is superseded by the bf(--address) command-line option.
dit(bf(socket options)) This option can provide endless fun for people
dit(bf(socket options)) This parameter can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
slower!). Read the man page for the code(setsockopt()) system call for
details on some of the options you may be able to set. By default no
special socket options are set. These settings are superseded by the
bf(--sockopts) command-line option.
special socket options are set. These settings can also be specified
via the bf(--sockopts) command-line option.
enddit()
manpagesection(MODULE PARAMETERS)
manpagesection(MODULE OPTIONS)
After the global options you should define a number of modules, each
After the global parameters 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.
followed by the parameters 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
@@ -120,12 +119,12 @@ discarded.
startdit()
dit(bf(comment)) The "comment" option specifies a description string
dit(bf(comment)) This parameter specifies a description string
that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the daemon's
filesystem to make available in this module. You must specify this option
dit(bf(path)) This parameter specifies the directory in the daemon's
filesystem to make available in this module. You must specify this parameter
for each module in tt(rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
@@ -158,7 +157,7 @@ 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
When this parameter 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.
@@ -172,32 +171,32 @@ 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).
that parameter). At that point it will be safe to enable the mapping of users
and groups by name using the "numeric ids" daemon parameter (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
dit(bf(numeric ids)) Enabling this parameter 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
This enabling 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
A chroot-enabled module should not have this parameter 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
dit(bf(munge symlinks)) This parameter 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
If you disable this parameter 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
@@ -205,27 +204,28 @@ 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,
as long as that directory does not exist. When this parameter 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
a directory. When using the "munge symlinks" parameter 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
the module's hierarchy are as safe as you want them to be (unless, of
course, it just copied in the whole hierarchy). 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
When this parameter 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.
better trust your users if you choose this combination of parameters.
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,
@@ -240,14 +240,14 @@ 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
dit(bf(max connections)) This parameter allows you to
specify the maximum number of simultaneous connections you will allow.
Any clients connecting when the maximum has been reached will receive a
message telling them to try later. The default is 0, which means no limit.
A negative value disables the module.
See also the "lock file" option.
See also the "lock file" parameter.
dit(bf(log file)) When the "log file" option is set to a non-empty
dit(bf(log file)) When the "log file" parameter is set to a non-empty
string, the rsync daemon will log messages to the indicated file rather
than using syslog. This is particularly useful on systems (such as AIX)
where code(syslog()) doesn't work for chrooted programs. The file is
@@ -256,11 +256,11 @@ the transfer. If this value is set on a per-module basis instead of
globally, the global log will still contain any authorization failures
or config-file error messages.
If the daemon fails to open to specified file, it will fall back to
If the daemon fails to open the specified file, it will fall back to
using syslog and output an error about the failure. (Note that the
failure to open the specified log file used to be a fatal error.)
dit(bf(syslog facility)) The "syslog facility" option allows you to
dit(bf(syslog facility)) This parameter allows you to
specify the syslog facility name to use when logging messages from the
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
@@ -270,43 +270,43 @@ is daemon. This setting has no effect if the "log file" setting is a
non-empty string (either set in the per-modules settings, or inherited
from the global settings).
dit(bf(max verbosity)) The "max verbosity" option allows you to control
dit(bf(max verbosity)) This parameter allows you to control
the maximum amount of verbose information that you'll allow the daemon to
generate (since the information goes into the log file). The default is 1,
which allows the client to request one level of verbosity.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync daemon uses record
dit(bf(lock file)) This parameter specifies the file to use to
support the "max connections" parameter. The rsync daemon uses record
locking on this file to ensure that the max connections limit is not
exceeded for the modules sharing the lock file.
The default is tt(/var/run/rsyncd.lock).
dit(bf(read only)) The "read only" option determines whether clients
dit(bf(read only)) This parameter determines whether clients
will be able to upload files or not. If "read only" is true then any
attempted uploads will fail. If "read only" is false then uploads will
be possible if file permissions on the daemon side allow them. The default
is for all modules to be read only.
dit(bf(write only)) The "write only" option determines whether clients
dit(bf(write only)) This parameter determines whether clients
will be able to download files or not. If "write only" is true then any
attempted downloads will fail. If "write only" is false then downloads
will be possible if file permissions on the daemon side allow them. The
default is for this option to be disabled.
default is for this parameter to be disabled.
dit(bf(list)) The "list" option determines if this module should be
dit(bf(list)) This parameter determines if this module should be
listed when the client asks for a listing of available modules. By
setting this to false you can create hidden modules. The default is
for modules to be listable.
dit(bf(uid)) The "uid" option specifies the user name or user ID that
dit(bf(uid)) This parameter specifies the user name or user ID that
file transfers to and from that module should take place as when the daemon
was run as root. In combination with the "gid" option this determines what
was run as root. In combination with the "gid" parameter this determines what
file permissions are available. The default is uid -2, which is normally
the user "nobody".
dit(bf(gid)) The "gid" option specifies the group name or group ID that
dit(bf(gid)) This parameter specifies the group name or group ID that
file transfers to and from that module should take place as when the daemon
was run as root. This complements the "uid" option. The default is gid -2,
was run as root. This complements the "uid" parameter. The default is gid -2,
which is normally the group "nobody".
dit(bf(fake super)) Setting "fake super = yes" for a module causes the
@@ -341,7 +341,7 @@ 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)) The "exclude" parameter takes a space-separated list of daemon
dit(bf(exclude)) This 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
@@ -351,7 +351,7 @@ 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(exclude from)) The "exclude from" parameter specifies the name of a file
dit(bf(exclude from)) This 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"
@@ -363,7 +363,7 @@ 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
dit(bf(incoming chmod)) This parameter allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
incoming files (files that are being received by the daemon). These
changes happen after all other permission calculations, and this will
@@ -372,7 +372,7 @@ client does not specify bf(--perms).
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(outgoing chmod)) This option allows you to specify a set of
dit(bf(outgoing chmod)) This parameter allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
outgoing files (files that are being sent out from the daemon). These
changes happen first, making the sent permissions appear to be different
@@ -382,7 +382,7 @@ be on to the clients.
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(auth users)) The "auth users" option specifies a comma and
dit(bf(auth users)) This parameter specifies a comma and
space-separated list of usernames that will be allowed to connect to
this module. The usernames do not need to exist on the local
system. The usernames may also contain shell wildcard characters. If
@@ -390,7 +390,7 @@ system. The usernames may also contain shell wildcard characters. If
username and password to connect to the module. A challenge response
authentication protocol is used for this exchange. The plain text
usernames and passwords are stored in the file specified by the
"secrets file" option. The default is for all users to be able to
"secrets file" parameter. The default is for all users to be able to
connect without a password (this is called "anonymous rsync").
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
@@ -398,28 +398,28 @@ PROGRAM" section in bf(rsync)(1) for information on how handle an
rsyncd.conf-level username that differs from the remote-shell-level
username when using a remote shell to connect to an rsync daemon.
dit(bf(secrets file)) The "secrets file" option specifies the name of
dit(bf(secrets file)) This parameter specifies the name of
a file that contains the username:password pairs used for
authenticating this module. This file is only consulted if the "auth
users" option is specified. The file is line based and contains
users" parameter is specified. The file is line based and contains
username:password pairs separated by a single colon. Any line starting
with a hash (#) is considered a comment and is skipped. The passwords
can contain any characters but be warned that many operating systems
limit the length of passwords that can be typed at the client end, so
you may find that passwords longer than 8 characters don't work.
There is no default for the "secrets file" option, you must choose a name
There is no default for the "secrets file" parameter, you must choose a name
(such as tt(/etc/rsyncd.secrets)). The file must normally not be readable
by "other"; see "strict modes".
dit(bf(strict modes)) The "strict modes" option determines whether or not
dit(bf(strict modes)) This parameter determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
true, then the secrets file must not be readable by any user ID other
than the one that the rsync daemon is running under. If "strict modes" is
false, the check is not performed. The default is true. This option
false, the check is not performed. The default is true. This parameter
was added to accommodate rsync running on the Windows operating system.
dit(bf(hosts allow)) The "hosts allow" option allows you to specify a
dit(bf(hosts allow)) This parameter allows you to specify a
list of patterns that are matched against a connecting clients
hostname and IP address. If none of the patterns match then the
connection is rejected.
@@ -454,28 +454,28 @@ 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 is
parameter. If both parameters are specified then the "hosts allow" parameter 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
connect. The "hosts deny" parameter is then checked and a match means
that the host is rejected. If the host does not match either the
"hosts allow" or the "hosts deny" patterns then it is allowed to
connect.
The default is no "hosts allow" option, which means all hosts can connect.
The default is no "hosts allow" parameter, which means all hosts can connect.
dit(bf(hosts deny)) The "hosts deny" option allows you to specify a
dit(bf(hosts deny)) This parameter allows you to specify a
list of patterns that are matched against a connecting clients
hostname and IP address. If the pattern matches then the connection is
rejected. See the "hosts allow" option for more information.
rejected. See the "hosts allow" parameter for more information.
The default is no "hosts deny" option, which means all hosts can connect.
The default is no "hosts deny" parameter, which means all hosts can connect.
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
dit(bf(ignore errors)) This parameter tells rsyncd to
ignore I/O errors on the daemon when deciding whether to run the delete
phase of the transfer. Normally rsync skips the bf(--delete) step if any
I/O errors have occurred in order to prevent disastrous deletion due
to a temporary resource shortage or other I/O error. In some cases this
test is counter productive so you can use this option to turn off this
test is counter productive so you can use this parameter to turn off this
behavior.
dit(bf(ignore nonreadable)) This tells the rsync daemon to completely
@@ -483,14 +483,14 @@ ignore files that are not readable by the user. This is useful for
public archives that may have some non-readable files among the
directories, and the sysadmin doesn't want those files to be seen at all.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
dit(bf(transfer logging)) This parameter enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. The daemon always logs the transfer at the end, so
if a transfer is aborted, no mention will be made in the log file.
If you want to customize the log lines, see the "log format" option.
If you want to customize the log lines, see the "log format" parameter.
dit(bf(log format)) The "log format" option allows you to specify the
dit(bf(log format)) This parameter allows you to specify the
format used for logging file transfers when transfer logging is enabled.
The format is a text string containing embedded single-character escape
sequences prefixed with a percent (%) character. An optional numeric
@@ -498,7 +498,7 @@ field width may also be specified between the percent and the escape
letter (e.g. "bf(%-50n %8l %07p)").
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
is always prefixed when using the "log file" option.
is always prefixed when using the "log file" parameter.
(A perl script that will summarize this default log format is included
in the rsync source code distribution in the "support" subdirectory:
rsyncstats.)
@@ -509,7 +509,7 @@ quote(itemization(
it() %a the remote IP address
it() %b the number of bytes actually transferred
it() %B the permission bits of the file (e.g. rwxrwxrwt)
it() %c the checksum bytes received for this file (only when sending)
it() %c the total size of the block checksums received for the basis file (only when sending)
it() %f the filename (long form on sender; no trailing "/")
it() %G the gid of the file (decimal) or "DEFAULT"
it() %h the remote host name
@@ -534,14 +534,14 @@ Note that some of the logged output changes when talking with older
rsync versions. For instance, deleted files were only output as verbose
messages prior to rsync 2.6.4.
dit(bf(timeout)) The "timeout" option allows you to override the
clients choice for I/O timeout for this module. Using this option you
dit(bf(timeout)) This parameter allows you to override the
clients choice for I/O timeout for this module. Using this parameter you
can ensure that rsync won't wait on a dead client forever. The timeout
is specified in seconds. A value of zero means no timeout and is the
default. A good choice for anonymous rsync daemons may be 600 (giving
a 10 minute timeout).
dit(bf(refuse options)) The "refuse options" option allows you to
dit(bf(refuse options)) This parameter allows you to
specify a space-separated list of rsync command line options that will
be refused by your rsync daemon.
You may specify the full option name, its one-letter abbreviation, or a
@@ -564,21 +564,21 @@ you can use "dont compress = *" (see below)
instead of "refuse options = compress" to avoid returning an error to a
client that requests compression.
dit(bf(dont compress)) The "dont compress" option allows you to select
dit(bf(dont compress)) This parameter allows you to select
filenames based on wildcard patterns that should not be compressed
when pulling files from the daemon (no analogous option exists to
when pulling files from the daemon (no analogous parameter exists to
govern the pushing of files to a daemon).
Compression is expensive in terms of CPU usage, so it
is usually good to not try to compress files that won't compress well,
such as already compressed files.
The "dont compress" option takes a space-separated list of
The "dont compress" parameter takes a space-separated list of
case-insensitive wildcard patterns. Any source filename matching one
of the patterns will not be compressed during transfer.
See the bf(--skip-compress) option in the bf(rsync)(1) manpage for the list
See the bf(--skip-compress) parameter in the bf(rsync)(1) manpage for the list
of file suffixes that are not compressed by default. Specifying a value
for the "dont compress" option changes the default when the daemon is
for the "dont compress" parameter 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
@@ -700,7 +700,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.1 of rsync.
This man page is current for version 3.0.4 of rsync.
manpagesection(CREDITS)

View File

@@ -154,12 +154,21 @@ fi
RSYNC="$rsync_bin $*"
#RSYNC="valgrind $rsync_bin $*"
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC
TLS_ARGS=''
if egrep '^#define HAVE_LUTIMES 1' config.h >/dev/null; then
TLS_ARGS="$TLS_ARGS -l"
fi
if egrep '#undef CHOWN_MODIFIES_SYMLINK' config.h >/dev/null; then
TLS_ARGS="$TLS_ARGS -L"
fi
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC TLS_ARGS
echo "============================================================"
echo "$0 running in $TOOLDIR"
echo " rsync_bin=$RSYNC"
echo " srcdir=$srcdir"
echo " TLS_ARGS=$TLS_ARGS"
if [ -f /usr/bin/whoami ]; then
testuser=`/usr/bin/whoami`
@@ -229,7 +238,10 @@ prep_scratch() {
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
$setfacl_nodef "$scratchdir" || true
chmod g-s "$scratchdir"
ln -s "$srcdir" "$scratchdir/src"
case "$srcdir" in
/*) ln -s "$srcdir" "$scratchdir/src" ;;
*) ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
esac
return 0
}

View File

@@ -127,13 +127,7 @@ void successful_send(int ndx)
if (!remove_source_files)
return;
if (!(flist = flist_for_ndx(ndx))) {
rprintf(FERROR,
"INTERNAL ERROR: unable to find flist for item %d\n",
ndx);
return;
}
flist = flist_for_ndx(ndx, "successful_send");
file = flist->files[ndx - flist->ndx_start];
if (!change_pathname(file, NULL, 0))
return;
@@ -281,7 +275,7 @@ void send_files(int f_in, int f_out)
if (!(s = receive_sums(f_in))) {
io_error |= IOERR_GENERAL;
rprintf(FERROR, "receive_sums failed\n");
rprintf(FERROR_XFER, "receive_sums failed\n");
exit_cleanup(RERR_PROTOCOL);
}
@@ -309,7 +303,7 @@ void send_files(int f_in, int f_out)
/* map the local file */
if (do_fstat(fd, &st) != 0) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR, errno, "fstat failed");
rsyserr(FERROR_XFER, errno, "fstat failed");
free_sums(s);
close(fd);
exit_cleanup(RERR_PROTOCOL);

View File

@@ -31,6 +31,7 @@
#include <netinet/tcp.h>
extern char *bind_address;
extern char *sockopts;
extern int default_af_hint;
extern int connect_timeout;
@@ -272,6 +273,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
alarm(connect_timeout);
}
set_socket_options(s, sockopts);
while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
if (connect_timeout < 0)
exit_cleanup(RERR_CONTIMEOUT);
@@ -433,6 +435,10 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&one, sizeof one);
if (sockopts)
set_socket_options(s, sockopts);
else
set_socket_options(s, lp_socket_options());
#ifdef IPV6_V6ONLY
if (resp->ai_family == AF_INET6) {

36
support/deny-rsync Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
# Send an error message via the rsync-protocol to a non-daemon client rsync.
#
# Usage: deny-rsync "message"
protocol_version=29
exit_code=4 # same as a daemon that refuses an option
# e.g. byte_escape 29 => \035
function byte_escape {
echo -ne "\\0$(printf "%o" $1)"
}
msg="$1"
if [ "${#msg}" -gt 254 ]; then
# truncate a message that is too long for this naive script to handle
msg="${msg:0:251}..."
fi
msglen=$(( ${#msg} + 1 )) # add 1 for the newline we append below
# Send protocol version. All numbers are LSB-first 4-byte ints.
echo -ne "$(byte_escape $protocol_version)\\000\\000\\000"
# Send a zero checksum seed.
echo -ne "\\000\\000\\000\\000"
# The following is equivalent to rprintf(FERROR_XFER, "%s\n", $msg).
# 1. Message header: ((MPLEX_BASE + FERROR_XFER) << 24) + $msglen.
echo -ne "$(byte_escape $msglen)\\000\\000\\010"
# 2. The actual data.
echo -E "$msg"
# Make sure the client gets our message, not a write failure.
sleep 1
exit $exit_code

View File

@@ -6,18 +6,30 @@
# we get a -l USER option, we try to use "sudo -u USER" to run the
# command.
user=''
prefix=''
cd # Default path is home dir, just like ssh.
do_cd=y # Default path is user's home dir, just like ssh.
while : ; do
case "$1" in
-l) shift ; prefix="sudo -u $1"; shift ;;
-l*) prefix=`echo $1 | sed 's/-l/sudo -u /'`; shift ;;
-l) user="$2"; shift; shift ;;
-l*) user=`echo $1 | sed 's/^-l//'`; shift ;;
--no-cd) do_cd=n; shift ;;
-*) shift ;;
localhost) shift; break ;;
*) exit 1 ;;
*) echo "lsh: unable to connect to host $1" 1>&2; exit 1 ;;
esac
done
if [ "$user" ]; then
prefix="sudo -H -u $user"
if [ $do_cd = y ]; then
home=`perl -e "print((getpwnam("$user"))[7])"`
# Yeah, this may fail, but attempts to get sudo to cd are harder.
cd $home
fi
elif [ $do_cd = y ]; then
cd
fi
eval $prefix "${@}"

View File

@@ -26,6 +26,7 @@ int module_id = -1;
int relative_paths = 0;
int human_readable = 0;
int module_dirlen = 0;
int preserve_xattrs = 0;
mode_t orig_umask = 002;
char *partial_dir;
char *module_dir;
@@ -69,6 +70,11 @@ struct filter_list_struct daemon_filter_list;
return -1;
}
int copy_xattrs(UNUSED(const char *source), UNUSED(const char *dest))
{
return -1;
}
char *lp_name(UNUSED(int mod))
{
return NULL;

View File

@@ -36,7 +36,7 @@ for fn in deep/name1 deep/name2; do
done
echo deleted-file >"$todir/dname"
cp -p "$todir/dname" "$chkdir"
cp_touch "$todir/dname" "$chkdir"
checkit "$RSYNC -avv --no-whole-file --delete-delay \
--backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \

View File

@@ -17,7 +17,7 @@ case $0 in
*fake*)
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
RSYNC="$RSYNC --fake-super"
TLS_ARGS=--fake-super
TLS_ARGS="$TLS_ARGS --fake-super"
case "`xattr 2>&1`" in
*--list:*)
chown() {

View File

@@ -19,35 +19,71 @@
# checking the log file
# password authentication
# TODO: Put the common framework in a common file, so that we can have
# subtests fail and keep going.
. "$suitedir/rsync.fns"
SSH="$scratchdir/pretend-ssh"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
cat >"$SSH" <<'EOT'
while : ; do
case "$1" in
-*) shift ;;
localhost) shift; break ;;
*) exit 1 ;;
esac
done
eval "${@}"
EOT
chmod +x "$SSH"
SSH="src/support/lsh --no-cd"
DIR_REPL='s/^\(d[^ ]*\) *[0-9][0-9]* /\1 DIR /'
LS_REPL='s;[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9];####/##/## ##:##:##;'
build_rsyncd_conf
makepath "$fromdir/foo" "$fromdir/bar/baz"
makepath "$todir"
echo one >"$fromdir/foo/one"
echo two >"$fromdir/bar/two"
echo three >"$fromdir/bar/baz/three"
cd "$scratchdir"
ln -s test-rsyncd.conf rsyncd.conf
$RSYNC -ve $SSH --rsync-path="$RSYNC" localhost::
confopt=''
case `id -u` in
0)
# Root needs to specify the config file, or it uses /etc/rsyncd.conf.
echo "Forcing --config=$conf"
confopt=" --config=$conf"
;;
esac
$RSYNC -ve "$SSH" --rsync-path="$RSYNC$confopt" localhost::
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
$RSYNC -v localhost::
$RSYNC -v localhost:: \
| tee "$outfile"
# These have a space-padded 15-char name, then a tab, then a comment.
sed 's/NOCOMMENT//' <<EOT >"$chkfile"
test-from r/o
test-to r/w
test-scratch NOCOMMENT
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -r localhost::test-hidden \
| sed "$DIR_REPL" | sed "$LS_REPL" \
| tee "$outfile"
cat <<EOT >"$chkfile"
drwxr-xr-x DIR ####/##/## ##:##:## .
drwxr-xr-x DIR ####/##/## ##:##:## bar
-rw-r--r-- 4 ####/##/## ##:##:## bar/two
drwxr-xr-x DIR ####/##/## ##:##:## bar/baz
-rw-r--r-- 6 ####/##/## ##:##:## bar/baz/three
drwxr-xr-x DIR ####/##/## ##:##:## foo
-rw-r--r-- 4 ####/##/## ##:##:## foo/one
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
$RSYNC -r localhost::test-from/f* \
| sed "$DIR_REPL" | sed "$LS_REPL" \
| tee "$outfile"
cat <<EOT >"$chkfile"
drwxr-xr-x DIR ####/##/## ##:##:## foo
-rw-r--r-- 4 ####/##/## ##:##:## foo/one
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"

View File

@@ -18,7 +18,7 @@ case $0 in
*fake*)
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
RSYNC="$RSYNC --fake-super"
TLS_ARGS=--fake-super
TLS_ARGS="$TLS_ARGS --fake-super"
case "`xattr 2>&1`" in
*--list:*)
mknod() {
@@ -76,7 +76,8 @@ mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node"
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo"
touch -r "$fromdir/block" "$fromdir/block2"
# Work around time rounding/truncating issue by touching both files.
touch -r "$fromdir/block" "$fromdir/block" "$fromdir/block2"
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"

View File

@@ -153,13 +153,13 @@ checkit "$RSYNC -avvC --filter='merge $excl' --delete-excluded \
rm "$chkdir"/foo/file1
rm "$chkdir"/bar/down/to/bar/baz/*.deep
cp -p "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp -p "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
cp_touch "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp_touch "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
$RSYNC -av --existing -f 'show .filt*' -f 'hide,! */' --del "$fromdir/" "$todir/"
echo retained >"$todir"/bar/down/to/bar/baz/nodel.deep
cp -p "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
cp_touch "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"

View File

@@ -13,7 +13,7 @@ mkdir "$fromdir"
mkdir "$todir"
cp -p "$srcdir"/rsync.c "$fromdir"/rsync.c
cp -p "$fromdir"/rsync.c "$todir"/rsync2.c
cp_touch "$fromdir"/rsync.c "$todir"/rsync2.c
sleep 1
# Let's do it!

View File

@@ -11,6 +11,8 @@
. "$suitedir/rsync.fns"
SSH="$scratchdir/src/support/lsh"
outfile="$scratchdir/rsync.out"
# Build some hardlinks
@@ -44,8 +46,8 @@ checkit "$RSYNC -aHivv --no-whole-file '$fromdir/' '$todir/'" "$fromdir" "$todir
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
for x in 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 0 1 2 3 4 5 6 7 8 9; do
for y in 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 0 1 2 3 4 5 6 7 8 9; do
files="$files $x$y"
done
done
@@ -54,7 +56,7 @@ done
ln "$name1" "$fromdir/subdir/down/deep/new-file"
rm "$todir/text"
checkit "$RSYNC -aHivv '$fromdir/' '$todir/'" "$fromdir" "$todir"
checkit "$RSYNC -aHivve '$SSH' --rsync-path='$RSYNC' '$fromdir/' localhost:'$todir/'" "$fromdir" "$todir"
# Do some duplicate copies using --link-dest and --copy-dest to test that
# we hard-link all locally-inherited items.

View File

@@ -28,8 +28,7 @@ ln "$fromdir/foo/config1" "$fromdir/foo/extra"
rm -f "$to2dir"
# 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
if egrep '^#define CAN_HARDLINK_SYMLINK 1' config.h >/dev/null; then
L=hL
else
L=cL

View File

@@ -19,15 +19,15 @@ mkdir from2/sub1 from3/sub1
mkdir from3/sub2 from1/dir-and-not-dir
mkdir chk chk/sub1 chk/sub2 chk/dir-and-not-dir
echo "one" >from1/one
cp -p from1/one from2/one
cp -p from1/one from3/one
cp_touch from1/one from2/one
cp_touch from1/one from3/one
echo "two" >from1/two
echo "three" >from2/three
echo "four" >from3/four
echo "five" >from1/five
echo "six" >from3/six
echo "sub1" >from2/sub1/uno
cp -p from2/sub1/uno from3/sub1/uno
cp_touch from2/sub1/uno from3/sub1/uno
echo "sub2" >from3/sub1/dos
echo "sub3" >from2/sub1/tres
echo "subby" >from3/sub2/subby
@@ -36,11 +36,11 @@ echo "not-dir" >from3/dir-and-not-dir
echo "arg-test" >deep/arg-test
echo "shallow" >shallow
cp -p from1/one from1/two from2/three from3/four from1/five from3/six chk
cp -p deep/arg-test shallow chk
cp -p from1/dir-and-not-dir/inside chk/dir-and-not-dir
cp -p from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1
cp -p from3/sub2/subby chk/sub2
cp_touch from1/one from1/two from2/three from3/four from1/five from3/six chk
cp_touch deep/arg-test shallow chk
cp_touch from1/dir-and-not-dir/inside chk/dir-and-not-dir
cp_touch from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1
cp_touch from3/sub2/subby chk/sub2
# Make sure that time has moved on.
sleep 1

View File

@@ -52,6 +52,29 @@ runtest() {
fi
}
set_cp_destdir() {
while test $# -gt 1; do
shift
done
destdir="$1"
}
# Perform a "cp -p", making sure that timestamps are really the same,
# even if the copy rounded microsecond times on the destination file.
cp_touch() {
cp -p "${@}" || test_fail "cp -p failed"
if test $# -gt 2 -o -d "$2"; then
set_cp_destdir "${@}" # sets destdir var
while test $# -gt 1; do
destname="$destdir/`basename $1`"
touch -r "$destname" "$1" "$destname"
shift
done
else
touch -r "$2" "$1" "$2"
fi
}
# Call this if you want to filter out verbose messages (-v or -vv) from
# the output of an rsync run (whittling the output down to just the file
# messages). This isn't needed if you use -i without -v.
@@ -244,7 +267,7 @@ 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
transfer logging = yes
exclude = foobar.baz
exclude = ? foobar.baz
max verbosity = 9
uid = 0
gid = 0
@@ -252,14 +275,20 @@ gid = 0
[test-from]
path = $fromdir
read only = yes
comment = r/o
[test-to]
path = $todir
read only = no
comment = r/w
[test-scratch]
path = $scratchdir
read only = no
[test-hidden]
path = $fromdir
list = no
EOF
# Build a helper script to ignore exit code 23

View File

@@ -10,20 +10,7 @@
. "$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"
SSH="$scratchdir/src/support/lsh"
if test x"$rsync_enable_ssh_tests" = xyes; then
if type ssh >/dev/null ; then
@@ -31,7 +18,7 @@ if test x"$rsync_enable_ssh_tests" = xyes; then
fi
fi
if ! [ "`"$SSH" -o'BatchMode yes' localhost echo yes`" = "yes" ]; then
if ! [ "`$SSH -o'BatchMode yes' localhost echo yes`" = "yes" ]; then
test_skipped "Skipping SSH tests because ssh conection to localhost not authorised"
fi

View File

@@ -46,7 +46,7 @@ echo deeper >"$fromdir/foo/bar/file5"
makepath "$chkdir/foo"
echo wow >"$chkdir/file1"
cp -p "$fromdir/foo/file3" "$chkdir/foo"
cp_touch "$fromdir/foo/file3" "$chkdir/foo"
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
@@ -64,6 +64,10 @@ xset user.foo foo file2
xset user.bar bar file2
xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
xset user.dir1 'need to test directory xattrs too' foo
xset user.dir2 'another xattr' foo
xset user.dir3 'this is one last one for the moment' foo
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
@@ -91,12 +95,16 @@ cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
xset user.nice 'this is nice, but different' file1
xls $files >"$scratchdir/xattrs.txt"
rm -rf "$todir"
xset user.nice 'this is nice, but different' file1
checkit "$RSYNC -aiX --fake-super . ../chk" "$fromdir" "$chkdir"
cd "$chkdir"
xls $files >"$scratchdir/xattrs.txt"
cd "$fromdir"
checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
cd "$todir"
@@ -109,5 +117,31 @@ if [ -s "$scratchdir/ls-diff" ]; then
exit 1
fi
cd "$fromdir"
rm -rf "$todir" "$chkdir"
$RSYNC -aX file1 file2
$RSYNC -aX file1 file2 ../chk/
$RSYNC -aX --del ../chk/ .
$RSYNC -aX file1 ../lnk/
xls file1 file2 >"$scratchdir/xattrs.txt"
checkit "$RSYNC -aiiX --copy-dest=../lnk . ../to" "$chkdir" "$todir"
cd "$todir"
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
rm "$todir/file2"
echo extra >file1
$RSYNC -aX . ../chk/
checkit "$RSYNC -aiiX . ../to" "$chkdir" "$todir"
cd "$todir"
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
# The script would have aborted on error, so getting here means we've won.
exit 0

14
tls.c
View File

@@ -45,6 +45,8 @@ int dry_run = 0;
int am_root = 0;
int read_only = 1;
int list_only = 0;
int link_times = 0;
int link_owner = 0;
int preserve_perms = 0;
int preserve_executability = 0;
@@ -134,12 +136,14 @@ static void list_file(const char *fname)
/* On some BSD platforms the mode bits of a symlink are
* undefined. Also it tends not to be possible to reset a
* symlink's mtime, so we have to ignore it too. */
* symlink's mtime, so we default to ignoring it too. */
if (S_ISLNK(buf.st_mode)) {
int len;
buf.st_mode &= ~0777;
buf.st_mtime = (time_t)0;
buf.st_uid = buf.st_gid = 0;
if (!link_times)
buf.st_mtime = (time_t)0;
if (!link_owner)
buf.st_uid = buf.st_gid = 0;
strlcpy(linkbuf, " -> ", sizeof linkbuf);
/* const-cast required for silly UNICOS headers */
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
@@ -184,6 +188,8 @@ static void list_file(const char *fname)
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"link-times", 'l', POPT_ARG_NONE, &link_times, 0, 0, 0 },
{"link-owner", 'L', POPT_ARG_NONE, &link_owner, 0, 0, 0 },
#ifdef SUPPORT_XATTRS
{"fake-super", 'f', POPT_ARG_VAL, &am_root, -1, 0, 0 },
#endif
@@ -197,6 +203,8 @@ static void tls_usage(int ret)
fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
fprintf(F,"Trivial file listing program for portably checking rsync\n");
fprintf(F,"\nOptions:\n");
fprintf(F," -l, --link-times display the time on a symlink\n");
fprintf(F," -L, --link-owner display the owner+group on a symlink\n");
#ifdef SUPPORT_XATTRS
fprintf(F," -f, --fake-super display attributes including fake-super xattrs\n");
#endif

123
util.c
View File

@@ -29,6 +29,7 @@ extern int module_id;
extern int modify_window;
extern int relative_paths;
extern int human_readable;
extern int preserve_xattrs;
extern char *module_dir;
extern unsigned int module_dirlen;
extern mode_t orig_umask;
@@ -264,6 +265,8 @@ static int safe_read(int desc, char *ptr, size_t len)
/* 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.
* In either case, if --xattrs are being preserved, the dest file will
* have its xattrs set from the source file.
*
* This is used in conjunction with the --temp-dir, --backup, and
* --copy-dest options. */
@@ -275,38 +278,54 @@ int copy_file(const char *source, const char *dest, int ofd,
int len; /* Number of bytes read into `buf'. */
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
errno = save_errno;
return -1;
}
if (ofd < 0) {
if (robust_unlink(dest) && errno != ENOENT) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
errno = save_errno;
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;
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
close(ifd);
errno = save_errno;
return -1;
}
}
}
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
close(ifd);
close(ofd);
errno = save_errno;
return -1;
}
}
if (len < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
close(ifd);
close(ofd);
errno = save_errno;
return -1;
}
@@ -316,11 +335,18 @@ int copy_file(const char *source, const char *dest, int ofd,
}
if (close(ofd) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "close failed on %s",
full_fname(dest));
errno = save_errno;
return -1;
}
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
copy_xattrs(source, dest);
#endif
return 0;
}
@@ -401,14 +427,17 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
switch (errno) {
#ifdef ETXTBSY
case ETXTBSY:
if (robust_unlink(to) != 0)
if (robust_unlink(to) != 0) {
errno = ETXTBSY;
return -1;
}
errno = ETXTBSY;
break;
#endif
case EXDEV:
if (partialptr) {
if (!handle_partial_dir(partialptr,PDIR_CREATE))
return -1;
return -2;
to = partialptr;
}
if (copy_file(from, to, -1, mode, 0) != 0)
@@ -582,7 +611,7 @@ static inline void call_glob_match(const char *name, int len, int from_glob,
} else
use_buf = glob.arg_buf;
if (from_glob || arg) {
if (from_glob || (arg && len)) {
STRUCT_STAT st;
int is_dir;
@@ -1083,12 +1112,16 @@ int handle_partial_dir(const char *fname, int create)
STRUCT_STAT st;
int statret = do_lstat(dir, &st);
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (do_unlink(dir) < 0)
if (do_unlink(dir) < 0) {
*fn = '/';
return 0;
}
statret = -1;
}
if (statret < 0 && do_mkdir(dir, 0700) < 0)
if (statret < 0 && do_mkdir(dir, 0700) < 0) {
*fn = '/';
return 0;
}
} else
do_rmdir(dir);
*fn = '/';
@@ -1160,6 +1193,28 @@ int unsafe_symlink(const char *dest, const char *src)
return (depth < 0);
}
#define HUMANIFY(mult) \
do { \
if (num >= mult || num <= -mult) { \
double dnum = (double)num / mult; \
char units; \
if (num < 0) \
dnum = -dnum; \
if (dnum < mult) \
units = 'K'; \
else if ((dnum /= mult) < mult) \
units = 'M'; \
else { \
dnum /= mult; \
units = 'G'; \
} \
if (num < 0) \
dnum = -dnum; \
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \
return bufs[n]; \
} \
} while (0)
/* Return the int64 number as a string. If the --human-readable option was
* specified, we may output the number in K, M, or G units. We can return
* up to 4 buffers at a time. */
@@ -1168,27 +1223,15 @@ char *human_num(int64 num)
static char bufs[4][128]; /* more than enough room */
static unsigned int n;
char *s;
int negated;
n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
if (human_readable) {
char units = '\0';
int mult = human_readable == 1 ? 1000 : 1024;
double dnum = 0;
if (num > mult*mult*mult) {
dnum = (double)num / (mult*mult*mult);
units = 'G';
} else if (num > mult*mult) {
dnum = (double)num / (mult*mult);
units = 'M';
} else if (num > mult) {
dnum = (double)num / mult;
units = 'K';
}
if (units) {
snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units);
return bufs[n];
}
if (human_readable == 1)
HUMANIFY(1000);
else
HUMANIFY(1024);
}
s = bufs[n] + sizeof bufs[0] - 1;
@@ -1196,10 +1239,23 @@ char *human_num(int64 num)
if (!num)
*--s = '0';
if (num < 0) {
/* A maximum-size negated number can't fit as a positive,
* so do one digit in negated form to start us off. */
*--s = (char)(-(num % 10)) + '0';
num = -(num / 10);
negated = 1;
} else
negated = 0;
while (num) {
*--s = (char)(num % 10) + '0';
num /= 10;
}
if (negated)
*--s = '-';
return s;
}
@@ -1212,8 +1268,8 @@ char *human_dnum(double dnum, int decimal_digits)
int len = strlen(buf);
if (isDigit(buf + len - 1)) {
/* There's extra room in buf prior to the start of the num. */
buf -= decimal_digits + 1;
snprintf(buf, len + decimal_digits + 2, "%.*f", decimal_digits, dnum);
buf -= decimal_digits + 2;
snprintf(buf, len + decimal_digits + 3, "%.*f", decimal_digits, dnum);
}
return buf;
}
@@ -1329,7 +1385,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;
@@ -1550,7 +1606,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

@@ -44,9 +44,9 @@ extern int checksum_seed;
#define XATTR_ABBREV(x) ((size_t)((x).name - (x).datum) < (x).datum_len)
#define XSTATE_ABBREV 0
#define XSTATE_DONE 1
#define XSTATE_TODO 2
#define XSTATE_ABBREV 1
#define XSTATE_DONE 2
#define XSTATE_TODO 3
#define USER_PREFIX "user."
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
@@ -178,8 +178,9 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *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)))
if (datum_len + extra_len < datum_len)
overflow_exit("get_xattr_data");
if (!(ptr = new_array(char, datum_len + extra_len)))
out_of_memory("get_xattr_data");
if (datum_len) {
@@ -209,7 +210,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
size_t datum_len, name_offset;
char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
int user_only = am_sender ? 0 : !am_root;
int user_only = am_sender ? 0 : am_root <= 0;
#endif
rsync_xa *rxa;
int count;
@@ -287,6 +288,48 @@ int get_xattr(const char *fname, stat_x *sxp)
return 0;
}
int copy_xattrs(const char *source, const char *dest)
{
ssize_t list_len, name_len;
size_t datum_len;
char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
int user_only = am_root <= 0;
#endif
/* This puts the name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(source)) < 0)
return -1;
for (name = namebuf; list_len > 0; name += name_len) {
name_len = strlen(name) + 1;
list_len -= name_len;
#ifdef HAVE_LINUX_XATTRS
/* We always ignore the system namespace, and non-root
* ignores everything but the user namespace. */
if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
: HAS_PREFIX(name, SYSTEM_PREFIX))
continue;
#endif
datum_len = 0;
if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
return -1;
if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
int save_errno = errno ? errno : EINVAL;
rsyserr(FERROR_XFER, errno,
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
dest, name);
errno = save_errno;
return -1;
}
free(ptr);
}
return 0;
}
static int find_matching_xattr(item_list *xalp)
{
size_t i, j;
@@ -460,9 +503,11 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
return !xattrs_equal;
}
/* When called by the generator with a NULL fname, this tells the sender
* which abbreviated xattr values we need. When called by the sender
* (with a non-NULL fname), we send all the extra xattr data it needs. */
/* When called by the generator (with a NULL fname), this tells the sender
* all the abbreviated xattr values we need. When called by the sender
* (with a non-NULL fname), we send all the extra xattr data it needs.
* The generator may also call with f_out < 0 to just change all the
* XSTATE_ABBREV states into XSTATE_DONE. */
void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
{
item_list *lst = rsync_xal_l.items;
@@ -481,6 +526,7 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
rxa->datum[0] = XSTATE_DONE;
continue;
case XSTATE_TODO:
assert(f_out >= 0);
break;
default:
continue;
@@ -509,7 +555,8 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
}
}
write_byte(f_out, 0); /* end the list */
if (f_out >= 0)
write_byte(f_out, 0); /* end the list */
}
/* When called by the sender, read the request from the generator and mark
@@ -543,8 +590,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
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());
if (!XATTR_ABBREV(*rxa) || rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "[%s] internal abbrev error on %s (%s, len=%ld)!\n",
who_am_i(), f_name(file, NULL), rxa->name, (long)rxa->datum_len);
exit_cleanup(RERR_STREAMIO);
}
@@ -557,7 +605,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
rxa->datum_len = read_varint(f_in);
if (rxa->name_len + rxa->datum_len < rxa->name_len)
out_of_memory("recv_xattr_request"); /* overflow */
overflow_exit("recv_xattr_request");
rxa->datum = new_array(char, rxa->datum_len + rxa->name_len);
if (!rxa->datum)
out_of_memory("recv_xattr_request");
@@ -609,10 +657,9 @@ void receive_xattr(struct file_struct *file, int f)
size_t datum_len = read_varint(f);
size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len;
size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0;
if (dget_len + extra_len < dget_len)
out_of_memory("receive_xattr"); /* overflow */
if (dget_len + extra_len + name_len < dget_len)
out_of_memory("receive_xattr"); /* overflow */
if ((dget_len + extra_len < dget_len)
|| (dget_len + extra_len + name_len < dget_len))
overflow_exit("receive_xattr");
ptr = new_array(char, dget_len + extra_len + name_len);
if (!ptr)
out_of_memory("receive_xattr");
@@ -698,6 +745,9 @@ 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];
#ifdef HAVE_LINUX_XATTRS
int user_only = am_root <= 0;
#endif
size_t name_len;
int ret = 0;
@@ -773,8 +823,8 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
#ifdef HAVE_LINUX_XATTRS
/* We always ignore the system namespace, and non-root
* ignores everything but the user namespace. */
if (am_root ? HAS_PREFIX(name, SYSTEM_PREFIX)
: !HAS_PREFIX(name, USER_PREFIX))
if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
: HAS_PREFIX(name, SYSTEM_PREFIX))
continue;
#endif
if (am_root < 0 && name_len > RPRE_LEN