mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-29 09:17:21 -04:00
Compare commits
137 Commits
v3.0.0pre5
...
v3.0.0pre9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
205393a2b5 | ||
|
|
5f0f2e0894 | ||
|
|
a5bb0902b4 | ||
|
|
d348d5fd5f | ||
|
|
21897ecbed | ||
|
|
01103e1870 | ||
|
|
2d8f9b1df0 | ||
|
|
68f1e7e594 | ||
|
|
87629cf2f6 | ||
|
|
e7f642cffe | ||
|
|
3e8fe565ed | ||
|
|
e96c7777d7 | ||
|
|
71daa07fb1 | ||
|
|
287bb276d5 | ||
|
|
ddc8110dea | ||
|
|
c0f4228d66 | ||
|
|
d6e6333a02 | ||
|
|
970ce063ee | ||
|
|
dd1f0da818 | ||
|
|
38a4bd432a | ||
|
|
3eabe6aa41 | ||
|
|
f2b7b64d86 | ||
|
|
b2057d38a9 | ||
|
|
964244b90d | ||
|
|
a7c1fa0049 | ||
|
|
42a28d9d3a | ||
|
|
19284e2ef8 | ||
|
|
2268defe66 | ||
|
|
643b018cfb | ||
|
|
e35ad79b1b | ||
|
|
da01d2e843 | ||
|
|
641dc0c51e | ||
|
|
69e2b4ee3a | ||
|
|
75a01a0734 | ||
|
|
b769ad6a3e | ||
|
|
6e59b97770 | ||
|
|
4da9fcd41d | ||
|
|
68ddbaf645 | ||
|
|
555a081fe2 | ||
|
|
513d3fd806 | ||
|
|
34aa616d41 | ||
|
|
ec8637f367 | ||
|
|
62a6b8df72 | ||
|
|
dd6f31f70f | ||
|
|
a5fd4b6e6e | ||
|
|
eca151d457 | ||
|
|
f859d3ded6 | ||
|
|
5288be3af7 | ||
|
|
83235dbc54 | ||
|
|
c78cb8f349 | ||
|
|
7210dbfd2a | ||
|
|
b6800a0b32 | ||
|
|
14eaa7a53b | ||
|
|
bc065415b0 | ||
|
|
9203c8d274 | ||
|
|
9468cf796d | ||
|
|
77d4c400c2 | ||
|
|
e3915dac76 | ||
|
|
78246d1a09 | ||
|
|
4bb319c6a6 | ||
|
|
293b11b8a5 | ||
|
|
8f42da0b50 | ||
|
|
a10186910d | ||
|
|
eb7715c1eb | ||
|
|
a7188cbf48 | ||
|
|
f7a2ac075f | ||
|
|
ce27f36d92 | ||
|
|
af5ed0f257 | ||
|
|
e6d05dcfca | ||
|
|
65b4e4b2a9 | ||
|
|
37adeae73e | ||
|
|
091b3459f6 | ||
|
|
85cdbb6be3 | ||
|
|
fcb1068f72 | ||
|
|
07ad305e8a | ||
|
|
bcfb738c93 | ||
|
|
b58f5e17ed | ||
|
|
87de82f2d0 | ||
|
|
87531e6302 | ||
|
|
eb67a6909b | ||
|
|
9217ce30e3 | ||
|
|
d52607ecd6 | ||
|
|
13e4914826 | ||
|
|
932fcfc1aa | ||
|
|
a2c770dc21 | ||
|
|
ba22c9e219 | ||
|
|
6a2456c501 | ||
|
|
ef3f14e6a7 | ||
|
|
9585b27678 | ||
|
|
5c77266d95 | ||
|
|
3db06222af | ||
|
|
aa6865d761 | ||
|
|
67b9b26ff3 | ||
|
|
b82ad9507f | ||
|
|
4d7c8e6b76 | ||
|
|
a685271de3 | ||
|
|
613c2d4431 | ||
|
|
225787a4a4 | ||
|
|
e107b6b122 | ||
|
|
5223b786ca | ||
|
|
3f0211b63a | ||
|
|
a6c6f8e650 | ||
|
|
ee6e80c753 | ||
|
|
ce72de30ce | ||
|
|
29bca53f9b | ||
|
|
dc2815c1fb | ||
|
|
3005a12bce | ||
|
|
fd913297fa | ||
|
|
90c98cdc39 | ||
|
|
b258ebf8ac | ||
|
|
97f0421523 | ||
|
|
ee8a733d6f | ||
|
|
20c7d7fd69 | ||
|
|
49ebb358ab | ||
|
|
1f41d42a91 | ||
|
|
813d2d101a | ||
|
|
86eb9f9595 | ||
|
|
18fa91296b | ||
|
|
8d3211447d | ||
|
|
805d8ac43d | ||
|
|
d26c7dfdb0 | ||
|
|
1e21cde315 | ||
|
|
c5d77e9659 | ||
|
|
2909586ede | ||
|
|
c5435b56bf | ||
|
|
2c386ff971 | ||
|
|
7f3b529367 | ||
|
|
6228239894 | ||
|
|
4da09a65f8 | ||
|
|
ab96610986 | ||
|
|
c8dccf8fb4 | ||
|
|
bdc12f41de | ||
|
|
2042c63251 | ||
|
|
6ec47d3d01 | ||
|
|
0c270e48af | ||
|
|
8aeac05d98 | ||
|
|
564dc9941e |
25
.cvsignore
25
.cvsignore
@@ -1,25 +0,0 @@
|
||||
ID
|
||||
Makefile
|
||||
autom4te*.cache
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
conftest*
|
||||
dox
|
||||
getgroups
|
||||
gmon.out
|
||||
rsync
|
||||
shconfig
|
||||
testdir
|
||||
tests-dont-exist
|
||||
testtmp
|
||||
tls
|
||||
trimslash
|
||||
t_unsafe
|
||||
wildtest
|
||||
getfsdev
|
||||
.rsync-filter
|
||||
mkrounding
|
||||
rounding.h
|
||||
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
*.[oa]
|
||||
*~
|
||||
dummy
|
||||
ID
|
||||
Makefile
|
||||
configure.sh
|
||||
config.cache
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
/proto.h
|
||||
/proto.h-tstamp
|
||||
/rsync.1
|
||||
/rsyncd.conf.5
|
||||
/autom4te*.cache
|
||||
/confdefs.h
|
||||
/conftest*
|
||||
/dox
|
||||
/getgroups
|
||||
/gmon.out
|
||||
/rsync
|
||||
/shconfig
|
||||
/testdir
|
||||
/tests-dont-exist
|
||||
/testtmp
|
||||
/tls
|
||||
/trimslash
|
||||
/t_unsafe
|
||||
/wildtest
|
||||
/getfsdev
|
||||
/rounding.h
|
||||
/doc/rsync.pdf
|
||||
/doc/rsync.ps
|
||||
/testsuite/chown-fake.test
|
||||
/testsuite/devices-fake.test
|
||||
/patches
|
||||
90
Makefile.in
90
Makefile.in
@@ -26,6 +26,7 @@ VERSION=@VERSION@
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
GENFILES=configure.sh config.h.in proto.h proto.h-tstamp rsync.1 rsyncd.conf.5
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h ifuncs.h lib/pool_alloc.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o lib/md5.o \
|
||||
lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattrs.o @LIBOBJS@
|
||||
@@ -50,7 +51,7 @@ CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
|
||||
CHECK_SYMLINKS = testsuite/chown-fake.test testsuite/devices-fake.test
|
||||
|
||||
# Objects for CHECK_PROGS to clean
|
||||
CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
CHECK_OBJS=tls.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
|
||||
# note that the -I. is needed to handle config.h when using VPATH
|
||||
.c.o:
|
||||
@@ -58,15 +59,15 @@ CHECK_OBJS=getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash.o wildtest.o
|
||||
$(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@
|
||||
@OBJ_RESTORE@
|
||||
|
||||
all: rsync$(EXEEXT)
|
||||
all: conf_stop make_stop rsync$(EXEEXT) @MAKE_MAN@
|
||||
|
||||
install: all
|
||||
-mkdir -p ${DESTDIR}${bindir}
|
||||
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
|
||||
-mkdir -p ${DESTDIR}${mandir}/man1
|
||||
-mkdir -p ${DESTDIR}${mandir}/man5
|
||||
${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1
|
||||
${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5
|
||||
if test -f $(srcdir)/rsync.1; then ${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1; fi
|
||||
if test -f $(srcdir)/rsyncd.conf.5; then ${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
|
||||
|
||||
install-strip:
|
||||
$(MAKE) INSTALL_STRIP='-s' install
|
||||
@@ -75,16 +76,25 @@ rsync$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): $(HEADERS)
|
||||
$(CHECK_OBJS): $(HEADERS)
|
||||
|
||||
flist.o: rounding.h
|
||||
|
||||
rounding.h: mkrounding$(EXEEXT)
|
||||
./mkrounding$(EXEEXT) >rounding.h
|
||||
|
||||
mkrounding$(EXEEXT): mkrounding.c rsync.h
|
||||
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
|
||||
@rm mkrounding.h
|
||||
rounding.h: rounding.c rsync.h
|
||||
@for r in 0 1 3; do \
|
||||
if $(CC) $(CFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >/dev/null 2>&1; then \
|
||||
echo "#define EXTRA_ROUNDING $$r" >rounding.h; \
|
||||
if test -f "$$HOME/build_farm/build_test.fns"; then \
|
||||
echo "EXTRA_ROUNDING is $$r" >&2; \
|
||||
fi; \
|
||||
break; \
|
||||
fi; \
|
||||
done
|
||||
@rm -f rounding
|
||||
@if test -f rounding.h; then : ; else \
|
||||
echo "Failed to create rounding.h!"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
@@ -103,18 +113,55 @@ T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
|
||||
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
|
||||
|
||||
gen:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
|
||||
gen: conf proto.h man
|
||||
|
||||
man:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
|
||||
gensend: gen
|
||||
rsync -aivzc $(GENFILES) samba.org:/home/ftp/pub/rsync/generated-files/
|
||||
|
||||
proto:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
|
||||
conf:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
|
||||
|
||||
conf_stop: configure.sh config.h.in
|
||||
|
||||
configure.sh config.h.in: configure.in aclocal.m4
|
||||
autoconf -o configure.sh
|
||||
autoheader && touch config.h.in
|
||||
@echo 'Configure files changed -- perhaps run:'
|
||||
@echo ' make reconfigure'
|
||||
@exit 1
|
||||
|
||||
reconfigure:
|
||||
./config.status --recheck
|
||||
./config.status
|
||||
|
||||
make_stop: Makefile
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
@./config.status
|
||||
@echo "Makefile updated -- rerun your make command."
|
||||
@exit 1
|
||||
|
||||
proto: proto.h-tstamp
|
||||
|
||||
proto.h: proto.h-tstamp
|
||||
@echo ' ' >/dev/null
|
||||
|
||||
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c
|
||||
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
|
||||
|
||||
man: rsync.1 rsyncd.conf.5
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 $(srcdir)/rsync.yo
|
||||
-$(srcdir)/tweak_manpage rsync.1
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
|
||||
-$(srcdir)/tweak_manpage rsyncd.conf.5
|
||||
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
mkrounding mkrounding.h rounding.h
|
||||
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
rounding rounding.h
|
||||
|
||||
cleantests:
|
||||
rm -rf ./testtmp*
|
||||
@@ -125,11 +172,10 @@ cleantests:
|
||||
distclean: clean
|
||||
rm -f Makefile config.h config.status
|
||||
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
|
||||
|
||||
rm -f config.cache config.log
|
||||
rm -f $(srcdir)/config.cache $(srcdir)/config.log
|
||||
|
||||
rm -f shconfig $(srcdir)/shconfig
|
||||
rm -f $(GENFILES)
|
||||
|
||||
# this target is really just for my use. It only works on a limited
|
||||
# range of machines and is used to produce a list of potentially
|
||||
@@ -160,7 +206,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)
|
||||
|
||||
|
||||
59
NEWS
59
NEWS
@@ -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
|
||||
@@ -21,8 +22,25 @@ 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.
|
||||
|
||||
- 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.
|
||||
|
||||
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.
|
||||
|
||||
- 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.
|
||||
|
||||
@@ -80,6 +98,13 @@ 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).
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- A new incremental-recursion algorithm is now used when rsync is talking
|
||||
@@ -112,7 +137,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
|
||||
@@ -167,6 +192,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).
|
||||
@@ -181,6 +210,9 @@ Changes since 2.6.9:
|
||||
compatibility with older rsync versions, any use of --append that is
|
||||
talking protocol 29 or older will revert to the --append-verify method.
|
||||
|
||||
- Added the --contimeout=SECONDS option that lets the user specify a
|
||||
connection timeout for rsync daemon access.
|
||||
|
||||
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
|
||||
that can be used to enhance the client side of a daemon connection.
|
||||
|
||||
@@ -218,6 +250,12 @@ Changes since 2.6.9:
|
||||
- Make sure that a daemon process doesn't mind if the client was weird and
|
||||
omitted the --server option.
|
||||
|
||||
- There are more internal logging categories available in protocol 30 than
|
||||
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
|
||||
categories allow some errors and warnings to go to stderr without causing
|
||||
an erroneous end-of-run warning about some files not being able to be
|
||||
transferred.
|
||||
|
||||
- Improved the use of "const" on pointers.
|
||||
|
||||
- Improved J.W.'s pool_alloc routines to add a way of freeing older
|
||||
@@ -231,6 +269,22 @@ Changes since 2.6.9:
|
||||
|
||||
- Rsync is now licensed under the GPLv3 or later.
|
||||
|
||||
- Rsync is now being maintained in a "git" repository instead of CVS
|
||||
(though the old CVS repository still exists). Several maintenance
|
||||
scripts were updated to work with git.
|
||||
|
||||
- Generated files are no longer committed into the source repository. The
|
||||
autoconf and autoheader commands are now automatically run during the
|
||||
normal use of "configure" and "make". The latest dev versions of all
|
||||
generated files can also be copied from the samba.org web site (see the
|
||||
"magic" configure script that now comes with rsync for its location).
|
||||
|
||||
- The "patches" directory of diff files is now built from branches in the
|
||||
rsync git repository (branch patch/FOO creates file patches/FOO.diff).
|
||||
|
||||
- The proto.h file is now built using a simple perl script rather than a
|
||||
complex awk script, which proved to be more widely compatible.
|
||||
|
||||
- When running the tests, we now put our per-test temp dirs into a sub-
|
||||
directory named testtmp (which is created, if missing). This allows
|
||||
someone to symlink the testtmp directory to another filesystem (which is
|
||||
@@ -245,3 +299,6 @@ Changes since 2.6.9:
|
||||
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
|
||||
does not have enough range to allow the main protocol number to be
|
||||
incremented for every minor tweak in that happens during development).
|
||||
|
||||
- The csprotocol.txt file was updated to mention the daemon protocol change
|
||||
in the 3.0.0 release.
|
||||
|
||||
2
OLDNEWS
2
OLDNEWS
@@ -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
|
||||
|
||||
29
acls.c
29
acls.c
@@ -300,7 +300,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
|
||||
ida->access = access;
|
||||
}
|
||||
if (rc) {
|
||||
rsyserr(FERROR, errno, "unpack_smb_acl: %s()", errfun);
|
||||
rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
|
||||
rsync_acl_free(racl);
|
||||
return False;
|
||||
}
|
||||
@@ -356,7 +356,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
|
||||
static int store_access_in_entry(uint32 access, SMB_ACL_ENTRY_T entry)
|
||||
{
|
||||
if (sys_acl_set_access_bits(entry, access)) {
|
||||
rsyserr(FERROR, errno, "store_access_in_entry sys_acl_set_access_bits()");
|
||||
rsyserr(FERROR_XFER, errno, "store_access_in_entry sys_acl_set_access_bits()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -375,7 +375,7 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
|
||||
SMB_ACL_ENTRY_T entry;
|
||||
|
||||
if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
|
||||
rsyserr(FERROR, errno, "pack_smb_acl: sys_acl_init()");
|
||||
rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
|
||||
return False;
|
||||
}
|
||||
|
||||
@@ -424,14 +424,14 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (sys_acl_valid(*smb_acl) < 0)
|
||||
rprintf(FERROR, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
|
||||
rprintf(FERROR_XFER, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
|
||||
#endif
|
||||
|
||||
return True;
|
||||
|
||||
error_exit:
|
||||
if (errfun) {
|
||||
rsyserr(FERROR, errno, "pack_smb_acl %s()", errfun);
|
||||
rsyserr(FERROR_XFER, errno, "pack_smb_acl %s()", errfun);
|
||||
}
|
||||
sys_acl_free_acl(*smb_acl);
|
||||
return False;
|
||||
@@ -514,7 +514,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
if (type == SMB_ACL_TYPE_ACCESS)
|
||||
rsync_acl_fake_perms(racl, mode);
|
||||
} else {
|
||||
rsyserr(FERROR, errno, "get_acl: sys_acl_get_file(%s, %s)",
|
||||
rsyserr(FERROR_XFER, errno, "get_acl: sys_acl_get_file(%s, %s)",
|
||||
fname, str_acl_type(type));
|
||||
return -1;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -655,7 +655,7 @@ static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
|
||||
access |= NAME_IS_USER;
|
||||
} else if (am_root >= 0 && access & ~SMB_ACL_VALID_OBJ_BITS) {
|
||||
value_error:
|
||||
rprintf(FERROR, "recv_acl_access: value out of range: %x\n",
|
||||
rprintf(FERROR_XFER, "recv_acl_access: value out of range: %x\n",
|
||||
access);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
@@ -710,7 +710,7 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
|
||||
int ndx = read_varint(f);
|
||||
|
||||
if (ndx < 0 || (size_t)ndx > racl_list->count) {
|
||||
rprintf(FERROR, "recv_acl_index: %s ACL index %d > %d\n",
|
||||
rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
|
||||
str_acl_type(type), ndx, (int)racl_list->count);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
@@ -855,7 +855,7 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
|
||||
if (rc) {
|
||||
error_exit:
|
||||
if (errfun) {
|
||||
rsyserr(FERROR, errno, "change_sacl_perms: %s()",
|
||||
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
|
||||
errfun);
|
||||
}
|
||||
return (mode_t)~0;
|
||||
@@ -887,7 +887,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
|
||||
#endif
|
||||
rc = sys_acl_delete_def_file(fname);
|
||||
if (rc < 0) {
|
||||
rsyserr(FERROR, errno, "set_acl: sys_acl_delete_def_file(%s)",
|
||||
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
|
||||
fname);
|
||||
return -1;
|
||||
}
|
||||
@@ -932,7 +932,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
|
||||
}
|
||||
#endif
|
||||
if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
|
||||
rsyserr(FERROR, errno, "set_acl: sys_acl_set_file(%s, %s)",
|
||||
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
|
||||
fname, str_acl_type(type));
|
||||
return -1;
|
||||
}
|
||||
@@ -1052,7 +1052,8 @@ int default_perms_for_dir(const char *dir)
|
||||
}
|
||||
/* Otherwise fall through. */
|
||||
default:
|
||||
rprintf(FERROR, "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
|
||||
rprintf(FWARNING,
|
||||
"default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
|
||||
dir, str_acl_type(SMB_ACL_TYPE_DEFAULT), strerror(errno));
|
||||
}
|
||||
return perms;
|
||||
@@ -1063,7 +1064,7 @@ int default_perms_for_dir(const char *dir)
|
||||
ok = unpack_smb_acl(sacl, &racl);
|
||||
sys_acl_free_acl(sacl);
|
||||
if (!ok) {
|
||||
rprintf(FERROR, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
|
||||
rprintf(FWARNING, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
|
||||
return perms;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern char *password_file;
|
||||
extern int log_got_error;
|
||||
|
||||
/***************************************************************************
|
||||
encode a buffer using base64 - simple and slow algorithm. null terminates
|
||||
@@ -164,7 +163,7 @@ static const char *getpassf(const char *filename)
|
||||
return NULL;
|
||||
|
||||
if ((fd = open(filename,O_RDONLY)) < 0) {
|
||||
rsyserr(FERROR, errno, "could not open password file \"%s\"",
|
||||
rsyserr(FWARNING, errno, "could not open password file \"%s\"",
|
||||
filename);
|
||||
if (envpw)
|
||||
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
@@ -172,18 +171,18 @@ static const char *getpassf(const char *filename)
|
||||
}
|
||||
|
||||
if (do_stat(filename, &st) == -1) {
|
||||
rsyserr(FERROR, errno, "stat(%s)", filename);
|
||||
rsyserr(FWARNING, errno, "stat(%s)", filename);
|
||||
ok = 0;
|
||||
} else if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FERROR, "password file must not be other-accessible\n");
|
||||
rprintf(FWARNING, "password file must not be other-accessible\n");
|
||||
ok = 0;
|
||||
} else if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
rprintf(FERROR, "password file must be owned by root when running as root\n");
|
||||
rprintf(FWARNING, "password file must be owned by root when running as root\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (!ok) {
|
||||
close(fd);
|
||||
rprintf(FERROR, "continuing without password file\n");
|
||||
rprintf(FWARNING, "continuing without password file\n");
|
||||
if (envpw)
|
||||
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
return NULL;
|
||||
@@ -308,9 +307,6 @@ void auth_client(int fd, const char *user, const char *challenge)
|
||||
pass = getpass("Password: ");
|
||||
}
|
||||
|
||||
/* Any errors output during password handling aren't transfer errors. */
|
||||
log_got_error = 0;
|
||||
|
||||
if (!pass)
|
||||
pass = "";
|
||||
|
||||
|
||||
76
batch.c
76
batch.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int io_error;
|
||||
extern int keep_partial;
|
||||
extern int log_got_error;
|
||||
extern int got_xfer_error;
|
||||
extern char *partial_dir;
|
||||
extern char *logfile_name;
|
||||
|
||||
@@ -174,7 +174,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
code = exit_code = RERR_DEL_LIMIT;
|
||||
if (io_error & IOERR_VANISHED)
|
||||
code = exit_code = RERR_VANISHED;
|
||||
if (io_error & IOERR_GENERAL || log_got_error)
|
||||
if (io_error & IOERR_GENERAL || got_xfer_error)
|
||||
code = exit_code = RERR_PARTIAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int output_motd;
|
||||
extern int list_only;
|
||||
extern int am_sender;
|
||||
@@ -39,6 +40,7 @@ extern int remote_protocol;
|
||||
extern int protocol_version;
|
||||
extern int io_timeout;
|
||||
extern int no_detach;
|
||||
extern int write_batch;
|
||||
extern int default_af_hint;
|
||||
extern int logfile_format_has_i;
|
||||
extern int logfile_format_has_o_or_i;
|
||||
@@ -56,6 +58,7 @@ extern char curr_dir[];
|
||||
char *auth_user;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int munge_symlinks = 0;
|
||||
struct chmod_mode_struct *daemon_chmod_modes;
|
||||
|
||||
/* module_dirlen is the length of the module_dir string when in daemon
|
||||
@@ -242,7 +245,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (list_only && strncmp(*argv, modname, modlen) == 0
|
||||
if (strncmp(*argv, modname, modlen) == 0
|
||||
&& argv[0][modlen] == '\0')
|
||||
sargs[sargc++] = modname; /* we send "modname/" */
|
||||
else
|
||||
@@ -352,8 +355,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)
|
||||
@@ -622,6 +629,18 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
sanitize_paths = 1;
|
||||
}
|
||||
|
||||
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
|
||||
munge_symlinks = !use_chroot;
|
||||
if (munge_symlinks) {
|
||||
STRUCT_STAT st;
|
||||
if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
|
||||
SYMLINK_PREFIX);
|
||||
io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
if (am_root) {
|
||||
/* XXXX: You could argue that if the daemon is started
|
||||
* by a non-root user and they explicitly specify a
|
||||
@@ -681,6 +700,12 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
am_server = 1; /* Don't let someone try to be tricky. */
|
||||
if (lp_ignore_errors(module_id))
|
||||
ignore_errors = 1;
|
||||
if (write_batch < 0)
|
||||
dry_run = 1;
|
||||
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
|
||||
if (lp_fake_super(i))
|
||||
am_root = -1;
|
||||
|
||||
7
compat.c
7
compat.c
@@ -171,6 +171,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 +233,12 @@ void setup_protocol(int f_out,int f_in)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
} else if (protocol_version >= 30) {
|
||||
/* The inc_recurse var MUST be set to 0 or 1. */
|
||||
if (am_server) {
|
||||
inc_recurse = allow_inc_recurse;
|
||||
inc_recurse = allow_inc_recurse ? 1 : 0;
|
||||
write_byte(f_out, inc_recurse);
|
||||
} else
|
||||
inc_recurse = read_byte(f_in);
|
||||
inc_recurse = read_byte(f_in) ? 1 : 0;
|
||||
if (inc_recurse && !allow_inc_recurse) {
|
||||
/* This should only be able to happen in a batch. */
|
||||
fprintf(stderr,
|
||||
|
||||
25
configure
vendored
Executable file
25
configure
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh -e
|
||||
# This configure script ensures that the configure.sh script exists, and
|
||||
# if not, it tries to fetch rsync's generated files or build them. We
|
||||
# then transfer control to the configure.sh script to do the real work.
|
||||
|
||||
dir=`dirname $0`
|
||||
realconfigure="$dir/configure.sh"
|
||||
|
||||
if test ! -f "$realconfigure"; then
|
||||
if test -f "$HOME/build_farm/build_test.fns"; then
|
||||
# Allow the build farm to grab latest files via rsync.
|
||||
actions='build fetch'
|
||||
else
|
||||
actions='build'
|
||||
fi
|
||||
if "$dir/prepare-source" $actions; then
|
||||
:
|
||||
else
|
||||
echo 'Failed to build configure.sh and/or config.h.in -- giving up.' >&2
|
||||
rm -f "$realconfigure"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "$realconfigure" "${@}"
|
||||
13
configure.in
13
configure.in
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
RSYNC_VERSION=3.0.0pre5
|
||||
RSYNC_VERSION=3.0.0pre9
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -123,6 +123,11 @@ else
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
|
||||
AC_CHECK_PROG(HAVE_YODL2MAN, yodl2man, 1, 0)
|
||||
if test x$HAVE_YODL2MAN = x1; then
|
||||
MAKE_MAN=man
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(nobody-group,
|
||||
AC_HELP_STRING([--with-nobody-group=GROUP],
|
||||
[set the default unprivileged group (default nobody or nogroup)]),
|
||||
@@ -549,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
|
||||
@@ -813,6 +823,7 @@ AC_SUBST(OBJ_SAVE)
|
||||
AC_SUBST(OBJ_RESTORE)
|
||||
AC_SUBST(CC_SHOBJ_FLAG)
|
||||
AC_SUBST(BUILD_POPT)
|
||||
AC_SUBST(MAKE_MAN)
|
||||
|
||||
AC_CHECK_HEADERS(sys/acl.h acl/libacl.h)
|
||||
AC_CHECK_FUNCS(_acl __acl _facl __facl)
|
||||
|
||||
@@ -3,21 +3,22 @@ basically a summary of clientserver.c and authenticate.c.
|
||||
|
||||
-- Martin Pool <mbp@samba.org>
|
||||
|
||||
$Id$
|
||||
|
||||
|
||||
|
||||
|
||||
This is the protocol used for rsync --daemon; i.e. connections to port
|
||||
873 rather than invocations over a remote shell.
|
||||
|
||||
When the server accepts a connection, it prints a greeting
|
||||
|
||||
@RSYNCD: <version>
|
||||
@RSYNCD: <version>.<subprotocol>
|
||||
|
||||
where <version> is the numeric version; currently 24. It follows this
|
||||
with a free text message-of-the-day. It expects to see a similar
|
||||
greeting back from the client.
|
||||
where <version> is the numeric version (see PROTOCOL_VERSION in rsync.h)
|
||||
'.' is a literal period, and <subprotocol> is the numeric subprotocol
|
||||
version (see SUBPROTOCOL_VERSION -- it will be 0 for final releases).
|
||||
Protocols prior to 30 only output <version> alone. The daemon expects
|
||||
to see a similar greeting back from the client. For protocols prior to
|
||||
30, an absent ".<subprotocol>" value is assumed to be 0. For protocol
|
||||
30, an absent value is a fatal error. The daemon then follows this line
|
||||
with a free-format text message-of-the-day (if any is defined).
|
||||
|
||||
The server is now in the connected state. The client can either send
|
||||
the command
|
||||
@@ -75,8 +76,13 @@ stay tuned (or write it yourself!).
|
||||
------------
|
||||
Protocol version changes
|
||||
|
||||
25 (2001-08-20, 2.4.7pre2)
|
||||
30 (2007-10-04, 3.0.0pre1)
|
||||
|
||||
Send an explicit "@RSYNC EXIT" command at the end of the
|
||||
module listing. We never intentionally end the transmission
|
||||
by just closing the socket anymore.
|
||||
The use of a ".<subprotocol>" number was added to
|
||||
@RSYNCD: <version>.<subprotocol>
|
||||
|
||||
25 (2001-08-20, 2.4.7pre2)
|
||||
|
||||
Send an explicit "@RSYNC EXIT" command at the end of the
|
||||
module listing. We never intentionally end the transmission
|
||||
by just closing the socket anymore.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
rsync.pdf
|
||||
rsync.ps
|
||||
@@ -45,6 +45,7 @@
|
||||
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
|
||||
|
||||
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
|
||||
#define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */
|
||||
|
||||
/* Although it doesn't seem to be specified anywhere,
|
||||
* ssh and the shell seem to return these values:
|
||||
|
||||
@@ -26,7 +26,6 @@ extern int verbose;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int eol_nulls;
|
||||
extern int recurse;
|
||||
extern int io_error;
|
||||
extern int local_server;
|
||||
extern int prune_empty_dirs;
|
||||
@@ -296,7 +295,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
|
||||
strlcpy(to, merge_file, *len_ptr + 1);
|
||||
merge_file = to;
|
||||
}
|
||||
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
|
||||
if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
|
||||
rprintf(FERROR, "merge-file name overflows: %s\n",
|
||||
merge_file);
|
||||
return NULL;
|
||||
|
||||
174
flist.c
174
flist.c
@@ -63,6 +63,7 @@ extern int copy_links;
|
||||
extern int copy_unsafe_links;
|
||||
extern int protocol_version;
|
||||
extern int sanitize_paths;
|
||||
extern int munge_symlinks;
|
||||
extern int need_unsorted_flist;
|
||||
extern int unsort_ndx;
|
||||
extern struct stats stats;
|
||||
@@ -120,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)
|
||||
@@ -200,6 +200,11 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf)
|
||||
}
|
||||
return x_stat(path, stp, NULL);
|
||||
}
|
||||
if (munge_symlinks && am_sender && llen > SYMLINK_PREFIX_LEN
|
||||
&& strncmp(linkbuf, SYMLINK_PREFIX, SYMLINK_PREFIX_LEN) == 0) {
|
||||
memmove(linkbuf, linkbuf + SYMLINK_PREFIX_LEN,
|
||||
llen - SYMLINK_PREFIX_LEN + 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
@@ -346,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;
|
||||
@@ -384,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)
|
||||
@@ -451,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;
|
||||
@@ -671,7 +676,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
|
||||
clean_fname(thisname, 0);
|
||||
|
||||
if (sanitize_paths)
|
||||
sanitize_path(thisname, thisname, "", 0, NULL);
|
||||
sanitize_path(thisname, thisname, "", 0);
|
||||
|
||||
if ((basename = strrchr(thisname, '/')) != NULL) {
|
||||
int len = basename++ - thisname;
|
||||
@@ -725,8 +730,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
|
||||
if (protocol_version >= 30) {
|
||||
modtime = read_varlong(f, 4);
|
||||
#if SIZEOF_TIME_T < SIZEOF_INT64
|
||||
if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) {
|
||||
rprintf(FERROR,
|
||||
if (!am_generator && (int64)(time_t)modtime != modtime) {
|
||||
rprintf(FERROR_XFER,
|
||||
"Time value of %s truncated on receiver.\n",
|
||||
lastname);
|
||||
}
|
||||
@@ -794,6 +799,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
|
||||
linkname_len - 1);
|
||||
overflow_exit("recv_file_entry");
|
||||
}
|
||||
if (munge_symlinks)
|
||||
linkname_len += SYMLINK_PREFIX_LEN;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -821,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 */
|
||||
@@ -835,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");
|
||||
@@ -914,10 +921,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
|
||||
if (first_hlink_ndx >= flist->ndx_start) {
|
||||
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
|
||||
memcpy(bp, F_SYMLINK(first), linkname_len);
|
||||
} else
|
||||
} else if (munge_symlinks) {
|
||||
strlcpy(bp, SYMLINK_PREFIX, linkname_len);
|
||||
bp += SYMLINK_PREFIX_LEN;
|
||||
linkname_len -= SYMLINK_PREFIX_LEN;
|
||||
read_sbuf(f, bp, linkname_len - 1);
|
||||
if (sanitize_paths)
|
||||
sanitize_path(bp, bp, "", lastdir_depth, NULL);
|
||||
} else {
|
||||
read_sbuf(f, bp, linkname_len - 1);
|
||||
if (sanitize_paths)
|
||||
sanitize_path(bp, bp, "", lastdir_depth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -925,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 {
|
||||
@@ -1008,7 +1020,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
}
|
||||
clean_fname(thisname, 0);
|
||||
if (sanitize_paths)
|
||||
sanitize_path(thisname, thisname, "", 0, NULL);
|
||||
sanitize_path(thisname, thisname, "", 0);
|
||||
|
||||
if (stp && S_ISDIR(stp->st_mode)) {
|
||||
st = *stp; /* Needed for "symlink/." with --relative. */
|
||||
@@ -1025,24 +1037,30 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
}
|
||||
if (save_errno == ENOENT) {
|
||||
#ifdef SUPPORT_LINKS
|
||||
/* Avoid "vanished" error if symlink points nowhere. */
|
||||
if (copy_links && x_lstat(thisname, &st, NULL) == 0
|
||||
&& S_ISLNK(st.st_mode)) {
|
||||
/* When our options tell us to follow a symlink that
|
||||
* points nowhere, tell the user about the symlink
|
||||
* instead of giving a "vanished" message. We only
|
||||
* dereference a symlink if one of the --copy*links
|
||||
* options was specified, so there's no need for the
|
||||
* extra lstat() if one of these options isn't on. */
|
||||
if ((copy_links || copy_unsafe_links || copy_dirlinks)
|
||||
&& x_lstat(thisname, &st, NULL) == 0
|
||||
&& S_ISLNK(st.st_mode)) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "symlink has no referent: %s\n",
|
||||
rprintf(FERROR_XFER, "symlink has no referent: %s\n",
|
||||
full_fname(thisname));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
enum logcode c = am_daemon && protocol_version < 28
|
||||
? FERROR : FINFO;
|
||||
? FERROR : FWARNING;
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(thisname));
|
||||
}
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, save_errno, "readlink %s failed",
|
||||
rsyserr(FERROR_XFER, save_errno, "readlink %s failed",
|
||||
full_fname(thisname));
|
||||
}
|
||||
return NULL;
|
||||
@@ -1100,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;
|
||||
@@ -1221,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;
|
||||
}
|
||||
@@ -1310,7 +1330,7 @@ static void send_if_directory(int f, struct file_list *flist,
|
||||
fbuf[--len] = '\0';
|
||||
if (len >= MAXPATHLEN - 1) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "skipping long-named directory: %s\n",
|
||||
rprintf(FERROR_XFER, "skipping long-named directory: %s\n",
|
||||
full_fname(fbuf));
|
||||
return;
|
||||
}
|
||||
@@ -1449,7 +1469,7 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
|
||||
|
||||
if (!(d = opendir(fbuf))) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "opendir %s failed", full_fname(fbuf));
|
||||
rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1486,7 +1506,7 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
|
||||
|
||||
if (errno) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "readdir(%s)", full_fname(fbuf));
|
||||
rsyserr(FERROR_XFER, errno, "readdir(%s)", full_fname(fbuf));
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
@@ -1511,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
|
||||
@@ -1554,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);
|
||||
@@ -1572,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)
|
||||
@@ -1596,7 +1621,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
|
||||
STRUCT_STAT st;
|
||||
if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "link_stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
|
||||
full_fname(fbuf));
|
||||
return;
|
||||
}
|
||||
@@ -1633,7 +1658,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
|
||||
STRUCT_STAT st;
|
||||
if (link_stat(fbuf, &st, 1) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "link_stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
|
||||
full_fname(fbuf));
|
||||
continue;
|
||||
}
|
||||
@@ -1705,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);
|
||||
@@ -1791,7 +1812,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
disable_buffering = io_start_buffering_out(f);
|
||||
if (filesfrom_fd >= 0) {
|
||||
if (argv[0] && !push_dir(argv[0], 0)) {
|
||||
rsyserr(FERROR, errno, "push_dir %s failed in %s",
|
||||
rsyserr(FERROR_XFER, errno, "push_dir %s failed in %s",
|
||||
full_fname(argv[0]), curr_dir);
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -1804,13 +1825,13 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
if (use_ff_fd) {
|
||||
if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0)
|
||||
break;
|
||||
sanitize_path(fbuf, fbuf, "", 0, NULL);
|
||||
sanitize_path(fbuf, fbuf, "", 0);
|
||||
} else {
|
||||
if (argc-- == 0)
|
||||
break;
|
||||
strlcpy(fbuf, *argv++, MAXPATHLEN);
|
||||
if (sanitize_paths)
|
||||
sanitize_path(fbuf, fbuf, "", 0, NULL);
|
||||
sanitize_path(fbuf, fbuf, "", 0);
|
||||
}
|
||||
|
||||
len = strlen(fbuf);
|
||||
@@ -1820,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");
|
||||
@@ -1918,7 +1939,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
|
||||
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno, "link_stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
|
||||
full_fname(fbuf));
|
||||
continue;
|
||||
}
|
||||
@@ -1964,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);
|
||||
@@ -2007,27 +2028,15 @@ 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)
|
||||
send_id_list(f);
|
||||
|
||||
@@ -2126,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);
|
||||
|
||||
@@ -2147,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);
|
||||
@@ -2167,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 */
|
||||
@@ -2307,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++;
|
||||
@@ -2364,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;
|
||||
@@ -2544,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) {
|
||||
@@ -2795,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)
|
||||
|
||||
232
generator.c
232
generator.c
@@ -91,6 +91,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 +114,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 +136,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 +148,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 +159,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 +172,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 +187,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 +206,18 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
|
||||
}
|
||||
|
||||
check_ret:
|
||||
if (replace && ret != DR_SUCCESS) {
|
||||
rprintf(FERROR, "could not make way for new %s: %s\n",
|
||||
replace, fbuf);
|
||||
if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {
|
||||
const char *desc;
|
||||
switch (flags & DEL_MAKE_ROOM) {
|
||||
case DEL_FOR_FILE: desc = "regular file"; break;
|
||||
case DEL_FOR_DIR: desc = "directory"; break;
|
||||
case DEL_FOR_SYMLINK: desc = "symlink"; break;
|
||||
case DEL_FOR_DEVICE: desc = "device file"; break;
|
||||
case DEL_FOR_SPECIAL: desc = "special file"; break;
|
||||
default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
|
||||
}
|
||||
rprintf(FERROR_XFER, "could not make way for new %s: %s\n",
|
||||
desc, fbuf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -242,7 +262,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 +278,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 +339,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 +362,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 +403,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 +432,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 +502,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,7 +878,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 +902,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
|
||||
@@ -947,10 +982,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))) {
|
||||
@@ -1082,7 +1113,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
|
||||
#endif
|
||||
&& !S_ISDIR(file->mode)) {
|
||||
if (do_link(cmpbuf, fname) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to hard-link %s with %s",
|
||||
cmpbuf, fname);
|
||||
return j;
|
||||
@@ -1198,11 +1229,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1239,7 +1268,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if (relative_paths && !implied_dirs
|
||||
&& do_stat(dn, &sx.st) < 0
|
||||
&& create_directory_path(fname) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"recv_generator: mkdir %s failed",
|
||||
full_fname(dn));
|
||||
}
|
||||
@@ -1285,6 +1314,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (statret == 0 && sx.st.st_uid == our_uid)
|
||||
del_opts |= DEL_OWNED_BY_US;
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
|
||||
goto cleanup;
|
||||
@@ -1296,7 +1328,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 +1340,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;
|
||||
}
|
||||
@@ -1342,7 +1374,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if (!relative_paths || errno != ENOENT
|
||||
|| create_directory_path(fname) < 0
|
||||
|| (do_mkdir(fname, file->mode) < 0 && errno != EEXIST)) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"recv_generator: mkdir %s failed",
|
||||
full_fname(fname));
|
||||
skipping_dir_contents:
|
||||
@@ -1365,7 +1397,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) {
|
||||
mode_t mode = file->mode | S_IWUSR;
|
||||
if (do_chmod(fname, mode) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to modify permissions on %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
@@ -1427,7 +1459,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
|
||||
if (itemizing)
|
||||
itemize(fname, file, ndx, 0, &sx, 0, 0, NULL);
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
#if defined SUPPORT_HARD_LINKS && defined CAN_HARDLINK_SYMLINK
|
||||
if (preserve_hard_links && F_IS_HLINKED(file))
|
||||
finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);
|
||||
#endif
|
||||
@@ -1437,7 +1469,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,
|
||||
@@ -1462,7 +1494,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
}
|
||||
#endif
|
||||
if (do_symlink(sl, fname) != 0) {
|
||||
rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
|
||||
rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
|
||||
full_fname(fname), sl);
|
||||
} else {
|
||||
set_file_attrs(fname, file, NULL, NULL, 0);
|
||||
@@ -1491,15 +1523,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 +1548,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,
|
||||
@@ -1546,7 +1578,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
(long)major(rdev), (long)minor(rdev));
|
||||
}
|
||||
if (do_mknod(fname, file->mode, rdev) < 0) {
|
||||
rsyserr(FERROR, errno, "mknod %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "mknod %s failed",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
set_file_attrs(fname, file, NULL, NULL, 0);
|
||||
@@ -1607,7 +1639,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;
|
||||
@@ -1664,7 +1696,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
#endif
|
||||
if (stat_errno == ENOENT)
|
||||
goto notify_others;
|
||||
rsyserr(FERROR, stat_errno, "recv_generator: failed to stat %s",
|
||||
rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1754,7 +1786,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto pretend_missing;
|
||||
}
|
||||
if (robust_unlink(backupptr) && errno != ENOENT) {
|
||||
rsyserr(FERROR, errno, "unlink %s",
|
||||
rsyserr(FERROR_XFER, errno, "unlink %s",
|
||||
full_fname(backupptr));
|
||||
unmake_file(back_file);
|
||||
back_file = NULL;
|
||||
@@ -1764,7 +1796,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0
|
||||
&& (errno != ENOENT || make_bak_dir(backupptr) < 0
|
||||
|| (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) {
|
||||
rsyserr(FERROR, errno, "open %s",
|
||||
rsyserr(FERROR_XFER, errno, "open %s",
|
||||
full_fname(backupptr));
|
||||
unmake_file(back_file);
|
||||
back_file = NULL;
|
||||
@@ -1899,57 +1931,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;
|
||||
|
||||
@@ -2040,7 +2078,7 @@ void generate_files(int f_out, const char *local_name)
|
||||
f_name(fp, fbuf);
|
||||
ndx = cur_flist->ndx_start - 1;
|
||||
recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
|
||||
if (delete_during && dry_run < 2) {
|
||||
if (delete_during && dry_run < 2 && !list_only) {
|
||||
if (BITS_SETnUNSET(fp->flags, FLAG_CONTENT_DIR, FLAG_MISSING_DIR)) {
|
||||
dev_t dirdev;
|
||||
if (one_file_system) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
51
hlink.c
51
hlink.c
@@ -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();
|
||||
}
|
||||
@@ -217,7 +220,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
|
||||
if (!make_backup(fname))
|
||||
return -1;
|
||||
} else if (robust_unlink(fname)) {
|
||||
rsyserr(FERROR, errno, "unlink %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "unlink %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -317,7 +320,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|
||||
}
|
||||
|
||||
if (link_stat(prev_name, &prev_st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "stat %s failed",
|
||||
full_fname(prev_name));
|
||||
return -1;
|
||||
}
|
||||
@@ -390,10 +393,10 @@ int hard_link_one(struct file_struct *file, const char *fname,
|
||||
enum logcode code;
|
||||
if (terse) {
|
||||
if (!verbose)
|
||||
return -1;
|
||||
return 0;
|
||||
code = FINFO;
|
||||
} else
|
||||
code = FERROR;
|
||||
code = FERROR_XFER;
|
||||
rsyserr(code, errno, "link %s => %s failed",
|
||||
full_fname(fname), oldname);
|
||||
return 0;
|
||||
@@ -417,7 +420,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
|
||||
if (stp == NULL && prev_ndx >= 0) {
|
||||
if (link_stat(fname, &st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return;
|
||||
}
|
||||
|
||||
61
io.c
61
io.c
@@ -413,15 +413,17 @@ static void read_msg_fd(void)
|
||||
readfd(fd, buf, 4);
|
||||
got_flist_entry_status(FES_NO_SEND, buf);
|
||||
break;
|
||||
case MSG_SOCKERR:
|
||||
case MSG_ERROR_SOCKET:
|
||||
case MSG_CLIENT:
|
||||
if (!am_generator)
|
||||
goto invalid_msg;
|
||||
if (tag == MSG_SOCKERR)
|
||||
if (tag == MSG_ERROR_SOCKET)
|
||||
io_end_multiplex_out();
|
||||
/* FALL THROUGH */
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
case MSG_ERROR_XFER:
|
||||
case MSG_WARNING:
|
||||
case MSG_LOG:
|
||||
while (len) {
|
||||
n = len;
|
||||
@@ -468,41 +470,38 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len,
|
||||
char buffer[BIGPATHBUFLEN]; /* Oversized for use by iconv code. */
|
||||
size_t n = len;
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert && ic_send == (iconv_t)-1)
|
||||
#endif
|
||||
convert = 0;
|
||||
/* We need to convert buf before doing anything else so that we
|
||||
* can include the (converted) byte length in the message header. */
|
||||
if (convert && ic_send != (iconv_t)-1) {
|
||||
xbuf outbuf, inbuf;
|
||||
|
||||
if (convert || n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
|
||||
n = 0;
|
||||
INIT_XBUF(outbuf, buffer + 4, 0, sizeof buffer - 4);
|
||||
INIT_XBUF(inbuf, (char*)buf, len, -1);
|
||||
|
||||
iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
|
||||
if (inbuf.len > 0) {
|
||||
rprintf(FERROR, "overflowed conversion buffer in mplex_write");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
n = len = outbuf.len;
|
||||
} else
|
||||
#endif
|
||||
if (n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
|
||||
n = 0; /* We'd rather do 2 writes than too much memcpy(). */
|
||||
else
|
||||
memcpy(buffer + 4, buf, n);
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
defer_forwarding_keep = 1; /* defer_forwarding_messages++ on return */
|
||||
writefd_unbuffered(fd, buffer, n+4);
|
||||
defer_forwarding_keep = 0;
|
||||
|
||||
len -= n;
|
||||
buf += n;
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert) {
|
||||
xbuf outbuf, inbuf;
|
||||
|
||||
INIT_CONST_XBUF(outbuf, buffer);
|
||||
INIT_XBUF(inbuf, (char*)buf, len, -1);
|
||||
|
||||
do {
|
||||
iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
|
||||
writefd_unbuffered(fd, outbuf.buf, outbuf.len);
|
||||
} while (inbuf.len);
|
||||
} else
|
||||
#endif
|
||||
if (len)
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
if (len > n)
|
||||
writefd_unbuffered(fd, buf+n, len-n);
|
||||
|
||||
if (!--defer_forwarding_messages && !no_flush)
|
||||
msg_flush();
|
||||
@@ -754,7 +753,7 @@ static int read_timeout(int fd, char *buf, size_t len)
|
||||
/* Don't write errors on a dead socket. */
|
||||
if (fd == sock_f_in) {
|
||||
io_end_multiplex_out();
|
||||
rsyserr(FSOCKERR, errno, "read error");
|
||||
rsyserr(FERROR_SOCKET, errno, "read error");
|
||||
} else
|
||||
rsyserr(FERROR, errno, "read error");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
@@ -1060,7 +1059,7 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
int pos = 0;
|
||||
|
||||
INIT_CONST_XBUF(outbuf, line);
|
||||
inbuf.buf = ibuf;
|
||||
INIT_XBUF(inbuf, ibuf, 0, -1);
|
||||
|
||||
while (msg_bytes) {
|
||||
inbuf.len = msg_bytes > sizeof ibuf
|
||||
@@ -1109,6 +1108,8 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
break;
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
case MSG_ERROR_XFER:
|
||||
case MSG_WARNING:
|
||||
if (msg_bytes >= sizeof line) {
|
||||
overflow:
|
||||
rprintf(FERROR,
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
dummy
|
||||
@@ -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;
|
||||
|
||||
19
loadparm.c
19
loadparm.c
@@ -157,6 +157,7 @@ typedef struct
|
||||
BOOL ignore_errors;
|
||||
BOOL ignore_nonreadable;
|
||||
BOOL list;
|
||||
BOOL munge_symlinks;
|
||||
BOOL read_only;
|
||||
BOOL strict_modes;
|
||||
BOOL transfer_logging;
|
||||
@@ -205,6 +206,7 @@ static service sDefault =
|
||||
/* ignore_errors; */ False,
|
||||
/* ignore_nonreadable; */ False,
|
||||
/* list; */ True,
|
||||
/* munge_symlinks; */ (BOOL)-1,
|
||||
/* read_only; */ True,
|
||||
/* strict_modes; */ True,
|
||||
/* transfer_logging; */ False,
|
||||
@@ -319,6 +321,7 @@ static struct parm_struct parm_table[] =
|
||||
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
|
||||
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
|
||||
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
|
||||
{"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0},
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
|
||||
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
|
||||
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
|
||||
@@ -422,6 +425,7 @@ FN_LOCAL_BOOL(lp_fake_super, fake_super)
|
||||
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
|
||||
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
|
||||
FN_LOCAL_BOOL(lp_list, list)
|
||||
FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
|
||||
FN_LOCAL_BOOL(lp_read_only, read_only)
|
||||
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
|
||||
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
|
||||
@@ -558,7 +562,7 @@ static int map_parameter(char *parmname)
|
||||
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
|
||||
return(iIndex);
|
||||
|
||||
rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
|
||||
rprintf(FLOG, "Unknown Parameter encountered: \"%s\"\n", parmname);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@@ -584,7 +588,7 @@ static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
*pb = False;
|
||||
else
|
||||
{
|
||||
rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
|
||||
rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n",
|
||||
parmvalue);
|
||||
bRetval = False;
|
||||
}
|
||||
@@ -671,7 +675,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
|
||||
if (parmnum < 0)
|
||||
{
|
||||
rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
|
||||
rprintf(FLOG, "IGNORING unknown parameter \"%s\"\n", parmname);
|
||||
return(True);
|
||||
}
|
||||
|
||||
@@ -682,7 +686,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
parm_ptr = def_ptr;
|
||||
} else {
|
||||
if (parm_table[parmnum].class == P_GLOBAL) {
|
||||
rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
|
||||
rprintf(FLOG, "Global parameter %s found in service section!\n",parmname);
|
||||
return(True);
|
||||
}
|
||||
parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
|
||||
@@ -780,6 +784,11 @@ static BOOL do_section(char *sectionname)
|
||||
return(True);
|
||||
}
|
||||
|
||||
if (strchr(sectionname, '/') != NULL) {
|
||||
rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* if we have a current service, tidy it up before moving on */
|
||||
bRetval = True;
|
||||
|
||||
@@ -794,7 +803,7 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
|
||||
{
|
||||
rprintf(FERROR,"Failed to add a new service\n");
|
||||
rprintf(FLOG, "Failed to add a new service\n");
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
|
||||
39
log.c
39
log.c
@@ -61,7 +61,7 @@ static int logfile_was_closed;
|
||||
static FILE *logfile_fp;
|
||||
struct stats stats;
|
||||
|
||||
int log_got_error = 0;
|
||||
int got_xfer_error = 0;
|
||||
|
||||
struct {
|
||||
int code;
|
||||
@@ -86,6 +86,7 @@ struct {
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_VANISHED , "some files vanished before they could be transferred" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
|
||||
{ RERR_CMD_FAILED , "remote shell failed" },
|
||||
{ RERR_CMD_KILLED , "remote shell killed" },
|
||||
{ RERR_CMD_RUN , "remote command could not be run" },
|
||||
@@ -235,8 +236,8 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
|
||||
* certain fatal conditions. */
|
||||
* it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT. Note: recursion
|
||||
* can happen with certain fatal conditions. */
|
||||
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
{
|
||||
int trailing_CR_or_NL;
|
||||
@@ -259,7 +260,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
|
||||
if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */
|
||||
code = FERROR;
|
||||
|
||||
if (code == FCLIENT)
|
||||
@@ -267,7 +268,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
else if (am_daemon || logfile_name) {
|
||||
static int in_block;
|
||||
char msg[2048];
|
||||
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
|
||||
int priority = code == FINFO || code == FLOG ? LOG_INFO : LOG_WARNING;
|
||||
|
||||
if (in_block)
|
||||
return;
|
||||
@@ -283,12 +284,19 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
} else if (code == FLOG)
|
||||
return;
|
||||
|
||||
if (quiet && code != FERROR)
|
||||
if (quiet && code == FINFO)
|
||||
return;
|
||||
|
||||
if (am_server) {
|
||||
enum msgcode msg = (enum msgcode)code;
|
||||
if (protocol_version < 30) {
|
||||
if (msg == MSG_ERROR)
|
||||
msg = MSG_ERROR_XFER;
|
||||
else if (msg == MSG_WARNING)
|
||||
msg = MSG_INFO;
|
||||
}
|
||||
/* Pass the message to the non-server side. */
|
||||
if (send_msg((enum msgcode)code, buf, len, !is_utf8))
|
||||
if (send_msg(msg, buf, len, !is_utf8))
|
||||
return;
|
||||
if (am_daemon) {
|
||||
/* TODO: can we send the error to the user somehow? */
|
||||
@@ -297,8 +305,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case FERROR_XFER:
|
||||
got_xfer_error = 1;
|
||||
/* FALL THROUGH */
|
||||
case FERROR:
|
||||
log_got_error = 1;
|
||||
case FWARNING:
|
||||
f = stderr;
|
||||
break;
|
||||
case FINFO:
|
||||
@@ -342,8 +353,8 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR or
|
||||
* FLOG. */
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR_*,
|
||||
* FWARNING, FLOG, or FCLIENT. */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -421,10 +432,10 @@ void rflush(enum logcode code)
|
||||
if (am_daemon || code == FLOG)
|
||||
return;
|
||||
|
||||
if (code == FERROR || am_server)
|
||||
f = stderr;
|
||||
else
|
||||
if (code == FINFO && !am_server)
|
||||
f = stdout;
|
||||
else
|
||||
f = stderr;
|
||||
|
||||
fflush(f);
|
||||
}
|
||||
@@ -801,7 +812,7 @@ void log_exit(int code, const char *file, int line)
|
||||
|
||||
/* VANISHED is not an error, only a warning */
|
||||
if (code == RERR_VANISHED) {
|
||||
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
name, code, file, line, who_am_i(), RSYNC_VERSION);
|
||||
} else {
|
||||
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
|
||||
117
main.c
117
main.c
@@ -41,10 +41,11 @@ extern int remove_source_files;
|
||||
extern int need_messages_from_generator;
|
||||
extern int kluge_around_eof;
|
||||
extern int do_stats;
|
||||
extern int log_got_error;
|
||||
extern int got_xfer_error;
|
||||
extern int module_id;
|
||||
extern int copy_links;
|
||||
extern int copy_dirlinks;
|
||||
extern int copy_unsafe_links;
|
||||
extern int keep_dirlinks;
|
||||
extern int preserve_hard_links;
|
||||
extern int protocol_version;
|
||||
@@ -63,10 +64,13 @@ extern int read_batch;
|
||||
extern int write_batch;
|
||||
extern int batch_fd;
|
||||
extern int filesfrom_fd;
|
||||
extern int connect_timeout;
|
||||
extern pid_t cleanup_child_pid;
|
||||
extern unsigned int module_dirlen;
|
||||
extern struct stats stats;
|
||||
extern char *filesfrom_host;
|
||||
extern char *partial_dir;
|
||||
extern char *dest_option;
|
||||
extern char *basis_dir[];
|
||||
extern char *rsync_path;
|
||||
extern char *shell_cmd;
|
||||
@@ -79,6 +83,7 @@ extern struct filter_list_struct server_filter_list;
|
||||
extern iconv_t ic_send;
|
||||
#endif
|
||||
|
||||
uid_t our_uid;
|
||||
int local_server = 0;
|
||||
int daemon_over_rsh = 0;
|
||||
mode_t orig_umask = 0;
|
||||
@@ -275,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);
|
||||
@@ -330,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) {
|
||||
@@ -506,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:
|
||||
@@ -637,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,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)
|
||||
@@ -862,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) {
|
||||
@@ -883,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)) {
|
||||
@@ -924,26 +929,27 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
|
||||
/* Now that we know what our destination directory turned out to be,
|
||||
* we can sanitize the --link-/copy-/compare-dest args correctly. */
|
||||
if (sanitize_paths) {
|
||||
char **dir;
|
||||
for (dir = basis_dir; *dir; dir++) {
|
||||
*dir = sanitize_path(NULL, *dir, NULL, curr_dir_depth, NULL);
|
||||
}
|
||||
if (partial_dir) {
|
||||
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, NULL);
|
||||
}
|
||||
char **dir_p;
|
||||
for (dir_p = basis_dir; *dir_p; dir_p++)
|
||||
*dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth);
|
||||
if (partial_dir)
|
||||
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth);
|
||||
}
|
||||
fix_basis_dirs();
|
||||
check_alt_basis_dirs();
|
||||
|
||||
if (server_filter_list.head) {
|
||||
char **dir;
|
||||
char **dir_p;
|
||||
struct filter_list_struct *elp = &server_filter_list;
|
||||
|
||||
for (dir = basis_dir; *dir; dir++) {
|
||||
if (check_filter(elp, *dir, 1) < 0)
|
||||
for (dir_p = basis_dir; *dir_p; dir_p++) {
|
||||
char *dir = *dir_p;
|
||||
if (*dir == '/')
|
||||
dir += module_dirlen;
|
||||
if (check_filter(elp, dir, 1) < 0)
|
||||
goto options_rejected;
|
||||
}
|
||||
if (partial_dir && *partial_dir == '/'
|
||||
&& check_filter(elp, partial_dir, 1) < 0) {
|
||||
&& check_filter(elp, partial_dir + module_dirlen, 1) < 0) {
|
||||
options_rejected:
|
||||
rprintf(FERROR,
|
||||
"Your options have been rejected by the server.\n");
|
||||
@@ -1082,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 {
|
||||
@@ -1264,6 +1270,12 @@ static int start_client(int argc, char *argv[])
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (connect_timeout) {
|
||||
rprintf(FERROR, "The --contimeout option may only be "
|
||||
"used when connecting to an rsync daemon.\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (shell_machine) {
|
||||
p = strrchr(shell_machine,'@');
|
||||
if (p) {
|
||||
@@ -1310,7 +1322,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
|
||||
if (!am_server)
|
||||
output_summary();
|
||||
close_all();
|
||||
if (log_got_error)
|
||||
if (got_xfer_error)
|
||||
_exit(RERR_PARTIAL);
|
||||
_exit(0);
|
||||
}
|
||||
@@ -1417,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));
|
||||
|
||||
|
||||
83
match.c
83
match.c
@@ -39,40 +39,51 @@ static int total_matches;
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define TRADITIONAL_TABLESIZE (1<<16)
|
||||
|
||||
static uint32 tablesize;
|
||||
static int32 *hash_table;
|
||||
|
||||
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
|
||||
|
||||
static int32 build_hash_table(struct sum_struct *s, int32 start)
|
||||
{
|
||||
int32 i, end = s->count;
|
||||
#define BIG_SUM2HASH(sum) ((sum)%tablesize)
|
||||
|
||||
if (!hash_table) {
|
||||
hash_table = new_array(int32, TABLESIZE);
|
||||
static void build_hash_table(struct sum_struct *s)
|
||||
{
|
||||
static uint32 alloc_size;
|
||||
int32 i;
|
||||
|
||||
/* Dynamically calculate the hash table size so that the hash load
|
||||
* for big files is about 80%. A number greater than the traditional
|
||||
* size must be odd or s2 will not be able to span the entire set. */
|
||||
tablesize = (uint32)(s->count/8) * 10 + 11;
|
||||
if (tablesize < TRADITIONAL_TABLESIZE)
|
||||
tablesize = TRADITIONAL_TABLESIZE;
|
||||
if (tablesize > alloc_size || tablesize < alloc_size - 16*1024) {
|
||||
if (hash_table)
|
||||
free(hash_table);
|
||||
hash_table = new_array(int32, tablesize);
|
||||
if (!hash_table)
|
||||
out_of_memory("build_hash_table");
|
||||
alloc_size = tablesize;
|
||||
}
|
||||
|
||||
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
|
||||
memset(hash_table, 0xFF, tablesize * sizeof hash_table[0]);
|
||||
|
||||
if (end - start > TABLESIZE*8/10)
|
||||
end = start + TABLESIZE*8/10;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
uint32 t = SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
if (tablesize == TRADITIONAL_TABLESIZE) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
uint32 t = SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
uint32 t = BIG_SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "built hash table for entries %ld - %ld\n",
|
||||
(long)start, (long)end - 1);
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,8 +141,8 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
|
||||
static void hash_search(int f,struct sum_struct *s,
|
||||
struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
OFF_T offset, end, reset = 0;
|
||||
int32 k, want_i, backup, sum_pos = 0;
|
||||
OFF_T offset, end;
|
||||
int32 k, want_i, backup;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
int more;
|
||||
@@ -169,24 +180,21 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
int done_csum2 = 0;
|
||||
int32 i;
|
||||
|
||||
if (offset >= reset) {
|
||||
sum_pos = build_hash_table(s, sum_pos);
|
||||
if (sum_pos == s->count)
|
||||
reset = len;
|
||||
else
|
||||
reset = sum_pos * s->blength;
|
||||
}
|
||||
|
||||
if (verbose > 4) {
|
||||
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
|
||||
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
|
||||
}
|
||||
|
||||
i = hash_table[SUM2HASH2(s1,s2)];
|
||||
if (i < 0)
|
||||
goto null_hash;
|
||||
if (tablesize == TRADITIONAL_TABLESIZE) {
|
||||
if ((i = hash_table[SUM2HASH2(s1,s2)]) < 0)
|
||||
goto null_hash;
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
} else {
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
if ((i = hash_table[BIG_SUM2HASH(sum)]) < 0)
|
||||
goto null_hash;
|
||||
}
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
hash_hits++;
|
||||
do {
|
||||
int32 l;
|
||||
@@ -354,6 +362,11 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
}
|
||||
|
||||
if (len > 0 && s->count > 0) {
|
||||
build_hash_table(s);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"built hash table\n");
|
||||
|
||||
hash_search(f, s, buf, len);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
74
mkproto.awk
74
mkproto.awk
@@ -1,74 +0,0 @@
|
||||
# generate prototypes for Samba C code
|
||||
# tridge, June 1996
|
||||
|
||||
BEGIN {
|
||||
inheader=0;
|
||||
print "/* This file is automatically generated with \"make proto\". DO NOT EDIT */"
|
||||
print ""
|
||||
}
|
||||
|
||||
{
|
||||
if (inheader) {
|
||||
if (match($0,"[)][ \t]*$")) {
|
||||
inheader = 0;
|
||||
printf "%s;\n",$0;
|
||||
} else {
|
||||
printf "%s\n",$0;
|
||||
}
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
/^FN_LOCAL_BOOL/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "BOOL %s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_LOCAL_STRING/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "char *%s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_LOCAL_INT/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "int %s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_LOCAL_CHAR/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "char %s(int );\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_GLOBAL_BOOL/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "BOOL %s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_GLOBAL_STRING/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "char *%s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^FN_GLOBAL_INT/ {
|
||||
split($0,a,"[,()]")
|
||||
printf "int %s(void);\n", a[2]
|
||||
}
|
||||
|
||||
/^static|^extern/ || /[;]/ {
|
||||
next;
|
||||
}
|
||||
|
||||
!/^[A-Za-z][A-Za-z0-9_]* / {
|
||||
next;
|
||||
}
|
||||
|
||||
/[(].*[)][ \t]*$/ {
|
||||
printf "%s;\n",$0;
|
||||
next;
|
||||
}
|
||||
|
||||
/[(]/ {
|
||||
inheader=1;
|
||||
printf "%s\n",$0;
|
||||
next;
|
||||
}
|
||||
48
mkproto.pl
Normal file
48
mkproto.pl
Normal file
@@ -0,0 +1,48 @@
|
||||
# generate prototypes for rsync
|
||||
|
||||
$old_protos = '';
|
||||
if (open(IN, 'proto.h')) {
|
||||
$old_protos = join('', <IN>);
|
||||
close IN;
|
||||
}
|
||||
|
||||
%FN_MAP = (
|
||||
BOOL => 'BOOL ',
|
||||
CHAR => 'char ',
|
||||
INTEGER => 'int ',
|
||||
STRING => 'char *',
|
||||
);
|
||||
|
||||
$inheader = 0;
|
||||
$protos = qq|/* This file is automatically generated with "make proto". DO NOT EDIT */\n\n|;
|
||||
|
||||
while (<>) {
|
||||
if ($inheader) {
|
||||
if (/[)][ \t]*$/) {
|
||||
$inheader = 0;
|
||||
s/$/;/;
|
||||
}
|
||||
$protos .= $_;
|
||||
} elsif (/^FN_(LOCAL|GLOBAL)_([^(]+)\(([^,()]+)/) {
|
||||
$ret = $FN_MAP{$2};
|
||||
$func = $3;
|
||||
$arg = $1 eq 'LOCAL' ? 'int module_id' : 'void';
|
||||
$protos .= "$ret$func($arg);\n";
|
||||
} elsif (/^static|^extern/ || /[;]/ || !/^[A-Za-z][A-Za-z0-9_]* /) {
|
||||
;
|
||||
} elsif (/[(].*[)][ \t]*$/) {
|
||||
s/$/;/;
|
||||
$protos .= $_;
|
||||
} elsif (/[(]/) {
|
||||
$inheader = 1;
|
||||
$protos .= $_;
|
||||
}
|
||||
}
|
||||
|
||||
if ($old_protos ne $protos) {
|
||||
open(OUT, '>proto.h') or die $!;
|
||||
print OUT $protos;
|
||||
close OUT;
|
||||
}
|
||||
|
||||
open(OUT, '>proto.h-tstamp') and close OUT;
|
||||
66
mkrounding.c
66
mkrounding.c
@@ -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;
|
||||
}
|
||||
46
options.c
46
options.c
@@ -27,6 +27,7 @@
|
||||
extern int module_id;
|
||||
extern int sanitize_paths;
|
||||
extern int daemon_over_rsh;
|
||||
extern unsigned int module_dirlen;
|
||||
extern struct filter_list_struct filter_list;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
|
||||
@@ -99,6 +100,7 @@ int xfer_dirs = -1;
|
||||
int am_daemon = 0;
|
||||
int do_stats = 0;
|
||||
int do_progress = 0;
|
||||
int connect_timeout = 0;
|
||||
int keep_partial = 0;
|
||||
int safe_symlinks = 0;
|
||||
int copy_unsafe_links = 0;
|
||||
@@ -352,7 +354,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");
|
||||
@@ -377,7 +379,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --delay-updates put all updated files into place at transfer's end\n");
|
||||
rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n");
|
||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
|
||||
rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n");
|
||||
rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n");
|
||||
rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n");
|
||||
rprintf(F," --size-only skip files that match in size\n");
|
||||
rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n");
|
||||
@@ -603,6 +606,7 @@ static struct poptOption long_options[] = {
|
||||
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
|
||||
{"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 },
|
||||
{"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 },
|
||||
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
|
||||
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
|
||||
@@ -1001,16 +1005,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
case OPT_INCLUDE_FROM:
|
||||
arg = poptGetOptArg(pc);
|
||||
if (sanitize_paths)
|
||||
arg = sanitize_path(NULL, arg, NULL, 0, NULL);
|
||||
arg = sanitize_path(NULL, arg, NULL, 0);
|
||||
if (server_filter_list.head) {
|
||||
int rej;
|
||||
char *cp = strdup(arg);
|
||||
char *dir, *cp = strdup(arg);
|
||||
if (!cp)
|
||||
out_of_memory("parse_arguments");
|
||||
if (!*cp)
|
||||
goto options_rejected;
|
||||
clean_fname(cp, 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;
|
||||
@@ -1301,7 +1306,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
batch_name = NULL;
|
||||
} else if (dry_run)
|
||||
write_batch = 0;
|
||||
}
|
||||
} else if (write_batch < 0 && dry_run)
|
||||
write_batch = 0;
|
||||
if (read_batch && files_from) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--read-batch cannot be used with --files-from\n");
|
||||
@@ -1394,26 +1400,30 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
if (sanitize_paths) {
|
||||
int i;
|
||||
for (i = argc; i-- > 0; )
|
||||
argv[i] = sanitize_path(NULL, argv[i], "", 0, NULL);
|
||||
argv[i] = sanitize_path(NULL, argv[i], "", 0);
|
||||
if (tmpdir)
|
||||
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
|
||||
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
|
||||
if (backup_dir)
|
||||
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
|
||||
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
|
||||
}
|
||||
if (server_filter_list.head && !am_sender) {
|
||||
struct filter_list_struct *elp = &server_filter_list;
|
||||
if (tmpdir) {
|
||||
char *dir;
|
||||
if (!*tmpdir)
|
||||
goto options_rejected;
|
||||
clean_fname(tmpdir, 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;
|
||||
}
|
||||
}
|
||||
@@ -1602,12 +1612,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
}
|
||||
} else {
|
||||
if (sanitize_paths)
|
||||
files_from = sanitize_path(NULL, files_from, NULL, 0, NULL);
|
||||
files_from = sanitize_path(NULL, files_from, NULL, 0);
|
||||
if (server_filter_list.head) {
|
||||
char *dir;
|
||||
if (!*files_from)
|
||||
goto options_rejected;
|
||||
clean_fname(files_from, 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);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.0.0pre5
|
||||
Version: 3.0.0pre9
|
||||
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
|
||||
* Thu Nov 08 2007 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.0pre5.
|
||||
* Sun Feb 10 2008 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.0pre9.
|
||||
|
||||
@@ -14,16 +14,13 @@ use strict;
|
||||
use Getopt::Long;
|
||||
use Date::Format;
|
||||
|
||||
# Choose any dir where a pristine rsync has been checked out of CVS.
|
||||
our $unpacked = $ENV{HOME} . '/release/nightly';
|
||||
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
|
||||
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
|
||||
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
|
||||
our $dest = $ENV{HOME} . '/samba-rsync-ftp/nightly';
|
||||
our $nightly_symlink = "$dest/rsync-HEAD.tar.gz";
|
||||
|
||||
our($cvs_update, $make_tar, $upload, $help_opt);
|
||||
our($make_tar, $upload, $help_opt);
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'cvs-update|c' => \$cvs_update,
|
||||
'make-tar|t' => \$make_tar,
|
||||
'upload|u' => \$upload,
|
||||
'help|h' => \$help_opt,
|
||||
@@ -32,70 +29,65 @@ our($cvs_update, $make_tar, $upload, $help_opt);
|
||||
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
|
||||
our $ztoday = time2str('%d %b %Y', time);
|
||||
our $today = $ztoday;
|
||||
our $gen_target = $upload ? 'gensend' : 'gen';
|
||||
|
||||
chdir($unpacked) or die $!;
|
||||
|
||||
if ($cvs_update) {
|
||||
print "Updating from cvs...\n";
|
||||
system 'cvs -q up' and die $!;
|
||||
}
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
die "There is no .git dir in the current directory.\n" unless -d '.git';
|
||||
die "There is no rsync checkout in the current directory.\n" unless -f 'rsyncd.conf.yo';
|
||||
|
||||
if ($make_tar) {
|
||||
print "Generating list of active CVS files...\n";
|
||||
my($dir, @files);
|
||||
open(CVS, '-|', 'cvs status 2>&1') or die $!;
|
||||
while (<CVS>) {
|
||||
if (/^cvs status: Examining (.*)/) {
|
||||
if ($1 eq '.') {
|
||||
$dir = '';
|
||||
} else {
|
||||
push(@files, $1);
|
||||
$dir = $1 . '/';
|
||||
}
|
||||
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
|
||||
push(@files, $dir . $1);
|
||||
if ($2 ne 'Up-to-date') {
|
||||
print "*** Not up-to-date: $dir$1\n";
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
|
||||
system "make $gen_target" and die "make $gen_target failed!\n";
|
||||
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
while (<IN>) {
|
||||
if (s/^GENFILES=//) {
|
||||
while (s/\\$//) {
|
||||
$_ .= <IN>;
|
||||
}
|
||||
@extra_files = split(' ', $_);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close CVS;
|
||||
close IN;
|
||||
|
||||
print "Creating $name.tar.gz\n";
|
||||
system "rsync -a @extra_files $name/";
|
||||
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
|
||||
system "support/git-set-file-times --prefix=$name/";
|
||||
system "fakeroot tar czf $dest/$name.tar.gz $name; rm -rf $name";
|
||||
|
||||
print "Creating $unpacked/$name.tar.gz\n";
|
||||
chdir('..') or die $!;
|
||||
rename($unpacked, $name) or die $!;
|
||||
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $nightly/$name.tar.gz $name") or die $!;
|
||||
foreach (@files) {
|
||||
print TAR "$name/$_\n";
|
||||
}
|
||||
close TAR;
|
||||
rename($name, $unpacked) or die $!;
|
||||
unlink($nightly_symlink);
|
||||
symlink("$name.tar.gz", $nightly_symlink);
|
||||
}
|
||||
|
||||
chdir($nightly) or die $!;
|
||||
|
||||
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
|
||||
my $html_fn = $fn;
|
||||
$html_fn =~ s/\.yo/.html/;
|
||||
my $yo_tmp = "$dest/$fn";
|
||||
(my $html_fn = "$dest/$fn") =~ s/\.yo/.html/;
|
||||
|
||||
open(IN, '<', "$unpacked/$fn") or die $!;
|
||||
open(IN, '<', $fn) or die $!;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
|
||||
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
|
||||
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
|
||||
|
||||
open(OUT, '>', $fn) or die $!;
|
||||
open(OUT, '>', $yo_tmp) or die $!;
|
||||
print OUT $_;
|
||||
close OUT;
|
||||
|
||||
system "yodl2html -o $html_fn $fn";
|
||||
system 'yodl2html', '-o', $html_fn, $yo_tmp;
|
||||
|
||||
unlink($fn);
|
||||
unlink($yo_tmp);
|
||||
}
|
||||
|
||||
chdir($dest) or die $!;
|
||||
|
||||
my $cnt = 0;
|
||||
open(PIPE, '-|', 'ls -1t rsync-HEAD-*') or die $!;
|
||||
while (<PIPE>) {
|
||||
@@ -122,8 +114,7 @@ sub usage
|
||||
die <<EOT;
|
||||
Usage: nightly-rsync [OPTIONS]
|
||||
|
||||
-c, --cvs-update update $unpacked via CVS.
|
||||
-t, --make-tar create a new tar file in $nightly
|
||||
-t, --make-tar create a new tar file in $dest
|
||||
-u, --upload upload the revised nightly dir to samba.org
|
||||
-h, --help display this help
|
||||
EOT
|
||||
|
||||
@@ -1,91 +1,74 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to
|
||||
# be a copy of the /home/ftp/pub/rsync dir on samba.org. If it is run
|
||||
# in test mode, it instead expects a dir named ~/tmp/samba-rsync-ftp
|
||||
# (e.g. copy ~/samba-rsync-ftp into ~/tmp and you can do a trial-run of
|
||||
# a release without affecting the files in the ~/samba-rsync-ftp dir).
|
||||
#
|
||||
# Run this as "release-rsync live" to affect ~/samba-rsync-ftp instead
|
||||
# of ~/tmp/samba-rsync-ftp.
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
|
||||
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
|
||||
# the git repository in the current directory will be updated, and the local
|
||||
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
|
||||
|
||||
use Cwd;
|
||||
use Date::Format;
|
||||
|
||||
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
|
||||
my $releasedir = $ENV{HOME} . '/release';
|
||||
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
|
||||
|
||||
my $cl_today = time2str('* %a %b %d %Y', time);
|
||||
my $ztoday = time2str('%d %b %Y', time);
|
||||
(my $today = $ztoday) =~ s/^0//;
|
||||
|
||||
my $break = <<EOT;
|
||||
==========================================================================
|
||||
EOT
|
||||
my $note = <<EOT;
|
||||
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
|
||||
EOT
|
||||
my $curdir = Cwd::cwd;
|
||||
|
||||
my $live = shift;
|
||||
my $skipping = '';
|
||||
|
||||
print $break;
|
||||
if ($live) {
|
||||
print <<EOT;
|
||||
== This will release a new version of rsync onto an unsuspecting world. ==
|
||||
EOT
|
||||
} else {
|
||||
print <<EOT;
|
||||
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
|
||||
EOT
|
||||
$dest =~ s#([^/]+$)#tmp/$1#;
|
||||
$skipping = ' ** SKIPPING **';
|
||||
}
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
|
||||
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
|
||||
|
||||
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
|
||||
chdir($releasedir) or die $!;
|
||||
|
||||
system 'rm -rf rsync';
|
||||
|
||||
my(%dirs, @files);
|
||||
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
|
||||
while (<CVS>) {
|
||||
print $_;
|
||||
next if /\.(cvs)?ignore$/;
|
||||
if (m#^[UP] rsync/(.*)#) {
|
||||
my $fn = $1;
|
||||
my($dir) = $fn =~ m#^(.+)/#;
|
||||
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
|
||||
push(@files, $fn);
|
||||
}
|
||||
}
|
||||
|
||||
chdir('rsync') or die $!;
|
||||
|
||||
my($version, $lastversion);
|
||||
open(IN, '<', 'configure.in') or die $!;
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$version = $lastversion = $1;
|
||||
if (s/^GENFILES=//) {
|
||||
while (s/\\$//) {
|
||||
$_ .= <IN>;
|
||||
}
|
||||
@extra_files = split(' ', $_);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
if ($lastversion =~ /cvs$/) {
|
||||
my $break = <<EOT;
|
||||
==========================================================================
|
||||
EOT
|
||||
|
||||
print $break, <<EOT, $break, "\n";
|
||||
== This will release a new version of rsync onto an unsuspecting world. ==
|
||||
EOT
|
||||
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
die "There is no .git dir in the current directory.\n" unless -d '.git';
|
||||
die "'a' must not exist in the current directory.\n" if -e 'a';
|
||||
die "'b' must not exist in the current directory.\n" if -e 'b';
|
||||
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
|
||||
|
||||
my $lastversion;
|
||||
open(IN, '<', 'configure.in') or die $!;
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$lastversion = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
if ($lastversion =~ /dev$/) {
|
||||
open(IN, '<', 'OLDNEWS') or die $!;
|
||||
$_ = <IN>;
|
||||
close IN;
|
||||
($lastversion) = /(\d+\.\d+\.\d+)/;
|
||||
}
|
||||
|
||||
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
|
||||
my $version = $lastversion;
|
||||
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
|
||||
|
||||
print $break, "\nPlease enter the version number of this release: [$version] ";
|
||||
print "Please enter the version number of this release: [$version] ";
|
||||
chomp($_ = <STDIN>);
|
||||
if ($_ eq '.') {
|
||||
$version =~ s/pre\d+//;
|
||||
@@ -94,12 +77,6 @@ if ($_ eq '.') {
|
||||
}
|
||||
$version =~ s/[-.]*pre[-.]*/pre/;
|
||||
|
||||
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
|
||||
|
||||
my $cvstag = "release-$version";
|
||||
$cvstag =~ s/[.]/-/g;
|
||||
$cvstag =~ s/pre/-pre/;
|
||||
|
||||
print "Enter the previous version to produce a patch against: [$lastversion] ";
|
||||
chomp($_ = <STDIN>);
|
||||
$lastversion = $_ if $_ ne '';
|
||||
@@ -111,49 +88,44 @@ chomp($_ = <STDIN>);
|
||||
$release = $_ if $_ ne '';
|
||||
|
||||
my $diffdir;
|
||||
my $skipping2;
|
||||
my $skipping;
|
||||
if ($lastversion =~ /pre/) {
|
||||
if ($version !~ /pre/) {
|
||||
die "You should not diff a release version against a pre-release version.\n";
|
||||
}
|
||||
$diffdir = "$dest/old-previews";
|
||||
$skipping2 = ' ** SKIPPING **';
|
||||
$skipping = ' ** SKIPPING **';
|
||||
} elsif ($version =~ /pre/) {
|
||||
$diffdir = $dest;
|
||||
$skipping2 = ' ** SKIPPING **';
|
||||
$skipping = ' ** SKIPPING **';
|
||||
} else {
|
||||
$diffdir = "$dest/old-versions";
|
||||
$skipping2 = '';
|
||||
$skipping = '';
|
||||
}
|
||||
|
||||
print "\n", $break, <<EOT;
|
||||
\$version is "$version"
|
||||
\$lastversion is "$lastversion"
|
||||
\$cvstag is "$cvstag"
|
||||
\$dest is "$dest"
|
||||
\$releasedir is "$releasedir"
|
||||
\$curdir is "$curdir"
|
||||
\$diffdir is "$diffdir"
|
||||
\$release is "$release"
|
||||
|
||||
About to:
|
||||
- make sure that SUBPROTOCOL_VERSION is 0$skipping2
|
||||
- tweak the version in configure.in, configure, and the spec files
|
||||
- make sure that configure, config.h.in, and proto.h are updated
|
||||
- tweak NEWS and OLDNEWS to update the release date$skipping2
|
||||
- tweak the date in the *.yo files and re-generate the man pages
|
||||
- make sure that the patches dir has been updated
|
||||
- page through the "cvs diff" output
|
||||
- make sure that SUBPROTOCOL_VERSION is 0$skipping
|
||||
- tweak the version in configure.in and the spec files
|
||||
- tweak NEWS and OLDNEWS to update the release date$skipping
|
||||
- tweak the date in the *.yo files and generate the man pages
|
||||
- generate configure.sh, config.h.in, and proto.h
|
||||
- page through the differences
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
my $f_opt = /f/ ? ' -f' : '';
|
||||
|
||||
print $break;
|
||||
system "./prepare-source && touch proto.h";
|
||||
|
||||
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
|
||||
glob('*.yo'), qw( configure.in configure ) );
|
||||
glob('*.yo'), qw( configure.in ) );
|
||||
|
||||
if ($version !~ /pre/) {
|
||||
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
|
||||
}
|
||||
@@ -187,64 +159,44 @@ foreach my $fn (@tweak_files) {
|
||||
close OUT;
|
||||
}
|
||||
|
||||
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage rsync.1";
|
||||
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage rsyncd.conf.5";
|
||||
|
||||
mkdir('patches/tmp') or die $!;
|
||||
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
|
||||
|
||||
print "\n", $break, $note, $break;
|
||||
system "patches/verify-patches -n -an$f_opt";
|
||||
|
||||
print $break;
|
||||
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
|
||||
system "git diff --color | less -p '^diff .*'";
|
||||
|
||||
my $srctar_name = "rsync-$version.tar.gz";
|
||||
my $pattar_name = "rsync-patches-$version.tar.gz";
|
||||
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
|
||||
my $srctar_file = "$dest/$srctar_name";
|
||||
my $pattar_file = "$dest/$pattar_name";
|
||||
my $diff_file = "$dest/$diff_name";
|
||||
my $lasttar_file = "$dest/rsync-$lastversion.tar.gz";
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to:
|
||||
- "cvs commit" all changes$skipping
|
||||
- "cvs tag" this release as $cvstag$skipping
|
||||
- change the diffs in the patches dir to include generated files
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
if ($live) {
|
||||
system "cvs commit -m 'Preparing for release of $version'";
|
||||
system "cvs tag -F $cvstag .";
|
||||
}
|
||||
|
||||
if (!/skip/i) {
|
||||
print "\n", $break, $note, $break;
|
||||
system "patches/verify-patches -pun -an";
|
||||
}
|
||||
|
||||
my $tar_name = "rsync-$version.tar.gz";
|
||||
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
|
||||
my $tar_file = "$dest/$tar_name";
|
||||
my $diff_file = "$dest/$diff_name";
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to do the following in the samba-rsync-ftp dir:
|
||||
- commit all changes
|
||||
- tag this release as v$version
|
||||
- move the old tar/diff files into the appropriate old-* dirs
|
||||
- hard-link the moved tar/diff files on samba.org$skipping
|
||||
- create release tar, "$tar_name"
|
||||
- hard-link the moved tar/diff files on samba.org
|
||||
- create release tar, "$srctar_name"
|
||||
- create patches tar, "$pattar_name"
|
||||
- create release diffs, "$diff_name"
|
||||
- update README, *NEWS, TODO, and cvs.log
|
||||
- update patch branches and generate patch/* files
|
||||
- update README, *NEWS, TODO, and changelog
|
||||
- update rsync*.html man pages
|
||||
- gpg-sign the release files$skipping
|
||||
- gpg-sign the release files
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
chdir($releasedir) or die $!;
|
||||
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
|
||||
system "git tag -s -m 'Version $version.' v$version" and exit 1;
|
||||
|
||||
print $break;
|
||||
system "rm -rf rsync-$version";
|
||||
rename('rsync', "rsync-$version") or die $!;
|
||||
# Extract some files from the old tar before we do the shuffle.
|
||||
@_ = @extra_files;
|
||||
map { s#^#rsync-$lastversion/# } @_;
|
||||
system "tar xzf $lasttar_file @_";
|
||||
rename("rsync-$lastversion", 'a');
|
||||
|
||||
# When creating a pre-release after a normal release, there's nothing to move.
|
||||
if ($diffdir ne $dest) {
|
||||
@@ -278,53 +230,44 @@ if ($diffdir ne $dest) {
|
||||
|
||||
# Optimize our future upload (in the absence of --detect-renamed) by
|
||||
# using rsync to hard-link the above files on samba.org.
|
||||
if ($live) {
|
||||
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
|
||||
}
|
||||
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
|
||||
foreach (@moved_files) {
|
||||
unlink($_);
|
||||
}
|
||||
|
||||
chdir($releasedir) or die $!;
|
||||
chdir($curdir) or die $!;
|
||||
}
|
||||
|
||||
print "Creating $tar_file ...\n";
|
||||
system "fakeroot tar czf $tar_file rsync-$version";
|
||||
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
|
||||
foreach (@files) {
|
||||
print TAR "rsync-$version/$_\n";
|
||||
}
|
||||
close TAR;
|
||||
|
||||
print "Creating $diff_file ...\n";
|
||||
system "rm -rf rsync-$version rsync-$lastversion";
|
||||
system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
|
||||
## TWEAK THE VERSIONS AS DESIRED HERE ##
|
||||
#mkdir("rsync-$lastversion/support", 0755) or die $!;
|
||||
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
|
||||
#unlink("rsync-$lastversion/.ignore");
|
||||
## END ##
|
||||
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
|
||||
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
|
||||
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
|
||||
system "(git diff v$lastversion v$version; diff -up a b | sed -r '$sed_script') | gzip -9 >$diff_file";
|
||||
system "rm -rf a";
|
||||
rename('b', "rsync-$version");
|
||||
|
||||
print "Creating $srctar_file ...\n";
|
||||
system "git archive --format=tar --prefix=rsync-$version/ v$version | tar xf -";
|
||||
system "support/git-set-file-times --prefix=rsync-$version/";
|
||||
system "fakeroot tar czf $srctar_file rsync-$version; rm -rf rsync-$version";
|
||||
|
||||
mkdir("rsync-$version", 0755);
|
||||
mkdir("rsync-$version/patches", 0755);
|
||||
system "support/patch-update --skip-check --gen=rsync-$version/patches";
|
||||
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
|
||||
|
||||
print "Updating the other files in $dest ...\n";
|
||||
system "rsync -a rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
|
||||
system "rsync -a README NEWS OLDNEWS TODO $dest";
|
||||
unlink("$dest/rsync-$version-NEWS");
|
||||
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
|
||||
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
|
||||
system "git log --name-status | gzip -9 >$dest/changelog.gz";
|
||||
|
||||
system "yodl2html -o $dest/rsync.html rsync-$version/rsync.yo";
|
||||
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
|
||||
system "yodl2html -o $dest/rsync.html rsync.yo";
|
||||
system "yodl2html -o $dest/rsyncd.conf.html rsyncd.conf.yo";
|
||||
|
||||
system "rm -rf rsync-*";
|
||||
|
||||
if ($live) {
|
||||
chdir($dest) or die $!;
|
||||
system "gpg -ba $tar_name; gpg -ba $diff_name";
|
||||
print $break, <<EOT;
|
||||
chdir($dest) or die $!;
|
||||
system "gpg -ba $srctar_name; gpg -ba $pattar_name; gpg -ba $diff_name";
|
||||
print $break, <<EOT;
|
||||
|
||||
All done. Remember to announce the release on *BOTH*
|
||||
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
|
||||
EOT
|
||||
} else {
|
||||
print $break, "All done.\n";
|
||||
}
|
||||
|
||||
26
params.c
26
params.c
@@ -211,7 +211,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func);
|
||||
rprintf(FLOG, "%s Memory re-allocation failure.", func);
|
||||
return( False );
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
bufr[end] = '\0';
|
||||
if( 0 == end ) /* Don't allow an empty name. */
|
||||
{
|
||||
rprintf(FERROR, "%s Empty section name in configuration file.\n", func );
|
||||
rprintf(FLOG, "%s Empty section name in configuration file.\n", func );
|
||||
return( False );
|
||||
}
|
||||
if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */
|
||||
@@ -236,7 +236,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
if( i < 0 )
|
||||
{
|
||||
bufr[end] = '\0';
|
||||
rprintf(FERROR, "%s Badly formed line in configuration file: %s\n",
|
||||
rprintf(FLOG, "%s Badly formed line in configuration file: %s\n",
|
||||
func, bufr );
|
||||
return( False );
|
||||
}
|
||||
@@ -261,7 +261,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
}
|
||||
|
||||
/* We arrive here if we've met the EOF before the closing bracket. */
|
||||
rprintf(FERROR, "%s Unexpected EOF in the configuration file: %s\n", func, bufr );
|
||||
rprintf(FLOG, "%s Unexpected EOF in the configuration file: %s\n", func, bufr );
|
||||
return( False );
|
||||
} /* Section */
|
||||
|
||||
@@ -305,7 +305,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
|
||||
rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
|
||||
return( False );
|
||||
}
|
||||
}
|
||||
@@ -315,7 +315,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
case '=': /* Equal sign marks end of param name. */
|
||||
if( 0 == end ) /* Don't allow an empty name. */
|
||||
{
|
||||
rprintf(FERROR, "%s Invalid parameter name in config. file.\n", func );
|
||||
rprintf(FLOG, "%s Invalid parameter name in config. file.\n", func );
|
||||
return( False );
|
||||
}
|
||||
bufr[end++] = '\0'; /* Mark end of string & advance. */
|
||||
@@ -329,7 +329,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
if( i < 0 )
|
||||
{
|
||||
bufr[end] = '\0';
|
||||
rprintf(FERROR, "%s Ignoring badly formed line in configuration file: %s\n",
|
||||
rprintf(FLOG, "%s Ignoring badly formed line in configuration file: %s\n",
|
||||
func, bufr );
|
||||
return( True );
|
||||
}
|
||||
@@ -340,7 +340,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
case '\0': /* Shouldn't have EOF within param name. */
|
||||
case EOF:
|
||||
bufr[i] = '\0';
|
||||
rprintf(FERROR, "%s Unexpected end-of-file at: %s\n", func, bufr );
|
||||
rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr );
|
||||
return( True );
|
||||
|
||||
default:
|
||||
@@ -370,7 +370,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
|
||||
rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
|
||||
return( False );
|
||||
}
|
||||
}
|
||||
@@ -485,14 +485,14 @@ static FILE *OpenConfFile( char *FileName )
|
||||
|
||||
if( NULL == FileName || 0 == *FileName )
|
||||
{
|
||||
rprintf(FERROR,"%s No configuration filename specified.\n", func);
|
||||
rprintf(FLOG, "%s No configuration filename specified.\n", func);
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
OpenedFile = fopen( FileName, "r" );
|
||||
if( NULL == OpenedFile )
|
||||
{
|
||||
rsyserr(FERROR, errno, "unable to open configuration file \"%s\"",
|
||||
rsyserr(FLOG, errno, "unable to open configuration file \"%s\"",
|
||||
FileName);
|
||||
}
|
||||
|
||||
@@ -534,7 +534,7 @@ BOOL pm_process( char *FileName,
|
||||
bufr = new_array( char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR,"%s memory allocation failure.\n", func);
|
||||
rprintf(FLOG, "%s memory allocation failure.\n", func);
|
||||
fclose(InFile);
|
||||
return( False );
|
||||
}
|
||||
@@ -548,7 +548,7 @@ BOOL pm_process( char *FileName,
|
||||
|
||||
if( !result ) /* Generic failure. */
|
||||
{
|
||||
rprintf(FERROR,"%s Failed. Error returned from params.c:parse().\n", func);
|
||||
rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func);
|
||||
return( False );
|
||||
}
|
||||
|
||||
|
||||
12
pipe.c
12
pipe.c
@@ -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");
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
ID
|
||||
Makefile
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
dummy
|
||||
@@ -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
|
||||
|
||||
@@ -1,25 +1,7 @@
|
||||
gen: configure config.h.in proto.h man
|
||||
conf: configure.sh config.h.in
|
||||
|
||||
configure: configure.in aclocal.m4
|
||||
autoconf
|
||||
configure.sh: configure.in aclocal.m4
|
||||
autoconf -o configure.sh
|
||||
|
||||
config.h.in: configure.in aclocal.m4
|
||||
autoheader && touch config.h.in
|
||||
|
||||
proto.h: *.c lib/compat.c
|
||||
cat *.c lib/compat.c | awk -f mkproto.awk >proto.h.new
|
||||
if diff proto.h proto.h.new >/dev/null; then \
|
||||
rm proto.h.new; \
|
||||
else \
|
||||
mv proto.h.new proto.h; \
|
||||
fi
|
||||
|
||||
man: rsync.1 rsyncd.conf.5
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 rsync.yo
|
||||
-./tweak_manpage rsync.1
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
|
||||
-./tweak_manpage rsyncd.conf.5
|
||||
|
||||
16
progress.c
16
progress.c
@@ -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) {
|
||||
|
||||
76
receiver.c
76
receiver.c
@@ -110,7 +110,7 @@ int get_tmpname(char *fnametmp, const char *fname)
|
||||
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
|
||||
|
||||
if (maxname < 1) {
|
||||
rprintf(FERROR, "temporary filename too long: %s\n", fname);
|
||||
rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
|
||||
fnametmp[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
|
||||
#endif
|
||||
|
||||
if (fd == -1) {
|
||||
rsyserr(FERROR, errno, "mkstemp %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
|
||||
full_fname(fnametmp));
|
||||
return -1;
|
||||
}
|
||||
@@ -211,7 +211,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
}
|
||||
offset = sum.flength;
|
||||
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
|
||||
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
|
||||
rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
|
||||
full_fname(fname), (double)j, (double)offset);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
@@ -266,7 +266,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
goto report_write_error;
|
||||
offset += len;
|
||||
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"lseek of %s returned %.0f, not %.0f",
|
||||
full_fname(fname),
|
||||
(double)pos, (double)offset);
|
||||
@@ -293,7 +293,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
report_write_error:
|
||||
rsyserr(FERROR, errno, "write failed on %s",
|
||||
rsyserr(FERROR_XFER, errno, "write failed on %s",
|
||||
full_fname(fname));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
@@ -335,7 +335,7 @@ static void handle_delayed_updates(char *local_name)
|
||||
/* We don't use robust_rename() here because the
|
||||
* partial-dir must be on the same drive. */
|
||||
if (do_rename(partialptr, fname) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rename failed for %s (from %s)",
|
||||
full_fname(fname), partialptr);
|
||||
} else {
|
||||
@@ -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
|
||||
@@ -598,7 +601,7 @@ int recv_files(int f_in, char *local_name)
|
||||
st.st_mode = 0;
|
||||
st.st_size = 0;
|
||||
} else if (do_fstat(fd1,&st) != 0) {
|
||||
rsyserr(FERROR, errno, "fstat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "fstat %s failed",
|
||||
full_fname(fnamecmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
close(fd1);
|
||||
@@ -613,7 +616,7 @@ int recv_files(int f_in, char *local_name)
|
||||
* and the underlying robust_unlink could cope
|
||||
* with directories
|
||||
*/
|
||||
rprintf(FERROR,"recv_files: %s is a directory\n",
|
||||
rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
|
||||
full_fname(fnamecmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
close(fd1);
|
||||
@@ -647,7 +650,7 @@ int recv_files(int f_in, char *local_name)
|
||||
if (inplace) {
|
||||
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
|
||||
if (fd2 == -1) {
|
||||
rsyserr(FERROR, errno, "open %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "open %s failed",
|
||||
full_fname(fname));
|
||||
}
|
||||
} else {
|
||||
@@ -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 : FINFO;
|
||||
if (msgtype == FERROR || verbose) {
|
||||
break;
|
||||
case 0: {
|
||||
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
|
||||
if (msgtype == FERROR_XFER || verbose) {
|
||||
char *errstr, *redostr, *keptstr;
|
||||
if (!(keep_partial && partialptr) && !inplace)
|
||||
keptstr = "discarded";
|
||||
@@ -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
38
rounding.c
Normal 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;
|
||||
}
|
||||
104
rsync.c
104
rsync.c
@@ -264,12 +264,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;
|
||||
@@ -350,7 +351,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
if (dry_run)
|
||||
return 1;
|
||||
if (link_stat(fname, &sx2.st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
@@ -371,16 +372,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
new_mode |= S_ISGID;
|
||||
}
|
||||
|
||||
if (daemon_chmod_modes && !S_ISLNK(new_mode))
|
||||
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
|
||||
get_acl(fname, sxp);
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (am_root < 0)
|
||||
set_stat_xattr(fname, file, new_mode);
|
||||
if (preserve_xattrs && fnamecmp)
|
||||
set_xattr(fname, file, fnamecmp, sxp);
|
||||
if (am_root < 0)
|
||||
set_stat_xattr(fname, file);
|
||||
#endif
|
||||
|
||||
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
|
||||
@@ -389,7 +393,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
|
||||
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno, "failed to set times on %s",
|
||||
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -418,31 +422,28 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
|
||||
}
|
||||
}
|
||||
if (am_root < 0) {
|
||||
;
|
||||
} else if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
* unless have the privilege */
|
||||
rsyserr(FERROR, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
} else
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
* destination had the setuid or setgid bits set due
|
||||
* to the side effect of the chown call */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
if (am_root >= 0) {
|
||||
if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* We shouldn't have attempted to change uid
|
||||
* or gid unless have the privilege. */
|
||||
rsyserr(FERROR_XFER, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
/* A lchown had been done, so we need to re-stat if
|
||||
* the destination had the setuid or setgid bits set
|
||||
* (due to the side effect of the chown call). */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
}
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
if (daemon_chmod_modes && !S_ISLNK(new_mode))
|
||||
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
/* It's OK to call set_acl() now, even for a dir, as the generator
|
||||
* will enable owner-writability using chmod, if necessary.
|
||||
@@ -458,7 +459,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
|
||||
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to set permissions on %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
@@ -503,15 +504,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 +524,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 +533,39 @@ void finish_transfer(const char *fname, const char *fnametmp,
|
||||
/* move tmp file over real file */
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
|
||||
ret = robust_rename(fnametmp, fname, partialptr,
|
||||
ret = robust_rename(fnametmp, fname, temp_copy_name,
|
||||
file->mode & INITACCESSPERMS);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
|
||||
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
|
||||
ret == -2 ? "copy" : "rename",
|
||||
full_fname(fnametmp), fname);
|
||||
do_unlink(fnametmp);
|
||||
return;
|
||||
if (!partialptr || (ret == -2 && temp_copy_name)
|
||||
|| robust_rename(fnametmp, partialptr, NULL,
|
||||
file->mode & INITACCESSPERMS) < 0)
|
||||
do_unlink(fnametmp);
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* The file was moved into place (not copied), so it's done. */
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
/* The file was copied, so tweak the perms of the copied file. If it
|
||||
* was copied to partialptr, move it into its final destination. */
|
||||
fnametmp = partialptr ? partialptr : fname;
|
||||
fnametmp = temp_copy_name ? temp_copy_name : fname;
|
||||
|
||||
do_set_file_attrs:
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
|
||||
|
||||
if (partialptr) {
|
||||
if (temp_copy_name) {
|
||||
if (do_rename(fnametmp, fname) < 0) {
|
||||
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
|
||||
rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
|
||||
full_fname(fnametmp), fname);
|
||||
} else
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
return 0;
|
||||
}
|
||||
handle_partial_dir(temp_copy_name, PDIR_DELETE);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct file_list *flist_for_ndx(int ndx)
|
||||
@@ -572,7 +580,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;
|
||||
}
|
||||
|
||||
30
rsync.h
30
rsync.h
@@ -32,6 +32,9 @@
|
||||
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
|
||||
#define URL_PREFIX "rsync://"
|
||||
|
||||
#define SYMLINK_PREFIX "/rsyncd-munged/"
|
||||
#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
|
||||
|
||||
#define BACKUP_SUFFIX "~"
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
@@ -90,7 +93,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 14
|
||||
#define SUBPROTOCOL_VERSION 16
|
||||
|
||||
/* 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
|
||||
@@ -188,17 +191,24 @@
|
||||
#define CFN_DROP_TRAILING_DOT_DIR (1<<2)
|
||||
#define CFN_COLLAPSE_DOT_DOT_DIRS (1<<3)
|
||||
|
||||
/* Log-message categories. Only FERROR and FINFO get sent over the socket,
|
||||
* but FLOG and FSOCKERR can be sent over the receiver -> generator pipe.
|
||||
* FLOG only goes to the log file, not the client; FCLIENT is the opposite. */
|
||||
enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
|
||||
/* Log-message categories. FLOG only goes to the log file, not the client;
|
||||
* FCLIENT is the opposite. */
|
||||
enum logcode {
|
||||
FNONE=0, /* never sent */
|
||||
FERROR_XFER=1, FINFO=2, /* sent over socket for any protocol */
|
||||
FERROR=3, FWARNING=4, /* sent over socket for protocols >= 30 */
|
||||
FERROR_SOCKET=5, FLOG=6, /* only sent via receiver -> generator pipe */
|
||||
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
|
||||
};
|
||||
|
||||
/* Messages types that are sent over the message channel. The logcode
|
||||
* values must all be present here with identical numbers. */
|
||||
enum msgcode {
|
||||
MSG_DATA=0, /* raw data on the multiplexed stream */
|
||||
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
|
||||
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, MSG_SOCKERR=FSOCKERR, /* sibling logging */
|
||||
MSG_ERROR_XFER=FERROR_XFER, MSG_INFO=FINFO, /* remote logging */
|
||||
MSG_ERROR=FERROR, MSG_WARNING=FWARNING, /* protocol-30 remote logging */
|
||||
MSG_ERROR_SOCKET=FERROR_SOCKET, /* sibling logging */
|
||||
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, /* sibling logging */
|
||||
MSG_REDO=9, /* reprocess indicated flist index */
|
||||
MSG_FLIST=20, /* extra file list over sibling socket */
|
||||
MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
|
||||
@@ -530,6 +540,7 @@ struct hashtable {
|
||||
void *nodes;
|
||||
int32 size, entries;
|
||||
uint32 node_size;
|
||||
int key64;
|
||||
};
|
||||
|
||||
struct ht_int32_node {
|
||||
@@ -662,7 +673,7 @@ extern int xattrs_ndx;
|
||||
|
||||
/* This optional item might follow an F_HL_*() item.
|
||||
* (Note: a device doesn't need to check LEN64_BUMP(f).) */
|
||||
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + 2 - 1)->unum)
|
||||
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + DEV_EXTRA_CNT - 1)->unum)
|
||||
|
||||
/* The sum is only present on regular files. */
|
||||
#define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
|
||||
@@ -713,7 +724,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;
|
||||
};
|
||||
@@ -804,7 +815,6 @@ struct stats {
|
||||
int64 flist_size;
|
||||
int num_files;
|
||||
int num_transferred_files;
|
||||
int current_file_index;
|
||||
};
|
||||
|
||||
struct chmod_mode_struct;
|
||||
|
||||
48
rsync.yo
48
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(8 Nov 2007)()()
|
||||
manpage(rsync)(1)(10 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
|
||||
@@ -378,7 +378,8 @@ to the detailed description below for a complete description. verb(
|
||||
--delay-updates put all updated files into place at end
|
||||
-m, --prune-empty-dirs prune empty directory chains from file-list
|
||||
--numeric-ids don't map uid/gid values by user/group name
|
||||
--timeout=TIME set I/O timeout in seconds
|
||||
--timeout=SECONDS set I/O timeout in seconds
|
||||
--contimeout=SECONDS set daemon connection timeout in seconds
|
||||
-I, --ignore-times don't skip files that match size and time
|
||||
--size-only skip files that match in size
|
||||
--modify-window=NUM compare mod-times with reduced accuracy
|
||||
@@ -816,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.
|
||||
@@ -1037,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
|
||||
@@ -1292,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.
|
||||
|
||||
@@ -1582,6 +1599,10 @@ dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
|
||||
timeout in seconds. If no data is transferred for the specified time
|
||||
then rsync will exit. The default is 0, which means no timeout.
|
||||
|
||||
dit(bf(--contimeout)) This option allows you to set the amount of time
|
||||
that rsync will wait for its connection to an rsync daemon to succeed.
|
||||
If the timeout is reached, rsync exits with an error.
|
||||
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address when
|
||||
connecting to an rsync daemon. The bf(--address) option allows you to
|
||||
specify a specific IP address (or hostname) to bind to. See also this
|
||||
@@ -1939,6 +1960,8 @@ dit(bf(--password-file)) This option allows you to provide a password in a
|
||||
file for accessing an rsync daemon. The file must not be world readable.
|
||||
It should contain just the password as a single line.
|
||||
|
||||
This option does not supply a password to a remote shell transport such as
|
||||
ssh; to learn how to do that, consult the remote shell's documentation.
|
||||
When accessing an rsync daemon using a remote shell as the transport, this
|
||||
option only comes into effect after the remote shell finishes its
|
||||
authentication (i.e. if you have also specified a password in the daemon's
|
||||
@@ -2010,7 +2033,8 @@ 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).
|
||||
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591). (Run
|
||||
"iconv --list" to see a list of the charset names that a machine supports.)
|
||||
Finally, you can specify 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.
|
||||
@@ -2775,6 +2799,7 @@ dit(bf(23)) Partial transfer due to error
|
||||
dit(bf(24)) Partial transfer due to vanished source files
|
||||
dit(bf(25)) The --max-delete limit stopped deletions
|
||||
dit(bf(30)) Timeout in data send/receive
|
||||
dit(bf(35)) Timeout waiting for daemon connection
|
||||
enddit()
|
||||
|
||||
manpagesection(ENVIRONMENT VARIABLES)
|
||||
@@ -2794,7 +2819,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".
|
||||
@@ -2828,7 +2854,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.0pre5 of rsync.
|
||||
This man page is current for version 3.0.0pre9 of rsync.
|
||||
|
||||
manpagesection(INTERNAL OPTIONS)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(8 Nov 2007)()()
|
||||
manpage(rsyncd.conf)(5)(10 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()
|
||||
|
||||
@@ -130,12 +134,15 @@ the advantage of extra protection against possible implementation security
|
||||
holes, but it has the disadvantages of requiring super-user privileges,
|
||||
of not being able to follow symbolic links that are either absolute or outside
|
||||
of the new root path, and of complicating the preservation of usernames and groups
|
||||
(see below). When "use chroot" is false, for security reasons,
|
||||
symlinks may only be relative paths pointing to other files within the root
|
||||
path, and leading slashes are removed from most absolute paths (options
|
||||
such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
|
||||
rooted in the module's "path" dir, just as if chroot was specified).
|
||||
The default for "use chroot" is true.
|
||||
(see below). When "use chroot" is false, 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.
|
||||
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
|
||||
use the standard library functions for looking up names and IDs (i.e.
|
||||
@@ -159,6 +166,40 @@ 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).
|
||||
|
||||
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.
|
||||
|
||||
If you disable this option on a daemon that is not read-only, there
|
||||
are tricks that a user can play with uploaded symlinks to access
|
||||
daemon-excluded items (if your module has any), and, if "use chroot"
|
||||
is off, rsync can even be tricked into showing or changing data that
|
||||
is outside the module's path (as access-permissions allow).
|
||||
|
||||
The way rsync disables the use of symlinks is to prefix each one with
|
||||
the string "/rsyncd-munged/". This prevents the links from being used
|
||||
as long as that directory does not exist. When this option is enabled,
|
||||
rsync will refuse to run if that path is a directory or a symlink to
|
||||
a directory. When using the "munge symlinks" option in a chroot area,
|
||||
you should add this path to the exclude setting for the module so that
|
||||
a user can't try to create it.
|
||||
|
||||
Note: rsync makes no attempt to verify that any pre-existing symlinks in
|
||||
the hierarchy are as safe as you want them to be. If you setup an rsync
|
||||
daemon on a new area or locally add symlinks, you can manually protect your
|
||||
symlinks from being abused by prefixing "/rsyncd-munged/" to the start of
|
||||
every symlink's value. There is a perl script in the support directory
|
||||
of the source code named "munge-symlinks" that can be used to add or remove
|
||||
this prefix from your symlinks.
|
||||
|
||||
When this option is disabled on a writable module and "use chroot" is off,
|
||||
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(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
|
||||
@@ -614,7 +655,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.0pre5 of rsync.
|
||||
This man page is current for version 3.0.0pre9 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
|
||||
11
sender.c
11
sender.c
@@ -229,7 +229,7 @@ void send_files(int f_in, int f_out)
|
||||
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
|
||||
recv_xattr_request(file, f_in);
|
||||
#endif
|
||||
|
||||
@@ -265,7 +265,8 @@ void send_files(int f_in, int f_out)
|
||||
updating_basis_file = inplace && (protocol_version >= 29
|
||||
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
|
||||
|
||||
stats.current_file_index = ndx;
|
||||
if (!am_server && do_progress)
|
||||
set_current_file_index(file, ndx);
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += F_LENGTH(file);
|
||||
|
||||
@@ -289,13 +290,13 @@ void send_files(int f_in, int f_out)
|
||||
if (errno == ENOENT) {
|
||||
enum logcode c = am_daemon
|
||||
&& protocol_version < 28 ? FERROR
|
||||
: FINFO;
|
||||
: FWARNING;
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"send_files failed to open %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
@@ -349,7 +350,7 @@ void send_files(int f_in, int f_out)
|
||||
j = unmap_file(mbuf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, j,
|
||||
rsyserr(FERROR_XFER, j,
|
||||
"read errors mapping %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
|
||||
26
socket.c
26
socket.c
@@ -32,6 +32,7 @@
|
||||
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
extern int connect_timeout;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
@@ -157,6 +158,11 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* connect() timeout handler based on alarm() */
|
||||
static RETSIGTYPE contimeout_handler(UNUSED(int val))
|
||||
{
|
||||
connect_timeout = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a socket to a tcp remote host with the specified port .
|
||||
@@ -261,11 +267,27 @@ int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
if (connect_timeout > 0) {
|
||||
SIGACTION(SIGALRM, contimeout_handler);
|
||||
alarm(connect_timeout);
|
||||
}
|
||||
|
||||
while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
if (connect_timeout < 0)
|
||||
exit_cleanup(RERR_CONTIMEOUT);
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (connect_timeout > 0)
|
||||
alarm(0);
|
||||
|
||||
if (s < 0)
|
||||
continue;
|
||||
|
||||
if (proxied
|
||||
&& establish_proxy_connection(s, host, port,
|
||||
proxy_user, proxy_pass) != 0) {
|
||||
|
||||
18
support/extern-squish
Executable file
18
support/extern-squish
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
# This script finds extraneous "extern" variables in the *.c files.
|
||||
# Run it from inside the main rsync directory.
|
||||
|
||||
use strict;
|
||||
|
||||
my @files = glob('*.c');
|
||||
|
||||
foreach my $fn (@files) {
|
||||
open(IN, '<', $fn) or die;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
my @externs = /^extern .*?([^[\s(*;&.]+)(?:\[.*?\])?;/mg;
|
||||
foreach my $find (@externs) {
|
||||
my @matches = /(?<!\sstruct )\b(\Q$find\E)\b/g;
|
||||
print $fn, ': ', $find, "\n" if @matches == 1;
|
||||
}
|
||||
}
|
||||
36
support/git-set-file-times
Executable file
36
support/git-set-file-times
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
# Sets mtime and atime of files to the latest commit time in git.
|
||||
#
|
||||
# This is useful after the first clone of the rsync repository BEFORE you
|
||||
# do any building. It is also safe if you have done a "make distclean".
|
||||
|
||||
my %ls;
|
||||
my $commit_time;
|
||||
my $prefix = @ARGV && $ARGV[0] =~ s/^--prefix=// ? shift : '';
|
||||
|
||||
$/ = "\0";
|
||||
open FH, 'git ls-files -z|' or die $!;
|
||||
while (<FH>) {
|
||||
chomp;
|
||||
$ls{$_} = $_;
|
||||
}
|
||||
close FH;
|
||||
|
||||
$/ = "\n";
|
||||
open FH, "git log -r --name-only --no-color --pretty=raw -z @ARGV |" or die $!;
|
||||
while (<FH>) {
|
||||
chomp;
|
||||
if (/^committer .*? (\d+) (?:[\-\+]\d+)$/) {
|
||||
$commit_time = $1;
|
||||
} elsif (s/\0\0commit [a-f0-9]{40}$// or s/\0$//) {
|
||||
my @files = delete @ls{split(/\0/, $_)};
|
||||
@files = grep { defined $_ } @files;
|
||||
next unless @files;
|
||||
map { s/^/$prefix/ } @files;
|
||||
utime $commit_time, $commit_time, @files;
|
||||
}
|
||||
last unless %ls;
|
||||
}
|
||||
close FH;
|
||||
60
support/munge-symlinks
Executable file
60
support/munge-symlinks
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/perl
|
||||
# This script will either prefix all symlink values with the string
|
||||
# "/rsyncd-munged/" or remove that prefix.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
my $SYMLINK_PREFIX = '/rsyncd-munged/';
|
||||
|
||||
my $munge_opt;
|
||||
|
||||
&GetOptions(
|
||||
'munge' => sub { $munge_opt = 1 },
|
||||
'unmunge' => sub { $munge_opt = 0 },
|
||||
'all' => \( my $all_opt ),
|
||||
'help|h' => \( my $help_opt ),
|
||||
) or &usage;
|
||||
|
||||
&usage if $help_opt || !defined $munge_opt;
|
||||
|
||||
my $munged_re = $all_opt ? qr/^($SYMLINK_PREFIX)+(?=.)/ : qr/^$SYMLINK_PREFIX(?=.)/;
|
||||
|
||||
push(@ARGV, '.') unless @ARGV;
|
||||
|
||||
open(PIPE, '-|', 'find', @ARGV, '-type', 'l') or die $!;
|
||||
|
||||
while (<PIPE>) {
|
||||
chomp;
|
||||
my $lnk = readlink($_) or next;
|
||||
if ($munge_opt) {
|
||||
next if !$all_opt && $lnk =~ /$munged_re/;
|
||||
$lnk =~ s/^/$SYMLINK_PREFIX/;
|
||||
} else {
|
||||
next unless $lnk =~ s/$munged_re//;
|
||||
}
|
||||
if (!unlink($_)) {
|
||||
warn "Unable to unlink symlink: $_ ($!)\n";
|
||||
} elsif (!symlink($lnk, $_)) {
|
||||
warn "Unable to recreate symlink: $_ -> $lnk ($!)\n";
|
||||
} else {
|
||||
print "$_ -> $lnk\n";
|
||||
}
|
||||
}
|
||||
|
||||
close PIPE;
|
||||
exit;
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: munge-symlinks --munge|--unmunge [--all] [DIR|SYMLINK...]
|
||||
|
||||
--munge Add the $SYMLINK_PREFIX prefix to symlinks if not already
|
||||
present, or always when combined with --all.
|
||||
--unmunge Remove one $SYMLINK_PREFIX prefix from symlinks or all
|
||||
such prefixes with --all.
|
||||
|
||||
See the "munge symlinks" option in the rsyncd.conf manpage for more details.
|
||||
EOT
|
||||
}
|
||||
190
support/patch-update
Executable file
190
support/patch-update
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/perl -w
|
||||
# This script is used to turn one or more of the "patch/*" branches
|
||||
# into one or more diffs in the "patches" directory. Pass the option
|
||||
# --gen if you want generated files in the diffs. Pass the name of
|
||||
# one or more diffs if you want to just update a subset of all the
|
||||
# diffs.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
my $patches_dir = 'patches';
|
||||
my $tmp_dir = "patches.$$";
|
||||
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'skip-check' => \( my $skip_branch_check ),
|
||||
'gen:s' => \( my $incl_generated_files ),
|
||||
'help|h' => \( my $help_opt ),
|
||||
);
|
||||
&usage if $help_opt;
|
||||
|
||||
if (defined $incl_generated_files) {
|
||||
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
|
||||
$incl_generated_files = 1;
|
||||
}
|
||||
|
||||
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
|
||||
die "No '.git' directory present in the current dir.\n" unless -d '.git';
|
||||
|
||||
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>) {
|
||||
if (s/^GENFILES=//) {
|
||||
while (s/\\$//) {
|
||||
$_ .= <IN>;
|
||||
}
|
||||
@extra_files = split(' ', $_);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
if ($incl_generated_files) {
|
||||
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
|
||||
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
|
||||
}
|
||||
my $last_touch = time;
|
||||
|
||||
my(@patches, %local_patch);
|
||||
|
||||
# Start by finding all patches so that we can load all possible parents.
|
||||
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
|
||||
while (<PIPE>) {
|
||||
if (m# origin/patch/(.*)#) {
|
||||
push(@patches, $1);
|
||||
} elsif (m# patch/(.*)#) {
|
||||
$local_patch{$1} = 1;
|
||||
}
|
||||
}
|
||||
close PIPE;
|
||||
|
||||
my(%parent, %description);
|
||||
foreach my $patch (@patches) {
|
||||
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
|
||||
my $desc = '';
|
||||
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
|
||||
while (<PIPE>) {
|
||||
last if /^@@ /;
|
||||
}
|
||||
while (<PIPE>) {
|
||||
next unless s/^[ +]//;
|
||||
if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
|
||||
$parent{$patch} = $1;
|
||||
}
|
||||
$desc .= $_;
|
||||
}
|
||||
$description{$patch} = $desc;
|
||||
}
|
||||
|
||||
if (@ARGV) {
|
||||
# Limit the list of patches to actually process based on @ARGV.
|
||||
@patches = ( );
|
||||
foreach (@ARGV) {
|
||||
s{^(patches|patch|origin/patch)/} {};
|
||||
s{\.diff$} {};
|
||||
push(@patches, $_);
|
||||
}
|
||||
}
|
||||
|
||||
my %completed;
|
||||
foreach my $patch (@patches) {
|
||||
next if $completed{$patch}++;
|
||||
update_patch($patch);
|
||||
}
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "rm -rf $tmp_dir";
|
||||
}
|
||||
|
||||
sleep 1 if $last_touch == time;
|
||||
system "git checkout master" and exit 1;
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
sub update_patch
|
||||
{
|
||||
my($patch) = @_;
|
||||
|
||||
my $parent = $parent{$patch};
|
||||
if (defined $parent) {
|
||||
unless ($completed{$parent}++) {
|
||||
update_patch($parent);
|
||||
}
|
||||
$parent = "patch/$parent";
|
||||
} else {
|
||||
$parent = 'master';
|
||||
}
|
||||
|
||||
print "======== $patch ========\n";
|
||||
|
||||
sleep 1 if $incl_generated_files && $last_touch == time;
|
||||
if ($local_patch{$patch}) {
|
||||
system "git checkout patch/$patch" and exit 1;
|
||||
} else {
|
||||
system "git checkout --track -b patch/$patch origin/patch/$patch" and exit 1;
|
||||
}
|
||||
|
||||
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
|
||||
print OUT $description{$patch}, "\n";
|
||||
|
||||
if (system("git merge $parent") != 0) {
|
||||
print qq|"git merge $parent" incomplete -- please fix.\n|;
|
||||
$ENV{PS1} = "[$parent] patch/$patch: ";
|
||||
system $ENV{SHELL} and exit 1;
|
||||
}
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
|
||||
}
|
||||
$last_touch = time;
|
||||
|
||||
open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
|
||||
DIFF: while (<PIPE>) {
|
||||
while (m{^diff --git a/PATCH}) {
|
||||
while (<PIPE>) {
|
||||
last if m{^diff --git a/};
|
||||
}
|
||||
last DIFF if !defined $_;
|
||||
}
|
||||
next if /^index /;
|
||||
print OUT $_;
|
||||
}
|
||||
close PIPE;
|
||||
|
||||
if ($incl_generated_files) {
|
||||
$parent =~ s#.*/##;
|
||||
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
|
||||
while (<PIPE>) {
|
||||
s#^(diff -up) $tmp_dir/[^/]+/(.*?) $tmp_dir/[^/]+/(.*)#$1 a/$2 b/$3#o;
|
||||
s#^\Q---\E $tmp_dir/[^/]+/([^\t]+)\t.*#--- a/$1#o;
|
||||
s#^\Q+++\E $tmp_dir/[^/]+/([^\t]+)\t.*#+++ b/$1#o;
|
||||
print OUT $_;
|
||||
}
|
||||
close PIPE;
|
||||
}
|
||||
|
||||
close OUT;
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: patch-update [OPTIONS]
|
||||
|
||||
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
|
||||
--skip-check Skip the check that ensures starting with a clean master branch.
|
||||
EOT
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -234,6 +234,7 @@ build_rsyncd_conf() {
|
||||
|
||||
pid file = $pidfile
|
||||
use chroot = no
|
||||
munge symlinks = no
|
||||
hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
|
||||
log file = $logfile
|
||||
log format = %i %h [%a] %m (%u) %l %f%L
|
||||
@@ -255,6 +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"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
1
tls.c
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
12
uidlist.c
12
uidlist.c
@@ -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)
|
||||
@@ -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;
|
||||
|
||||
81
util.c
81
util.c
@@ -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);
|
||||
@@ -274,20 +275,20 @@ int copy_file(const char *source, const char *dest, int ofd,
|
||||
int len; /* Number of bytes read into `buf'. */
|
||||
|
||||
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
|
||||
rsyserr(FERROR, errno, "open %s", full_fname(source));
|
||||
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ofd < 0) {
|
||||
if (robust_unlink(dest) && errno != ENOENT) {
|
||||
rsyserr(FERROR, errno, "unlink %s", full_fname(dest));
|
||||
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
|
||||
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|
||||
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
|
||||
rsyserr(FERROR, errno, "open %s", full_fname(dest));
|
||||
rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest));
|
||||
close(ifd);
|
||||
return -1;
|
||||
}
|
||||
@@ -295,7 +296,7 @@ int copy_file(const char *source, const char *dest, int ofd,
|
||||
|
||||
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
|
||||
if (full_write(ofd, buf, len) < 0) {
|
||||
rsyserr(FERROR, errno, "write %s", full_fname(dest));
|
||||
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
return -1;
|
||||
@@ -303,19 +304,19 @@ int copy_file(const char *source, const char *dest, int ofd,
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
rsyserr(FERROR, errno, "read %s", full_fname(source));
|
||||
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(ifd) < 0) {
|
||||
rsyserr(FINFO, errno, "close failed on %s",
|
||||
rsyserr(FWARNING, errno, "close failed on %s",
|
||||
full_fname(source));
|
||||
}
|
||||
|
||||
if (close(ofd) < 0) {
|
||||
rsyserr(FERROR, errno, "close failed on %s",
|
||||
rsyserr(FERROR_XFER, errno, "close failed on %s",
|
||||
full_fname(dest));
|
||||
return -1;
|
||||
}
|
||||
@@ -371,7 +372,7 @@ int robust_unlink(const char *fname)
|
||||
} while ((rc = access(path, 0)) == 0 && counter != start);
|
||||
|
||||
if (verbose > 0) {
|
||||
rprintf(FINFO,"renaming %s to %s because of text busy\n",
|
||||
rprintf(FWARNING, "renaming %s to %s because of text busy\n",
|
||||
fname, path);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -549,7 +546,7 @@ void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
|
||||
s = ".";
|
||||
|
||||
if (sanitize_paths)
|
||||
s = sanitize_path(NULL, s, "", 0, NULL);
|
||||
s = sanitize_path(NULL, s, "", 0);
|
||||
else
|
||||
s = strdup(s);
|
||||
if (!s)
|
||||
@@ -766,8 +763,7 @@ unsigned int clean_fname(char *name, int flags)
|
||||
* Specify NULL to get the default of "module_dir".
|
||||
*
|
||||
* The depth var is a count of how many '..'s to allow at the start of the
|
||||
* path. If symlink is set, combine its value with the "p" value to get
|
||||
* the target path, and **return NULL if any '..'s try to escape**.
|
||||
* path.
|
||||
*
|
||||
* We also clean the path in a manner similar to clean_fname() but with a
|
||||
* few differences:
|
||||
@@ -777,17 +773,11 @@ unsigned int clean_fname(char *name, int flags)
|
||||
* ALWAYS collapses ".." elements (except for those at the start of the
|
||||
* string up to "depth" deep). If the resulting name would be empty,
|
||||
* change it into a ".". */
|
||||
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
const char *symlink)
|
||||
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
|
||||
{
|
||||
char *start, *sanp, *save_dest = dest;
|
||||
char *start, *sanp;
|
||||
int rlen = 0, leave_one_dotdir = relative_paths;
|
||||
|
||||
if (symlink && *symlink == '/') {
|
||||
p = symlink;
|
||||
symlink = "";
|
||||
}
|
||||
|
||||
if (dest != p) {
|
||||
int plen = strlen(p);
|
||||
if (*p == '/') {
|
||||
@@ -810,18 +800,7 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
}
|
||||
|
||||
start = sanp = dest + rlen;
|
||||
while (1) {
|
||||
if (*p == '\0') {
|
||||
if (!symlink || !*symlink)
|
||||
break;
|
||||
while (sanp != start && sanp[-1] != '/') {
|
||||
/* strip last element */
|
||||
sanp--;
|
||||
}
|
||||
/* Append a relative symlink */
|
||||
p = symlink;
|
||||
symlink = "";
|
||||
}
|
||||
while (*p) {
|
||||
/* discard leading or extra slashes */
|
||||
if (*p == '/') {
|
||||
p++;
|
||||
@@ -843,11 +822,6 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
|
||||
/* ".." component followed by slash or end */
|
||||
if (depth <= 0 || sanp != start) {
|
||||
if (symlink && sanp == start) {
|
||||
if (!save_dest)
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
p += 2;
|
||||
if (sanp != start) {
|
||||
/* back up sanp one level */
|
||||
@@ -921,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)
|
||||
rprintf(FINFO, "[%s] dir is now %s\n", who_am_i(), curr_dir);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
202
xattrs.c
202
xattrs.c
@@ -47,7 +47,6 @@ extern int checksum_seed;
|
||||
#define XSTATE_ABBREV 0
|
||||
#define XSTATE_DONE 1
|
||||
#define XSTATE_TODO 2
|
||||
#define XSTATE_LOCAL 3
|
||||
|
||||
#define USER_PREFIX "user."
|
||||
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
|
||||
@@ -70,6 +69,7 @@ extern int checksum_seed;
|
||||
typedef struct {
|
||||
char *datum, *name;
|
||||
size_t datum_len, name_len;
|
||||
int num;
|
||||
} rsync_xa;
|
||||
|
||||
static size_t namebuf_len = 0;
|
||||
@@ -111,6 +111,7 @@ static int rsync_xal_compare_names(const void *x1, const void *x2)
|
||||
static ssize_t get_xattr_names(const char *fname)
|
||||
{
|
||||
ssize_t list_len;
|
||||
double arg;
|
||||
|
||||
if (!namebuf) {
|
||||
namebuf_len = 1024;
|
||||
@@ -119,23 +120,26 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
out_of_memory("get_xattr_names");
|
||||
}
|
||||
|
||||
/* The length returned includes all the '\0' terminators. */
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len > (ssize_t)namebuf_len) {
|
||||
list_len = -1;
|
||||
errno = ERANGE;
|
||||
}
|
||||
if (list_len >= 0)
|
||||
return list_len;
|
||||
if (errno == ENOTSUP)
|
||||
return 0;
|
||||
if (errno == ERANGE) {
|
||||
while (1) {
|
||||
/* The length returned includes all the '\0' terminators. */
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len >= 0) {
|
||||
if ((size_t)list_len <= namebuf_len)
|
||||
break;
|
||||
} else if (errno == ENOTSUP)
|
||||
return 0;
|
||||
else if (errno != ERANGE) {
|
||||
arg = (double)namebuf_len;
|
||||
got_error:
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
|
||||
fname, arg);
|
||||
return -1;
|
||||
}
|
||||
list_len = sys_llistxattr(fname, NULL, 0);
|
||||
if (list_len < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",0) failed",
|
||||
fname);
|
||||
return -1;
|
||||
arg = 0;
|
||||
goto got_error;
|
||||
}
|
||||
if (namebuf_len)
|
||||
free(namebuf);
|
||||
@@ -143,15 +147,9 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
namebuf = new_array(char, namebuf_len);
|
||||
if (!namebuf)
|
||||
out_of_memory("get_xattr_names");
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len >= 0)
|
||||
return list_len;
|
||||
}
|
||||
|
||||
rsyserr(FERROR, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%ld) failed",
|
||||
fname, (long)namebuf_len);
|
||||
return -1;
|
||||
return list_len;
|
||||
}
|
||||
|
||||
/* On entry, the *len_ptr parameter contains the size of the extra space we
|
||||
@@ -169,7 +167,7 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
|
||||
if (datum_len == (size_t)-1) {
|
||||
if (errno == ENOTSUP || no_missing_error)
|
||||
return NULL;
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
|
||||
fname, name);
|
||||
return NULL;
|
||||
@@ -185,11 +183,11 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
|
||||
size_t len = sys_lgetxattr(fname, name, ptr, datum_len);
|
||||
if (len != datum_len) {
|
||||
if (len == (size_t)-1) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
|
||||
" failed", fname, name, (long)datum_len);
|
||||
} else {
|
||||
rprintf(FERROR,
|
||||
rprintf(FERROR_XFER,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
|
||||
" returned %ld\n", fname, name,
|
||||
(long)datum_len, (long)len);
|
||||
@@ -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 *rxas;
|
||||
|
||||
name_len = strlen(name) + 1;
|
||||
list_len -= name_len;
|
||||
|
||||
@@ -230,9 +228,12 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
|
||||
#endif
|
||||
|
||||
/* No rsync.%FOO attributes are copied w/o 2 -X options. */
|
||||
if (preserve_xattrs < 2 && name_len > RPRE_LEN
|
||||
&& name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX))
|
||||
continue;
|
||||
if (name_len > RPRE_LEN && name[RPRE_LEN] == '%'
|
||||
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
|
||||
if ((am_sender && preserve_xattrs < 2)
|
||||
|| (am_root < 0 && strcmp(name, XSTAT_ATTR) == 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
datum_len = name_len; /* Pass extra size to get_xattr_data() */
|
||||
if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
|
||||
@@ -253,22 +254,26 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
|
||||
name_offset = datum_len;
|
||||
|
||||
#ifdef HAVE_LINUX_XATTRS
|
||||
if (am_root < 0 && name_len > RPRE_LEN
|
||||
if (am_root < 0 && name_len > RPRE_LEN && name[RPRE_LEN] != '%'
|
||||
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
|
||||
name += RPRE_LEN;
|
||||
name_len -= RPRE_LEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
|
||||
rxas->name = ptr + name_offset;
|
||||
memcpy(rxas->name, name, name_len);
|
||||
rxas->datum = ptr;
|
||||
rxas->name_len = name_len;
|
||||
rxas->datum_len = datum_len;
|
||||
rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
|
||||
rxa->name = ptr + name_offset;
|
||||
memcpy(rxa->name, name, name_len);
|
||||
rxa->datum = ptr;
|
||||
rxa->name_len = name_len;
|
||||
rxa->datum_len = datum_len;
|
||||
}
|
||||
if (xalp->count > 1)
|
||||
qsort(xalp->items, xalp->count, sizeof (rsync_xa), rsync_xal_compare_names);
|
||||
count = xalp->count;
|
||||
rxa = xalp->items;
|
||||
if (count > 1)
|
||||
qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names);
|
||||
for (rxa += count-1; count; count--, rxa--)
|
||||
rxa->num = count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -456,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;
|
||||
@@ -478,16 +484,19 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
/* Flag that we handled this abbreviated item. */
|
||||
rxa->datum[0] = XSTATE_DONE;
|
||||
|
||||
write_varint(f_out, j - prior_req);
|
||||
prior_req = j;
|
||||
write_varint(f_out, rxa->num - prior_req);
|
||||
prior_req = rxa->num;
|
||||
|
||||
if (fname) {
|
||||
size_t len = 0;
|
||||
char *ptr;
|
||||
|
||||
/* Re-read the long datum. */
|
||||
if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0)))
|
||||
if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) {
|
||||
rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname);
|
||||
write_varint(f_out, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
write_varint(f_out, len); /* length might have changed! */
|
||||
write_buf(f_out, ptr, len);
|
||||
@@ -498,37 +507,16 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
write_byte(f_out, 0); /* end the list */
|
||||
}
|
||||
|
||||
/* Any items set locally by the generator that the receiver doesn't
|
||||
* get told about get changed back to XSTATE_ABBREV. */
|
||||
void xattr_clear_locals(struct file_struct *file)
|
||||
{
|
||||
item_list *lst = rsync_xal_l.items;
|
||||
rsync_xa *rxa;
|
||||
int cnt;
|
||||
|
||||
if (F_XATTR(file) < 0)
|
||||
return;
|
||||
|
||||
lst += F_XATTR(file);
|
||||
cnt = lst->count;
|
||||
for (rxa = lst->items; cnt--; rxa++) {
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM)
|
||||
continue;
|
||||
if (rxa->datum[0] == XSTATE_LOCAL)
|
||||
rxa->datum[0] = XSTATE_ABBREV;
|
||||
}
|
||||
}
|
||||
|
||||
/* When called by the sender, read the request from the generator and mark
|
||||
* any needed xattrs with a flag that lets us know they need to be sent to
|
||||
* the receiver. When called by the receiver, reads the sent data and
|
||||
* stores it in place of its checksum. */
|
||||
void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
int recv_xattr_request(struct file_struct *file, int f_in)
|
||||
{
|
||||
item_list *lst = rsync_xal_l.items;
|
||||
char *old_datum, *name;
|
||||
rsync_xa *rxa;
|
||||
int rel_pos, cnt;
|
||||
int rel_pos, cnt, num, got_xattr_data = 0;
|
||||
|
||||
if (F_XATTR(file) < 0) {
|
||||
rprintf(FERROR, "recv_xattr_request: internal data error!\n");
|
||||
@@ -538,13 +526,20 @@ void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
|
||||
cnt = lst->count;
|
||||
rxa = lst->items;
|
||||
rxa -= 1;
|
||||
num = 0;
|
||||
while ((rel_pos = read_varint(f_in)) != 0) {
|
||||
rxa += rel_pos;
|
||||
cnt -= rel_pos;
|
||||
if (cnt < 0 || rxa->datum_len <= MAX_FULL_DATUM
|
||||
|| rxa->datum[0] != XSTATE_ABBREV) {
|
||||
rprintf(FERROR, "recv_xattr_request: internal abbrev error!\n");
|
||||
num += rel_pos;
|
||||
while (cnt && rxa->num < num) {
|
||||
rxa++;
|
||||
cnt--;
|
||||
}
|
||||
if (!cnt || rxa->num != num) {
|
||||
rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",
|
||||
who_am_i(), num, f_name(file, NULL));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) {
|
||||
rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i());
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
@@ -566,7 +561,10 @@ void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
rxa->name = name;
|
||||
free(old_datum);
|
||||
read_buf(f_in, rxa->datum, rxa->datum_len);
|
||||
got_xattr_data = 1;
|
||||
}
|
||||
|
||||
return got_xattr_data;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -575,7 +573,7 @@ void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
void receive_xattr(struct file_struct *file, int f)
|
||||
{
|
||||
static item_list temp_xattr = EMPTY_ITEM_LIST;
|
||||
int count;
|
||||
int count, num;
|
||||
int ndx = read_varint(f);
|
||||
|
||||
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
|
||||
@@ -594,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);
|
||||
@@ -618,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
|
||||
@@ -654,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 */
|
||||
@@ -722,7 +721,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
if (fname == fnamecmp)
|
||||
; /* Value is already set when identical */
|
||||
else if (sys_lsetxattr(fname, name, ptr, len) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
ret = -1;
|
||||
@@ -730,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;
|
||||
}
|
||||
@@ -745,7 +742,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
}
|
||||
|
||||
if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
ret = -1;
|
||||
@@ -765,6 +762,9 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
: !HAS_PREFIX(name, USER_PREFIX))
|
||||
continue;
|
||||
#endif
|
||||
if (am_root < 0 && name_len > RPRE_LEN
|
||||
&& name[RPRE_LEN] == '%' && strcmp(name, XSTAT_ATTR) == 0)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < xalp->count; i++) {
|
||||
if (strcmp(name, rxas[i].name) == 0)
|
||||
@@ -772,7 +772,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
}
|
||||
if (i == xalp->count) {
|
||||
if (sys_lremovexattr(fname, name) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
ret = -1;
|
||||
@@ -815,7 +815,7 @@ int set_xattr_acl(const char *fname, int is_access_acl, const char *buf, size_t
|
||||
{
|
||||
const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
|
||||
if (sys_lsetxattr(fname, name, buf, buf_len) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"set_xattr_acl: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
return -1;
|
||||
@@ -860,7 +860,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst
|
||||
xst->st_gid = 0;
|
||||
return 0;
|
||||
}
|
||||
rsyserr(FERROR, errno, "failed to read xattr %s for %s",
|
||||
rsyserr(FERROR_XFER, errno, "failed to read xattr %s for %s",
|
||||
XSTAT_ATTR, full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
@@ -881,7 +881,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
|
||||
{
|
||||
STRUCT_STAT fst, xst;
|
||||
dev_t rdev;
|
||||
@@ -891,19 +891,19 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
return 0;
|
||||
|
||||
if (read_only || list_only) {
|
||||
rsyserr(FERROR, EROFS, "failed to write xattr %s for %s",
|
||||
rsyserr(FERROR_XFER, EROFS, "failed to write xattr %s for %s",
|
||||
XSTAT_ATTR, full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x_lstat(fname, &fst, &xst) < 0) {
|
||||
rsyserr(FERROR, errno, "failed to re-stat %s",
|
||||
rsyserr(FERROR_XFER, errno, "failed to re-stat %s",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fst.st_mode &= (_S_IFMT | CHMOD_BITS);
|
||||
fmode = file->mode & (_S_IFMT | CHMOD_BITS);
|
||||
fmode = new_mode & (_S_IFMT | CHMOD_BITS);
|
||||
|
||||
if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) {
|
||||
uint32 *devp = F_RDEV_P(file);
|
||||
@@ -923,7 +923,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
&& fst.st_uid == F_OWNER(file) && fst.st_gid == F_GROUP(file)) {
|
||||
/* xst.st_mode will be 0 if there's no current stat xattr */
|
||||
if (xst.st_mode && sys_lremovexattr(fname, XSTAT_ATTR) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"delete of stat xattr failed for %s",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
@@ -941,7 +941,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
if (sys_lsetxattr(fname, XSTAT_ATTR, buf, len) < 0) {
|
||||
if (errno == EPERM && S_ISLNK(fst.st_mode))
|
||||
return 0;
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to write xattr %s for %s",
|
||||
XSTAT_ATTR, full_fname(fname));
|
||||
return -1;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
dummy
|
||||
Reference in New Issue
Block a user