Compare commits

..

104 Commits

Author SHA1 Message Date
Wayne Davison
698bc16e87 Preparing for release of 3.0.0pre10 2008-02-19 18:28:00 -08:00
Wayne Davison
7b4f48650c Make a few more char pointers const. 2008-02-19 16:35:22 -08:00
Wayne Davison
a43ff267e9 Tweaked a comparison that "checker" was complaining about. 2008-02-19 11:52:00 -08:00
Wayne Davison
717d04669a Fixed the hard-link check again, adding a comment as to
why it is coded the way it is.
2008-02-18 17:16:08 -08:00
Wayne Davison
15dbffc215 Fixed a compilation problem when iconv support is disabled. 2008-02-18 16:48:20 -08:00
Wayne Davison
0099e42332 Only set FLAG_TIME_FAILED if receiver_symlink_times is set. 2008-02-18 16:48:04 -08:00
Wayne Davison
1ed56a05c2 Extended the protocol-30 info-passing code at startup, and use it to
tell the client if the server can set the times on a symlink (both
the server->client byte and the client->server use of -e).  Make use
of this info to allow the proper output of the 't' flag when rsync
can set the time on a symlink (and we're talking protocol >= 30).
Added output of "[no] symtimes" info in the --version message.
Fixed the itemize.test so that it works when rsync believes that it
can set the time of a symlink, but it can't really do it.
2008-02-18 15:57:59 -08:00
Wayne Davison
28fb6365d0 Added --no-one-file-system and --no-x options. 2008-02-18 12:42:04 -08:00
Wayne Davison
8365126b8d Some permssion fixes:
- Changed itemized output to only report 'p' with -p or -E.
 - Fixed a duplicate output of a link-dest file with -vv but no -i.
 - Improved unchanged_attrs() to handle -E.
2008-02-18 10:20:50 -08:00
Wayne Davison
d770837ec0 Fixed a typo reported in a Debian bug report. 2008-02-18 09:59:44 -08:00
Wayne Davison
59658acfec Mention the leading '*'-char rule for itemized output. 2008-02-18 08:25:15 -08:00
Wayne Davison
46f800e8c7 Decided to pad the "*deleting" message to make the names line up. 2008-02-17 23:46:26 -08:00
Wayne Davison
1c65a93d03 The daemon no longer logs a recv entry for a file that is not
actually being updated due to the --only-write-batch option.
2008-02-17 23:44:52 -08:00
Wayne Davison
cae7885e2f Don't output a duplicate warning when the daemon-config excludes a
directory or when a directory is ignored via --ignore-non-existing.
Use a new var, is_dir, to simplify the dir code in recv_generator().
2008-02-17 22:34:08 -08:00
Wayne Davison
eaa28e654f Use the name "ChangeLog" for the ftp copy of the repository history. 2008-02-16 14:45:22 -08:00
Wayne Davison
beef86d0dd A few minor changes, including better push_dir()/pop_dir() verbosity. 2008-02-15 22:19:43 -08:00
Wayne Davison
2fe1feea75 Added a way to specify where the chroot should occur in the module's
path, which allows a daemon admin to have chroot protection and still
have files that are outside the transfer area (such as libraries).
2008-02-15 19:01:35 -08:00
Wayne Davison
0b52f94da7 Some daemon security improvements, including the new parameters
"charset" and "numeric ids".
2008-02-15 17:39:21 -08:00
Wayne Davison
f96bac8468 (Matt) Dropped a superfluous word from a sentence. 2008-02-12 17:30:02 -08:00
Wayne Davison
8444a7c00d (Matt) Needed to remove a few more files for distclean target. 2008-02-12 17:29:09 -08:00
Wayne Davison
c9d3bc3fca A few more NEWS tweaks. 2008-02-10 21:21:24 -08:00
Wayne Davison
8340aa9670 Mention a couple more items. 2008-02-10 21:02:05 -08:00
Wayne Davison
3e2c0024d5 Made reconfigure target check if configure.sh was up-to-date. 2008-02-10 20:39:31 -08:00
Wayne Davison
205393a2b5 Preparing for release of 3.0.0pre9 2008-02-10 20:16:25 -08:00
Wayne Davison
5f0f2e0894 Some improvements for --hard-links and --filter options. 2008-02-10 20:10:13 -08:00
Wayne Davison
a5bb0902b4 One more fix in set_modtime() when we get ENOSYS on a symlink. 2008-02-10 15:39:21 -08:00
Wayne Davison
d348d5fd5f Add a trailing slash to a modname arg that has no path information.
This ensures that the user gets a "skipping" message if they didn't
specify -r or -d.  (A trailing-slash was already being added to a
lone modname for --list-only transfers.)
2008-02-09 22:07:03 -08:00
Wayne Davison
21897ecbed Improved the "symlink has no referent" logic to work with all the
--copy*links options.
2008-02-09 21:41:50 -08:00
Wayne Davison
01103e1870 Make do_recv() reset copy_unsafe_links too (just like it does for
copy_links and copy_dirlinks).
2008-02-09 21:33:13 -08:00
Wayne Davison
2d8f9b1df0 Ignore exit-code 23 when we expect a daemon-excluded file to be excluded. 2008-02-09 21:30:49 -08:00
Wayne Davison
68f1e7e594 (Matt) Made a daemon-refused file an FERROR_XFER with a better message. 2008-02-07 11:24:38 -08:00
Wayne Davison
87629cf2f6 Re-indent some code in set_file_attrs() to make the flow clearer. 2008-02-07 07:24:58 -08:00
Wayne Davison
e7f642cffe Using rebase for the patches has become a failing-hunk
pain in the neck, so I'm switching to using merge.
2008-02-06 16:39:53 -08:00
Wayne Davison
3e8fe565ed A daemon needs to call setup_iconv() after parsing the options
it receives.
2008-02-06 16:13:37 -08:00
Wayne Davison
e96c7777d7 Fixed return code from hard_link_one() when not verbose. 2008-02-06 16:06:33 -08:00
Wayne Davison
71daa07fb1 Make get_xattr_names() even safer at fetching the list of attr names. 2008-02-06 07:52:00 -08:00
Wayne Davison
287bb276d5 Only check F_OWNER() if uid_ndx is non-zero. 2008-02-04 21:17:27 -08:00
Wayne Davison
ddc8110dea Fixed local_child() so that the client side really does handle
the log-file writing.
2008-02-04 12:52:41 -08:00
Wayne Davison
c0f4228d66 Don't try to use recv_xattr_request() with --dry-run. Fixes an
internal abbrev error on the sending side.
2008-02-04 12:34:02 -08:00
Wayne Davison
d6e6333a02 Store the key64 flag from hashtable_create() in the hashtable structure
so that hashtable_find() knows which hashtable is which on a 64-bit
architecture.
2008-02-04 07:29:22 -08:00
Wayne Davison
970ce063ee Fixed finding of parent's description when @ARGV doesn't mention it. 2008-02-04 00:12:01 -08:00
Wayne Davison
dd1f0da818 Improved the usage message. 2008-02-03 23:40:20 -08:00
Wayne Davison
38a4bd432a Fixed a couple DEL_OWNED_BY_US glitches. 2008-02-03 16:40:28 -08:00
Wayne Davison
3eabe6aa41 Dump delete_item()'s "replace" var to reduce recursive stack use. 2008-02-03 15:13:36 -08:00
Wayne Davison
f2b7b64d86 Fixed the diffing of generated files when creating a patch that has
a parent that is not the master branch.
2008-02-02 17:00:25 -08:00
Wayne Davison
b2057d38a9 Some extra password-clarification verbage from Matt. 2008-01-29 17:19:22 -08:00
Wayne Davison
964244b90d Fixed several glitches with failed updates and batch files:
- Correctly identify when a missing batch update is for a resend.
- Made a missing batch update an xfer error.
- Made a failed redo an xfer error.
- Identify a failed transfer file consistently when it is a solo file.
- Have --read-batch say "may try again" instead of "will try again".
2008-01-27 14:40:50 -08:00
Wayne Davison
a7c1fa0049 Moved the batch option checking until after the protocol-version
in the batch file is known.  Also simplified the do_compress
checking, which had some erroneous def_compress_level code.
2008-01-26 11:58:17 -08:00
Wayne Davison
42a28d9d3a Improved a comment. 2008-01-26 09:13:19 -08:00
Wayne Davison
19284e2ef8 When removing a file/dir that is owned by us but does not have
owner-write permission, set it before the removal.
2008-01-26 08:47:02 -08:00
Wayne Davison
2268defe66 Fix some typos and such. 2008-01-25 16:57:54 -08:00
Wayne Davison
643b018cfb Mention iconv --list. 2008-01-25 16:57:26 -08:00
Wayne Davison
e35ad79b1b Make do_chmod() report an error with -E. 2008-01-25 16:57:02 -08:00
Wayne Davison
da01d2e843 Improved option handling for protocol 30 batch files. 2008-01-19 11:21:07 -08:00
Wayne Davison
641dc0c51e Output (BATCH ONLY) rather than (DRY RUN) for --only-write-batch. 2008-01-19 11:20:42 -08:00
Wayne Davison
69e2b4ee3a Fixed the combination of --dry-run and --only-write-batch. 2008-01-19 11:20:17 -08:00
Wayne Davison
75a01a0734 Don't apply filter rules to implied directories. 2008-01-19 10:09:22 -08:00
Wayne Davison
b769ad6a3e Another xattr "internal abbrev" fix for an xattr object that is
shared by multiple files:  handle the case where one file has an
abbreviated item set correctly, but a following item does not.
Also extended testsuite/xattrs.test to verify that this works.
2008-01-12 22:16:37 -08:00
Wayne Davison
6e59b97770 Preparing for release of 3.0.0pre8 2008-01-12 10:53:10 -08:00
Wayne Davison
4da9fcd41d - Make sure the Makefile is up-to-date before running "make gen".
- The release-rsync script now creates the generated patches in a
  separate dir from the normal patches.
2008-01-12 10:52:46 -08:00
Wayne Davison
68ddbaf645 Fixed a bug with truncated xattr data requests when the receiver
needs to discard some of the items from the sender's list.
2008-01-12 09:14:56 -08:00
Wayne Davison
555a081fe2 If "make gensend" fails, abort the script. 2008-01-11 13:20:14 -08:00
Wayne Davison
513d3fd806 Improved check_for_finished_files() to be really, really sure
that we've processed all the items on the hard-linked and redo
queues before we return.
2008-01-11 13:13:15 -08:00
Wayne Davison
34aa616d41 Fixed a length problem parsing an arg of "./". 2008-01-09 11:51:44 -08:00
Wayne Davison
ec8637f367 Don't allow a slash to be specified in a module name.
Document the module-name limitations in rsyncd.conf.yo.
2008-01-09 11:41:23 -08:00
Wayne Davison
62a6b8df72 Made read_arg_from_pipe() handle EINTR. 2008-01-02 17:20:44 -08:00
Wayne Davison
dd6f31f70f Rebuild the Makefile when it is not up-to-date. 2008-01-01 10:43:55 -08:00
Wayne Davison
a5fd4b6e6e Renamed mkrounding.c to rounding.c. 2008-01-01 10:34:27 -08:00
Wayne Davison
eca151d457 Changed the creation of rounding.h to use a set of compile-time checks
similar to how configure determines the size of variables.
2008-01-01 10:27:19 -08:00
Wayne Davison
f859d3ded6 If we're cross-compiling, tell the user to run mkrounding on the
target machine to build the rounding.h file.
2008-01-01 08:59:26 -08:00
Wayne Davison
5288be3af7 Some minor tweaks:
- Improved some comments in hlink.c.
- Changed "the" to "a" in rsyncd.conf.yo.
- Improved the PATCH.name filtering loop in patch-update.
2007-12-31 20:40:51 -08:00
Wayne Davison
83235dbc54 Fixed a case where the receiver indicates a successful update when the
transfer succeeded, but the final rename failed.
2007-12-31 10:31:43 -08:00
Wayne Davison
c78cb8f349 Made some user-/group-name pointers "const". 2007-12-29 22:52:42 -08:00
Wayne Davison
7210dbfd2a Some minor tweaking to name_to_uid() and name_to_gid(). 2007-12-29 22:52:04 -08:00
Wayne Davison
b6800a0b32 Added check for libiconv_open when iconv_open isn't found. 2007-12-29 09:53:37 -08:00
Wayne Davison
14eaa7a53b Added reconfigure target to re-run configure. 2007-12-29 09:44:58 -08:00
Wayne Davison
bc065415b0 Fixed Source URL and changed from ftp to http. 2007-12-19 09:36:05 -08:00
Wayne Davison
9203c8d274 Improved prepare-source to make it more flexible. The script now
lets the user choose which actions to perform and their order.
2007-12-17 23:32:47 -08:00
Wayne Davison
9468cf796d Fixed a FALL THROUGH comment. 2007-12-16 17:51:36 -08:00
Wayne Davison
77d4c400c2 Only ignore ENOSYS error from lutimes(). 2007-12-16 17:18:01 -08:00
Wayne Davison
e3915dac76 Added the 'h' option to the tar command that creates the patches
tar file just in case the patches directory is a symlink.
2007-12-16 15:41:59 -08:00
Wayne Davison
78246d1a09 Preparing for release of 3.0.0pre7 2007-12-16 15:09:43 -08:00
Wayne Davison
4bb319c6a6 Fixed extracting files from old tar file. 2007-12-16 15:09:21 -08:00
Wayne Davison
293b11b8a5 Mention 2 more changes in the NEWS. 2007-12-16 15:04:12 -08:00
Wayne Davison
8f42da0b50 Added a "fetchall" option. 2007-12-16 15:02:42 -08:00
Wayne Davison
a10186910d Fixed the check_filter() calls that might be checking an absolute path
in "use chroot = no" mode against a daemon's exclude restriction.
2007-12-16 14:16:37 -08:00
Wayne Davison
eb7715c1eb Moved the dir_count increment into an even better spot and make sure that
send_file_name() returned a non-NULL pointer before doing any DOT_NAME
processing in inc_recurse mode.
2007-12-16 14:14:35 -08:00
Wayne Davison
a7188cbf48 Fixed a potential memory leak in make_file(). 2007-12-15 11:57:34 -08:00
Wayne Davison
f7a2ac075f Refer to delta-transfer algorithm rather than rsync algorithm. 2007-12-15 08:35:45 -08:00
Wayne Davison
ce27f36d92 Check on the alternate destination dirs and report any problems. 2007-12-15 08:19:56 -08:00
Wayne Davison
af5ed0f257 Make push_dir() output where we are when verbosity is high. 2007-12-15 07:39:33 -08:00
Wayne Davison
e6d05dcfca Move incrementing of dir_count so that it can't get incremented
for a directory that isn't going to be included in the transfer.
2007-12-13 07:00:38 -08:00
Wayne Davison
65b4e4b2a9 Updated indexing for accurate progress and improved raw ndx values.
The sending side now has a sorted file-list in iconv mode so that it
can output progress in sorted order.  Simplified the over-the-wire
index values to ensure both sides will always agree on the values.
Optimized the allocation of the dir_flist->sorted array on the
receiving side with --iconv and incremental recursion.
2007-12-08 11:39:47 -08:00
Wayne Davison
37adeae73e A few more additions of $(srcdir) to Makefile.in. 2007-11-30 19:08:54 -08:00
Wayne Davison
091b3459f6 Fixed a build problem for those building in a different dir from
the srcdir.  Also got rid of "cd" code in configure stub.
2007-11-30 19:02:50 -08:00
Wayne Davison
85cdbb6be3 Reorganize the build-farm "prepare-source" magic a little.
This makes it easier for a user to request a copy of the
configure scripts via rsync ("./prepare-source fetch").
2007-11-30 18:01:18 -08:00
Wayne Davison
fcb1068f72 Improved header-file dependency rules even more. 2007-11-30 07:42:47 -08:00
Wayne Davison
07ad305e8a Make sure that the test programs get rebuilt when a header
file changes.
2007-11-29 23:44:40 -08:00
Wayne Davison
bcfb738c93 One build-farm system needs to fetch the proto.h* files too. 2007-11-29 23:21:51 -08:00
Wayne Davison
b58f5e17ed Simplified the time_t overflow check and moved an extra_len rounding
check into the right spot in recv_file_entry().
2007-11-29 22:52:20 -08:00
Wayne Davison
87de82f2d0 Make sure that the inc_recurse value is always set to
either 0 or 1.
2007-11-29 22:46:43 -08:00
Wayne Davison
87531e6302 Get rid of some compiler warnings in the AIX sysacls code. 2007-11-29 17:12:54 -08:00
Wayne Davison
eb67a6909b Don't try to process hard-link data in list-only mode. 2007-11-29 10:27:16 -08:00
Wayne Davison
9217ce30e3 Revised release-rsync and nightly-rsync code to create a tar files
with the right timestamps.
2007-11-29 09:29:45 -08:00
47 changed files with 1268 additions and 747 deletions

1
.gitignore vendored
View File

@@ -29,7 +29,6 @@ config.status
/t_unsafe
/wildtest
/getfsdev
/mkrounding
/rounding.h
/doc/rsync.pdf
/doc/rsync.ps

View File

@@ -51,7 +51,7 @@ CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
# Objects for CHECK_PROGS to clean
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
@@ -59,7 +59,7 @@ CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: conf_stop rsync$(EXEEXT) @MAKE_MAN@
all: conf_stop make_stop rsync$(EXEEXT) @MAKE_MAN@
install: all
-mkdir -p ${DESTDIR}${bindir}
@@ -76,16 +76,25 @@ rsync$(EXEEXT): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
$(OBJS): $(HEADERS)
$(CHECK_OBJS): $(HEADERS)
flist.o: rounding.h
rounding.h: mkrounding$(EXEEXT)
./mkrounding$(EXEEXT) >rounding.h
mkrounding$(EXEEXT): mkrounding.c rsync.h
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
@rm mkrounding.h
rounding.h: rounding.c rsync.h
@for r in 0 1 3; do \
if $(CC) $(CFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >/dev/null 2>&1; then \
echo "#define EXTRA_ROUNDING $$r" >rounding.h; \
if test -f "$$HOME/build_farm/build_test.fns"; then \
echo "EXTRA_ROUNDING is $$r" >&2; \
fi; \
break; \
fi; \
done
@rm -f rounding
@if test -f rounding.h; then : ; else \
echo "Failed to create rounding.h!"; \
exit 1; \
fi
tls$(EXEEXT): $(TLS_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
@@ -118,7 +127,18 @@ configure.sh config.h.in: configure.in aclocal.m4
autoconf -o configure.sh
autoheader && touch config.h.in
@echo 'Configure files changed -- perhaps run:'
@echo ' ./config.status --recheck; ./config.status'
@echo ' make reconfigure'
@exit 1
reconfigure: configure.sh
./config.status --recheck
./config.status
make_stop: Makefile
Makefile: Makefile.in config.status
@./config.status
@echo "Makefile updated -- rerun your make command."
@exit 1
proto: proto.h-tstamp
@@ -126,22 +146,22 @@ proto: proto.h-tstamp
proto.h: proto.h-tstamp
@echo ' ' >/dev/null
proto.h-tstamp: *.c lib/compat.c
perl mkproto.pl *.c lib/compat.c
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
man: rsync.1 rsyncd.conf.5
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
-./tweak_manpage rsync.1
yodl2man -o rsync.1 $(srcdir)/rsync.yo
-$(srcdir)/tweak_manpage rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
-./tweak_manpage rsyncd.conf.5
yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
-$(srcdir)/tweak_manpage rsyncd.conf.5
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
mkrounding mkrounding.h rounding.h
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
rounding rounding.h
cleantests:
rm -rf ./testtmp*
@@ -151,11 +171,14 @@ cleantests:
# the source directory.
distclean: clean
rm -f Makefile config.h config.status
rm -f lib/dummy popt/dummy zlib/dummy
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
rm -f $(srcdir)/lib/dummy $(srcdir)/popt/dummy $(srcdir)/zlib/dummy
rm -f config.cache config.log
rm -f $(srcdir)/config.cache $(srcdir)/config.log
rm -f shconfig $(srcdir)/shconfig
rm -f $(GENFILES)
rm -rf autom4te.cache
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
@@ -186,7 +209,7 @@ check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
wildtest.o: wildtest.c lib/wildmatch.c rsync.h config.h
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)

56
NEWS
View File

@@ -11,6 +11,7 @@ Changes since 2.6.9:
an implied dir be duplicated as a symlink, you should specify the
transfer of the symlink and the transfer of the referent directory as
separate args. (See also --keep-dirlinks and --no-implied-dirs.)
Also, exclude rules no longer have a partial effect on implied dirs.
- Requesting a remote file list without specifying -r (--recursive) now
sends the -d (--dirs) option to the remote rsync rather than sending -r
@@ -20,15 +21,40 @@ Changes since 2.6.9:
- In --dry-run mode, the last line of the verbose summary text is output
with a "(DRY RUN)" suffix to help remind you that no updates were made.
Similarly, --only-write-batch outputs "(BATCH ONLY)".
- A writable rsync daemon that disables "use chroot" now defaults to a
- A writable rsync daemon with "use chroot" disabled now defaults to a
symlink-munging behavior designed to make symlinks safer while also
allowing absolute symlinks to be stored and retrieved. This also has
the effect of making symlinks unusable while they're in the daemon's
hierarchy. See the daemon option "munge symlinks" for full details.
hierarchy. See the daemon's "munge symlinks" parameter for details.
BUG FIXES:
- A daemon with "use chroot = no" and excluded items listed in the daemon
config file now properly checks an absolute-path arg specified for these
options: --compare-dest, --link-dest, --copy-dest, --partial-dir,
--backup-dir, --temp-dir, and --files-from.
- A daemon can now be told to disable all user- and group-name translation
on a per-module basis. This avoids a potential problem with a writable
daemon module that has "use chroot" enabled -- if precautions weren't
taken, a user could try to add a missing library and get rsync to use
it. This makes rsync safer by default, and more configurable when id-
translation is not desired. See the daemon's "numeric ids" parameter
for full details.
- A chroot daemon can now indicate which part of its path should affect the
chroot call, and which part should become an inside-chroot path for the
module. This allows you to have outside-the-transfer paths (such as for
libraries) even when you enable chroot protection.
- If a file's data arrived successfully on the receiving side but the
rename of the temporary file to the destination file failed AND the
--remove-source-files (or the deprecated --remove-sent-files) option
was specified, rsync no longer erroneously removes the associated
source file.
- Fixed the output of -ii when combined with one of the --*-dest options:
it now itemizes all the items, not just the changed ones.
@@ -86,9 +112,19 @@ Changes since 2.6.9:
- Any errors output about password-file reading no longer cause an error at
the end of the run about a partial transfer.
- The --read-batch option for protocol 30 now ensures that several more
options are set correctly for the current batch file: --iconv, --acls,
--xattrs, --inplace, --append, and --append-verify.
- Using --only-write-batch to a daemon receiver now work properly (older
versions would update some files while writing the batch).
- Avoid outputting a "file has vanished" message when the file is a broken
symlink and --copy-unsafe-links or --copy-dirlinks are used (the code
already handled this for --copy-links).
- Fixed the combination of --only-write-batch and --dry-run.
ENHANCEMENTS:
- A new incremental-recursion algorithm is now used when rsync is talking
@@ -121,7 +157,7 @@ Changes since 2.6.9:
- Added the --acls (-A) option to preserve Access Control Lists. This is
an improved version of the prior patch that was available, and it even
supports OS X ACLs. If you need to have backward compatibility with old,
acl-patched versions of rsync, apply the acls.diff file from the patches
ACL-patched versions of rsync, apply the acls.diff file from the patches
dir.
- Added the --xattrs (-X) option to preserver extended attributes. This is
@@ -133,7 +169,7 @@ Changes since 2.6.9:
- Added the --fake-super option that allows a non-super user to preserve
all attributes of a file by using a special extended-attribute idiom.
It even supports the storing of foreign ACL data on your backup server.
There is also an analogous "fake super" option for an rsync daemon.
There is also an analogous "fake super" parameter for an rsync daemon.
- Added the --iconv option, which allows rsync to convert filenames from
one character-set to another during the transfer. The default is to make
@@ -145,9 +181,12 @@ Changes since 2.6.9:
"--enable-iconv=." is a good choice. See the rsync manpage for an
explanation of the --iconv option's settings.
- A new daemon config parameter, "charset", lets you control the character-
set that is used during an --iconv transfer to/from a daemon module.
- Added the --skip-compress=LIST option to override the default list of
file suffixes that will not be compressed when using --compress.
- The daemon's default for "dont compress" was extended to include:
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
The matching routine was also optimized to run more quickly.
@@ -176,6 +215,10 @@ Changes since 2.6.9:
that should not have an effect in a directory that is being deleted. e.g.
-f '-p .svn/' would only affect "live" .svn directories.
- Rsync checks all the alternate-destination args for validity (e.g.
--link-dest). This lets the user know when they specified a directory
that does not exist.
- If we get an error setting the time on a symlink, we don't complain about
it anymore (since some operating systems don't support that, and it's not
that important).
@@ -210,6 +253,9 @@ Changes since 2.6.9:
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
- Made the file-deletion code use a little less stack when recursing
through a directory hierarchy of extraneous files.
- Fixed a build problem with older (2.x) versions of gcc.
- Added some isType() functions that make dealing with signed characters

View File

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

2
acls.c
View File

@@ -556,7 +556,7 @@ static void send_ida_entries(const ida_entries *idal, int f)
for (ida = idal->idas; count--; ida++) {
uint32 xbits = ida->access << 2;
char *name;
const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
name = add_uid(ida->id);

76
batch.c
View File

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

View File

@@ -35,6 +35,7 @@ extern int ignore_errors;
extern int kluge_around_eof;
extern int daemon_over_rsh;
extern int sanitize_paths;
extern int numeric_ids;
extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
@@ -54,6 +55,10 @@ extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
extern char curr_dir[];
#ifdef ICONV_OPTION
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
char *auth_user;
int read_only = 0;
@@ -62,7 +67,8 @@ int munge_symlinks = 0;
struct chmod_mode_struct *daemon_chmod_modes;
/* module_dirlen is the length of the module_dir string when in daemon
* mode, not chrooted, and the path is not "/"; otherwise 0. */
* mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
* enabled module can have a non-"/" module_dir these days.) */
char *module_dir = NULL;
unsigned int module_dirlen = 0;
@@ -245,7 +251,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
if (list_only && strncmp(*argv, modname, modlen) == 0
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
else
@@ -355,8 +361,12 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
char *bp = buf, *eob = buf + limit - 1;
while (1) {
if (read(fd, bp, 1) != 1)
int got = read(fd, bp, 1);
if (got != 1) {
if (got < 0 && errno == EINTR)
continue;
return -1;
}
if (*bp == '\0')
break;
if (bp < eob)
@@ -370,7 +380,7 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
{
int argc, opt_cnt;
char **argv;
char **argv, *chroot_path = NULL;
char line[BIGPATHBUFLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
@@ -381,6 +391,13 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
pid_t pre_exec_pid = 0;
char *request = NULL;
#ifdef ICONV_OPTION
iconv_opt = lp_charset(i);
if (*iconv_opt)
setup_iconv();
iconv_opt = NULL;
#endif
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
@@ -463,18 +480,32 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
/* TODO: Perhaps take a list of gids, and make them into the
* supplementary groups. */
/* We do a push_dir() without actually calling chdir() in order
* to make sure that the module's path is absolute. After this
* check, module_dir will be set to an absolute path. */
module_dir = lp_path(i);
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0';
p += 2;
} else if ((p = strdup("/")) == NULL)
out_of_memory("rsync_module");
}
/* We do a push_dir() that doesn't actually call chdir()
* just to make a relative path absolute. */
strlcpy(line, curr_dir, sizeof line);
if (!push_dir(module_dir, 1))
goto chdir_failed;
if (strcmp(curr_dir, module_dir) != 0)
module_dir = strdup(curr_dir);
if (strcmp(curr_dir, module_dir) != 0
&& (module_dir = strdup(curr_dir)) == NULL)
out_of_memory("rsync_module");
push_dir(line, 1); /* Restore curr_dir. */
if (use_chroot || (module_dirlen = strlen(module_dir)) == 1) {
if (use_chroot) {
chroot_path = module_dir;
module_dir = p; /* p is "/" or our inside-chroot path */
}
module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
if (module_dirlen == 1) {
module_dirlen = 0;
set_filter_dir("/", 1);
} else
@@ -507,8 +538,17 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (!use_chroot)
p = module_dir;
else if (module_dirlen) {
pathjoin(line, sizeof line, chroot_path, module_dir+1);
p = line;
} else
p = chroot_path;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", module_dir) < 0
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", p) < 0
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
@@ -608,13 +648,15 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(module_dir)) {
rsyserr(FLOG, errno, "chroot %s failed", module_dir);
if (chroot(chroot_path)) {
rsyserr(FLOG, errno, "chroot %s failed", chroot_path);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0))
if (!push_dir(module_dir, 0))
goto chdir_failed;
if (module_dirlen)
sanitize_paths = 1;
} else {
if (!push_dir(module_dir, 0)) {
chdir_failed:
@@ -626,7 +668,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
}
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
munge_symlinks = !use_chroot;
munge_symlinks = !use_chroot || module_dirlen;
if (munge_symlinks) {
STRUCT_STAT st;
if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
@@ -764,6 +806,23 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
exit_cleanup(RERR_UNSUPPORTED);
}
#ifdef ICONV_OPTION
if (!iconv_opt) {
if (ic_send != (iconv_t)-1) {
iconv_close(ic_send);
ic_send = (iconv_t)-1;
}
if (ic_recv != (iconv_t)-1) {
iconv_close(ic_recv);
ic_recv = (iconv_t)-1;
}
}
#endif
if (!numeric_ids
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
set_io_timeout(lp_timeout(i));

View File

@@ -48,7 +48,7 @@ extern int preserve_acls;
extern int preserve_xattrs;
extern int need_messages_from_generator;
extern int delete_mode, delete_before, delete_during, delete_after;
extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */
extern char *shell_cmd;
extern char *partial_dir;
extern char *dest_option;
extern char *files_from;
@@ -62,10 +62,17 @@ extern iconv_t ic_send, ic_recv;
/* 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 */
#ifdef ICONV_OPTION
int filesfrom_convert = 0;
#endif
#define CF_INC_RECURSE (1<<0)
#define CF_SYMLINK_TIMES (1<<1)
static const char *client_info;
/* The server makes sure that if either side only supports a pre-release
* version of a protocol, that both sides must speak a compatible version
* of that protocol for it to be advertised as available. */
@@ -79,8 +86,9 @@ static void check_sub_protocol(void)
int our_sub = 0;
#endif
if (!shell_cmd || !(dot = strchr(shell_cmd, '.'))
|| !(their_protocol = atoi(shell_cmd))
/* client_info starts with VER.SUB string if client is a pre-release. */
if (!(their_protocol = atoi(client_info))
|| !(dot = strchr(client_info, '.'))
|| !(their_sub = atoi(dot+1))) {
#if SUBPROTOCOL_VERSION != 0
if (our_sub)
@@ -103,6 +111,8 @@ static void check_sub_protocol(void)
void set_allow_inc_recurse(void)
{
client_info = shell_cmd ? shell_cmd : "";
if (!recurse || use_qsort)
allow_inc_recurse = 0;
else if (!am_sender
@@ -110,7 +120,7 @@ void set_allow_inc_recurse(void)
|| delay_updates || prune_empty_dirs))
allow_inc_recurse = 0;
else if (am_server && !local_server
&& (!shell_cmd || strchr(shell_cmd, 'i') == NULL))
&& (strchr(client_info, 'i') == NULL))
allow_inc_recurse = 0;
}
@@ -171,6 +181,8 @@ void setup_protocol(int f_out,int f_in)
PROTOCOL_VERSION, am_server? "Server" : "Client");
exit_cleanup(RERR_PROTOCOL);
}
if (read_batch)
check_batch_flags();
if (protocol_version < 30) {
if (append_mode == 1)
@@ -231,11 +243,26 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
} else if (protocol_version >= 30) {
int compat_flags;
if (am_server) {
inc_recurse = allow_inc_recurse;
write_byte(f_out, inc_recurse);
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
write_byte(f_out, compat_flags);
} else
inc_recurse = read_byte(f_in);
compat_flags = read_byte(f_in);
/* The inc_recurse var MUST be set to 0 or 1. */
inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0;
if (am_sender) {
receiver_symlink_times = am_server
? strchr(client_info, 'L') != NULL
: !!(compat_flags & CF_SYMLINK_TIMES);
}
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
else
receiver_symlink_times = 1;
#endif
if (inc_recurse && !allow_inc_recurse) {
/* This should only be able to happen in a batch. */
fprintf(stderr,

22
configure vendored
View File

@@ -6,26 +6,20 @@
dir=`dirname $0`
realconfigure="$dir/configure.sh"
if [ ! -f "$realconfigure" ]; then
if test x"$dir" != x -a x"$dir" != x.; then
curdir=`pwd`
cd "$dir"
else
curdir=''
fi
if make -f prepare-source.mak conf; then
:
elif [ -f "$HOME/build_farm/build_test.fns" ]; then
if test ! -f "$realconfigure"; then
if test -f "$HOME/build_farm/build_test.fns"; then
# Allow the build farm to grab latest files via rsync.
rsync -pvz rsync://rsync.samba.org/rsyncftp/generated-files/'c*' .
actions='build fetch'
else
actions='build'
fi
if "$dir/prepare-source" $actions; then
:
else
echo 'Failed to build configure.sh and/or config.h.in -- giving up.' >&2
rm -f "$realconfigure"
exit 1
fi
if test x"$curdir" != x; then
cd "$curdir"
fi
fi
exec "$realconfigure" "${@}"

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=3.0.0pre6
RSYNC_VERSION=3.0.0pre10
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -554,6 +554,11 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
extattr_get_link sigaction sigprocmask setattrlist)
dnl cygwin iconv.h defines iconv_open as libiconv_open
if test x"$ac_cv_func_iconv_open" != x"yes"; then
AC_CHECK_FUNC(libiconv_open, [ac_cv_func_iconv_open=yes; AC_DEFINE(HAVE_ICONV_OPEN, 1)])
fi
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP

126
flist.c
View File

@@ -121,9 +121,8 @@ static char tmp_sum[MAX_DIGEST_LEN];
static char empty_sum[MAX_DIGEST_LEN];
static int flist_count_offset; /* for --delete --progress */
static int dir_count = 0;
static int high_hlink_ndx;
static void clean_flist(struct file_list *flist, int strip_root);
static void flist_sort_and_clean(struct file_list *flist, int strip_root);
static void output_flist(struct file_list *flist);
void init_flist(void)
@@ -352,7 +351,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
static uint32 rdev_major;
static uid_t uid;
static gid_t gid;
static char *user_name, *group_name;
static const char *user_name, *group_name;
static char lastname[MAXPATHLEN];
char fname[MAXPATHLEN];
int first_hlink_ndx = -1;
@@ -390,6 +389,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
/* Initialize starting value of xflags. */
if (protocol_version >= 30 && S_ISDIR(file->mode)) {
dir_count++;
if (file->flags & FLAG_CONTENT_DIR)
xflags = file->flags & FLAG_TOP_DIR;
else if (file->flags & FLAG_IMPLIED_DIR)
@@ -457,8 +457,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino);
first_hlink_ndx = (int32)(long)np->data - 1;
if (first_hlink_ndx < 0) {
high_hlink_ndx = ndx + first_ndx;
np->data = (void*)(long)(high_hlink_ndx + 1);
np->data = (void*)(long)(first_ndx + ndx + 1);
xflags |= XMIT_HLINK_FIRST;
}
xflags |= XMIT_HLINKED;
@@ -731,7 +730,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (protocol_version >= 30) {
modtime = read_varlong(f, 4);
#if SIZEOF_TIME_T < SIZEOF_INT64
if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) {
if (!am_generator && (int64)(time_t)modtime != modtime) {
rprintf(FERROR_XFER,
"Time value of %s truncated on receiver.\n",
lastname);
@@ -829,11 +828,6 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
extra_len += EXTRA_LEN;
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
#endif
if (inc_recurse && S_ISDIR(mode)) {
if (one_file_system) {
/* Room to save the dir's device for -x */
@@ -843,6 +837,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
} else
pool = flist->file_pool;
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
#endif
alloc_len = FILE_STRUCT_LEN + extra_len + basename_len
+ linkname_len;
bp = pool_alloc(pool, alloc_len, "recv_file_entry");
@@ -939,8 +938,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (preserve_hard_links && xflags & XMIT_HLINKED) {
if (protocol_version >= 30) {
if (xflags & XMIT_HLINK_FIRST) {
high_hlink_ndx = flist->ndx_start + flist->used;
F_HL_GNUM(file) = high_hlink_ndx;
F_HL_GNUM(file) = flist->ndx_start + flist->used;
} else
F_HL_GNUM(file) = first_hlink_ndx;
} else {
@@ -1039,9 +1037,15 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
}
if (save_errno == ENOENT) {
#ifdef SUPPORT_LINKS
/* Avoid "vanished" error if symlink points nowhere. */
if (copy_links && x_lstat(thisname, &st, NULL) == 0
&& S_ISLNK(st.st_mode)) {
/* When our options tell us to follow a symlink that
* points nowhere, tell the user about the symlink
* instead of giving a "vanished" message. We only
* dereference a symlink if one of the --copy*links
* options was specified, so there's no need for the
* extra lstat() if one of these options isn't on. */
if ((copy_links || copy_unsafe_links || copy_dirlinks)
&& x_lstat(thisname, &st, NULL) == 0
&& S_ISLNK(st.st_mode)) {
io_error |= IOERR_GENERAL;
rprintf(FERROR_XFER, "symlink has no referent: %s\n",
full_fname(thisname));
@@ -1114,7 +1118,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
extra_len += DIRNODE_EXTRA_CNT * EXTRA_LEN;
if (relative_paths)
extra_len += PTR_EXTRA_CNT * EXTRA_LEN;
dir_count++;
pool = dir_flist->file_pool;
} else
pool = flist->file_pool;
@@ -1235,11 +1238,14 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
file->mode = save_mode;
}
if (basename_len == 0+1)
if (basename_len == 0+1) {
if (!pool)
unmake_file(file);
return NULL;
}
if (unsort_ndx)
F_NDX(file) = dir_count - 1;
F_NDX(file) = dir_count;
return file;
}
@@ -1525,8 +1531,10 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
relnamecache **rnpp;
char *slash;
int len, need_new_dir;
struct filter_list_struct save_filter_list = filter_list;
flags = (flags | FLAG_IMPLIED_DIR) & ~(FLAG_TOP_DIR | FLAG_CONTENT_DIR);
filter_list.head = filter_list.tail = NULL; /* Don't filter implied dirs. */
if (inc_recurse) {
if (lastpath_struct && F_PATHNAME(lastpath_struct) == pathname
@@ -1568,11 +1576,11 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
xfer_dirs = save_xfer_dirs;
if (!inc_recurse)
return;
goto done;
}
if (!lastpath_struct)
return; /* dir must have vanished */
goto done; /* dir must have vanished */
len = strlen(limit+1);
memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list);
@@ -1586,6 +1594,9 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
out_of_memory("send_implied_dirs");
(*rnpp)->name_type = name_type;
strlcpy((*rnpp)->fname, limit+1, len + 1);
done:
filter_list = save_filter_list;
}
static void send1extra(int f, struct file_struct *file, struct file_list *flist)
@@ -1719,11 +1730,7 @@ void send_extra_file_list(int f, int at_least)
} else
flist->sorted = flist->files;
clean_flist(flist, 0);
flist->ndx_end = flist->ndx_start + flist->used - 1;
if (!need_unsorted_flist)
flist->ndx_end -= (dir_count - dstart);
flist_sort_and_clean(flist, 0);
add_dirs_to_tree(send_dir_ndx, flist, dir_count - dstart);
flist_done_allocating(flist);
@@ -1834,7 +1841,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
} else if (!len || fbuf[len - 1] == '/') {
if (len == 2 && fbuf[0] == '.') {
/* Turn "./" into just "." rather than "./." */
fbuf[1] = '\0';
fbuf[--len] = '\0';
} else {
if (len + 1 >= MAXPATHLEN)
overflow_exit("send_file_list");
@@ -1978,7 +1985,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
file = send_file_name(f, flist, fbuf, &st,
top_flags, ALL_FILTERS);
if (inc_recurse) {
if (name_type == DOT_NAME) {
if (name_type == DOT_NAME && file) {
if (send_dir_depth < 0) {
send_dir_depth = 0;
change_local_filter_dir(fbuf, len, send_dir_depth);
@@ -2021,28 +2028,16 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
* recursion mode, the sender marks duplicate dirs so that it can
* send them together in a single file-list. */
if (need_unsorted_flist) {
if (inc_recurse) {
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
out_of_memory("send_file_list");
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
clean_flist(flist, 0);
} else {
flist->sorted = flist->files;
flist->low = 0;
flist->high = flist->used - 1;
}
} else {
if (!(flist->sorted = new_array(struct file_struct *, flist->used)))
out_of_memory("send_file_list");
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
} else
flist->sorted = flist->files;
clean_flist(flist, 0);
}
flist_sort_and_clean(flist, 0);
file_total += flist->used;
/* We don't subtract dir_count for the first send since we
* might have one or more dot dirs which need to get sent. */
flist->ndx_end = flist->ndx_start + flist->used - 1;
if (!numeric_ids && !inc_recurse)
if (numeric_ids <= 0 && !inc_recurse)
send_id_list(f);
/* send the io_error flag */
@@ -2140,10 +2135,6 @@ struct file_list *recv_file_list(int f)
}
file_total += flist->used;
flist->ndx_end = flist->ndx_start + flist->used - 1;
if (inc_recurse && !need_unsorted_flist && flist->ndx_start > 1)
flist->ndx_end -= dir_flist->used - dstart;
if (verbose > 2)
rprintf(FINFO, "received %d names\n", flist->used);
@@ -2161,9 +2152,13 @@ struct file_list *recv_file_list(int f)
memcpy(flist->sorted, flist->files,
flist->used * sizeof (struct file_struct*));
if (inc_recurse && dir_flist->used > dstart) {
dir_flist->sorted = realloc_array(dir_flist->sorted,
struct file_struct *,
dir_flist->used);
static int dir_flist_malloced = 0;
if (dir_flist_malloced < dir_flist->malloced) {
dir_flist->sorted = realloc_array(dir_flist->sorted,
struct file_struct *,
dir_flist->malloced);
dir_flist_malloced = dir_flist->malloced;
}
memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
(dir_flist->used - dstart) * sizeof (struct file_struct*));
fsort(dir_flist->sorted + dstart, dir_flist->used - dstart);
@@ -2181,7 +2176,7 @@ struct file_list *recv_file_list(int f)
else if (f >= 0)
recv_id_list(f, flist);
clean_flist(flist, relative_paths);
flist_sort_and_clean(flist, relative_paths);
if (protocol_version < 30) {
/* Recv the io_error flag */
@@ -2321,18 +2316,19 @@ struct file_list *flist_new(int flags, char *msg)
if (!flist->file_pool)
out_of_memory(msg);
flist->ndx_start = inc_recurse ? 1 : 0;
flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0;
first_flist = cur_flist = flist->prev = flist;
} else {
struct file_list *prev = first_flist->prev;
flist->file_pool = first_flist->file_pool;
flist->ndx_start = first_flist->prev->ndx_end + 2;
if (flist->ndx_start <= high_hlink_ndx)
flist->ndx_start = high_hlink_ndx + 1;
flist->ndx_start = prev->ndx_start + prev->used + 1;
flist->flist_num = prev->flist_num + 1;
flist->prev = first_flist->prev;
flist->prev->next = first_flist->prev = flist;
flist->prev = prev;
prev->next = first_flist->prev = flist;
}
flist->pool_boundary = pool_boundary(flist->file_pool, 0);
flist_cnt++;
@@ -2378,7 +2374,7 @@ void flist_free(struct file_list *flist)
/* This routine ensures we don't have any duplicate names in our file list.
* duplicate names can cause corruption because of the pipelining. */
static void clean_flist(struct file_list *flist, int strip_root)
static void flist_sort_and_clean(struct file_list *flist, int strip_root)
{
char fbuf[MAXPATHLEN];
int i, prev_i;
@@ -2558,8 +2554,8 @@ static void output_flist(struct file_list *flist)
const char *who = who_am_i();
int i;
rprintf(FINFO, "[%s] flist start=%d, end=%d, used=%d, low=%d, high=%d\n",
who, flist->ndx_start, flist->ndx_end, flist->used, flist->low, flist->high);
rprintf(FINFO, "[%s] flist start=%d, used=%d, low=%d, high=%d\n",
who, flist->ndx_start, flist->used, flist->low, flist->high);
for (i = 0; i < flist->used; i++) {
file = flist->files[i];
if ((am_root || am_sender) && uid_ndx) {
@@ -2809,7 +2805,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
prune_empty_dirs = 0;
dirlist->sorted = dirlist->files;
clean_flist(dirlist, 0);
flist_sort_and_clean(dirlist, 0);
prune_empty_dirs = save_prune_empty_dirs;
if (verbose > 3)

View File

@@ -27,6 +27,7 @@ extern int dry_run;
extern int do_xfers;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int receiver_symlink_times;
extern int am_root;
extern int am_server;
extern int am_daemon;
@@ -41,6 +42,7 @@ extern int preserve_links;
extern int preserve_devices;
extern int preserve_specials;
extern int preserve_hard_links;
extern int preserve_executability;
extern int preserve_perms;
extern int preserve_times;
extern int uid_ndx;
@@ -91,6 +93,7 @@ extern int one_file_system;
extern struct stats stats;
extern dev_t filesystem_dev;
extern mode_t orig_umask;
extern uid_t our_uid;
extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
@@ -113,8 +116,16 @@ static int need_retouch_dir_perms;
static const char *solo_file = NULL;
/* For calling delete_item() and delete_dir_contents(). */
#define DEL_RECURSE (1<<1) /* recurse */
#define DEL_OWNED_BY_US (1<<0) /* file/dir has our uid */
#define DEL_RECURSE (1<<1) /* if dir, delete all contents */
#define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */
#define DEL_FOR_FILE (1<<3) /* making room for a replacement file */
#define DEL_FOR_DIR (1<<4) /* making room for a replacement dir */
#define DEL_FOR_SYMLINK (1<<5) /* making room for a replacement symlink */
#define DEL_FOR_DEVICE (1<<6) /* making room for a replacement device */
#define DEL_FOR_SPECIAL (1<<7) /* making room for a replacement special */
#define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
enum nonregtype {
TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
@@ -127,7 +138,6 @@ enum delret {
/* Forward declaration for delete_item(). */
static enum delret delete_dir_contents(char *fname, int flags);
static int is_backup_file(char *fn)
{
int k = strlen(fn) - backup_suffix_len;
@@ -140,7 +150,7 @@ static int is_backup_file(char *fn)
* Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
* a directory! (The buffer is used for recursion, but returned unchanged.)
*/
static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
static enum delret delete_item(char *fbuf, int mode, int flags)
{
enum delret ret;
char *what;
@@ -151,6 +161,9 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
fbuf, mode, flags);
}
if (!am_root && !(mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
do_chmod(fbuf, mode |= S_IWUSR);
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
ignore_perishable = 1;
/* If DEL_RECURSE is not set, this just reports emptiness. */
@@ -161,7 +174,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
/* OK: try to delete the directory. */
}
if (!replace && max_delete >= 0 && ++deletion_count > max_delete)
if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)
return DR_AT_LIMIT;
if (S_ISDIR(mode)) {
@@ -176,7 +189,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
}
if (ok) {
if (!replace)
if (!(flags & DEL_MAKE_ROOM))
log_delete(fbuf, mode);
ret = DR_SUCCESS;
} else {
@@ -195,9 +208,18 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
}
check_ret:
if (replace && ret != DR_SUCCESS) {
if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {
const char *desc;
switch (flags & DEL_MAKE_ROOM) {
case DEL_FOR_FILE: desc = "regular file"; break;
case DEL_FOR_DIR: desc = "directory"; break;
case DEL_FOR_SYMLINK: desc = "symlink"; break;
case DEL_FOR_DEVICE: desc = "device file"; break;
case DEL_FOR_SPECIAL: desc = "special file"; break;
default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
}
rprintf(FERROR_XFER, "could not make way for new %s: %s\n",
replace, fbuf);
desc, fbuf);
}
return ret;
}
@@ -242,7 +264,7 @@ static enum delret delete_dir_contents(char *fname, int flags)
remainder = MAXPATHLEN - (p - fname);
/* We do our own recursion, so make delete_item() non-recursive. */
flags = (flags & ~DEL_RECURSE) | DEL_DIR_IS_EMPTY;
flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM)) | DEL_DIR_IS_EMPTY;
for (j = dirlist->used; j--; ) {
struct file_struct *fp = dirlist->files[j];
@@ -258,11 +280,18 @@ static enum delret delete_dir_contents(char *fname, int flags)
}
strlcpy(p, fp->basename, remainder);
if (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid)
flags |= DEL_OWNED_BY_US;
else
flags &= ~DEL_OWNED_BY_US;
/* Save stack by recursing to ourself directly. */
if (S_ISDIR(fp->mode)
&& delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
if (delete_item(fname, fp->mode, NULL, flags) != DR_SUCCESS)
if (S_ISDIR(fp->mode)) {
if (!am_root && !(fp->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
do_chmod(fname, fp->mode |= S_IWUSR);
if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
@@ -312,14 +341,17 @@ static int flush_delete_delay(void)
return 1;
}
static int remember_delete(struct file_struct *file, const char *fname)
static int remember_delete(struct file_struct *file, const char *fname, int flags)
{
const char *plus = (!am_root && !(file->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
? "+" : "";
int len;
while (1) {
len = snprintf(deldelay_buf + deldelay_cnt,
deldelay_size - deldelay_cnt,
"%x %s%c", (int)file->mode, fname, '\0');
"%s%x %s%c",
plus, (int)file->mode, fname, '\0');
if ((deldelay_cnt += len) <= deldelay_size)
break;
if (deldelay_fd < 0 && !start_delete_delay_temp())
@@ -332,7 +364,7 @@ static int remember_delete(struct file_struct *file, const char *fname)
return 1;
}
static int read_delay_line(char *buf)
static int read_delay_line(char *buf, int *own_flag_p)
{
static int read_pos = 0;
int j, len, mode;
@@ -373,6 +405,11 @@ static int read_delay_line(char *buf)
}
bp = deldelay_buf + read_pos;
if (*bp == '+') {
bp++;
*own_flag_p = DEL_OWNED_BY_US;
} else
*own_flag_p = 0;
if (sscanf(bp, "%x ", &mode) != 1) {
invalid_data:
@@ -397,15 +434,15 @@ static int read_delay_line(char *buf)
static void do_delayed_deletions(char *delbuf)
{
int mode;
int mode, own_flag;
if (deldelay_fd >= 0) {
if (deldelay_cnt && !flush_delete_delay())
return;
lseek(deldelay_fd, 0, 0);
}
while ((mode = read_delay_line(delbuf)) >= 0)
delete_item(delbuf, mode, NULL, DEL_RECURSE);
while ((mode = read_delay_line(delbuf, &own_flag)) >= 0)
delete_item(delbuf, mode, own_flag | DEL_RECURSE);
if (deldelay_fd >= 0)
close(deldelay_fd);
}
@@ -467,12 +504,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
continue;
}
if (flist_find(cur_flist, fp) < 0) {
int flags = DEL_RECURSE
| (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid ? DEL_OWNED_BY_US : 0);
f_name(fp, delbuf);
if (delete_during == 2) {
if (!remember_delete(fp, delbuf))
if (!remember_delete(fp, delbuf, flags))
break;
} else
delete_item(delbuf, fp->mode, NULL, DEL_RECURSE);
delete_item(delbuf, fp->mode, flags);
}
}
@@ -515,7 +554,7 @@ static void do_delete_pass(void)
int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
{
#ifndef HAVE_LUTIMES
#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
if (S_ISLNK(file->mode)) {
;
} else
@@ -526,6 +565,9 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
return 0;
if (preserve_executability && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
return 0;
if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
return 0;
@@ -558,8 +600,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
{
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
int keep_time = !preserve_times ? 0
: S_ISDIR(file->mode) ? preserve_times > 1
: !S_ISLNK(file->mode);
: S_ISDIR(file->mode) ? preserve_times > 1 :
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
(receiver_symlink_times && !(file->flags & FLAG_TIME_FAILED)) ||
#endif
!S_ISLNK(file->mode);
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
iflags |= ITEM_REPORT_SIZE;
@@ -573,7 +618,8 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
;
} else
#endif
if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
if ((preserve_perms || preserve_executability)
&& !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
iflags |= ITEM_REPORT_PERMS;
if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
iflags |= ITEM_REPORT_OWNER;
@@ -841,7 +887,7 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru
{
char buf[MAXPATHLEN];
const char *copy_to, *partialptr;
int fd_w;
int ok, fd_w;
if (inplace) {
/* Let copy_file open the destination in place. */
@@ -865,11 +911,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;
if (partialptr && *partialptr == '/')
partialptr = NULL;
finish_transfer(dest, copy_to, src, partialptr, file, 1, 0);
ok = finish_transfer(dest, copy_to, src, partialptr, file, 1, 0);
cleanup_disable();
return 0;
return ok ? 0 : -1;
}
/* This is only called for regular files. We return -2 if we've finished
@@ -925,7 +969,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
goto try_a_copy;
if (preserve_hard_links && F_IS_HLINKED(file))
finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j);
if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
if (!maybe_ATTRS_REPORT && (verbose > 1 || stdout_format_has_i > 1)) {
itemize(cmpbuf, file, ndx, 1, sxp,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
0, "");
@@ -947,10 +991,6 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
return -1;
if (itemizing)
itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
xattr_clear_locals(file);
#endif
if (maybe_ATTRS_REPORT
&& ((!itemizing && verbose && match_level == 2)
|| (verbose > 1 && match_level == 3))) {
@@ -1171,38 +1211,40 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
uchar fnamecmp_type;
int implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;
int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;
int is_dir = !S_ISDIR(file->mode) ? 0
: inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1
: 1;
if (verbose > 2)
rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx);
if (list_only) {
if (S_ISDIR(file->mode)
&& ((!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
|| (inc_recurse && ndx != cur_flist->ndx_start - 1)))
if (is_dir < 0
|| (is_dir && !implied_dirs && file->flags & FLAG_IMPLIED_DIR))
return;
list_file_entry(file);
return;
}
if (server_filter_list.head) {
int filtered = check_filter(&server_filter_list, fname, is_dir) < 0;
if (is_dir < 0 && filtered)
return;
if (excluded_below >= 0) {
if (F_DEPTH(file) > excluded_below
&& (!implied_dirs_are_missing || f_name_has_prefix(file, excluded_dir)))
goto skipping;
excluded_below = -1;
}
if (check_filter(&server_filter_list, fname,
S_ISDIR(file->mode)) < 0) {
if (S_ISDIR(file->mode)) {
if (filtered) {
if (is_dir) {
excluded_below = F_DEPTH(file);
excluded_dir = file;
}
skipping:
if (verbose) {
rprintf(FINFO,
"skipping server-excluded file \"%s\"\n",
fname);
}
rprintf(FERROR_XFER,
"skipping daemon-excluded file \"%s\"\n",
fname);
return;
}
}
@@ -1214,7 +1256,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
dry_run--;
missing_below = -1;
} else if (!dry_run) {
if (S_ISDIR(file->mode))
if (is_dir)
file->flags |= FLAG_MISSING_DIR;
return;
}
@@ -1262,18 +1304,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
need_fuzzy_dirlist = 0;
}
statret = link_stat(fname, &sx.st,
keep_dirlinks && S_ISDIR(file->mode));
statret = link_stat(fname, &sx.st, keep_dirlinks && is_dir);
stat_errno = errno;
}
if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {
if (verbose > 1) {
rprintf(FINFO, "not creating new %s \"%s\"\n",
S_ISDIR(file->mode) ? "directory" : "file",
fname);
}
if (S_ISDIR(file->mode)) {
if (is_dir) {
if (is_dir < 0)
return;
if (missing_below < 0) {
if (dry_run)
dry_run++;
@@ -1282,13 +1320,20 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
file->flags |= FLAG_MISSING_DIR;
}
if (verbose > 1) {
rprintf(FINFO, "not creating new %s \"%s\"\n",
is_dir ? "directory" : "file", fname);
}
return;
}
if (S_ISDIR(file->mode)) {
if (statret == 0 && sx.st.st_uid == our_uid)
del_opts |= DEL_OWNED_BY_US;
if (is_dir) {
if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
goto cleanup;
if (inc_recurse && ndx != cur_flist->ndx_start - 1) {
if (is_dir < 0) {
/* In inc_recurse mode we want to make sure any missing
* directories get created while we're still processing
* the parent dir (which allows us to touch the parent
@@ -1296,7 +1341,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
* full later (right before we handle its contents). */
if (statret == 0
&& (S_ISDIR(sx.st.st_mode)
|| delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0))
|| delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
goto cleanup; /* Any errors get reported later. */
if (do_mkdir(fname, file->mode & 0700) == 0)
file->flags |= FLAG_DIR_CREATED;
@@ -1308,7 +1353,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
* we need to delete it. If it doesn't exist, then
* (perhaps recursively) create it. */
if (statret == 0 && !S_ISDIR(sx.st.st_mode)) {
if (delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0)
goto skipping_dir_contents;
statret = -1;
}
@@ -1437,7 +1482,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
}
/* Not the right symlink (or not a symlink), so
* delete it. */
if (delete_item(fname, sx.st.st_mode, "symlink", del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_SYMLINK) != 0)
goto cleanup;
} else if (basis_dir[0] != NULL) {
int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
@@ -1491,15 +1536,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
uint32 *devp = F_RDEV_P(file);
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
if (statret == 0) {
char *t;
int del_for_flag;
if (IS_DEVICE(file->mode)) {
if (!IS_DEVICE(sx.st.st_mode))
statret = -1;
t = "device file";
del_for_flag = DEL_FOR_DEVICE;
} else {
if (!IS_SPECIAL(sx.st.st_mode))
statret = -1;
t = "special file";
del_for_flag = DEL_FOR_SPECIAL;
}
if (statret == 0
&& BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
@@ -1516,7 +1561,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
goto return_with_success;
goto cleanup;
}
if (delete_item(fname, sx.st.st_mode, t, del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | del_for_flag) != 0)
goto cleanup;
} else if (basis_dir[0] != NULL) {
int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
@@ -1607,7 +1652,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
fnamecmp_type = FNAMECMP_FNAME;
if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
if (delete_item(fname, sx.st.st_mode, "regular file", del_opts) != 0)
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0)
goto cleanup;
statret = -1;
stat_errno = ENOENT;
@@ -1899,57 +1944,63 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
char fbuf[MAXPATHLEN];
int ndx;
while (1) {
#ifdef SUPPORT_HARD_LINKS
while (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
flist = flist_for_ndx(ndx);
assert(flist != NULL);
file = flist->files[ndx - flist->ndx_start];
assert(file->flags & FLAG_HLINKED);
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
flist->in_progress--;
}
if (preserve_hard_links && (ndx = get_hlink_num()) != -1) {
flist = flist_for_ndx(ndx);
assert(flist != NULL);
file = flist->files[ndx - flist->ndx_start];
assert(file->flags & FLAG_HLINKED);
finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
flist->in_progress--;
continue;
}
#endif
while (check_redo && (ndx = get_redo_num()) != -1) {
csum_length = SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups; /* avoid dup backup w/inplace */
ignore_times++;
if (check_redo && (ndx = get_redo_num()) != -1) {
csum_length = SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups; /* avoid dup backup w/inplace */
ignore_times++;
flist = cur_flist;
cur_flist = flist_for_ndx(ndx);
flist = cur_flist;
cur_flist = flist_for_ndx(ndx);
file = cur_flist->files[ndx - cur_flist->ndx_start];
if (solo_file)
strlcpy(fbuf, solo_file, sizeof fbuf);
else
f_name(file, fbuf);
recv_generator(fbuf, file, ndx, itemizing, code, sock_f_out);
cur_flist->to_redo--;
file = cur_flist->files[ndx - cur_flist->ndx_start];
if (solo_file)
strlcpy(fbuf, solo_file, sizeof fbuf);
else
f_name(file, fbuf);
recv_generator(fbuf, file, ndx, itemizing, code, sock_f_out);
cur_flist->to_redo--;
cur_flist = flist;
cur_flist = flist;
csum_length = SHORT_SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups;
ignore_times--;
}
csum_length = SHORT_SUM_LENGTH;
max_size = -max_size;
min_size = -min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
append_mode = -append_mode;
make_backups = -make_backups;
ignore_times--;
continue;
}
while (cur_flist != first_flist) { /* only possible with inc_recurse */
if (cur_flist == first_flist)
break;
/* We only get here if inc_recurse is enabled. */
if (first_flist->in_progress || first_flist->to_redo)
break;

View File

@@ -24,7 +24,7 @@
struct hashtable *hashtable_create(int size, int key64)
{
struct hashtable *tbl;
int node_size = key64 ? sizeof (struct ht_int64_node )
int node_size = key64 ? sizeof (struct ht_int64_node)
: sizeof (struct ht_int32_node);
/* Pick a power of 2 that can hold the requested size. */
@@ -41,6 +41,7 @@ struct hashtable *hashtable_create(int size, int key64)
tbl->size = size;
tbl->entries = 0;
tbl->node_size = node_size;
tbl->key64 = key64;
return tbl;
}
@@ -55,7 +56,7 @@ void hashtable_destroy(struct hashtable *tbl)
* already existing. Returns NULL if not allocating and not found. */
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
{
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
int key64 = tbl->key64;
struct ht_int32_node *node;
uint32 ndx;

43
hlink.c
View File

@@ -24,6 +24,7 @@
extern int verbose;
extern int dry_run;
extern int list_only;
extern int am_sender;
extern int inc_recurse;
extern int do_xfers;
@@ -142,7 +143,7 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
if (gnum != gnum_next)
break;
F_HL_PREV(file) = prev;
/* The linked list must use raw ndx values. */
/* The linked list uses over-the-wire ndx values. */
if (unsort_ndx)
prev = F_NDX(file);
else
@@ -174,23 +175,25 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
* to first when we're done. */
void match_hard_links(struct file_list *flist)
{
int i, ndx_count = 0;
int32 *ndx_list;
if (!list_only) {
int i, ndx_count = 0;
int32 *ndx_list;
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
if (!(ndx_list = new_array(int32, flist->used)))
out_of_memory("match_hard_links");
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
for (i = 0; i < flist->used; i++) {
if (F_IS_HLINKED(flist->sorted[i]))
ndx_list[ndx_count++] = i;
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
}
hlink_flist = flist;
if (ndx_count)
match_gnums(ndx_list, ndx_count);
free(ndx_list);
if (protocol_version < 30)
idev_destroy();
}
@@ -272,13 +275,13 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
if (!prev_name) {
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
/* Is the previous link is not complete yet? */
/* Is the previous link not complete yet? */
if (!(prev_file->flags & FLAG_HLINK_DONE)) {
/* Is the previous link being transferred? */
if (prev_file->flags & FLAG_FILE_SENT) {
/* Add ourselves to the list of files that will be
* updated when the transfer completes, and mark
* ourself as waiting for the transfer. */
/* Add ourselves to the list of files that will
* be updated when the transfer completes, and
* mark ourself as waiting for the transfer. */
F_HL_PREV(file) = F_HL_PREV(prev_file);
F_HL_PREV(prev_file) = ndx;
file->flags |= FLAG_FILE_SENT;
@@ -390,7 +393,7 @@ int hard_link_one(struct file_struct *file, const char *fname,
enum logcode code;
if (terse) {
if (!verbose)
return -1;
return 0;
code = FINFO;
} else
code = FERROR_XFER;

View File

@@ -1735,6 +1735,13 @@ int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
struct new_acl_entry *entry;
int keep_going;
if (entry_id == SMB_ACL_FIRST_ENTRY)
theacl->count = 0;
else if (entry_id != SMB_ACL_NEXT_ENTRY) {
errno = EINVAL;
return -1;
}
DEBUG(10,("This is the count: %d\n",theacl->count));
/* Check if count was previously set to -1. *
@@ -1804,7 +1811,6 @@ SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
struct acl_entry_link *acl_entry_link_head;
int i;
int rc = 0;
uid_t user_id;
/* AIX has no DEFAULT */
if ( type == SMB_ACL_TYPE_DEFAULT ) {
@@ -2025,7 +2031,6 @@ SMB_ACL_T sys_acl_get_fd(int fd)
struct acl_entry_link *acl_entry_link_head;
int i;
int rc = 0;
uid_t user_id;
/* Get the acl using fstatacl */
@@ -2255,6 +2260,11 @@ SMB_ACL_T sys_acl_init( int count)
{
struct acl_entry_link *theacl = NULL;
if (count < 0) {
errno = EINVAL;
return NULL;
}
DEBUG(10,("Entering sys_acl_init\n"));
theacl = SMB_MALLOC_P(struct acl_entry_link);
@@ -2373,7 +2383,6 @@ int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl
struct acl_entry *acl_entry = NULL;
struct ace_id *ace_id = NULL;
uint id_type;
uint ace_access;
uint user_id;
uint acl_length;
uint rc;
@@ -2551,7 +2560,7 @@ int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
}
#endif
int sys_acl_delete_def_file(const char *name)
int sys_acl_delete_def_file(UNUSED(const char *name))
{
/* AIX has no default ACL */
return 0;

View File

@@ -124,6 +124,7 @@ static global Globals;
typedef struct
{
char *auth_users;
char *charset;
char *comment;
char *dont_compress;
char *exclude;
@@ -158,6 +159,7 @@ typedef struct
BOOL ignore_nonreadable;
BOOL list;
BOOL munge_symlinks;
BOOL numeric_ids;
BOOL read_only;
BOOL strict_modes;
BOOL transfer_logging;
@@ -173,7 +175,8 @@ typedef struct
static service sDefault =
{
/* auth_users; */ NULL,
/* comment; */ NULL,
/* charset; */ NULL,
/* comment; */ NULL,
/* dont_compress; */ DEFAULT_DONT_COMPRESS,
/* exclude; */ NULL,
/* exclude_from; */ NULL,
@@ -207,6 +210,7 @@ static service sDefault =
/* ignore_nonreadable; */ False,
/* list; */ True,
/* munge_symlinks; */ (BOOL)-1,
/* numeric_ids; */ (BOOL)-1,
/* read_only; */ True,
/* strict_modes; */ True,
/* transfer_logging; */ False,
@@ -301,6 +305,7 @@ static struct parm_struct parm_table[] =
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
{"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
@@ -323,6 +328,7 @@ static struct parm_struct parm_table[] =
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
{"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
{"numeric ids", P_BOOL, P_LOCAL, &sDefault.numeric_ids, NULL,0},
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
#ifdef HAVE_PUTENV
@@ -392,6 +398,7 @@ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_charset, charset)
FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
FN_LOCAL_STRING(lp_exclude, exclude)
@@ -413,12 +420,12 @@ FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_BOOL(lp_fake_super, fake_super)
@@ -426,6 +433,7 @@ FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
@@ -784,6 +792,11 @@ static BOOL do_section(char *sectionname)
return(True);
}
if (strchr(sectionname, '/') != NULL) {
rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
return False;
}
/* if we have a current service, tidy it up before moving on */
bRetval = True;

8
log.c
View File

@@ -41,6 +41,7 @@ extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern int receiver_symlink_times;
extern mode_t orig_umask;
extern char *auth_user;
extern char *stdout_format;
@@ -307,7 +308,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
switch (code) {
case FERROR_XFER:
got_xfer_error = 1;
/* CONTINUE */
/* FALL THROUGH */
case FERROR:
case FWARNING:
f = stderr;
@@ -623,7 +624,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
break;
case 'i':
if (iflags & ITEM_DELETED) {
n = "*deleting";
n = "*deleting ";
break;
}
n = c = buf2 + MAXPATHLEN - 32;
@@ -638,7 +639,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
c[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
: !preserve_times || (!receiver_symlink_times && S_ISLNK(file->mode))
? 'T' : 't';
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';

104
main.c
View File

@@ -45,6 +45,7 @@ extern int got_xfer_error;
extern int module_id;
extern int copy_links;
extern int copy_dirlinks;
extern int copy_unsafe_links;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
@@ -65,9 +66,11 @@ extern int batch_fd;
extern int filesfrom_fd;
extern int connect_timeout;
extern pid_t cleanup_child_pid;
extern unsigned int module_dirlen;
extern struct stats stats;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *dest_option;
extern char *basis_dir[];
extern char *rsync_path;
extern char *shell_cmd;
@@ -80,6 +83,7 @@ extern struct filter_list_struct server_filter_list;
extern iconv_t ic_send;
#endif
uid_t our_uid;
int local_server = 0;
int daemon_over_rsh = 0;
mode_t orig_umask = 0;
@@ -276,7 +280,7 @@ static void output_summary(void)
rprintf(FINFO, "total size is %s speedup is %.2f%s\n",
human_num(stats.total_size),
(double)stats.total_size / (total_written+total_read),
dry_run ? " (DRY RUN)" : "");
write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
}
fflush(stdout);
@@ -331,7 +335,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
int i, argc = 0;
char *args[MAX_ARGS];
pid_t ret;
char *dir = NULL;
int dash_l_set = 0;
if (!read_batch && !local_server) {
@@ -507,9 +510,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
ret = piped_child(args, f_in_p, f_out_p);
}
if (dir)
free(dir);
return ret;
oom:
@@ -638,36 +638,41 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
return cp + 1;
}
/* Call this if the destination dir (which is assumed to be in curr_dir)
* does not yet exist and we can't create it due to being in dry-run
* mode. We'll fix dirs that can be relative to the non-existent dir. */
static void fix_basis_dirs(void)
/* This function checks on our alternate-basis directories. If we're in
* dry-run mode and the destination dir does not yet exist, we'll try to
* tweak any dest-relative paths to make them work for a dry-run (the
* destination dir must be in curr_dir[] when this function is called).
* We also warn about any arg that is non-existent or not a directory. */
static void check_alt_basis_dirs(void)
{
char **dir, *new, *slash;
int len;
STRUCT_STAT st;
char **dir_p, *slash = strrchr(curr_dir, '/');
if (dry_run <= 1)
return;
slash = strrchr(curr_dir, '/');
for (dir = basis_dir; *dir; dir++) {
if (**dir == '/')
continue;
len = curr_dir_len + 1 + strlen(*dir) + 1;
if (!(new = new_array(char, len)))
out_of_memory("fix_basis_dirs");
if (slash && strncmp(*dir, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir);
*dir = new;
for (dir_p = basis_dir; *dir_p; dir_p++) {
if (dry_run > 1 && **dir_p != '/') {
int len = curr_dir_len + 1 + strlen(*dir_p) + 1;
char *new = new_array(char, len);
if (!new)
out_of_memory("check_alt_basis_dirs");
if (slash && strncmp(*dir_p, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir_p + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir_p);
*dir_p = new;
}
if (do_stat(*dir_p, &st) < 0) {
rprintf(FWARNING, "%s arg does not exist: %s\n",
dest_option, *dir_p);
} else if (!S_ISDIR(st.st_mode)) {
rprintf(FWARNING, "%s arg is not a dir: %s\n",
dest_option, *dir_p);
}
}
}
@@ -755,7 +760,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
/* The receiving side mustn't obey this, or an existing symlink that
* points to an identical file won't be replaced by the referent. */
copy_links = copy_dirlinks = 0;
copy_links = copy_dirlinks = copy_unsafe_links = 0;
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && !inc_recurse)
@@ -863,7 +868,6 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
int exit_code;
struct file_list *flist;
char *local_name = NULL;
char *dir = NULL;
int save_verbose = verbose;
if (filesfrom_fd >= 0) {
@@ -884,7 +888,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
}
if (argc > 0) {
dir = argv[0];
char *dir = argv[0];
argc--;
argv++;
if (!am_daemon && !push_dir(dir, 0)) {
@@ -925,26 +929,27 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
/* Now that we know what our destination directory turned out to be,
* we can sanitize the --link-/copy-/compare-dest args correctly. */
if (sanitize_paths) {
char **dir;
for (dir = basis_dir; *dir; dir++) {
*dir = sanitize_path(NULL, *dir, NULL, curr_dir_depth);
}
if (partial_dir) {
char **dir_p;
for (dir_p = basis_dir; *dir_p; dir_p++)
*dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth);
if (partial_dir)
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth);
}
}
fix_basis_dirs();
check_alt_basis_dirs();
if (server_filter_list.head) {
char **dir;
char **dir_p;
struct filter_list_struct *elp = &server_filter_list;
for (dir = basis_dir; *dir; dir++) {
if (check_filter(elp, *dir, 1) < 0)
for (dir_p = basis_dir; *dir_p; dir_p++) {
char *dir = *dir_p;
if (*dir == '/')
dir += module_dirlen;
if (check_filter(elp, dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
&& check_filter(elp, partial_dir, 1) < 0) {
&& check_filter(elp, partial_dir + module_dirlen, 1) < 0) {
options_rejected:
rprintf(FERROR,
"Your options have been rejected by the server.\n");
@@ -1083,7 +1088,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (flist && flist->used > 0) {
local_name = get_local_name(flist, argv[0]);
fix_basis_dirs();
check_alt_basis_dirs();
exit_code2 = do_recv(f_in, f_out, local_name);
} else {
@@ -1424,7 +1429,8 @@ int main(int argc,char *argv[])
#endif
starttime = time(NULL);
am_root = (MY_UID() == 0);
our_uid = MY_UID();
am_root = our_uid == 0;
memset(&stats, 0, sizeof(stats));

View File

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

View File

@@ -27,6 +27,7 @@
extern int module_id;
extern int sanitize_paths;
extern int daemon_over_rsh;
extern unsigned int module_dirlen;
extern struct filter_list_struct filter_list;
extern struct filter_list_struct server_filter_list;
@@ -201,7 +202,7 @@ static int itemize_changes = 0;
static int refused_delete, refused_archive_part, refused_compress;
static int refused_partial, refused_progress, refused_delete_before;
static int refused_delete_during;
static int refused_inplace;
static int refused_inplace, refused_no_iconv;
static char *max_size_arg, *min_size_arg;
static char tmp_partialdir[] = ".~tmp~";
@@ -217,6 +218,7 @@ static void print_rsync_version(enum logcode f)
char const *got_socketpair = "no ";
char const *have_inplace = "no ";
char const *hardlinks = "no ";
char const *symtimes = "no ";
char const *acls = "no ";
char const *xattrs = "no ";
char const *links = "no ";
@@ -251,6 +253,9 @@ static void print_rsync_version(enum logcode f)
#ifdef ICONV_OPTION
iconv = "";
#endif
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
symtimes = "";
#endif
rprintf(f, "%s version %s protocol version %d%s\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
@@ -264,8 +269,8 @@ static void print_rsync_version(enum logcode f)
(int)(sizeof (int64) * 8));
rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
got_socketpair, hardlinks, links, ipv6, have_inplace);
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv\n",
have_inplace, acls, xattrs, iconv);
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
have_inplace, acls, xattrs, iconv, symtimes);
#ifdef MAINTAINER_MODE
rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
@@ -353,7 +358,7 @@ void usage(enum logcode F)
#endif
rprintf(F," -S, --sparse handle sparse files efficiently\n");
rprintf(F," -n, --dry-run perform a trial run with no changes made\n");
rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n");
rprintf(F," -W, --whole-file copy files whole (without delta-xfer algorithm)\n");
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
rprintf(F," -B, --block-size=SIZE force a fixed checksum block-size\n");
rprintf(F," -e, --rsh=COMMAND specify the remote shell to use\n");
@@ -440,7 +445,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
OPT_NO_D, OPT_APPEND,
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
OPT_SERVER, OPT_REFUSED_BASE = 9000};
static struct poptOption long_options[] = {
@@ -523,6 +528,8 @@ static struct poptOption long_options[] = {
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
{"no-one-file-system",'x',POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"no-x", 'x', POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
{"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
{"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
@@ -611,6 +618,7 @@ static struct poptOption long_options[] = {
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
#ifdef ICONV_OPTION
{"iconv", 0, POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
{"no-iconv", 0, POPT_ARG_NONE, 0, OPT_NO_ICONV, 0, 0 },
#endif
{"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
{"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
@@ -757,6 +765,8 @@ static void set_refuse_options(char *bp)
refused_progress = op->val;
else if (wildmatch("inplace", op->longName))
refused_inplace = op->val;
else if (wildmatch("no-iconv", op->longName))
refused_no_iconv = op->val;
break;
}
if (!is_wild)
@@ -877,8 +887,11 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
if (ref && *ref)
set_refuse_options(ref);
if (am_daemon)
if (am_daemon) {
set_refuse_options("log-file*");
if (!*lp_charset(module_id))
set_refuse_options("iconv");
}
#ifdef ICONV_OPTION
if (!am_daemon && !protect_args && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
@@ -1007,13 +1020,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
arg = sanitize_path(NULL, arg, NULL, 0);
if (server_filter_list.head) {
int rej;
char *cp = strdup(arg);
char *dir, *cp = strdup(arg);
if (!cp)
out_of_memory("parse_arguments");
if (!*cp)
goto options_rejected;
clean_fname(cp, CFN_COLLAPSE_DOT_DOT_DIRS);
rej = check_filter(&server_filter_list, cp, 0) < 0;
dir = cp + (*cp == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
rej = check_filter(&server_filter_list, dir, 0) < 0;
free(cp);
if (rej)
goto options_rejected;
@@ -1125,6 +1139,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
read_batch = 1;
break;
case OPT_NO_ICONV:
#ifdef ICONV_OPTION
iconv_opt = NULL;
#endif
break;
case OPT_MAX_SIZE:
if ((max_size = parse_size_arg(&max_size_arg, 'b')) <= 0) {
snprintf(err_buf, sizeof err_buf,
@@ -1252,6 +1272,10 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
else
need_unsorted_flist = 1;
}
if (refused_no_iconv && !iconv_opt) {
create_refuse_error(refused_no_iconv);
return 0;
}
#endif
if (protect_args == 1) {
@@ -1304,7 +1328,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
batch_name = NULL;
} else if (dry_run)
write_batch = 0;
}
} else if (write_batch < 0 && dry_run)
write_batch = 0;
if (read_batch && files_from) {
snprintf(err_buf, sizeof err_buf,
"--read-batch cannot be used with --files-from\n");
@@ -1406,17 +1431,21 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
if (server_filter_list.head && !am_sender) {
struct filter_list_struct *elp = &server_filter_list;
if (tmpdir) {
char *dir;
if (!*tmpdir)
goto options_rejected;
clean_fname(tmpdir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, tmpdir, 1) < 0)
dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, dir, 1) < 0)
goto options_rejected;
}
if (backup_dir) {
char *dir;
if (!*backup_dir)
goto options_rejected;
clean_fname(backup_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, backup_dir, 1) < 0)
dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(elp, dir, 1) < 0)
goto options_rejected;
}
}
@@ -1607,10 +1636,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
if (sanitize_paths)
files_from = sanitize_path(NULL, files_from, NULL, 0);
if (server_filter_list.head) {
char *dir;
if (!*files_from)
goto options_rejected;
clean_fname(files_from, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&server_filter_list, files_from, 0) < 0)
dir = files_from + (*files_from == '/' ? module_dirlen : 0);
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
if (check_filter(&server_filter_list, dir, 0) < 0)
goto options_rejected;
}
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
@@ -1752,24 +1783,24 @@ void server_options(char **args, int *argc_p)
argstr[x++] = 'z';
/* We make use of the -e option to let the server know about any
* pre-release protocol version && our allow_inc_recurse status. */
set_allow_inc_recurse();
* pre-release protocol version && some behavior flags. */
argstr[x++] = 'e';
#if SUBPROTOCOL_VERSION != 0
if (protocol_version == PROTOCOL_VERSION) {
x += snprintf(argstr+x, sizeof argstr - x,
"e%d.%d%s", PROTOCOL_VERSION, SUBPROTOCOL_VERSION,
allow_inc_recurse ? "i" : "");
"%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
} else
#endif
if (allow_inc_recurse) {
argstr[x++] = 'e';
argstr[x++] = '.';
set_allow_inc_recurse();
if (allow_inc_recurse)
argstr[x++] = 'i';
}
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
argstr[x++] = 'L';
#endif
argstr[x] = '\0';
if (x != 1)
args[ac++] = argstr;
args[ac++] = argstr;
#ifdef ICONV_OPTION
if (iconv_opt) {

View File

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

View File

@@ -29,6 +29,7 @@ our($make_tar, $upload, $help_opt);
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
our $ztoday = time2str('%d %b %Y', time);
our $today = $ztoday;
our $gen_target = $upload ? 'gensend' : 'gen';
die "$dest does not exist\n" unless -d $dest;
die "There is no .git dir in the current directory.\n" unless -d '.git';
@@ -40,6 +41,7 @@ if ($make_tar) {
close IN;
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
system "make $gen_target" and die "make $gen_target failed!\n";
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
@@ -53,14 +55,13 @@ if ($make_tar) {
}
}
close IN;
map { s#^#$name/# } @extra_files;
print "Creating $name.tar.gz\n";
system 'make gen';
symlink('.', $name);
system "git archive --format=tar --prefix=$name/ HEAD >$dest/$name.tar";
system "fakeroot tar rf $dest/$name.tar @extra_files; gzip -9 $dest/$name.tar";
unlink($name);
system "rsync -a @extra_files $name/";
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
system "support/git-set-file-times --prefix=$name/";
system "fakeroot tar czf $dest/$name.tar.gz $name; rm -rf $name";
unlink($nightly_symlink);
symlink("$name.tar.gz", $nightly_symlink);
}

View File

@@ -123,8 +123,6 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
print $break;
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in ) );
@@ -161,8 +159,6 @@ foreach my $fn (@tweak_files) {
close OUT;
}
system 'make gen';
print $break;
system "git diff --color | less -p '^diff .*'";
@@ -185,7 +181,7 @@ About to:
- create patches tar, "$pattar_name"
- create release diffs, "$diff_name"
- update patch branches and generate patch/* files
- update README, *NEWS, TODO, and changelog
- update README, *NEWS, TODO, and ChangeLog
- update rsync*.html man pages
- gpg-sign the release files
@@ -193,18 +189,15 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
$_[0] =~ s/configure\.sh/configure/; # XXX remove soon
system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
rename("a/configure", "a/configure.sh"); # XXX remove soon
system "rsync -a @extra_files rsync-$version/";
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
system "git tag -s -m 'Version $version.' v$version" and exit 1;
# Extract some files from the old tar before we do the shuffle.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
chdir($dest) or die $!;
@@ -245,28 +238,28 @@ if ($diffdir ne $dest) {
chdir($curdir) or die $!;
}
print "Creating $srctar_file ...\n";
(my $srctar_tmp = $srctar_file) =~ s/\.gz$//;
system "git archive --format=tar --prefix=rsync-$version/ v$version >$srctar_tmp";
system "fakeroot tar rf $srctar_tmp rsync-$version/*; gzip -9 $srctar_tmp";
print "Creating $diff_file ...\n";
rename("rsync-$version", 'b');
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
system "(git diff v$lastversion v$version; diff -up a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "rm -rf a b";
system "rm -rf a";
rename('b', "rsync-$version");
system "support/patch-update --gen";
print "Creating $srctar_file ...\n";
system "git archive --format=tar --prefix=rsync-$version/ v$version | tar xf -";
system "support/git-set-file-times --prefix=rsync-$version/";
system "fakeroot tar czf $srctar_file rsync-$version; rm -rf rsync-$version";
symlink('.', "rsync-$version");
system "tar czf $pattar_file rsync-$version/patches";
unlink("rsync-$version");
mkdir("rsync-$version", 0755);
mkdir("rsync-$version/patches", 0755);
system "support/patch-update --skip-check --gen=rsync-$version/patches";
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
print "Updating the other files in $dest ...\n";
system "rsync -a README NEWS OLDNEWS TODO $dest";
unlink("$dest/rsync-$version-NEWS");
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
system "git log --name-status | gzip -9 >$dest/changelog.gz";
system "git log --name-status | gzip -9 >$dest/ChangeLog.gz";
system "yodl2html -o $dest/rsync.html rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsyncd.conf.yo";

12
pipe.c
View File

@@ -133,6 +133,12 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
filesfrom_fd = -1;
chmod_modes = NULL; /* Let the sending side handle this. */
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
@@ -150,12 +156,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
child_main(argc, argv);
}
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rsyserr(FERROR, errno, "Failed to close");

View File

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

View File

@@ -22,8 +22,10 @@
#include "rsync.h"
extern struct stats stats;
extern int am_server;
extern int need_unsorted_flist;
extern struct stats stats;
extern struct file_list *cur_flist;
#define PROGRESS_HISTORY_SECS 5
@@ -41,6 +43,7 @@ struct progress_history {
static struct progress_history ph_start;
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
static int newest_hpos, oldest_hpos;
static int current_file_index;
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
{
@@ -104,7 +107,7 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
if (is_last) {
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
stats.num_transferred_files,
stats.num_files - stats.current_file_index - 1,
stats.num_files - current_file_index - 1,
stats.num_files);
} else
strlcpy(eol, "\r", sizeof eol);
@@ -112,6 +115,15 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
human_num(ofs), pct, rate, units, rembuf, eol);
}
void set_current_file_index(struct file_struct *file, int ndx)
{
if (need_unsorted_flist)
current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start;
else
current_file_index = ndx;
current_file_index -= cur_flist->flist_num;
}
void end_progress(OFF_T size)
{
if (!am_server) {

View File

@@ -352,10 +352,11 @@ static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
{
while (next_gen_ndx < desired_ndx) {
if (next_gen_ndx >= 0) {
rprintf(FINFO,
struct file_struct *file = cur_flist->files[next_gen_ndx];
rprintf(FERROR_XFER,
"(No batched update for%s \"%s\")\n",
redoing ? " resend of" : "",
f_name(cur_flist->files[next_gen_ndx], NULL));
file->flags & FLAG_FILE_SENT ? " resend of" : "",
f_name(file, NULL));
}
next_gen_ndx = read_int(fd);
if (next_gen_ndx == -1) {
@@ -481,9 +482,11 @@ int recv_files(int f_in, char *local_name)
}
}
stats.current_file_index = ndx;
if (!am_server && do_progress)
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.total_transferred_size += F_LENGTH(file);
cleanup_got_literal = 0;
if (server_filter_list.head
@@ -499,7 +502,7 @@ int recv_files(int f_in, char *local_name)
continue;
}
if (write_batch < 0) {
log_item(FINFO, file, &stats, iflags, NULL);
log_item(FCLIENT, file, &stats, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, F_LENGTH(file));
continue;
@@ -686,26 +689,23 @@ int recv_files(int f_in, char *local_name)
}
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
char *temp_copy_name;
if (partialptr == fname)
partialptr = temp_copy_name = NULL;
else if (*partial_dir == '/')
temp_copy_name = NULL;
else
temp_copy_name = partialptr;
finish_transfer(fname, fnametmp, fnamecmp,
temp_copy_name, file, recv_ok, 1);
if (fnamecmp == partialptr) {
partialptr = NULL;
if (!finish_transfer(fname, fnametmp, fnamecmp,
partialptr, file, recv_ok, 1))
recv_ok = -1;
else if (fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir);
if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
file, recv_ok, !partial_dir))
recv_ok = -1;
else if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, ndx);
recv_ok = 2;
}
} else {
partialptr = NULL;
@@ -714,13 +714,15 @@ int recv_files(int f_in, char *local_name)
cleanup_disable();
if (recv_ok > 0) {
switch (recv_ok) {
case 1:
if (remove_source_files || inc_recurse
|| (preserve_hard_links && F_IS_HLINKED(file)))
send_msg_int(MSG_SUCCESS, ndx);
} else if (!recv_ok) {
enum logcode msgtype = redoing || read_batch ? FERROR : FWARNING;
if (msgtype == FERROR || verbose) {
break;
case 0: {
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
if (msgtype == FERROR_XFER || verbose) {
char *errstr, *redostr, *keptstr;
if (!(keep_partial && partialptr) && !inplace)
keptstr = "discarded";
@@ -728,22 +730,30 @@ int recv_files(int f_in, char *local_name)
keptstr = "put into partial-dir";
else
keptstr = "retained";
if (msgtype == FERROR) {
if (msgtype == FERROR_XFER) {
errstr = "ERROR";
redostr = "";
} else {
errstr = "WARNING";
redostr = " (will try again)";
redostr = read_batch ? " (may try again)"
: " (will try again)";
}
rprintf(msgtype,
"%s: %s failed verification -- update %s%s.\n",
errstr, fname, keptstr, redostr);
errstr, local_name ? f_name(file, NULL) : fname,
keptstr, redostr);
}
if (!redoing) {
send_msg_int(MSG_REDO, ndx);
file->flags |= FLAG_FILE_SENT;
} else if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
break;
}
case -1:
if (inc_recurse)
send_msg_int(MSG_NO_SEND, ndx);
break;
}
}
if (make_backups < 0)

38
rounding.c Normal file
View File

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

87
rsync.c
View File

@@ -41,6 +41,7 @@ extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int protocol_version;
extern int receiver_symlink_times;
extern int uid_ndx;
extern int gid_ndx;
extern int inc_recurse;
@@ -264,12 +265,13 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
}
if (!(flist = flist_for_ndx(ndx))) {
int start, used;
invalid_ndx:
start = first_flist ? first_flist->ndx_start : 0;
used = first_flist ? first_flist->used : 0;
rprintf(FERROR,
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
ndx, first_flist ? first_flist->ndx_start - 1 : -1,
first_flist ? first_flist->prev->ndx_end : -1,
iflags, who_am_i());
ndx, start - 1, start + used -1, iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
cur_flist = flist;
@@ -398,6 +400,8 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
else if (receiver_symlink_times)
file->flags |= FLAG_TIME_FAILED;
}
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
@@ -421,24 +425,24 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
}
}
if (am_root < 0) {
;
} else if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
* unless have the privilege */
rsyserr(FERROR_XFER, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
} else
/* a lchown had been done - we have to re-stat if the
* destination had the setuid or setgid bits set due
* to the side effect of the chown call */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
if (am_root >= 0) {
if (do_lchown(fname,
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
/* We shouldn't have attempted to change uid
* or gid unless have the privilege. */
rsyserr(FERROR_XFER, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
}
/* A lchown had been done, so we need to re-stat if
* the destination had the setuid or setgid bits set
* (due to the side effect of the chown call). */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
}
}
updated = 1;
}
@@ -503,15 +507,17 @@ RETSIGTYPE sig_int(UNUSED(int val))
}
/* Finish off a file transfer: renaming the file and setting the file's
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
* NULL and the robust_rename() call is forced to copy the temp file, we
* stage the file into the partial-dir and then rename it into place. */
void finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
* attributes (e.g. permissions, ownership, etc.). If the robust_rename()
* call is forced to copy the temp file and partialptr is both non-NULL and
* not an absolute path, we stage the file into the partial-dir and then
* rename it into place. This returns 1 on succcess or 0 on failure. */
int finish_transfer(const char *fname, const char *fnametmp,
const char *fnamecmp, const char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
{
int ret;
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
if (inplace) {
if (verbose > 2)
@@ -521,7 +527,7 @@ void finish_transfer(const char *fname, const char *fnametmp,
}
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return;
return 1;
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -530,34 +536,39 @@ void finish_transfer(const char *fname, const char *fnametmp,
/* move tmp file over real file */
if (verbose > 2)
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
ret = robust_rename(fnametmp, fname, partialptr,
ret = robust_rename(fnametmp, fname, temp_copy_name,
file->mode & INITACCESSPERMS);
if (ret < 0) {
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname);
do_unlink(fnametmp);
return;
if (!partialptr || (ret == -2 && temp_copy_name)
|| robust_rename(fnametmp, partialptr, NULL,
file->mode & INITACCESSPERMS) < 0)
do_unlink(fnametmp);
return 0;
}
if (ret == 0) {
/* The file was moved into place (not copied), so it's done. */
return;
return 1;
}
/* The file was copied, so tweak the perms of the copied file. If it
* was copied to partialptr, move it into its final destination. */
fnametmp = partialptr ? partialptr : fname;
fnametmp = temp_copy_name ? temp_copy_name : fname;
do_set_file_attrs:
set_file_attrs(fnametmp, file, NULL, fnamecmp,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
if (partialptr) {
if (temp_copy_name) {
if (do_rename(fnametmp, fname) < 0) {
rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
full_fname(fnametmp), fname);
} else
handle_partial_dir(partialptr, PDIR_DELETE);
return 0;
}
handle_partial_dir(temp_copy_name, PDIR_DELETE);
}
return 1;
}
struct file_list *flist_for_ndx(int ndx)
@@ -572,7 +583,7 @@ struct file_list *flist_for_ndx(int ndx)
return NULL;
flist = flist->prev;
}
while (ndx > flist->ndx_end) {
while (ndx >= flist->ndx_start + flist->used) {
if (!(flist = flist->next))
return NULL;
}

View File

@@ -77,6 +77,7 @@
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator (checked on all types) */
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
#define FLAG_TIME_FAILED (1<<11)/* generator */
/* These flags are passed to functions but not stored. */
@@ -93,7 +94,7 @@
/* This is used when working on a new protocol version in CVS, and should
* be a new non-zero value for each CVS change that affects the protocol.
* It must ALWAYS be 0 when the protocol goes final! */
#define SUBPROTOCOL_VERSION 15
#define SUBPROTOCOL_VERSION 17
/* We refuse to interoperate with versions that are not in this range.
* Note that we assume we'll work with later versions: the onus is on
@@ -540,6 +541,7 @@ struct hashtable {
void *nodes;
int32 size, entries;
uint32 node_size;
int key64;
};
struct ht_int32_node {
@@ -723,7 +725,7 @@ struct file_list {
int used, malloced;
int low, high; /* 0-relative index values excluding empties */
int ndx_start; /* the start offset for inc_recurse mode */
int ndx_end; /* the end offset for inc_recurse mode */
int flist_num; /* 1-relative file_list number or 0 */
int parent_ndx; /* dir_flist index of parent directory */
int in_progress, to_redo;
};
@@ -814,7 +816,6 @@ struct stats {
int64 flist_size;
int num_files;
int num_transferred_files;
int current_file_index;
};
struct chmod_mode_struct;

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(28 Nov 2007)()()
manpage(rsync)(1)(19 Feb 2008)()()
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
manpagesynopsis()
@@ -353,7 +353,7 @@ to the detailed description below for a complete description. verb(
--fake-super store/recover privileged attrs using xattrs
-S, --sparse handle sparse files efficiently
-n, --dry-run perform a trial run with no changes made
-W, --whole-file copy files whole (without rsync algorithm)
-W, --whole-file copy files whole (w/o delta-xfer algorithm)
-x, --one-file-system don't cross filesystem boundaries
-B, --block-size=SIZE force a fixed checksum block-size
-e, --rsh=COMMAND specify the remote shell to use
@@ -528,7 +528,7 @@ either a changed size or a changed checksum are selected for transfer.
Note that rsync always verifies that each em(transferred) file was
correctly reconstructed on the receiving side by checking a whole-file
checksum that is generated when as the file is transferred, but that
checksum that is generated as the file is transferred, but that
automatic after-the-transfer verification has nothing to do with this
option's before-the-transfer "Does this file need to be updated?" check.
@@ -817,11 +817,24 @@ the transfer and link together the corresponding files on the receiving
side. Without this option, hard-linked files in the transfer are treated
as though they were separate files.
Note that rsync can only detect hard links if both parts of the link
are in the list of files being sent.
When you are updating a non-empty destination, this option only ensures
that files that are hard-linked together on the source are hard-linked
together on the destination. It does NOT currently endeavor to break
already existing hard links on the destination that do not exist between
the source files. Note, however, that if one or more extra-linked files
have content changes, they will become unlinked when updated (assuming you
are not using the bf(--inplace) option).
Note that rsync can only detect hard links between files that are inside
the transfer set. If rsync updates a file that has extra hard-link
connections to files outside the transfer, that linkage will be broken. If
you are tempted to use the bf(--inplace) option to avoid this breakage, be
very careful that you know how your files are being updated so that you are
certain that no unintended changes happen due to lingering hard links (and
see the bf(--inplace) option for more caveats).
If incremental recursion is active (see bf(--recursive)), rsync may transfer
a missing hard-linked file before it finds that another link for the file
a missing hard-linked file before it finds that another link for that contents
exists elsewhere in the hierarchy. This does not affect the accuracy of
the transfer, just its efficiency. One way to avoid this is to disable
incremental recursion using the bf(--no-inc-recursive) option.
@@ -1038,7 +1051,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 the delta-transfer algorithm
is not used and the whole file is sent as-is instead. The transfer may be
faster if this option is used when the bandwidth between the source and
destination machines is higher than the bandwidth to disk (especially when the
@@ -1293,7 +1306,10 @@ exclude certain files from the list of files to be transferred. This is
most useful in combination with a recursive transfer.
You may use as many bf(--filter) options on the command line as you like
to build up the list of files to exclude.
to build up the list of files to exclude. If the filter contains whitespace,
be sure to quote it so that the shell gives the rule to rsync as a single
argument. The text below also mentions that you can use an underscore to
replace the space that separates a rule from its arg.
See the FILTER RULES section for detailed information on this option.
@@ -1406,7 +1422,7 @@ characters are not translated (such as ~, $, ;, &, etc.). Wildcards are
expanded on the remote host by rsync (instead of the shell doing it).
If you use this option with bf(--iconv), the args will also be translated
from the local to the remote character set. The translation happens before
from the local to the remote character-set. The translation happens before
wild-cards are expanded. See also the bf(--files-from) option.
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
@@ -1416,7 +1432,7 @@ file in the same directory as the associated destination file.
This option is most often used when the receiving disk partition does not
have enough free space to hold a copy of the largest file in the transfer.
In this case (i.e. when the scratch directory in on a different disk
In this case (i.e. when the scratch directory is on a different disk
partition), rsync will not be able to rename each received temporary file
over the top of the associated destination file, but instead must copy it
into place. Rsync does this by copying the file over the top of the
@@ -1640,6 +1656,8 @@ quote(itemization(
bf(--hard-links)).
it() A bf(.) means that the item is not being updated (though it might
have attributes that are being modified).
it() A bf(*) means that the rest of the itemized-output area contains
a message (e.g. "deleting").
))
The file-types that replace the bf(X) are: bf(f) for a file, a bf(d) for a
@@ -1663,8 +1681,8 @@ quote(itemization(
it() A bf(t) means the modification time is different and is being updated
to the sender's value (requires bf(--times)). An alternate value of bf(T)
means that the modification time will be set to the transfer time, which happens
anytime a symlink is transferred, or when a regular file or device is
transferred without bf(--times).
when a file/symlink/device is updated without bf(--times) and when a
symlink is changed and the receiver can't set its time.
it() A bf(p) means the permissions are different and are being updated to
the sender's value (requires bf(--perms)).
it() An bf(o) means the owner is different and is being updated to the
@@ -1944,6 +1962,8 @@ dit(bf(--password-file)) This option allows you to provide a password in a
file for accessing an rsync daemon. The file must not be world readable.
It should contain just the password as a single line.
This option does not supply a password to a remote shell transport such as
ssh; to learn how to do that, consult the remote shell's documentation.
When accessing an rsync daemon using a remote shell as the transport, this
option only comes into effect after the remote shell finishes its
authentication (i.e. if you have also specified a password in the daemon's
@@ -2015,11 +2035,17 @@ dit(bf(--iconv=CONVERT_SPEC)) Rsync can convert filenames between character
sets using this option. Using a CONVERT_SPEC of "." tells rsync to look up
the default character-set via the locale setting. Alternately, you can
fully specify what conversion to do by giving a local and a remote charset
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591).
Finally, you can specify a CONVERT_SPEC of "-" to turn off any conversion.
separated by a comma in the order bf(--iconv=LOCAL,REMOTE), e.g.
bf(--iconv=utf8,iso88591). This order ensures that the option
will stay the same whether you're pushing or pulling files.
Finally, you can specify either bf(--no-iconv) or a CONVERT_SPEC of "-"
to turn off any conversion.
The default setting of this option is site-specific, and can also be
affected via the RSYNC_ICONV environment variable.
For a list of what charset names your local iconv library supports, you can
run "iconv --list".
If you specify the bf(--protect-args) option (bf(-s)), rsync will translate
the filenames you specify on the command-line that are being sent to the
remote host. See also the bf(--files-from) option.
@@ -2030,6 +2056,11 @@ specifying matching rules that can match on both sides of the transfer.
For instance, you can specify extra include/exclude rules if there are
filename differences on the two sides that need to be accounted for.
When you pass an bf(--iconv) option to an rsync daemon that allows it, the
daemon uses the charset specified in its "charset" configuration parameter
regardless of the remote charset you actually pass. Thus, you may feel free to
specify just the local charset for a daemon transfer (e.g. bf(--iconv=utf8)).
dit(bf(-4, --ipv4) or bf(-6, --ipv6)) Tells rsync to prefer IPv4/IPv6
when creating sockets. This only affects sockets that rsync has direct
control over, such as the outgoing socket when directly contacting an
@@ -2800,7 +2831,8 @@ rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
password allows you to run authenticated rsync connections to an rsync
daemon without user intervention. Note that this does not supply a
password to a shell transport such as ssh.
password to a remote shell transport such as ssh; to learn how to do that,
consult the remote shell's documentation.
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
are used to determine the default username sent to an rsync daemon.
If neither is set, the username defaults to "nobody".
@@ -2834,7 +2866,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.0pre6 of rsync.
This man page is current for version 3.0.0pre10 of rsync.
manpagesection(INTERNAL OPTIONS)

View File

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

View File

@@ -229,7 +229,7 @@ void send_files(int f_in, int f_out)
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
recv_xattr_request(file, f_in);
#endif
@@ -265,7 +265,8 @@ void send_files(int f_in, int f_out)
updating_basis_file = inplace && (protocol_version >= 29
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
stats.current_file_index = ndx;
if (!am_server && do_progress)
set_current_file_index(file, ndx);
stats.num_transferred_files++;
stats.total_transferred_size += F_LENGTH(file);

View File

@@ -8,6 +8,7 @@ use strict;
my %ls;
my $commit_time;
my $prefix = @ARGV && $ARGV[0] =~ s/^--prefix=// ? shift : '';
$/ = "\0";
open FH, 'git ls-files -z|' or die $!;
@@ -27,6 +28,7 @@ while (<FH>) {
my @files = delete @ls{split(/\0/, $_)};
@files = grep { defined $_ } @files;
next unless @files;
map { s/^/$prefix/ } @files;
utime $commit_time, $commit_time, @files;
}
last unless %ls;

View File

@@ -6,10 +6,35 @@
# diffs.
use strict;
use Getopt::Long;
die "No 'patches' directory present in the current dir.\n" unless -d 'patches';
my $patches_dir = 'patches';
my $tmp_dir = "patches.$$";
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'skip-check' => \( my $skip_branch_check ),
'gen:s' => \( my $incl_generated_files ),
'help|h' => \( my $help_opt ),
);
&usage if $help_opt;
if (defined $incl_generated_files) {
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
$incl_generated_files = 1;
}
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
die "No '.git' directory present in the current dir.\n" unless -d '.git';
unless ($skip_branch_check) {
open(IN, '-|', 'git status') or die $!;
my $status = join('', <IN>);
close IN;
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
}
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
while (<IN>) {
@@ -23,27 +48,17 @@ while (<IN>) {
}
close IN;
my $incl_generated_files = shift if @ARGV && $ARGV[0] eq '--gen';
system "git checkout master" and exit 1;
if ($incl_generated_files) {
die "'a' must not exist in the current directory.\n" if -e 'a';
die "'b' must not exist in the current directory.\n" if -e 'b';
system "make gen && rsync -a @extra_files a/" and exit 1;
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
}
my $last_touch = time;
my(@patches, %local_patch);
if (@ARGV) {
foreach (@ARGV) {
s{^(patches|patch|origin/patch)/} {};
s{\.diff$} {};
push(@patches, $_);
}
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
} else {
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
}
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
while (<PIPE>) {
if (m# origin/patch/(.*)#) {
push(@patches, $1);
@@ -59,7 +74,9 @@ foreach my $patch (@patches) {
my $desc = '';
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
while (<PIPE>) {
next if m{^\Q+++\E b/PATCH};
last if /^@@ /;
}
while (<PIPE>) {
next unless s/^[ +]//;
if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
$parent{$patch} = $1;
@@ -69,6 +86,16 @@ foreach my $patch (@patches) {
$description{$patch} = $desc;
}
if (@ARGV) {
# Limit the list of patches to actually process based on @ARGV.
@patches = ( );
foreach (@ARGV) {
s{^(patches|patch|origin/patch)/} {};
s{\.diff$} {};
push(@patches, $_);
}
}
my %completed;
foreach my $patch (@patches) {
next if $completed{$patch}++;
@@ -76,11 +103,11 @@ foreach my $patch (@patches) {
}
if ($incl_generated_files) {
system "rm -rf a b";
system "rm -rf $tmp_dir";
}
sleep 1 if $last_touch == time;
system "git checkout master";
system "git checkout master" and exit 1;
exit;
@@ -108,17 +135,17 @@ sub update_patch
system "git checkout --track -b patch/$patch origin/patch/$patch" and exit 1;
}
open(OUT, '>', "patches/$patch.diff") or die $!;
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
print OUT $description{$patch}, "\n";
if (system("git rebase -m $parent") != 0) {
print qq|"git rebase -m $parent" incomplete -- please fix.\n|;
if (system("git merge $parent") != 0) {
print qq|"git merge $parent" incomplete -- please fix.\n|;
$ENV{PS1} = "[$parent] patch/$patch: ";
system $ENV{SHELL} and exit 1;
}
if ($incl_generated_files) {
system "make gen && rsync -a @extra_files b/" and exit 1;
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
@@ -136,9 +163,12 @@ sub update_patch
close PIPE;
if ($incl_generated_files) {
open(PIPE, '-|', 'diff', '-up', 'a', 'b') or die $!;
$parent =~ s#.*/##;
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
while (<PIPE>) {
s/^((?:---|\+\+\+) [^\t]+)\t.*/$1/;
s#^(diff -up) $tmp_dir/[^/]+/(.*?) $tmp_dir/[^/]+/(.*)#$1 a/$2 b/$3#o;
s#^\Q---\E $tmp_dir/[^/]+/([^\t]+)\t.*#--- a/$1#o;
s#^\Q+++\E $tmp_dir/[^/]+/([^\t]+)\t.*#+++ b/$1#o;
print OUT $_;
}
close PIPE;
@@ -146,3 +176,15 @@ sub update_patch
close OUT;
}
exit;
sub usage
{
die <<EOT;
Usage: patch-update [OPTIONS]
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
--skip-check Skip the check that ensures starting with a clean master branch.
EOT
}

View File

@@ -34,6 +34,7 @@ extern int am_root;
extern int read_only;
extern int list_only;
extern int preserve_perms;
extern int preserve_executability;
#define RETURN_ERROR_IF(x,e) \
do { \
@@ -167,7 +168,7 @@ int do_chmod(const char *path, mode_t mode)
#endif
} else
code = chmod(path, mode & CHMOD_BITS);
if (code != 0 && preserve_perms)
if (code != 0 && (preserve_perms || preserve_executability))
return code;
return 0;
}

View File

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

View File

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

View File

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

View File

@@ -26,7 +26,8 @@ ln -s ../bar/baz/rsync "$fromdir/foo/sym"
umask 022
ln "$fromdir/foo/config1" "$fromdir/foo/extra"
# Check if the OS can hard-link symlinks or not
# Check if the OS can hard-link symlinks or not.
# (Note: the link we check MUST NOT point to a valid file!)
ln -s no-such-dir "$to2dir"
if ln "$to2dir" "$to2dir.test" 2>/dev/null; then
L=hL
@@ -35,6 +36,20 @@ else
fi
rm -f "$to2dir" "$to2dir.test"
# Check if rsync can preserve time on symlinks
case "$RSYNC" in
*protocol=2*)
T=.T
;;
*)
if $RSYNC --version | grep ", symtimes" >/dev/null; then
T=.t
else
T=.T
fi
;;
esac
$RSYNC -iplr "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
@@ -82,7 +97,7 @@ cat <<EOT >"$chkfile"
.d..t...... foo/
.f..t...... foo/config1
>fcstp..... foo/config2
cL..T...... foo/sym -> ../bar/baz/rsync
cL.$T...... foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
@@ -142,6 +157,21 @@ diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
$RSYNC -ivvplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
filter_outfile
case `tail -1 "$outfile"` in
cL..t*)
sym_dots='..t......'
L_sym_dots='cL..t......'
is_uptodate='-> ../bar/baz/rsync'
echo "cL$sym_dots foo/sym $is_uptodate" >"$chkfile.extra"
L=cL
;;
*)
sym_dots=' '
L_sym_dots='.L '
is_uptodate='is uptodate'
touch "$chkfile.extra"
;;
esac
cat <<EOT >"$chkfile"
cd ./
cd bar/
@@ -151,14 +181,14 @@ cd foo/
cf foo/config1
cf foo/config2
hf foo/extra => foo/config1
cL foo/sym -> ../bar/baz/rsync
cL$sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
hf foo/extra => foo/config1
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
@@ -176,7 +206,7 @@ foo/ is uptodate
foo/config1 is uptodate
foo/config2 is uptodate
foo/extra => foo/config1
foo/sym is uptodate
foo/sym $is_uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 10 failed"
@@ -193,21 +223,21 @@ cd foo/
hf foo/config1
hf foo/config2
hf foo/extra => foo/config1
$L foo/sym -> ../bar/baz/rsync
$L$sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --dry-run --link-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --link-dest=../to "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 13 failed"
@@ -224,7 +254,7 @@ foo/ is uptodate
foo/config1 is uptodate
foo/config2 is uptodate
foo/extra is uptodate
foo/sym is uptodate
foo/sym $is_uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
@@ -241,14 +271,14 @@ cd foo/
.f foo/config1
.f foo/config2
.f foo/extra
.L foo/sym -> ../bar/baz/rsync
$L_sym_dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
rm -rf "$to2dir"
$RSYNC -iplrtH --compare-dest="$todir" "$fromdir/" "$to2dir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cat - "$chkfile.extra" <<EOT >"$chkfile"
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 16 failed"
@@ -265,7 +295,7 @@ foo/ is uptodate
foo/config1 is uptodate
foo/config2 is uptodate
foo/extra is uptodate
foo/sym is uptodate
foo/sym $is_uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 17 failed"

View File

@@ -256,6 +256,25 @@ gid = 0
path = $scratchdir
read only = no
EOF
# Build a helper script to ignore exit code 23
ignore23="$scratchdir/ignore23"
echo "building help script $ignore23"
cat >"$ignore23" <<'EOT'
if "${@}"; then
exit
fi
ret=$?
if test $ret = 23; then
exit
fi
exit $ret
EOT
chmod +x "$ignore23"
}

View File

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

1
tls.c
View File

@@ -46,6 +46,7 @@ int am_root = 0;
int read_only = 1;
int list_only = 0;
int preserve_perms = 0;
int preserve_executability = 0;
#ifdef SUPPORT_XATTRS

View File

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

View File

@@ -43,7 +43,7 @@ extern int numeric_ids;
struct idlist {
struct idlist *next;
char *name;
const char *name;
id_t id, id2;
uint16 flags;
};
@@ -51,7 +51,7 @@ struct idlist {
static struct idlist *uidlist;
static struct idlist *gidlist;
static struct idlist *add_to_list(struct idlist **root, id_t id, char *name,
static struct idlist *add_to_list(struct idlist **root, id_t id, const char *name,
id_t id2, uint16 flags)
{
struct idlist *node = new(struct idlist);
@@ -67,7 +67,7 @@ static struct idlist *add_to_list(struct idlist **root, id_t id, char *name,
}
/* turn a uid into a user name */
static char *uid_to_name(uid_t uid)
static const char *uid_to_name(uid_t uid)
{
struct passwd *pass = getpwuid(uid);
if (pass)
@@ -76,7 +76,7 @@ static char *uid_to_name(uid_t uid)
}
/* turn a gid into a group name */
static char *gid_to_name(gid_t gid)
static const char *gid_to_name(gid_t gid)
{
struct group *grp = getgrgid(gid);
if (grp)
@@ -84,7 +84,7 @@ static char *gid_to_name(gid_t gid)
return NULL;
}
static uid_t map_uid(uid_t id, char *name)
static uid_t map_uid(uid_t id, const char *name)
{
uid_t uid;
if (id != 0 && name_to_uid(name, &uid))
@@ -92,7 +92,7 @@ static uid_t map_uid(uid_t id, char *name)
return id;
}
static gid_t map_gid(gid_t id, char *name)
static gid_t map_gid(gid_t id, const char *name)
{
gid_t gid;
if (id != 0 && name_to_gid(name, &gid))
@@ -160,7 +160,7 @@ static int is_in_group(gid_t gid)
}
/* Add a uid to the list of uids. Only called on receiving side. */
static struct idlist *recv_add_uid(uid_t id, char *name)
static struct idlist *recv_add_uid(uid_t id, const char *name)
{
uid_t id2 = name ? map_uid(id, name) : id;
struct idlist *node;
@@ -176,7 +176,7 @@ static struct idlist *recv_add_uid(uid_t id, char *name)
}
/* Add a gid to the list of gids. Only called on receiving side. */
static struct idlist *recv_add_gid(gid_t id, char *name)
static struct idlist *recv_add_gid(gid_t id, const char *name)
{
gid_t id2 = name ? map_gid(id, name) : id;
struct idlist *node;
@@ -237,7 +237,7 @@ gid_t match_gid(gid_t gid, uint16 *flags_ptr)
}
/* Add a uid to the list of uids. Only called on sending side. */
char *add_uid(uid_t uid)
const char *add_uid(uid_t uid)
{
struct idlist *list;
struct idlist *node;
@@ -255,7 +255,7 @@ char *add_uid(uid_t uid)
}
/* Add a gid to the list of gids. Only called on sending side. */
char *add_gid(gid_t gid)
const char *add_gid(gid_t gid)
{
struct idlist *list;
struct idlist *node;
@@ -316,6 +316,10 @@ uid_t recv_user_name(int f, uid_t uid)
if (!name)
out_of_memory("recv_user_name");
read_sbuf(f, name, len);
if (numeric_ids < 0) {
free(name);
name = NULL;
}
node = recv_add_uid(uid, name); /* node keeps name's memory */
return node->id2;
}
@@ -328,6 +332,10 @@ gid_t recv_group_name(int f, gid_t gid, uint16 *flags_ptr)
if (!name)
out_of_memory("recv_group_name");
read_sbuf(f, name, len);
if (numeric_ids < 0) {
free(name);
name = NULL;
}
node = recv_add_gid(gid, name); /* node keeps name's memory */
if (flags_ptr && node->flags & FLAG_SKIP_GROUP)
*flags_ptr |= FLAG_SKIP_GROUP;
@@ -341,13 +349,13 @@ void recv_id_list(int f, struct file_list *flist)
id_t id;
int i;
if ((preserve_uid || preserve_acls) && !numeric_ids) {
if ((preserve_uid || preserve_acls) && numeric_ids <= 0) {
/* read the uid list */
while ((id = read_varint30(f)) != 0)
recv_user_name(f, id);
}
if ((preserve_gid || preserve_acls) && !numeric_ids) {
if ((preserve_gid || preserve_acls) && numeric_ids <= 0) {
/* read the gid list */
while ((id = read_varint30(f)) != 0)
recv_group_name(f, id, NULL);

35
util.c
View File

@@ -147,8 +147,9 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
t[1].tv_usec = 0;
# ifdef HAVE_LUTIMES
if (S_ISLNK(mode)) {
lutimes(fname, t);
return 0; /* ignore errors */
if (lutimes(fname, t) < 0)
return errno == ENOSYS ? 1 : -1;
return 0;
}
# endif
return utimes(fname, t);
@@ -465,31 +466,27 @@ void kill_all(int sig)
}
/** Turn a user name into a uid */
int name_to_uid(const char *name, uid_t *uid)
int name_to_uid(const char *name, uid_t *uid_p)
{
struct passwd *pass;
if (!name || !*name)
return 0;
pass = getpwnam(name);
if (pass) {
*uid = pass->pw_uid;
return 1;
}
return 0;
if (!(pass = getpwnam(name)))
return 0;
*uid_p = pass->pw_uid;
return 1;
}
/** Turn a group name into a gid */
int name_to_gid(const char *name, gid_t *gid)
int name_to_gid(const char *name, gid_t *gid_p)
{
struct group *grp;
if (!name || !*name)
return 0;
grp = getgrnam(name);
if (grp) {
*gid = grp->gr_gid;
return 1;
}
return 0;
if (!(grp = getgrnam(name)))
return 0;
*gid_p = grp->gr_gid;
return 1;
}
/** Lock a byte range in a open file */
@@ -898,6 +895,9 @@ int push_dir(const char *dir, int set_path_only)
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
}
if (verbose >= 5 && !set_path_only)
rprintf(FINFO, "[%s] push_dir(%s)\n", who_am_i(), curr_dir);
return 1;
}
@@ -916,6 +916,9 @@ int pop_dir(const char *dir)
if (sanitize_paths)
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
if (verbose >= 5)
rprintf(FINFO, "[%s] pop_dir(%s)\n", who_am_i(), curr_dir);
return 1;
}

138
xattrs.c
View File

@@ -47,7 +47,6 @@ extern int checksum_seed;
#define XSTATE_ABBREV 0
#define XSTATE_DONE 1
#define XSTATE_TODO 2
#define XSTATE_LOCAL 3
#define USER_PREFIX "user."
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
@@ -70,6 +69,7 @@ extern int checksum_seed;
typedef struct {
char *datum, *name;
size_t datum_len, name_len;
int num;
} rsync_xa;
static size_t namebuf_len = 0;
@@ -111,6 +111,7 @@ static int rsync_xal_compare_names(const void *x1, const void *x2)
static ssize_t get_xattr_names(const char *fname)
{
ssize_t list_len;
double arg;
if (!namebuf) {
namebuf_len = 1024;
@@ -119,23 +120,26 @@ static ssize_t get_xattr_names(const char *fname)
out_of_memory("get_xattr_names");
}
/* The length returned includes all the '\0' terminators. */
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
if (list_len > (ssize_t)namebuf_len) {
list_len = -1;
errno = ERANGE;
}
if (list_len >= 0)
return list_len;
if (errno == ENOTSUP)
return 0;
if (errno == ERANGE) {
while (1) {
/* The length returned includes all the '\0' terminators. */
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
if (list_len >= 0) {
if ((size_t)list_len <= namebuf_len)
break;
} else if (errno == ENOTSUP)
return 0;
else if (errno != ERANGE) {
arg = (double)namebuf_len;
got_error:
rsyserr(FERROR_XFER, errno,
"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
fname, arg);
return -1;
}
list_len = sys_llistxattr(fname, NULL, 0);
if (list_len < 0) {
rsyserr(FERROR_XFER, errno,
"get_xattr_names: llistxattr(\"%s\",0) failed",
fname);
return -1;
arg = 0;
goto got_error;
}
if (namebuf_len)
free(namebuf);
@@ -143,15 +147,9 @@ static ssize_t get_xattr_names(const char *fname)
namebuf = new_array(char, namebuf_len);
if (!namebuf)
out_of_memory("get_xattr_names");
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
if (list_len >= 0)
return list_len;
}
rsyserr(FERROR_XFER, errno,
"get_xattr_names: llistxattr(\"%s\",%ld) failed",
fname, (long)namebuf_len);
return -1;
return list_len;
}
/* On entry, the *len_ptr parameter contains the size of the extra space we
@@ -210,14 +208,14 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
#ifdef HAVE_LINUX_XATTRS
int user_only = am_sender ? 0 : !am_root;
#endif
rsync_xa *rxa;
int count;
/* This puts the name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(fname)) < 0)
return -1;
for (name = namebuf; list_len > 0; name += name_len) {
rsync_xa *rxa;
name_len = strlen(name) + 1;
list_len -= name_len;
@@ -270,8 +268,12 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
rxa->name_len = name_len;
rxa->datum_len = datum_len;
}
if (xalp->count > 1)
qsort(xalp->items, xalp->count, sizeof (rsync_xa), rsync_xal_compare_names);
count = xalp->count;
rxa = xalp->items;
if (count > 1)
qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names);
for (rxa += count-1; count; count--, rxa--)
rxa->num = count;
return 0;
}
@@ -459,18 +461,19 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
{
item_list *lst = rsync_xal_l.items;
int j, cnt, prior_req = -1;
int cnt, prior_req = 0;
rsync_xa *rxa;
lst += F_XATTR(file);
cnt = lst->count;
for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) {
for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) {
if (rxa->datum_len <= MAX_FULL_DATUM)
continue;
switch (rxa->datum[0]) {
case XSTATE_LOCAL:
/* Items set locally will get cached by receiver. */
rxa->datum[0] = XSTATE_DONE;
case XSTATE_ABBREV:
/* Items left abbreviated matched the sender's checksum, so
* the receiver will cache the local data for future use. */
if (am_generator)
rxa->datum[0] = XSTATE_DONE;
continue;
case XSTATE_TODO:
break;
@@ -481,8 +484,8 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
/* Flag that we handled this abbreviated item. */
rxa->datum[0] = XSTATE_DONE;
write_varint(f_out, j - prior_req);
prior_req = j;
write_varint(f_out, rxa->num - prior_req);
prior_req = rxa->num;
if (fname) {
size_t len = 0;
@@ -504,27 +507,6 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
write_byte(f_out, 0); /* end the list */
}
/* Any items set locally by the generator that the receiver doesn't
* get told about get changed back to XSTATE_ABBREV. */
void xattr_clear_locals(struct file_struct *file)
{
item_list *lst = rsync_xal_l.items;
rsync_xa *rxa;
int cnt;
if (F_XATTR(file) < 0)
return;
lst += F_XATTR(file);
cnt = lst->count;
for (rxa = lst->items; cnt--; rxa++) {
if (rxa->datum_len <= MAX_FULL_DATUM)
continue;
if (rxa->datum[0] == XSTATE_LOCAL)
rxa->datum[0] = XSTATE_ABBREV;
}
}
/* When called by the sender, read the request from the generator and mark
* any needed xattrs with a flag that lets us know they need to be sent to
* the receiver. When called by the receiver, reads the sent data and
@@ -534,7 +516,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
item_list *lst = rsync_xal_l.items;
char *old_datum, *name;
rsync_xa *rxa;
int rel_pos, cnt, got_xattr_data = 0;
int rel_pos, cnt, num, got_xattr_data = 0;
if (F_XATTR(file) < 0) {
rprintf(FERROR, "recv_xattr_request: internal data error!\n");
@@ -544,13 +526,20 @@ int recv_xattr_request(struct file_struct *file, int f_in)
cnt = lst->count;
rxa = lst->items;
rxa -= 1;
num = 0;
while ((rel_pos = read_varint(f_in)) != 0) {
rxa += rel_pos;
cnt -= rel_pos;
if (cnt < 0 || rxa->datum_len <= MAX_FULL_DATUM
|| rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "recv_xattr_request: internal abbrev error!\n");
num += rel_pos;
while (cnt && rxa->num < num) {
rxa++;
cnt--;
}
if (!cnt || rxa->num != num) {
rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",
who_am_i(), num, f_name(file, NULL));
exit_cleanup(RERR_STREAMIO);
}
if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i());
exit_cleanup(RERR_STREAMIO);
}
@@ -584,7 +573,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
void receive_xattr(struct file_struct *file, int f)
{
static item_list temp_xattr = EMPTY_ITEM_LIST;
int count;
int count, num;
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
@@ -603,7 +592,7 @@ void receive_xattr(struct file_struct *file, int f)
temp_xattr.count = 0;
}
while (count--) {
for (num = 1; num <= count; num++) {
char *ptr, *name;
rsync_xa *rxa;
size_t name_len = read_varint(f);
@@ -627,14 +616,14 @@ void receive_xattr(struct file_struct *file, int f)
}
#ifdef HAVE_LINUX_XATTRS
/* Non-root can only save the user namespace. */
if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
if (!am_root) {
free(ptr);
continue;
}
name -= RPRE_LEN;
name_len += RPRE_LEN;
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
if (!am_root) {
free(ptr);
continue;
}
name -= RPRE_LEN;
name_len += RPRE_LEN;
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
}
#else
/* This OS only has a user namespace, so we either
@@ -663,6 +652,7 @@ void receive_xattr(struct file_struct *file, int f)
rxa->datum = ptr;
rxa->name_len = name_len;
rxa->datum_len = datum_len;
rxa->num = num;
}
ndx = rsync_xal_l.count; /* pre-incremented count */
@@ -739,8 +729,6 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
sxp->st.st_mtime = (time_t)-1;
if (am_generator) { /* generator items stay abbreviated */
if (rxas[i].datum[0] == XSTATE_ABBREV)
rxas[i].datum[0] = XSTATE_LOCAL;
free(ptr);
continue;
}