mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
385 Commits
v3.0.0pre1
...
v3.0.1pre3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cd3c6dccf | ||
|
|
29a89172f7 | ||
|
|
2089375179 | ||
|
|
f8949e7647 | ||
|
|
84ecaa0eca | ||
|
|
3f2d8d683a | ||
|
|
fd2598022c | ||
|
|
b05c58cce6 | ||
|
|
05805cd6b7 | ||
|
|
a165be754b | ||
|
|
af3172c148 | ||
|
|
487cb52615 | ||
|
|
9793bbb364 | ||
|
|
f6f74b93ef | ||
|
|
7568ff448a | ||
|
|
56158b7e04 | ||
|
|
798a9e4e74 | ||
|
|
c202b4fa96 | ||
|
|
1df02d13d3 | ||
|
|
73cb6738b3 | ||
|
|
ba8672dfab | ||
|
|
a5e0bf3579 | ||
|
|
99ba99c74c | ||
|
|
469ff84e29 | ||
|
|
b5daf5300f | ||
|
|
f5aeb6ff9b | ||
|
|
4c74d44dab | ||
|
|
4a86fbcda0 | ||
|
|
bc267e0f57 | ||
|
|
fc05137846 | ||
|
|
c085ece623 | ||
|
|
91f625cee0 | ||
|
|
27b067f87b | ||
|
|
987a546756 | ||
|
|
4d30f17671 | ||
|
|
d48810ba5b | ||
|
|
819bfe4599 | ||
|
|
d2f6e19262 | ||
|
|
e889e0c43b | ||
|
|
6e0bf4d840 | ||
|
|
83a8ca7b14 | ||
|
|
100200d0d2 | ||
|
|
f28bf7f401 | ||
|
|
e0fd68f5ce | ||
|
|
cc12c488aa | ||
|
|
99c3e591b2 | ||
|
|
1aefb7ef73 | ||
|
|
d7b6774d82 | ||
|
|
d4c5cb2b01 | ||
|
|
df476bfcff | ||
|
|
aa0e6b9977 | ||
|
|
1ba6468f1b | ||
|
|
f490102454 | ||
|
|
18f3cb6957 | ||
|
|
7abcfd85b7 | ||
|
|
6de417d9d4 | ||
|
|
ffe8feb265 | ||
|
|
c9b62cf375 | ||
|
|
7bc595785e | ||
|
|
022dec7aba | ||
|
|
ddaef70ced | ||
|
|
2357a51e09 | ||
|
|
24ded29ff6 | ||
|
|
ddff23a7f9 | ||
|
|
53936ef935 | ||
|
|
7f9bf6b710 | ||
|
|
cfdb27b0c1 | ||
|
|
fc3ca11040 | ||
|
|
d6c9c3319b | ||
|
|
8afaef4219 | ||
|
|
11faa893ca | ||
|
|
600b56b316 | ||
|
|
ee39281d14 | ||
|
|
0607c30700 | ||
|
|
492ad04277 | ||
|
|
1ed9018e69 | ||
|
|
ff0e15804f | ||
|
|
894e6299c1 | ||
|
|
c080190365 | ||
|
|
26f0e56587 | ||
|
|
b4e6aac985 | ||
|
|
7c21776e54 | ||
|
|
d724dd186e | ||
|
|
cbbd8e2e8b | ||
|
|
af6241f7ad | ||
|
|
852e763b89 | ||
|
|
0f71592015 | ||
|
|
e63d3a29e2 | ||
|
|
38cef641a5 | ||
|
|
6226396c4a | ||
|
|
89b47d43de | ||
|
|
d1c06c2180 | ||
|
|
800a4485f3 | ||
|
|
fede378577 | ||
|
|
3bc207b9dd | ||
|
|
ebac031925 | ||
|
|
3cbe640d3c | ||
|
|
4cb6197b21 | ||
|
|
d3d07a5e86 | ||
|
|
62ca38262f | ||
|
|
d62fb8894f | ||
|
|
fc29efc38d | ||
|
|
c4c9bb944b | ||
|
|
236adddc18 | ||
|
|
5b3aa8028b | ||
|
|
16e24c2043 | ||
|
|
7869953bbf | ||
|
|
d07edfc895 | ||
|
|
85b057cccf | ||
|
|
a2c473bb59 | ||
|
|
f587061a5b | ||
|
|
d9e92804a5 | ||
|
|
46e858a631 | ||
|
|
e0fe5231c2 | ||
|
|
698bc16e87 | ||
|
|
7b4f48650c | ||
|
|
a43ff267e9 | ||
|
|
717d04669a | ||
|
|
15dbffc215 | ||
|
|
0099e42332 | ||
|
|
1ed56a05c2 | ||
|
|
28fb6365d0 | ||
|
|
8365126b8d | ||
|
|
d770837ec0 | ||
|
|
59658acfec | ||
|
|
46f800e8c7 | ||
|
|
1c65a93d03 | ||
|
|
cae7885e2f | ||
|
|
eaa28e654f | ||
|
|
beef86d0dd | ||
|
|
2fe1feea75 | ||
|
|
0b52f94da7 | ||
|
|
f96bac8468 | ||
|
|
8444a7c00d | ||
|
|
c9d3bc3fca | ||
|
|
8340aa9670 | ||
|
|
3e2c0024d5 | ||
|
|
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 | ||
|
|
732b391720 | ||
|
|
879b6ad05c | ||
|
|
f153c9c943 | ||
|
|
1b411143e5 | ||
|
|
9456434688 | ||
|
|
268da8167a | ||
|
|
2213961e8f | ||
|
|
d100e733db | ||
|
|
15e4d40184 | ||
|
|
f7a76b9c45 | ||
|
|
84e1a34eaa | ||
|
|
41979f2518 | ||
|
|
4b1553e2d4 | ||
|
|
e516b69ef6 | ||
|
|
7df593f21f | ||
|
|
cac80887a6 | ||
|
|
45a143cd51 | ||
|
|
0379c8eca1 | ||
|
|
c9b16cdaba | ||
|
|
77943e69aa | ||
|
|
d620219dc4 | ||
|
|
c0685c05f8 | ||
|
|
b7386d23d4 | ||
|
|
17a4977bef | ||
|
|
4f9b139ab9 | ||
|
|
9f802c7294 | ||
|
|
6e1fa33f67 | ||
|
|
4021aa455b | ||
|
|
6ec0f6977d | ||
|
|
8c702798f6 | ||
|
|
2ad3c71777 | ||
|
|
05bd302ab6 | ||
|
|
2b4d51f2e9 | ||
|
|
ee279980cc | ||
|
|
4e42173508 | ||
|
|
b58bfb2f20 | ||
|
|
6bb82fe0a8 | ||
|
|
c73f2a3831 | ||
|
|
b1eca24226 | ||
|
|
58b7b3d668 | ||
|
|
ce055e863d | ||
|
|
53ec55a88e | ||
|
|
2cce75453c | ||
|
|
93204ccae2 | ||
|
|
57d617192b | ||
|
|
ea118be593 | ||
|
|
6a85ee9623 | ||
|
|
5851ac2dfe | ||
|
|
e844a4a8a8 | ||
|
|
1d8638ce86 | ||
|
|
4c17cdcb64 | ||
|
|
c291d05759 | ||
|
|
9520ce4b65 | ||
|
|
0485b451ea | ||
|
|
4efa11680a | ||
|
|
2f39f112c1 | ||
|
|
0438c59fd0 | ||
|
|
1aa343e89c | ||
|
|
5ed353a881 | ||
|
|
c126e66ebd | ||
|
|
97bcf138be | ||
|
|
37ce167996 | ||
|
|
88a7426843 | ||
|
|
a1f7c8e250 | ||
|
|
52d9a554d1 | ||
|
|
aabb50d4e3 | ||
|
|
03646b4910 | ||
|
|
11b02d927f | ||
|
|
5cefa088e2 | ||
|
|
2e4e03f196 | ||
|
|
ea4e8cf8a1 | ||
|
|
95def6d957 | ||
|
|
9970bed4d9 | ||
|
|
494d049ce1 | ||
|
|
6a385e3b7e | ||
|
|
71456d301f | ||
|
|
dbd697b578 | ||
|
|
5ca70927be | ||
|
|
2e52ba36cb | ||
|
|
fd78520dca | ||
|
|
3f655ca08d | ||
|
|
76edd33498 | ||
|
|
e5f35681e6 | ||
|
|
32b9011ae9 | ||
|
|
fdad5aad3f | ||
|
|
90ac152deb | ||
|
|
e9df0a6242 | ||
|
|
4cf94b8a01 | ||
|
|
a6fa5bdef3 | ||
|
|
8f61dfdbd4 | ||
|
|
ddf8c2b0b2 | ||
|
|
44ae628c59 | ||
|
|
44a7ba4587 | ||
|
|
44c4492acf | ||
|
|
609e6dda6b | ||
|
|
3f30927214 | ||
|
|
ae11e4ee2d | ||
|
|
b61665d5b6 | ||
|
|
38943d29d3 | ||
|
|
ff0284ddc4 | ||
|
|
3f65576881 | ||
|
|
3caf40356d | ||
|
|
26bbb6aa4b | ||
|
|
bf66c2da14 | ||
|
|
65f6b6b0ef | ||
|
|
983f647c7e | ||
|
|
14dfad3873 | ||
|
|
215465713b | ||
|
|
6be5ac61bd | ||
|
|
90c71caeb3 | ||
|
|
d46b5646c6 |
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
|
||||
97
Makefile.in
97
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,27 @@ rsync$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): $(HEADERS)
|
||||
$(CHECK_OBJS): $(HEADERS)
|
||||
|
||||
flist.o: rounding.h
|
||||
|
||||
rounding.h: mkrounding$(EXEEXT)
|
||||
./mkrounding$(EXEEXT) >rounding.h
|
||||
|
||||
mkrounding$(EXEEXT): mkrounding.c rsync.h
|
||||
@sed '1,/^struct file_struct/d; /^}/,$$d' <$(srcdir)/rsync.h >mkrounding.h
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -I. $(srcdir)/mkrounding.c
|
||||
@rm mkrounding.h
|
||||
rounding.h: rounding.c rsync.h
|
||||
@for r in 0 1 3; do \
|
||||
if $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o rounding -DEXTRA_ROUNDING=$$r -I. $(srcdir)/rounding.c >rounding.out 2>&1; then \
|
||||
echo "#define EXTRA_ROUNDING $$r" >rounding.h; \
|
||||
if test -f "$$HOME/build_farm/build_test.fns"; then \
|
||||
echo "EXTRA_ROUNDING is $$r" >&2; \
|
||||
fi; \
|
||||
break; \
|
||||
fi; \
|
||||
done
|
||||
@rm -f rounding
|
||||
@if test -f rounding.h; then : ; else \
|
||||
cat rounding.out 1>&2; \
|
||||
echo "Failed to create rounding.h!" 1>&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
@rm -f rounding.out
|
||||
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
@@ -99,22 +111,59 @@ TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
|
||||
trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
|
||||
|
||||
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
|
||||
T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
|
||||
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
|
||||
|
||||
gen:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
|
||||
gen: conf proto.h man
|
||||
|
||||
man:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
|
||||
gensend: gen
|
||||
rsync -aivzc $(GENFILES) samba.org:/home/ftp/pub/rsync/generated-files/
|
||||
|
||||
proto:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
|
||||
conf:
|
||||
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
|
||||
|
||||
conf_stop: configure.sh config.h.in
|
||||
|
||||
configure.sh config.h.in: configure.in aclocal.m4
|
||||
autoconf -o configure.sh
|
||||
autoheader && touch config.h.in
|
||||
@echo 'Configure files changed -- perhaps run:'
|
||||
@echo ' make reconfigure'
|
||||
@exit 1
|
||||
|
||||
reconfigure: configure.sh
|
||||
./config.status --recheck
|
||||
./config.status
|
||||
|
||||
make_stop: Makefile
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
@./config.status
|
||||
@echo "Makefile updated -- rerun your make command."
|
||||
@exit 1
|
||||
|
||||
proto: proto.h-tstamp
|
||||
|
||||
proto.h: proto.h-tstamp
|
||||
@echo ' ' >/dev/null
|
||||
|
||||
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c
|
||||
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
|
||||
|
||||
man: rsync.1 rsyncd.conf.5
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 $(srcdir)/rsync.yo
|
||||
-$(srcdir)/tweak_manpage rsync.1
|
||||
|
||||
rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
|
||||
-$(srcdir)/tweak_manpage rsyncd.conf.5
|
||||
|
||||
clean: cleantests
|
||||
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
mkrounding mkrounding.h rounding.h
|
||||
rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
|
||||
rounding rounding.h
|
||||
|
||||
cleantests:
|
||||
rm -rf ./testtmp*
|
||||
@@ -124,12 +173,14 @@ cleantests:
|
||||
# the source directory.
|
||||
distclean: clean
|
||||
rm -f Makefile config.h config.status
|
||||
rm -f lib/dummy popt/dummy zlib/dummy
|
||||
rm -f $(srcdir)/Makefile $(srcdir)/config.h $(srcdir)/config.status
|
||||
|
||||
rm -f $(srcdir)/lib/dummy $(srcdir)/popt/dummy $(srcdir)/zlib/dummy
|
||||
rm -f config.cache config.log
|
||||
rm -f $(srcdir)/config.cache $(srcdir)/config.log
|
||||
|
||||
rm -f shconfig $(srcdir)/shconfig
|
||||
rm -f $(GENFILES)
|
||||
rm -rf autom4te.cache
|
||||
|
||||
# this target is really just for my use. It only works on a limited
|
||||
# range of machines and is used to produce a list of potentially
|
||||
@@ -160,7 +211,7 @@ check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
|
||||
check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
|
||||
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
|
||||
|
||||
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
|
||||
wildtest.o: wildtest.c lib/wildmatch.c rsync.h config.h
|
||||
wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
|
||||
|
||||
|
||||
287
NEWS
287
NEWS
@@ -1,223 +1,136 @@
|
||||
NEWS for rsync 3.0.0 (UNRELEASED)
|
||||
Protocol: 30 (changed)
|
||||
Changes since 2.6.9:
|
||||
NEWS for rsync 3.0.1 (UNRELEASED)
|
||||
Protocol: 30 (unchanged)
|
||||
Changes since 3.0.0:
|
||||
|
||||
NOTABLE CHANGE IN BEHAVIOR:
|
||||
NOTABLE CHANGES IN BEHAVIOR:
|
||||
|
||||
- The handling of implied directories when using --relative has changed
|
||||
to send them as directories (e.g. no implied dir is ever sent as a
|
||||
symlink). This avoids unexpected behavior and should not adversely
|
||||
affect most people. If you're one of those rare people who relied
|
||||
upon having an implied dir be duplicated as a symlink, either specify
|
||||
--keep-dirlinks or --no-implied-dirs.
|
||||
- Added the 'c'-flag to the itemizing of non-regular files so that the
|
||||
itemized output doesn't get hidden if there were no attribute changes,
|
||||
and also so that the itemizing of a --copy-links run will distinguish
|
||||
between copying an identical non-regular file and the creation of a
|
||||
revised version with a new value (e.g. a changed symlink referent, a
|
||||
new device number, etc.).
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fixed the output of -ii when combined with one of the --*-dest options:
|
||||
it now itemizes all the items, not just the changed ones.
|
||||
- Fixed a crash bug when a single-use rsync daemon (via remote shell) was
|
||||
run without specifying a --config=FILE option.
|
||||
|
||||
- Made the output of all file types consistent when using a --*-dest
|
||||
option. Prior versions used to output too many creation events for
|
||||
matching items.
|
||||
- Fixed a crash when backing up a directory that has a default ACL.
|
||||
|
||||
- The code that waits for a child pid now handles being interrupted by a
|
||||
signal. This fixes a problem with the pre-xfer exec function not being
|
||||
able to get the exit status from the script.
|
||||
- Fixed a bug in the handling of xattr values that could cause rsync to
|
||||
not think that a file's extended attributes are up-to-date.
|
||||
|
||||
- A negated filter rule (with a '!' modifier) no longer loses the negation
|
||||
when sending the filter rules to the remote rsync.
|
||||
- Fixed the working of --fake-super with --link-dest and --xattrs.
|
||||
|
||||
- Fixed a problem with the --out-format (aka --log-format) option %f: it
|
||||
would output superfluous directory information for a non-daemon rsync.
|
||||
- Fixed a hang when combining --dry-run with --remove-source-files.
|
||||
|
||||
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
|
||||
files (which includes local copies). Version 2.6.9 would complete the
|
||||
copy, but exit with an error when the receiver output its memory stats.
|
||||
- Fixed a bug with --iconv's handling of files that cannot be converted:
|
||||
a failed name can no longer cause a transfer failure.
|
||||
|
||||
- If --password-file is used on a non-daemon transfer, rsync now complains
|
||||
and exits. This should help users figure out that they can't use this
|
||||
option to control a remote shell's password prompt.
|
||||
- Fixed the building of the rounding.h file on systems that need custom
|
||||
CPPFLAGS to be used. Also improved the error reporting if the building
|
||||
of rounding.h fails.
|
||||
|
||||
- Make sure that directory permissions of a newly-created destination
|
||||
directory are handled right when --perms is left off.
|
||||
- Fixed the use of the --protect-args (-s) option when talking to a daemon.
|
||||
|
||||
- The itemized output of a newly-created destination directory is now
|
||||
output as a creation event, not a change event.
|
||||
- Fixed the --ignore-existing option's protection of files on the receiver
|
||||
that are non-regular files on the sender (e.g. if a symlink or a dir on
|
||||
the sender is trying to replace a file on the receiver). The reverse
|
||||
protection (protecting a dir/symlink/device from being replaced by a
|
||||
file) was already working.
|
||||
|
||||
- Improved --hard-link so that more corner cases are handled correctly
|
||||
when combined with options such as --link-dest and/or --ignore-existing.
|
||||
- Fixed an assert failure if --hard-links is combined with an option that
|
||||
can skip a file in a set of hard-linked files (i.e. --ignore-existing,
|
||||
--append, etc.), without skipping all the files in the set.
|
||||
|
||||
- The --append option no longer updates a file that has the same size.
|
||||
- Avoid setting the modify time on a directory that already has the right
|
||||
modify time set. This avoids tweaking the dir's ctime.
|
||||
|
||||
- Fixed a bug when combining --backup and --backup-dir with --inplace:
|
||||
any missing backup directories are now created.
|
||||
- Improved the daemon-exclude handling to do a better job of applying the
|
||||
exclude rules to path entries. It also sends the user an error just as
|
||||
if the files were actually missing (instead of silently ignoring the
|
||||
user's args), and avoids sending the user the filter-action messages
|
||||
for these non-user-initiated rules.
|
||||
|
||||
- Fixed a bug when using --backup and --inplace with --whole-file or
|
||||
--read-batch: backup files are actually created now.
|
||||
- Fixed some glitches with the dry-run code's missing-directory
|
||||
handling, including a problem when combined with --fuzzy.
|
||||
|
||||
- Starting up an extra copy of an rsync daemon does not delete the pidfile
|
||||
for the running daemon -- if the pidfile exists, the extra program will
|
||||
exit with an error.
|
||||
- Fixed some glitches with the skipped-directory handling.
|
||||
|
||||
- The daemon pidfile is checked and created sooner in the startup sequence.
|
||||
- Fixed the 'T'-flag itemizing of symlinks when --time isn't preserved.
|
||||
|
||||
- Fixed a glitch in the itemizing of permissions with the -E option.
|
||||
|
||||
- The --append option's restricting of transfers to those that add data no
|
||||
longer prevents the updating of non-content changes to otherwise up-to-
|
||||
date files (i.e. those with the same content but differing permissions,
|
||||
ownership, xattrs, etc.).
|
||||
|
||||
- Don't allow --fake-super to be specified with -XX (double --xattrs)
|
||||
because the options conflict. If a daemon has "fake super" enabled,
|
||||
it automatically downgrades a -XX request to -X.
|
||||
|
||||
- Fixed a couple bugs in the parsing of daemon-config excludes that could
|
||||
make a floating exclude rule get treated as matching an absolute path.
|
||||
|
||||
- A daemon doesn't try to auto-refuse the "iconv" option if iconv-support
|
||||
wasn't compiled in to the daemon (avoiding a warning in the logs).
|
||||
|
||||
- Fixed the inclusion of per-dir merge files from implied dirs.
|
||||
|
||||
- Fixed the support/rrsync script to work with the latest options that
|
||||
rsync sends (including its flag-specifying use of -e to the server).
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- A new incremental-recursion algorithm is now used when rsync is talking
|
||||
to another 3.x version. This starts the transfer going more quickly
|
||||
(before all the files have been found), and requires much less memory.
|
||||
See the --recursive option in the manpage for some restrictions.
|
||||
- Added the --old-dirs (--old-d) option to make it easier for a user to
|
||||
ask for file-listings with older rsync versions (this is easier than
|
||||
having to type "-r --exclude='/*/*'" manually).
|
||||
|
||||
- Saved memory in the non-incremental-recursion algorithm for typical
|
||||
option values (usually saving from 21-29 bytes per file).
|
||||
- When getting an error while asking an older rsync daemon for a file
|
||||
listing, rsync will try to notice if the error is a rejection of the
|
||||
--dirs (-d) option and let the user know how to work around the issue.
|
||||
|
||||
- The default --delete algorithm is now --delete-during when talking to a
|
||||
3.x rsync. This is a faster scan than using --delete-before (which is
|
||||
the default when talking to older rsync versions), and is compatible with
|
||||
the new incremental recursion mode.
|
||||
- Added a few more --no-OPTION overrides.
|
||||
|
||||
- Rsync now allows multiple remote-source args to be specified rather than
|
||||
having to rely on a special space-splitting side-effect of the remote-
|
||||
shell. Additional remote args must specify the same host or have an
|
||||
empty hostname, as seen here: :file1 ::module/file2. This means that
|
||||
local use of brace expansion now works: rsync -av host:path/{f1,f2} .
|
||||
- Improved the documentation of the --append option.
|
||||
|
||||
- Added the --delete-delay option, which is a more efficient way to delete
|
||||
files at the end of the transfer without needing a separate delete pass.
|
||||
|
||||
- Added the --acls (-A) option to preserve Access Control Lists. This is
|
||||
an improved version of the prior patch that was available, and it even
|
||||
supports OS X ACLs. (If you need to have backward compatibility with
|
||||
old, patched versions of rsync, apply the acls.diff file from the patches
|
||||
dir.)
|
||||
|
||||
- Added the --xattrs (-X) option to preserver extended attributes. This is
|
||||
an improved version of the prior patch that was available. (If you need
|
||||
to have backward compatibility with old, patched versions of rsync, apply
|
||||
the xattrs.diff file from the patches dir.)
|
||||
|
||||
- Added the --fake-super option that allows a non-super user to preserve
|
||||
all attributes of a file by using a special extended-attribute idiom.
|
||||
There is also an analogous "fake super" option for an rsync daemon.
|
||||
|
||||
- Added the --iconv option, which allows rsync to convert filenames from
|
||||
one character-set to another during the transfer. The default is to make
|
||||
this feature available as long as your system has iconv_open(). If
|
||||
compilation fails, specify --disable-iconv to configure, and then
|
||||
rebuild. If you want rsync to perform character-set conversions by
|
||||
default, you can specify --enable-iconv=CONVERT_STRING with the default
|
||||
value for the --iconv option that you wish to use. For example,
|
||||
--enable-iconv=. is a good choice. See the rsync manpage for an
|
||||
explanation of the --iconv option's settings.
|
||||
|
||||
- Added the --skip-compress=LIST option to override of the default list of
|
||||
file suffixes that will not be compressed when using --compress.
|
||||
|
||||
- The daemon's default for "dont compress" was extended to include:
|
||||
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
|
||||
The matching routine was also optimized to run more quickly.
|
||||
|
||||
- The --max-delete option now outputs a warning if it skipped any file
|
||||
deletions, including a count of how many deletions were skipped. (Older
|
||||
versions just silently stopped deleting things.)
|
||||
|
||||
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
|
||||
about extraneous files without deleting anything. If you're not sure
|
||||
what version the client is, you can use the less-obvious --max-delete=-1,
|
||||
as both old and new versions will treat that as the same request (though
|
||||
older versions don't warn).
|
||||
|
||||
- The --hard-link option now uses less memory on both the sending and
|
||||
receiving side for all protocol versions. For protocol 30, the use of a
|
||||
hashtable on the sending side allows us to more efficiently convey to the
|
||||
receiver what files are linked together. This reduces the amount of data
|
||||
sent over the socket by a considerable margin (rather than adding more
|
||||
data), and limits the in-memory storage of the device+inode information
|
||||
to just the sending side for the new protocol 30, or to the receiving
|
||||
side when speaking an older protocol (note that older rsync versions kept
|
||||
the device+inode information on both sides).
|
||||
|
||||
- The filter rules now support a perishable ("p") modifier that marks rules
|
||||
that should not have an effect in a directory that is being deleted. e.g.
|
||||
-f '-p .svn/' would only affect "live" .svn directories.
|
||||
|
||||
- If we get an error setting the time on a symlink, we don't complain about
|
||||
it anymore (since some operating systems don't support that, and it's not
|
||||
that important).
|
||||
|
||||
- Protocol 30 now uses MD5 checksums instead of MD4.
|
||||
|
||||
- If a daemon module's "path" value is not an absolute pathname, the code
|
||||
now makes it absolute internally (making it work properly).
|
||||
|
||||
- Changed the --append option to not checksum the existing data in the
|
||||
destination file, which speeds up file appending.
|
||||
|
||||
- Added the --append-verify option, which works like the older --append
|
||||
option (verifying the existing data in the destination file). For
|
||||
compatibility with older rsync versions, any use of --append that is
|
||||
talking protocol 29 or older will revert to the --append-verify method.
|
||||
|
||||
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
|
||||
that can be used to enhance the client side of a daemon connection.
|
||||
|
||||
- Added the --protect-args (-s) option, that tells rsync to send most of
|
||||
the command-line args at the start of the transfer rather than as args
|
||||
to the remote-shell command. This protects them from space-splitting,
|
||||
and only interprets basic wildcard special shell characters (*?[).
|
||||
|
||||
- Improved the dashes and double-quotes in the nroff manpage output.
|
||||
|
||||
- We now support a lot more --no-OPTION override options.
|
||||
- Improved the documentation of the filter/exclude/include daemon
|
||||
parameters.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- The file-list sorting algorithm now uses a sort that keeps any same-
|
||||
named items in the same order as they were specified. This allows
|
||||
rsync to always ensure that the first of the duplicates is the one
|
||||
that will be included in the copy. The new sort was also faster
|
||||
than the glibc version of qsort() and mergesort() in my testing.
|
||||
- Fixed a couple minor bugs in the included popt library (ones which I
|
||||
sent to the official popt project for inclusion in the 1.14 release).
|
||||
|
||||
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
|
||||
- Fixed a stat() call that should have been do_stat() so that the proper
|
||||
normal/64-bit stat() function gets called. (Was in an area that should
|
||||
not have caused problems, though.)
|
||||
|
||||
- Fixed a build problem with older (2.x) versions of gcc.
|
||||
|
||||
- Added some isType() functions that make dealing with signed characters
|
||||
easier without forcing variables via casts.
|
||||
|
||||
- Changed strcat/strcpy/sprintf function calls to use safer versions.
|
||||
|
||||
- Upgraded the included popt version to 1.10.2 and improved its use of
|
||||
string-handling functions.
|
||||
|
||||
- Added missing prototypes for compatibility functions from the lib dir.
|
||||
|
||||
- Configure determines if iconv() has a const arg, allowing us to avoid a
|
||||
compiler warning.
|
||||
|
||||
- Made the sending of some numbers more efficient for protocol 30.
|
||||
|
||||
- Make sure that a daemon process doesn't mind if the client was weird and
|
||||
omitted the --server option.
|
||||
|
||||
- Improved the use of "const" on pointers.
|
||||
|
||||
- Improved J.W.'s pool_alloc routines to add a way of freeing older
|
||||
sections of a pool's memory.
|
||||
- Changed the file-glob code to do a directory scan without using the
|
||||
"glob" and "glob.h". This lets us do the globbing with less memory
|
||||
churn, and also avoid adding daemon-excluded items to the returned
|
||||
args.
|
||||
|
||||
DEVELOPER RELATED:
|
||||
|
||||
- Rsync is now licensed under the GPLv3 or later.
|
||||
- The configure script tries to get the user's compiler to not warn about
|
||||
unused function parameters if the build is not including one or more of
|
||||
the ACL/xattrs/iconv features.
|
||||
|
||||
- When running the tests, we now put our per-test temp dirs into a sub-
|
||||
directory named testtmp (which is created, if missing). This allows
|
||||
someone to symlink the testtmp directory to another filesystem (which is
|
||||
useful if the build dir's filesystem does not support ACLs and xattrs,
|
||||
and another file system does).
|
||||
- The configure script now has better checks for figuring out if the
|
||||
included popt code should be used or not.
|
||||
|
||||
- Rsync now has a way of handling protocol-version changes during the
|
||||
development of a new protocol version. This exchange of sub-version
|
||||
info does not interfere with the {MIN,MAX}_PROTOCOL_VERSION checking
|
||||
in older versions (since we'd quickly exceed the MAX_PROTOCOL_VERSION
|
||||
if we incremented the main PROTOCOL_VERSION value for every minor
|
||||
change during development).
|
||||
- Fixed two testsuite glitches: avoid a failure if someone's "cd" command
|
||||
outputs the current directory when cd-ing to a relative path, and made
|
||||
the itemized test query how rsync was built to determine if it should
|
||||
expect hard-linked symlinks or not.
|
||||
|
||||
- Updated the testsuite to verify that various bug fixes remain fixed.
|
||||
|
||||
- The RPM spec file was updated to have: (1) comments for how to use the
|
||||
rsync-patch tar file, and (2) an /etc/xinetd.d/rsync file.
|
||||
|
||||
- Updated the build scripts to work with a revised FTP directory
|
||||
structure.
|
||||
|
||||
346
OLDNEWS
346
OLDNEWS
@@ -1,3 +1,346 @@
|
||||
NEWS for rsync 3.0.0 (1 Mar 2008)
|
||||
Protocol: 30 (changed)
|
||||
Changes since 2.6.9:
|
||||
|
||||
NOTABLE CHANGES IN BEHAVIOR:
|
||||
|
||||
- The handling of implied directories when using --relative has changed to
|
||||
send them as directories (e.g. no implied dir is ever sent as a symlink).
|
||||
This avoids unexpected behavior and should not adversely affect most
|
||||
people. If you're one of those rare individuals who relied upon having
|
||||
an implied dir be duplicated as a symlink, you should specify the
|
||||
transfer of the symlink and the transfer of the referent directory as
|
||||
separate args. (See also --keep-dirlinks and --no-implied-dirs.)
|
||||
Also, exclude rules no longer have a partial effect on implied dirs.
|
||||
|
||||
- Requesting a remote file-listing without specifying -r (--recursive) now
|
||||
sends the -d (--dirs) option to the remote rsync rather than sending -r
|
||||
along with an extra exclude of /*/*. If the remote rsync does not
|
||||
understand the -d option (i.e. it is 2.6.3 or older), you will need to
|
||||
either turn off -d (--no-d), or specify -r --exclude='/*/*' manually.
|
||||
|
||||
- In --dry-run mode, the last line of the verbose summary text is output
|
||||
with a "(DRY RUN)" suffix to help remind you that no updates were made.
|
||||
Similarly, --only-write-batch outputs "(BATCH ONLY)".
|
||||
|
||||
- A writable rsync daemon with "use chroot" disabled now defaults to a
|
||||
symlink-munging behavior designed to make symlinks safer while also
|
||||
allowing absolute symlinks to be stored and retrieved. This also has
|
||||
the effect of making symlinks unusable while they're in the daemon's
|
||||
hierarchy. See the daemon's "munge symlinks" parameter for details.
|
||||
|
||||
- Starting up an extra copy of an rsync daemon will not clobber the pidfile
|
||||
for the running daemon -- if the pidfile exists, the new daemon will exit
|
||||
with an error. This means that your wrapper script that starts the rsync
|
||||
daemon should be made to handle lock-breaking (if you want any automatic
|
||||
breaking of locks to be done).
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- A daemon with "use chroot = no" and excluded items listed in the daemon
|
||||
config file now properly checks an absolute-path arg specified for these
|
||||
options: --compare-dest, --link-dest, --copy-dest, --partial-dir,
|
||||
--backup-dir, --temp-dir, and --files-from.
|
||||
|
||||
- A daemon can now be told to disable all user- and group-name translation
|
||||
on a per-module basis. This avoids a potential problem with a writable
|
||||
daemon module that has "use chroot" enabled -- if precautions weren't
|
||||
taken, a user could try to add a missing library and get rsync to use
|
||||
it. This makes rsync safer by default, and more configurable when id-
|
||||
translation is not desired. See the daemon's "numeric ids" parameter
|
||||
for full details.
|
||||
|
||||
- A chroot daemon can now indicate which part of its path should affect the
|
||||
chroot call, and which part should become an inside-chroot path for the
|
||||
module. This allows you to have outside-the-transfer paths (such as for
|
||||
libraries) even when you enable chroot protection. The idiom used in the
|
||||
rsyncd.conf file is: path = /chroot/dirs/./dirs/inside
|
||||
|
||||
- If a file's data arrived successfully on the receiving side but the
|
||||
rename of the temporary file to the destination file failed AND the
|
||||
--remove-source-files (or the deprecated --remove-sent-files) option
|
||||
was specified, rsync no longer erroneously removes the associated
|
||||
source file.
|
||||
|
||||
- Fixed the output of -ii when combined with one of the --*-dest options:
|
||||
it now itemizes all the items, not just the changed ones.
|
||||
|
||||
- Made the output of all file types consistent when using a --*-dest
|
||||
option. Prior versions would output too many creation events for
|
||||
matching items.
|
||||
|
||||
- The code that waits for a child pid now handles being interrupted by a
|
||||
signal. This fixes a problem with the pre-xfer exec function not being
|
||||
able to get the exit status from the script.
|
||||
|
||||
- A negated filter rule (i.e. with a '!' modifier) no longer loses the
|
||||
negation when sending the filter rules to the remote rsync.
|
||||
|
||||
- Fixed a problem with the --out-format (aka --log-format) option %f: it
|
||||
no longer outputs superfluous directory info for a non-daemon rsync.
|
||||
|
||||
- Fixed a problem with -vv (double --verbose) and --stats when "pushing"
|
||||
files (which includes local copies). Version 2.6.9 would complete the
|
||||
copy, but exit with an error when the receiver output its memory stats.
|
||||
|
||||
- If --password-file is used on a non-daemon transfer, rsync now complains
|
||||
and exits. This should help users figure out that they can't use this
|
||||
option to control a remote shell's password prompt.
|
||||
|
||||
- Make sure that directory permissions of a newly-created destination
|
||||
directory are handled right when --perms is left off.
|
||||
|
||||
- The itemized output of a newly-created destination directory is now
|
||||
output as a creation event, not a change event.
|
||||
|
||||
- Improved --hard-link so that more corner cases are handled correctly
|
||||
when combined with options such as --link-dest and/or --ignore-existing.
|
||||
|
||||
- The --append option no longer updates a file that has the same size.
|
||||
|
||||
- Fixed a bug when combining --backup and --backup-dir with --inplace:
|
||||
any missing backup directories are now created.
|
||||
|
||||
- Fixed a bug when using --backup and --inplace with --whole-file or
|
||||
--read-batch: backup files are actually created now.
|
||||
|
||||
- The daemon pidfile is checked and created sooner in the startup sequence.
|
||||
|
||||
- If a daemon module's "path" value is not an absolute pathname, the code
|
||||
now makes it absolute internally (making it work properly).
|
||||
|
||||
- Ensure that a temporary file always has owner-write permission while we
|
||||
are writing to it. This avoids problems with some network filesystems
|
||||
when transfering read-only files.
|
||||
|
||||
- Any errors output about password-file reading no longer cause an error at
|
||||
the end of the run about a partial transfer.
|
||||
|
||||
- The --read-batch option for protocol 30 now ensures that several more
|
||||
options are set correctly for the current batch file: --iconv, --acls,
|
||||
--xattrs, --inplace, --append, and --append-verify.
|
||||
|
||||
- Using --only-write-batch to a daemon receiver now works properly (older
|
||||
versions would update some files while writing the batch).
|
||||
|
||||
- Avoid outputting a "file has vanished" message when the file is a broken
|
||||
symlink and --copy-unsafe-links or --copy-dirlinks is used (the code
|
||||
already handled this for --copy-links).
|
||||
|
||||
- Fixed the combination of --only-write-batch and --dry-run.
|
||||
|
||||
- Fixed rsync's ability to remove files that are not writable by the file's
|
||||
owner when rsync is running as the same user.
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- A new incremental-recursion algorithm is now used when rsync is talking
|
||||
to another 3.x version. This starts the transfer going more quickly
|
||||
(before all the files have been found), and requires much less memory.
|
||||
See the --recursive option in the manpage for some restrictions.
|
||||
|
||||
- Lowered memory use in the non-incremental-recursion algorithm for typical
|
||||
option values (usually saving from 21-29 bytes per file).
|
||||
|
||||
- The default --delete algorithm is now --delete-during when talking to a
|
||||
3.x rsync. This is a faster scan than using --delete-before (which is
|
||||
the default when talking to older rsync versions), and is compatible with
|
||||
the new incremental recursion mode.
|
||||
|
||||
- Rsync now allows multiple remote-source args to be specified rather than
|
||||
having to rely on a special space-splitting side-effect of the remote-
|
||||
shell. Additional remote args must specify the same host or an empty one
|
||||
(e.g. empty: :file1 or ::module/file2). For example, this means that
|
||||
local use of brace expansion now works: rsync -av host:dir/{f1,f2} .
|
||||
|
||||
- Added the --protect-args (-s) option, that tells rsync to send most of
|
||||
the command-line args at the start of the transfer rather than as args
|
||||
to the remote-shell command. This protects them from space-splitting,
|
||||
and only interprets basic wildcard special shell characters (*?[).
|
||||
|
||||
- Added the --delete-delay option, which is a more efficient way to delete
|
||||
files at the end of the transfer without needing a separate delete pass.
|
||||
|
||||
- Added the --acls (-A) option to preserve Access Control Lists. This is
|
||||
an improved version of the prior patch that was available, and it even
|
||||
supports OS X ACLs. If you need to have backward compatibility with old,
|
||||
ACL-patched versions of rsync, apply the acls.diff file from the patches
|
||||
dir.
|
||||
|
||||
- Added the --xattrs (-X) option to preserve extended attributes. This is
|
||||
an improved version of the prior patch that was available, and it even
|
||||
supports OS X xattrs (which includes their resource fork data). If you
|
||||
need to have backward compatibility with old, xattr-patched versions of
|
||||
rsync, apply the xattrs.diff file from the patches dir.
|
||||
|
||||
- Added the --fake-super option that allows a non-super user to preserve
|
||||
all attributes of a file by using a special extended-attribute idiom.
|
||||
It even supports the storing of foreign ACL data on your backup server.
|
||||
There is also an analogous "fake super" parameter for an rsync daemon.
|
||||
|
||||
- Added the --iconv option, which allows rsync to convert filenames from
|
||||
one character-set to another during the transfer. The default is to
|
||||
make this feature available as long as your system has iconv_open().
|
||||
If compilation fails, specify --disable-iconv to configure, and then
|
||||
rebuild. If you want rsync to perform character-set conversions by
|
||||
default, you can specify --enable-iconv=CONVERT_STRING with the default
|
||||
value for the --iconv option that you wish to use. For example,
|
||||
"--enable-iconv=." is a good choice. See the rsync manpage for an
|
||||
explanation of the --iconv option's settings.
|
||||
|
||||
- A new daemon config parameter, "charset", lets you control the character-
|
||||
set that is used during an --iconv transfer to/from a daemon module. You
|
||||
can also set your daemon to refuse "no-iconv" if you want to force the
|
||||
client to use an --iconv transfer (requiring an rsync 3.x client).
|
||||
|
||||
- Added the --skip-compress=LIST option to override the default list of
|
||||
file suffixes that will not be compressed when using --compress (-z).
|
||||
|
||||
- The daemon's default for "dont compress" was extended to include:
|
||||
*.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg
|
||||
The name-matching routine was also optimized to run more quickly.
|
||||
|
||||
- The --max-delete option now outputs a warning if it skipped any file
|
||||
deletions, including a count of how many deletions were skipped. (Older
|
||||
versions just silently stopped deleting things.)
|
||||
|
||||
- You may specify --max-delete=0 to a 3.0.0 client to request that it warn
|
||||
about extraneous files without deleting anything. If you're not sure
|
||||
what version the client is, you can use the less-obvious --max-delete=-1,
|
||||
as both old and new versions will treat that as the same request (though
|
||||
older versions don't warn).
|
||||
|
||||
- The --hard-link option now uses less memory on both the sending and
|
||||
receiving side for all protocol versions. For protocol 30, the use of a
|
||||
hashtable on the sending side allows us to more efficiently convey to the
|
||||
receiver what files are linked together. This reduces the amount of data
|
||||
sent over the socket by a considerable margin (rather than adding more
|
||||
data), and limits the in-memory storage of the device+inode information
|
||||
to just the sending side for the new protocol 30, or to the receiving
|
||||
side when speaking an older protocol (note that older rsync versions kept
|
||||
the device+inode information on both sides).
|
||||
|
||||
- The filter rules now support a perishable ("p") modifier that marks rules
|
||||
that should not have an effect in a directory that is being deleted. e.g.
|
||||
-f '-p .svn/' would only affect "live" .svn directories.
|
||||
|
||||
- Rsync checks all the alternate-destination args for validity (e.g.
|
||||
--link-dest). This lets the user know when they specified a directory
|
||||
that does not exist.
|
||||
|
||||
- If we get an ENOSYS error setting the time on a symlink, we don't
|
||||
complain about it anymore (for those systems that even support the
|
||||
setting of the modify-time on a symlink).
|
||||
|
||||
- Protocol 30 now uses MD5 checksums instead of MD4.
|
||||
|
||||
- Changed the --append option to not checksum the existing data in the
|
||||
destination file, which speeds up file appending.
|
||||
|
||||
- Added the --append-verify option, which works like the older --append
|
||||
option (verifying the existing data in the destination file). For
|
||||
compatibility with older rsync versions, any use of --append that is
|
||||
talking protocol 29 or older will revert to the --append-verify method.
|
||||
|
||||
- Added the --contimeout=SECONDS option that lets the user specify a
|
||||
connection timeout for rsync daemon access.
|
||||
|
||||
- Documented and extended the support for the RSYNC_CONNECT_PROG variable
|
||||
that can be used to enhance the client side of a daemon connection.
|
||||
|
||||
- Improved the dashes and double-quotes in the nroff manpage output.
|
||||
|
||||
- Rsync now supports a lot more --no-OPTION override options.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- The file-list sorting algorithm now uses a sort that keeps any same-
|
||||
named items in the same order as they were specified. This allows
|
||||
rsync to always ensure that the first of the duplicates is the one
|
||||
that will be included in the copy. The new sort is also faster
|
||||
than the glibc version of qsort() and mergesort().
|
||||
|
||||
- Rsync now supports the transfer of 64-bit timestamps (time_t values).
|
||||
|
||||
- Made the file-deletion code use a little less stack when recursing
|
||||
through a directory hierarchy of extraneous files.
|
||||
|
||||
- Fixed a build problem with older (2.x) versions of gcc.
|
||||
|
||||
- Added some isType() functions that make dealing with signed characters
|
||||
easier without forcing variables via casts.
|
||||
|
||||
- Changed strcat/strcpy/sprintf function calls to use safer versions.
|
||||
|
||||
- Upgraded the included popt version to 1.10.2 and improved its use of
|
||||
string-handling functions.
|
||||
|
||||
- Added missing prototypes for compatibility functions from the lib dir.
|
||||
|
||||
- Configure determines if iconv() has a const arg, allowing us to avoid a
|
||||
compiler warning.
|
||||
|
||||
- Made the sending of some numbers more efficient for protocol 30.
|
||||
|
||||
- Make sure that a daemon process doesn't mind if the client was weird and
|
||||
omitted the --server option.
|
||||
|
||||
- There are more internal logging categories available in protocol 30 than
|
||||
the age-old FINFO and FERROR, including FERROR_XFER and FWARN. These new
|
||||
categories allow some errors and warnings to go to stderr without causing
|
||||
an erroneous end-of-run warning about some files not being able to be
|
||||
transferred.
|
||||
|
||||
- Improved the use of "const" on pointers.
|
||||
|
||||
- Improved J.W.'s pool_alloc routines to add a way of incrementally freeing
|
||||
older sections of a pool's memory.
|
||||
|
||||
- The getaddrinfo.c compatibility code in the "lib" dir was replaced with
|
||||
some new code (derived from samba, derived from PostgreSQL) that has a
|
||||
better license than the old code.
|
||||
|
||||
DEVELOPER RELATED:
|
||||
|
||||
- Rsync is now licensed under the GPLv3 or later.
|
||||
|
||||
- Rsync is now being maintained in a "git" repository instead of CVS
|
||||
(though the old CVS repository still exists for historical access).
|
||||
Several maintenance scripts were updated to work with git.
|
||||
|
||||
- Generated files are no longer committed into the source repository. The
|
||||
autoconf and autoheader commands are now automatically run during the
|
||||
normal use of "configure" and "make". The latest dev versions of all
|
||||
generated files can also be copied from the samba.org web site (see the
|
||||
prepare-source script's fetch option).
|
||||
|
||||
- The "patches" directory of diff files is now built from branches in the
|
||||
rsync git repository (branch patch/FOO creates file patches/FOO.diff).
|
||||
This directory is now distributed in a separate separate tar file named
|
||||
rsync-patches-VERSION.tar.gz instead of the main rsync-VERSION.tar.gz.
|
||||
|
||||
- The proto.h file is now built using a simple perl script rather than a
|
||||
complex awk script, which proved to be more widely compatible.
|
||||
|
||||
- When running the tests, we now put our per-test temp dirs into a sub-
|
||||
directory named testtmp (which is created, if missing). This allows
|
||||
someone to symlink the testtmp directory to another filesystem (which is
|
||||
useful if the build dir's filesystem does not support ACLs and xattrs,
|
||||
but another filesystem does).
|
||||
|
||||
- Rsync now has a way of handling protocol-version changes during the
|
||||
development of a new protocol version. This causes any out-of-sync
|
||||
versions to speak an older protocol rather than fail in a cryptic manner.
|
||||
This addition makes it safer to deploy a pre-release version that may
|
||||
interact with the public. This new exchange of sub-version info does not
|
||||
interfere with the {MIN,MAX}_PROTOCOL_VERSION checking algorithm (which
|
||||
does not have enough range to allow the main protocol number to be
|
||||
incremented for every minor tweak in that happens during development).
|
||||
|
||||
- The csprotocol.txt file was updated to mention the daemon protocol change
|
||||
in the 3.0.0 release.
|
||||
|
||||
|
||||
NEWS for rsync 2.6.9 (6 Nov 2006)
|
||||
Protocol: 29 (unchanged)
|
||||
Changes since 2.6.8:
|
||||
@@ -2244,7 +2587,8 @@ 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.1 30
|
||||
01 Mar 2008 3.0.0 11 Nov 2006 30
|
||||
06 Nov 2006 2.6.9 29
|
||||
22 Apr 2006 2.6.8 29
|
||||
11 Mar 2006 2.6.7 29
|
||||
|
||||
2
access.c
2
access.c
@@ -2,7 +2,7 @@
|
||||
* Routines to authenticate access to a daemon (hosts allow/deny).
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
23
aclocal.m4
vendored
23
aclocal.m4
vendored
@@ -68,4 +68,25 @@ AC_DEFUN([TYPE_SOCKLEN_T],
|
||||
#include <sys/socket.h>])
|
||||
])
|
||||
|
||||
|
||||
dnl AC_HAVE_TYPE(TYPE,INCLUDES)
|
||||
AC_DEFUN([AC_HAVE_TYPE], [
|
||||
AC_REQUIRE([AC_HEADER_STDC])
|
||||
cv=`echo "$1" | sed 'y%./+- %__p__%'`
|
||||
AC_MSG_CHECKING(for $1)
|
||||
AC_CACHE_VAL([ac_cv_type_$cv],
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
AC_INCLUDES_DEFAULT
|
||||
$2]],
|
||||
[[$1 foo;]])],
|
||||
[eval "ac_cv_type_$cv=yes"],
|
||||
[eval "ac_cv_type_$cv=no"]))dnl
|
||||
ac_foo=`eval echo \\$ac_cv_type_$cv`
|
||||
AC_MSG_RESULT($ac_foo)
|
||||
if test "$ac_foo" = yes; then
|
||||
ac_tr_hdr=HAVE_`echo $1 | sed 'y%abcdefghijklmnopqrstuvwxyz./- %ABCDEFGHIJKLMNOPQRSTUVWXYZ____%'`
|
||||
if false; then
|
||||
AC_CHECK_TYPES($1)
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED($ac_tr_hdr, 1, [Define if you have type `$1'])
|
||||
fi
|
||||
])
|
||||
|
||||
64
acls.c
64
acls.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2006 Wayne Davison
|
||||
* Copyright (C) 2006-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -92,9 +92,19 @@ static item_list default_acl_list = EMPTY_ITEM_LIST;
|
||||
|
||||
static const char *str_acl_type(SMB_ACL_TYPE_T type)
|
||||
{
|
||||
return type == SMB_ACL_TYPE_ACCESS ? "SMB_ACL_TYPE_ACCESS"
|
||||
: type == SMB_ACL_TYPE_DEFAULT ? "SMB_ACL_TYPE_DEFAULT"
|
||||
: "unknown SMB_ACL_TYPE_T";
|
||||
switch (type) {
|
||||
case SMB_ACL_TYPE_ACCESS:
|
||||
#ifdef HAVE_OSX_ACLS
|
||||
return "ACL_TYPE_EXTENDED";
|
||||
#else
|
||||
return "ACL_TYPE_ACCESS";
|
||||
#endif
|
||||
case SMB_ACL_TYPE_DEFAULT:
|
||||
return "ACL_TYPE_DEFAULT";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown ACL type!";
|
||||
}
|
||||
|
||||
static int calc_sacl_entries(const rsync_acl *racl)
|
||||
@@ -300,7 +310,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
|
||||
ida->access = access;
|
||||
}
|
||||
if (rc) {
|
||||
rsyserr(FERROR, errno, "unpack_smb_acl: %s()", errfun);
|
||||
rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
|
||||
rsync_acl_free(racl);
|
||||
return False;
|
||||
}
|
||||
@@ -356,7 +366,7 @@ static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
|
||||
static int store_access_in_entry(uint32 access, SMB_ACL_ENTRY_T entry)
|
||||
{
|
||||
if (sys_acl_set_access_bits(entry, access)) {
|
||||
rsyserr(FERROR, errno, "store_access_in_entry sys_acl_set_access_bits()");
|
||||
rsyserr(FERROR_XFER, errno, "store_access_in_entry sys_acl_set_access_bits()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -375,7 +385,7 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
|
||||
SMB_ACL_ENTRY_T entry;
|
||||
|
||||
if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
|
||||
rsyserr(FERROR, errno, "pack_smb_acl: sys_acl_init()");
|
||||
rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
|
||||
return False;
|
||||
}
|
||||
|
||||
@@ -390,13 +400,10 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
|
||||
break;
|
||||
#endif
|
||||
COE( sys_acl_create_entry,(smb_acl, &entry) );
|
||||
COE( sys_acl_set_info,(entry,
|
||||
#ifdef SMB_ACL_NEED_SORT
|
||||
SMB_ACL_USER,
|
||||
#else
|
||||
ida->access & NAME_IS_USER ? SMB_ACL_USER : SMB_ACL_GROUP,
|
||||
#endif
|
||||
ida->access & ~NAME_IS_USER, ida->id) );
|
||||
COE( sys_acl_set_info,
|
||||
(entry,
|
||||
ida->access & NAME_IS_USER ? SMB_ACL_USER : SMB_ACL_GROUP,
|
||||
ida->access & ~NAME_IS_USER, ida->id) );
|
||||
}
|
||||
|
||||
#ifndef HAVE_OSX_ACLS
|
||||
@@ -427,14 +434,14 @@ static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (sys_acl_valid(*smb_acl) < 0)
|
||||
rprintf(FERROR, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
|
||||
rprintf(FERROR_XFER, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
|
||||
#endif
|
||||
|
||||
return True;
|
||||
|
||||
error_exit:
|
||||
if (errfun) {
|
||||
rsyserr(FERROR, errno, "pack_smb_acl %s()", errfun);
|
||||
rsyserr(FERROR_XFER, errno, "pack_smb_acl %s()", errfun);
|
||||
}
|
||||
sys_acl_free_acl(*smb_acl);
|
||||
return False;
|
||||
@@ -479,8 +486,10 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
if ((buf = get_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, &len)) == NULL)
|
||||
return 0;
|
||||
cnt = (len - 4*4) / (4+4);
|
||||
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4)
|
||||
if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
racl->user_obj = IVAL(buf, 0);
|
||||
racl->group_obj = IVAL(buf, 4);
|
||||
@@ -515,7 +524,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
|
||||
if (type == SMB_ACL_TYPE_ACCESS)
|
||||
rsync_acl_fake_perms(racl, mode);
|
||||
} else {
|
||||
rsyserr(FERROR, errno, "get_acl: sys_acl_get_file(%s, %s)",
|
||||
rsyserr(FERROR_XFER, errno, "get_acl: sys_acl_get_file(%s, %s)",
|
||||
fname, str_acl_type(type));
|
||||
return -1;
|
||||
}
|
||||
@@ -557,7 +566,7 @@ static void send_ida_entries(const ida_entries *idal, int f)
|
||||
|
||||
for (ida = idal->idas; count--; ida++) {
|
||||
uint32 xbits = ida->access << 2;
|
||||
char *name;
|
||||
const char *name;
|
||||
if (ida->access & NAME_IS_USER) {
|
||||
xbits |= XFLAG_NAME_IS_USER;
|
||||
name = add_uid(ida->id);
|
||||
@@ -656,7 +665,7 @@ static uint32 recv_acl_access(uchar *name_follows_ptr, int f)
|
||||
access |= NAME_IS_USER;
|
||||
} else if (am_root >= 0 && access & ~SMB_ACL_VALID_OBJ_BITS) {
|
||||
value_error:
|
||||
rprintf(FERROR, "recv_acl_access: value out of range: %x\n",
|
||||
rprintf(FERROR_XFER, "recv_acl_access: value out of range: %x\n",
|
||||
access);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
@@ -711,7 +720,7 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
|
||||
int ndx = read_varint(f);
|
||||
|
||||
if (ndx < 0 || (size_t)ndx > racl_list->count) {
|
||||
rprintf(FERROR, "recv_acl_index: %s ACL index %d > %d\n",
|
||||
rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
|
||||
str_acl_type(type), ndx, (int)racl_list->count);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
@@ -856,7 +865,7 @@ static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode
|
||||
if (rc) {
|
||||
error_exit:
|
||||
if (errfun) {
|
||||
rsyserr(FERROR, errno, "change_sacl_perms: %s()",
|
||||
rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
|
||||
errfun);
|
||||
}
|
||||
return (mode_t)~0;
|
||||
@@ -888,7 +897,7 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
|
||||
#endif
|
||||
rc = sys_acl_delete_def_file(fname);
|
||||
if (rc < 0) {
|
||||
rsyserr(FERROR, errno, "set_acl: sys_acl_delete_def_file(%s)",
|
||||
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
|
||||
fname);
|
||||
return -1;
|
||||
}
|
||||
@@ -933,8 +942,8 @@ static int set_rsync_acl(const char *fname, acl_duo *duo_item,
|
||||
}
|
||||
#endif
|
||||
if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
|
||||
rsyserr(FERROR, errno, "set_acl: sys_acl_set_file(%s, %s)",
|
||||
fname, str_acl_type(type));
|
||||
rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
|
||||
fname, str_acl_type(type));
|
||||
return -1;
|
||||
}
|
||||
if (type == SMB_ACL_TYPE_ACCESS)
|
||||
@@ -1053,7 +1062,8 @@ int default_perms_for_dir(const char *dir)
|
||||
}
|
||||
/* Otherwise fall through. */
|
||||
default:
|
||||
rprintf(FERROR, "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
|
||||
rprintf(FWARNING,
|
||||
"default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
|
||||
dir, str_acl_type(SMB_ACL_TYPE_DEFAULT), strerror(errno));
|
||||
}
|
||||
return perms;
|
||||
@@ -1064,7 +1074,7 @@ int default_perms_for_dir(const char *dir)
|
||||
ok = unpack_smb_acl(sacl, &racl);
|
||||
sys_acl_free_acl(sacl);
|
||||
if (!ok) {
|
||||
rprintf(FERROR, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
|
||||
rprintf(FWARNING, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
|
||||
return perms;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Support rsync daemon authentication.
|
||||
*
|
||||
* Copyright (C) 1998-2000 Andrew Tridgell
|
||||
* Copyright (C) 2002-2007 Wayne Davison
|
||||
* Copyright (C) 2002-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -163,34 +163,31 @@ static const char *getpassf(const char *filename)
|
||||
return NULL;
|
||||
|
||||
if ((fd = open(filename,O_RDONLY)) < 0) {
|
||||
rsyserr(FERROR, errno, "could not open password file \"%s\"",
|
||||
rsyserr(FWARNING, errno, "could not open password file \"%s\"",
|
||||
filename);
|
||||
if (envpw)
|
||||
rprintf(FERROR, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (do_stat(filename, &st) == -1) {
|
||||
rsyserr(FERROR, errno, "stat(%s)", filename);
|
||||
rsyserr(FWARNING, errno, "stat(%s)", filename);
|
||||
ok = 0;
|
||||
} else if ((st.st_mode & 06) != 0) {
|
||||
rprintf(FERROR,"password file must not be other-accessible\n");
|
||||
rprintf(FWARNING, "password file must not be other-accessible\n");
|
||||
ok = 0;
|
||||
} else if (MY_UID() == 0 && st.st_uid != 0) {
|
||||
rprintf(FERROR,"password file must be owned by root when running as root\n");
|
||||
rprintf(FWARNING, "password file must be owned by root when running as root\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (!ok) {
|
||||
rprintf(FERROR,"continuing without password file\n");
|
||||
if (envpw)
|
||||
rprintf(FERROR, "using RSYNC_PASSWORD environment variable.\n");
|
||||
close(fd);
|
||||
rprintf(FWARNING, "continuing without password file\n");
|
||||
if (envpw)
|
||||
rprintf(FINFO, "falling back to RSYNC_PASSWORD environment variable.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (envpw)
|
||||
rprintf(FERROR, "RSYNC_PASSWORD environment variable ignored\n");
|
||||
|
||||
n = read(fd, buffer, sizeof buffer - 1);
|
||||
close(fd);
|
||||
if (n > 0) {
|
||||
|
||||
2
backup.c
2
backup.c
@@ -2,7 +2,7 @@
|
||||
* Backup handling code.
|
||||
*
|
||||
* Copyright (C) 1999 Andrew Tridgell
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
78
batch.c
78
batch.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1999 Weiss
|
||||
* Copyright (C) 2004 Chris Shoemaker
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -31,15 +31,25 @@ extern int preserve_hard_links;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int always_checksum;
|
||||
extern int do_compression;
|
||||
extern int def_compress_level;
|
||||
extern int inplace;
|
||||
extern int append_mode;
|
||||
extern int protocol_version;
|
||||
extern char *batch_name;
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
#endif
|
||||
|
||||
extern struct filter_list_struct filter_list;
|
||||
|
||||
static int tweaked_compress_level;
|
||||
int batch_stream_flags;
|
||||
|
||||
static int tweaked_append;
|
||||
static int tweaked_append_verify;
|
||||
static int tweaked_iconv;
|
||||
|
||||
static int *flag_ptr[] = {
|
||||
&recurse, /* 0 */
|
||||
@@ -50,7 +60,13 @@ static int *flag_ptr[] = {
|
||||
&preserve_hard_links, /* 5 */
|
||||
&always_checksum, /* 6 */
|
||||
&xfer_dirs, /* 7 (protocol 29) */
|
||||
&tweaked_compress_level,/* 8 (protocol 29) */
|
||||
&do_compression, /* 8 (protocol 29) */
|
||||
&tweaked_iconv, /* 9 (protocol 30) */
|
||||
&preserve_acls, /* 10 (protocol 30) */
|
||||
&preserve_xattrs, /* 11 (protocol 30) */
|
||||
&inplace, /* 12 (protocol 30) */
|
||||
&tweaked_append, /* 13 (protocol 30) */
|
||||
&tweaked_append_verify, /* 14 (protocol 30) */
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -64,6 +80,12 @@ static char *flag_name[] = {
|
||||
"--checksum (-c)",
|
||||
"--dirs (-d)",
|
||||
"--compress (-z)",
|
||||
"--iconv",
|
||||
"--acls (-A)",
|
||||
"--xattrs (-X)",
|
||||
"--inplace",
|
||||
"--append",
|
||||
"--append-verify",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -71,16 +93,14 @@ void write_stream_flags(int fd)
|
||||
{
|
||||
int i, flags;
|
||||
|
||||
#if Z_DEFAULT_COMPRESSION == -1
|
||||
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
|
||||
#else
|
||||
#error internal logic error! Fix def_compress_level logic above and below too!
|
||||
tweaked_append = append_mode == 1;
|
||||
tweaked_append_verify = append_mode == 2;
|
||||
#ifdef ICONV_OPTION
|
||||
tweaked_iconv = iconv_opt != NULL;
|
||||
#endif
|
||||
|
||||
/* Start the batch file with a bitmap of data-stream-affecting
|
||||
* flags. */
|
||||
if (protocol_version < 29)
|
||||
flag_ptr[7] = NULL;
|
||||
for (i = 0, flags = 0; flag_ptr[i]; i++) {
|
||||
if (*flag_ptr[i])
|
||||
flags |= 1 << i;
|
||||
@@ -90,13 +110,31 @@ void write_stream_flags(int fd)
|
||||
|
||||
void read_stream_flags(int fd)
|
||||
{
|
||||
int i, flags;
|
||||
batch_stream_flags = read_int(fd);
|
||||
}
|
||||
|
||||
void check_batch_flags(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (protocol_version < 29)
|
||||
flag_ptr[7] = NULL;
|
||||
for (i = 0, flags = read_int(fd); flag_ptr[i]; i++) {
|
||||
int set = flags & (1 << i) ? 1 : 0;
|
||||
else if (protocol_version < 30)
|
||||
flag_ptr[9] = NULL;
|
||||
tweaked_append = append_mode == 1;
|
||||
tweaked_append_verify = append_mode == 2;
|
||||
#ifdef ICONV_OPTION
|
||||
tweaked_iconv = iconv_opt != NULL;
|
||||
#endif
|
||||
for (i = 0; flag_ptr[i]; i++) {
|
||||
int set = batch_stream_flags & (1 << i) ? 1 : 0;
|
||||
if (*flag_ptr[i] != set) {
|
||||
if (i == 9) {
|
||||
rprintf(FERROR,
|
||||
"%s specify the --iconv option to use this batch file.\n",
|
||||
set ? "Please" : "Do not");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (verbose) {
|
||||
rprintf(FINFO,
|
||||
"%sing the %s option to match the batchfile.\n",
|
||||
@@ -112,12 +150,10 @@ void read_stream_flags(int fd)
|
||||
xfer_dirs = 0;
|
||||
}
|
||||
|
||||
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
|
||||
do_compression = 0;
|
||||
else {
|
||||
do_compression = 1;
|
||||
def_compress_level = tweaked_compress_level - 2;
|
||||
}
|
||||
if (tweaked_append)
|
||||
append_mode = 1;
|
||||
else if (tweaked_append_verify)
|
||||
append_mode = 2;
|
||||
}
|
||||
|
||||
static void write_arg(int fd, char *arg)
|
||||
@@ -179,7 +215,7 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
if (fd < 0) {
|
||||
rsyserr(FERROR, errno, "Batch file %s open error",
|
||||
filename);
|
||||
exit_cleanup(1);
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
/* Write argvs info to BATCH.sh file */
|
||||
@@ -225,6 +261,6 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
|
||||
rsyserr(FERROR, errno, "Batch file %s write error",
|
||||
filename);
|
||||
exit_cleanup(1);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Simple byteorder handling.
|
||||
*
|
||||
* Copyright (C) 1992-1995 Andrew Tridgell
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
* Copyright (C) 2007-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
2
case_N.h
2
case_N.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* End-of-run cleanup helper code used by cleanup.c.
|
||||
*
|
||||
* Copyright (C) 2006-2007 Wayne Davison
|
||||
* Copyright (C) 2006-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
2
chmod.c
2
chmod.c
@@ -2,7 +2,7 @@
|
||||
* Implement the core of the --chmod option.
|
||||
*
|
||||
* Copyright (C) 2002 Scott Howard
|
||||
* Copyright (C) 2005-2007 Wayne Davison
|
||||
* Copyright (C) 2005-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
14
cleanup.c
14
cleanup.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,7 +26,7 @@ extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int io_error;
|
||||
extern int keep_partial;
|
||||
extern int log_got_error;
|
||||
extern int got_xfer_error;
|
||||
extern char *partial_dir;
|
||||
extern char *logfile_name;
|
||||
|
||||
@@ -78,8 +78,8 @@ void close_all(void)
|
||||
**/
|
||||
int cleanup_got_literal = 0;
|
||||
|
||||
static char *cleanup_fname;
|
||||
static char *cleanup_new_fname;
|
||||
static const char *cleanup_fname;
|
||||
static const char *cleanup_new_fname;
|
||||
static struct file_struct *cleanup_file;
|
||||
static int cleanup_fd_r, cleanup_fd_w;
|
||||
static pid_t cleanup_pid = 0;
|
||||
@@ -139,7 +139,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
|
||||
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
|
||||
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
|
||||
char *fname = cleanup_fname;
|
||||
const char *fname = cleanup_fname;
|
||||
cleanup_fname = NULL;
|
||||
if (cleanup_fd_r != -1)
|
||||
close(cleanup_fd_r);
|
||||
@@ -174,7 +174,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
|
||||
code = exit_code = RERR_DEL_LIMIT;
|
||||
if (io_error & IOERR_VANISHED)
|
||||
code = exit_code = RERR_VANISHED;
|
||||
if (io_error & IOERR_GENERAL || log_got_error)
|
||||
if (io_error & IOERR_GENERAL || got_xfer_error)
|
||||
code = exit_code = RERR_PARTIAL;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ void cleanup_disable(void)
|
||||
}
|
||||
|
||||
|
||||
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
|
||||
void cleanup_set(const char *fnametmp, const char *fname, struct file_struct *file,
|
||||
int fd_r, int fd_w)
|
||||
{
|
||||
cleanup_fname = fnametmp;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2007 Wayne Davison
|
||||
* Copyright (C) 2002-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -266,7 +266,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
|
||||
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
|
||||
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
|
||||
fn, ai->ai_addrlen);
|
||||
fn, (int)ai->ai_addrlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
251
clientserver.c
251
clientserver.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2007 Wayne Davison
|
||||
* Copyright (C) 2002-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,7 +22,9 @@
|
||||
#include "rsync.h"
|
||||
#include "ifuncs.h"
|
||||
|
||||
extern int quiet;
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int output_motd;
|
||||
extern int list_only;
|
||||
extern int am_sender;
|
||||
@@ -30,15 +32,19 @@ extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int am_root;
|
||||
extern int rsync_port;
|
||||
extern int protect_args;
|
||||
extern int ignore_errors;
|
||||
extern int preserve_xattrs;
|
||||
extern int kluge_around_eof;
|
||||
extern int daemon_over_rsh;
|
||||
extern int sanitize_paths;
|
||||
extern int numeric_ids;
|
||||
extern int filesfrom_fd;
|
||||
extern int remote_protocol;
|
||||
extern int protocol_version;
|
||||
extern int io_timeout;
|
||||
extern int no_detach;
|
||||
extern int write_batch;
|
||||
extern int default_af_hint;
|
||||
extern int logfile_format_has_i;
|
||||
extern int logfile_format_has_o_or_i;
|
||||
@@ -50,16 +56,22 @@ extern char *logfile_format;
|
||||
extern char *files_from;
|
||||
extern char *tmpdir;
|
||||
extern struct chmod_mode_struct *chmod_modes;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
extern struct filter_list_struct daemon_filter_list;
|
||||
extern char curr_dir[];
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
extern iconv_t ic_send, ic_recv;
|
||||
#endif
|
||||
|
||||
char *auth_user;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int munge_symlinks = 0;
|
||||
struct chmod_mode_struct *daemon_chmod_modes;
|
||||
|
||||
/* module_dirlen is the length of the module_dir string when in daemon
|
||||
* mode, not chrooted, and the path is not "/"; otherwise 0. */
|
||||
* mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
|
||||
* enabled module can have a non-"/" module_dir these days.) */
|
||||
char *module_dir = NULL;
|
||||
unsigned int module_dirlen = 0;
|
||||
|
||||
@@ -111,6 +123,10 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
|
||||
|
||||
set_socket_options(fd, sockopts);
|
||||
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
|
||||
ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
|
||||
|
||||
return ret ? ret : client_run(fd, fd, -1, argc, argv);
|
||||
@@ -192,21 +208,31 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int
|
||||
|
||||
int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int i, modlen;
|
||||
char line[BIGPATHBUFLEN];
|
||||
char *sargs[MAX_ARGS];
|
||||
int sargc = 0;
|
||||
char *p, *path = *argv;
|
||||
char *p, *modname;
|
||||
|
||||
if (argc == 0 && !am_sender)
|
||||
list_only |= 1;
|
||||
assert(argc > 0 && *argv != NULL);
|
||||
|
||||
if (*path == '/') {
|
||||
if (**argv == '/') {
|
||||
rprintf(FERROR,
|
||||
"ERROR: The remote path must start with a module name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(p = strchr(*argv, '/')))
|
||||
modlen = strlen(*argv);
|
||||
else
|
||||
modlen = p - *argv;
|
||||
|
||||
if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */
|
||||
out_of_memory("start_inband_exchange");
|
||||
strlcpy(modname, *argv, modlen + 1);
|
||||
modname[modlen] = '/';
|
||||
modname[modlen+1] = '\0';
|
||||
|
||||
if (!user)
|
||||
user = getenv("USER");
|
||||
if (!user)
|
||||
@@ -215,9 +241,6 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
if (exchange_protocols(f_in, f_out, line, sizeof line, 1) < 0)
|
||||
return -1;
|
||||
|
||||
if (list_only && protocol_version >= 29)
|
||||
list_only |= 2;
|
||||
|
||||
/* set daemon_over_rsh to false since we need to build the
|
||||
* true set of args passed through the rsh/ssh connection;
|
||||
* this is a no-op for direct-socket-connection mode */
|
||||
@@ -235,7 +258,12 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
sargs[sargc++] = *argv++;
|
||||
if (strncmp(*argv, modname, modlen) == 0
|
||||
&& argv[0][modlen] == '\0')
|
||||
sargs[sargc++] = modname; /* we send "modname/" */
|
||||
else
|
||||
sargs[sargc++] = *argv;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
@@ -244,10 +272,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
if (verbose > 1)
|
||||
print_child_argv("sending daemon args:", sargs);
|
||||
|
||||
p = strchr(path, '/');
|
||||
if (p) *p = '\0';
|
||||
io_printf(f_out, "%s\n", path);
|
||||
if (p) *p = '/';
|
||||
io_printf(f_out, "%.*s\n", modlen, modname);
|
||||
|
||||
/* Old servers may just drop the connection here,
|
||||
rather than sending a proper EXIT command. Yuck. */
|
||||
@@ -291,6 +316,8 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
|
||||
if (rl_nulls) {
|
||||
for (i = 0; i < sargc; i++) {
|
||||
if (!sargs[i]) /* stop at --protect-args NULL */
|
||||
break;
|
||||
write_sbuf(f_out, sargs[i]);
|
||||
write_byte(f_out, 0);
|
||||
}
|
||||
@@ -301,25 +328,38 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
write_sbuf(f_out, "\n");
|
||||
}
|
||||
|
||||
if (protect_args)
|
||||
send_protected_args(f_out, sargs);
|
||||
|
||||
if (protocol_version < 23) {
|
||||
if (protocol_version == 22 || !am_sender)
|
||||
io_start_multiplex_in();
|
||||
}
|
||||
|
||||
free(modname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *finish_pre_exec(pid_t pid, int fd, char *request,
|
||||
int argc, char *argv[])
|
||||
char **early_argv, char **argv)
|
||||
{
|
||||
int j, status = -1;
|
||||
int j = 0, status = -1;
|
||||
|
||||
if (!request)
|
||||
request = "(NONE)";
|
||||
|
||||
write_buf(fd, request, strlen(request)+1);
|
||||
for (j = 0; j < argc; j++)
|
||||
if (early_argv) {
|
||||
for ( ; *early_argv; early_argv++)
|
||||
write_buf(fd, *early_argv, strlen(*early_argv)+1);
|
||||
j = 1; /* Skip arg0 name in argv. */
|
||||
}
|
||||
for ( ; argv[j]; j++) {
|
||||
write_buf(fd, argv[j], strlen(argv[j])+1);
|
||||
if (argv[j][0] == '.' && argv[j][1] == '\0')
|
||||
break;
|
||||
}
|
||||
write_byte(fd, 0);
|
||||
|
||||
close(fd);
|
||||
@@ -341,8 +381,12 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
|
||||
char *bp = buf, *eob = buf + limit - 1;
|
||||
|
||||
while (1) {
|
||||
if (read(fd, bp, 1) != 1)
|
||||
int got = read(fd, bp, 1);
|
||||
if (got != 1) {
|
||||
if (got < 0 && errno == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
if (*bp == '\0')
|
||||
break;
|
||||
if (bp < eob)
|
||||
@@ -355,8 +399,8 @@ static int read_arg_from_pipe(int fd, char *buf, int limit)
|
||||
|
||||
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
{
|
||||
int argc, opt_cnt;
|
||||
char **argv;
|
||||
int argc;
|
||||
char **argv, **orig_argv, **orig_early_argv, *chroot_path = NULL;
|
||||
char line[BIGPATHBUFLEN];
|
||||
uid_t uid = (uid_t)-2; /* canonically "nobody" */
|
||||
gid_t gid = (gid_t)-2;
|
||||
@@ -367,6 +411,13 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
pid_t pre_exec_pid = 0;
|
||||
char *request = NULL;
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
iconv_opt = lp_charset(i);
|
||||
if (*iconv_opt)
|
||||
setup_iconv();
|
||||
iconv_opt = NULL;
|
||||
#endif
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
|
||||
name, host, addr);
|
||||
@@ -449,43 +500,57 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
/* TODO: Perhaps take a list of gids, and make them into the
|
||||
* supplementary groups. */
|
||||
|
||||
/* We do a push_dir() without actually calling chdir() in order
|
||||
* to make sure that the module's path is absolute. After this
|
||||
* check, module_dir will be set to an absolute path. */
|
||||
module_dir = lp_path(i);
|
||||
strlcpy(line, curr_dir, sizeof line);
|
||||
if (!push_dir(module_dir, 1))
|
||||
goto chdir_failed;
|
||||
if (strcmp(curr_dir, module_dir) != 0)
|
||||
module_dir = strdup(curr_dir);
|
||||
push_dir(line, 1); /* Restore curr_dir. */
|
||||
if (use_chroot) {
|
||||
if ((p = strstr(module_dir, "/./")) != NULL) {
|
||||
*p = '\0';
|
||||
p += 2;
|
||||
} else if ((p = strdup("/")) == NULL) /* MEMORY LEAK */
|
||||
out_of_memory("rsync_module");
|
||||
}
|
||||
|
||||
if (use_chroot || (module_dirlen = strlen(module_dir)) == 1) {
|
||||
/* We do a change_dir() that doesn't actually call chdir()
|
||||
* just to make a relative path absolute. */
|
||||
strlcpy(line, curr_dir, sizeof line);
|
||||
if (!change_dir(module_dir, CD_SKIP_CHDIR))
|
||||
goto chdir_failed;
|
||||
if (strcmp(curr_dir, module_dir) != 0
|
||||
&& (module_dir = strdup(curr_dir)) == NULL)
|
||||
out_of_memory("rsync_module");
|
||||
change_dir(line, CD_SKIP_CHDIR); /* Restore curr_dir. */
|
||||
|
||||
if (use_chroot) {
|
||||
chroot_path = module_dir;
|
||||
module_dir = p; /* p is "/" or our inside-chroot path */
|
||||
}
|
||||
module_dirlen = clean_fname(module_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
|
||||
|
||||
if (module_dirlen == 1) {
|
||||
module_dirlen = 0;
|
||||
set_filter_dir("/", 1);
|
||||
} else
|
||||
set_filter_dir(module_dir, module_dirlen);
|
||||
|
||||
p = lp_filter(i);
|
||||
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
|
||||
XFLG_ABS_IF_SLASH);
|
||||
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
|
||||
|
||||
p = lp_include_from(i);
|
||||
parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,
|
||||
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
|
||||
parse_filter_file(&daemon_filter_list, p, MATCHFLG_INCLUDE,
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
|
||||
|
||||
p = lp_include(i);
|
||||
parse_rule(&server_filter_list, p,
|
||||
parse_rule(&daemon_filter_list, p,
|
||||
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
|
||||
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
|
||||
|
||||
p = lp_exclude_from(i);
|
||||
parse_filter_file(&server_filter_list, p, 0,
|
||||
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
|
||||
parse_filter_file(&daemon_filter_list, p, 0,
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
|
||||
|
||||
p = lp_exclude(i);
|
||||
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
|
||||
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
|
||||
parse_rule(&daemon_filter_list, p, MATCHFLG_WORD_SPLIT,
|
||||
XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
|
||||
|
||||
log_init(1);
|
||||
|
||||
@@ -493,8 +558,17 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
|
||||
char *modname, *modpath, *hostaddr, *hostname, *username;
|
||||
int status;
|
||||
|
||||
if (!use_chroot)
|
||||
p = module_dir;
|
||||
else if (module_dirlen) {
|
||||
pathjoin(line, sizeof line, chroot_path, module_dir+1);
|
||||
p = line;
|
||||
} else
|
||||
p = chroot_path;
|
||||
|
||||
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
|
||||
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", module_dir) < 0
|
||||
|| asprintf(&modpath, "RSYNC_MODULE_PATH=%s", p) < 0
|
||||
|| asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
|
||||
|| asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
|
||||
|| asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
|
||||
@@ -594,15 +668,17 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
* a warning, unless a "require chroot" flag is set,
|
||||
* in which case we fail.
|
||||
*/
|
||||
if (chroot(module_dir)) {
|
||||
rsyserr(FLOG, errno, "chroot %s failed", module_dir);
|
||||
if (chroot(chroot_path)) {
|
||||
rsyserr(FLOG, errno, "chroot %s failed", chroot_path);
|
||||
io_printf(f_out, "@ERROR: chroot failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (!push_dir("/", 0))
|
||||
if (!change_dir(module_dir, CD_NORMAL))
|
||||
goto chdir_failed;
|
||||
if (module_dirlen)
|
||||
sanitize_paths = 1;
|
||||
} else {
|
||||
if (!push_dir(module_dir, 0)) {
|
||||
if (!change_dir(module_dir, CD_NORMAL)) {
|
||||
chdir_failed:
|
||||
rsyserr(FLOG, errno, "chdir %s failed\n", module_dir);
|
||||
io_printf(f_out, "@ERROR: chdir failed\n");
|
||||
@@ -611,6 +687,18 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
sanitize_paths = 1;
|
||||
}
|
||||
|
||||
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
|
||||
munge_symlinks = !use_chroot || module_dirlen;
|
||||
if (munge_symlinks) {
|
||||
STRUCT_STAT st;
|
||||
if (do_stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
|
||||
SYMLINK_PREFIX);
|
||||
io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
if (am_root) {
|
||||
/* XXXX: You could argue that if the daemon is started
|
||||
* by a non-root user and they explicitly specify a
|
||||
@@ -658,22 +746,40 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
|
||||
io_printf(f_out, "@RSYNCD: OK\n");
|
||||
|
||||
opt_cnt = read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
|
||||
read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
|
||||
orig_argv = argv;
|
||||
|
||||
verbose = 0; /* future verbosity is controlled by client options */
|
||||
ret = parse_arguments(&argc, (const char ***) &argv);
|
||||
if (protect_args && ret) {
|
||||
orig_early_argv = orig_argv;
|
||||
protect_args = 2;
|
||||
read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request);
|
||||
orig_argv = argv;
|
||||
ret = parse_arguments(&argc, (const char ***) &argv);
|
||||
} else
|
||||
orig_early_argv = NULL;
|
||||
|
||||
if (pre_exec_pid) {
|
||||
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
|
||||
opt_cnt, argv);
|
||||
orig_early_argv, orig_argv);
|
||||
}
|
||||
|
||||
verbose = 0; /* future verbosity is controlled by client options */
|
||||
ret = parse_arguments(&argc, (const char ***) &argv, 0);
|
||||
if (orig_early_argv)
|
||||
free(orig_early_argv);
|
||||
|
||||
am_server = 1; /* Don't let someone try to be tricky. */
|
||||
quiet = 0;
|
||||
if (lp_ignore_errors(module_id))
|
||||
ignore_errors = 1;
|
||||
if (write_batch < 0)
|
||||
dry_run = 1;
|
||||
|
||||
if (lp_fake_super(i))
|
||||
if (lp_fake_super(i)) {
|
||||
if (preserve_xattrs > 1)
|
||||
preserve_xattrs = 1;
|
||||
am_root = -1;
|
||||
else if (am_root < 0) /* Treat --fake-super from client as --super. */
|
||||
} else if (am_root < 0) /* Treat --fake-super from client as --super. */
|
||||
am_root = 2;
|
||||
|
||||
if (filesfrom_fd == 0)
|
||||
@@ -736,6 +842,23 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (!iconv_opt) {
|
||||
if (ic_send != (iconv_t)-1) {
|
||||
iconv_close(ic_send);
|
||||
ic_send = (iconv_t)-1;
|
||||
}
|
||||
if (ic_recv != (iconv_t)-1) {
|
||||
iconv_close(ic_recv);
|
||||
ic_recv = (iconv_t)-1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!numeric_ids
|
||||
&& (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
|
||||
numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
|
||||
|
||||
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
|
||||
set_io_timeout(lp_timeout(i));
|
||||
|
||||
@@ -773,6 +896,17 @@ static void send_listing(int fd)
|
||||
io_printf(fd,"@RSYNCD: EXIT\n");
|
||||
}
|
||||
|
||||
static int load_config(int globals_only)
|
||||
{
|
||||
if (!config_file) {
|
||||
if (am_server && am_root <= 0)
|
||||
config_file = RSYNCD_USERCONF;
|
||||
else
|
||||
config_file = RSYNCD_SYSCONF;
|
||||
}
|
||||
return lp_load(config_file, globals_only);
|
||||
}
|
||||
|
||||
/* this is called when a connection is established to a client
|
||||
and we want to start talking. The setup of the system is done from
|
||||
here */
|
||||
@@ -788,7 +922,7 @@ int start_daemon(int f_in, int f_out)
|
||||
* might cause log-file output to occur. This ensures that the
|
||||
* "log file" param gets honored for the 2 non-forked use-cases
|
||||
* (when rsync is run by init and run by a remote shell). */
|
||||
if (!lp_load(config_file, 0))
|
||||
if (!load_config(0))
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
|
||||
addr = client_addr(f_in);
|
||||
@@ -897,13 +1031,6 @@ static void become_daemon(void)
|
||||
|
||||
int daemon_main(void)
|
||||
{
|
||||
if (!config_file) {
|
||||
if (am_server && am_root <= 0)
|
||||
config_file = RSYNCD_USERCONF;
|
||||
else
|
||||
config_file = RSYNCD_SYSCONF;
|
||||
}
|
||||
|
||||
if (is_a_socket(STDIN_FILENO)) {
|
||||
int i;
|
||||
|
||||
@@ -918,7 +1045,7 @@ int daemon_main(void)
|
||||
return start_daemon(STDIN_FILENO, STDIN_FILENO);
|
||||
}
|
||||
|
||||
if (!lp_load(config_file, 1)) {
|
||||
if (!load_config(1)) {
|
||||
fprintf(stderr, "Failed to parse config file: %s\n", config_file);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
84
compat.c
84
compat.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) Andrew Tridgell 1996
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -48,25 +48,31 @@ extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int need_messages_from_generator;
|
||||
extern int delete_mode, delete_before, delete_during, delete_after;
|
||||
extern char *shell_cmd; /* contains VER.SUB string if client is a pre-release */
|
||||
extern char *shell_cmd;
|
||||
extern char *partial_dir;
|
||||
extern char *dest_option;
|
||||
extern char *files_from;
|
||||
extern char *filesfrom_host;
|
||||
extern struct filter_list_struct filter_list;
|
||||
extern int need_unsorted_flist;
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
extern iconv_t ic_send, ic_recv;
|
||||
#endif
|
||||
|
||||
/* These index values are for the file-list's extra-attribute array. */
|
||||
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx;
|
||||
#ifdef ICONV_OPTION
|
||||
int ic_ndx;
|
||||
int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
|
||||
|
||||
int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
int filesfrom_convert = 0;
|
||||
#endif
|
||||
|
||||
#define CF_INC_RECURSE (1<<0)
|
||||
#define CF_SYMLINK_TIMES (1<<1)
|
||||
|
||||
static const char *client_info;
|
||||
|
||||
/* The server makes sure that if either side only supports a pre-release
|
||||
* version of a protocol, that both sides must speak a compatible version
|
||||
* of that protocol for it to be advertised as available. */
|
||||
@@ -80,8 +86,9 @@ static void check_sub_protocol(void)
|
||||
int our_sub = 0;
|
||||
#endif
|
||||
|
||||
if (!shell_cmd || !(dot = strchr(shell_cmd, '.'))
|
||||
|| !(their_protocol = atoi(shell_cmd))
|
||||
/* client_info starts with VER.SUB string if client is a pre-release. */
|
||||
if (!(their_protocol = atoi(client_info))
|
||||
|| !(dot = strchr(client_info, '.'))
|
||||
|| !(their_sub = atoi(dot+1))) {
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
if (our_sub)
|
||||
@@ -102,6 +109,21 @@ static void check_sub_protocol(void)
|
||||
protocol_version--;
|
||||
}
|
||||
|
||||
void set_allow_inc_recurse(void)
|
||||
{
|
||||
client_info = shell_cmd ? shell_cmd : "";
|
||||
|
||||
if (!recurse || use_qsort)
|
||||
allow_inc_recurse = 0;
|
||||
else if (!am_sender
|
||||
&& (delete_before || delete_after
|
||||
|| delay_updates || prune_empty_dirs))
|
||||
allow_inc_recurse = 0;
|
||||
else if (am_server && !local_server
|
||||
&& (strchr(client_info, 'i') == NULL))
|
||||
allow_inc_recurse = 0;
|
||||
}
|
||||
|
||||
void setup_protocol(int f_out,int f_in)
|
||||
{
|
||||
if (am_sender)
|
||||
@@ -117,6 +139,9 @@ void setup_protocol(int f_out,int f_in)
|
||||
if (preserve_xattrs)
|
||||
xattrs_ndx = ++file_extra_cnt;
|
||||
|
||||
if (am_server)
|
||||
set_allow_inc_recurse();
|
||||
|
||||
if (remote_protocol == 0) {
|
||||
if (am_server && !local_server)
|
||||
check_sub_protocol();
|
||||
@@ -156,6 +181,8 @@ void setup_protocol(int f_out,int f_in)
|
||||
PROTOCOL_VERSION, am_server? "Server" : "Client");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (read_batch)
|
||||
check_batch_flags();
|
||||
|
||||
if (protocol_version < 30) {
|
||||
if (append_mode == 1)
|
||||
@@ -216,17 +243,42 @@ void setup_protocol(int f_out,int f_in)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
} else if (protocol_version >= 30) {
|
||||
if (recurse && allow_inc_recurse
|
||||
&& !delete_before && !delete_after && !delay_updates
|
||||
&& !use_qsort && !prune_empty_dirs)
|
||||
inc_recurse = 1;
|
||||
int compat_flags;
|
||||
if (am_server) {
|
||||
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
compat_flags |= CF_SYMLINK_TIMES;
|
||||
#endif
|
||||
write_byte(f_out, compat_flags);
|
||||
} else
|
||||
compat_flags = read_byte(f_in);
|
||||
/* The inc_recurse var MUST be set to 0 or 1. */
|
||||
inc_recurse = compat_flags & CF_INC_RECURSE ? 1 : 0;
|
||||
if (am_sender) {
|
||||
receiver_symlink_times = am_server
|
||||
? strchr(client_info, 'L') != NULL
|
||||
: !!(compat_flags & CF_SYMLINK_TIMES);
|
||||
}
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
else
|
||||
receiver_symlink_times = 1;
|
||||
#endif
|
||||
if (inc_recurse && !allow_inc_recurse) {
|
||||
/* This should only be able to happen in a batch. */
|
||||
fprintf(stderr,
|
||||
"Incompatible options specified for inc-recursive %s.\n",
|
||||
read_batch ? "batch file" : "connection");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
need_messages_from_generator = 1;
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
} else if (!am_sender) {
|
||||
receiver_symlink_times = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (iconv_opt && (!am_sender || inc_recurse))
|
||||
ic_ndx = ++file_extra_cnt;
|
||||
#endif
|
||||
if (need_unsorted_flist && (!am_sender || inc_recurse))
|
||||
unsort_ndx = ++file_extra_cnt;
|
||||
|
||||
if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
|
||||
int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
|
||||
|
||||
25
configure
vendored
Executable file
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" "${@}"
|
||||
94
configure.in
94
configure.in
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
RSYNC_VERSION=3.0.0pre1
|
||||
RSYNC_VERSION=3.0.1pre3
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -123,6 +123,11 @@ else
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
|
||||
AC_CHECK_PROG(HAVE_YODL2MAN, yodl2man, 1, 0)
|
||||
if test x$HAVE_YODL2MAN = x1; then
|
||||
MAKE_MAN=man
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(nobody-group,
|
||||
AC_HELP_STRING([--with-nobody-group=GROUP],
|
||||
[set the default unprivileged group (default nobody or nogroup)]),
|
||||
@@ -306,8 +311,10 @@ AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
|
||||
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
|
||||
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
|
||||
sys/un.h sys/attr.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
|
||||
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h \
|
||||
sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
|
||||
popt.h popt/popt.h)
|
||||
AC_HEADER_MAJOR
|
||||
|
||||
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
|
||||
@@ -353,10 +360,7 @@ AC_C_LONG_DOUBLE
|
||||
|
||||
AC_TYPE_SIGNAL
|
||||
AC_TYPE_UID_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_PID_T
|
||||
AC_CHECK_TYPES([mode_t,off_t,size_t,pid_t,id_t])
|
||||
AC_TYPE_GETGROUPS
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
|
||||
@@ -438,6 +442,10 @@ dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
|
||||
AC_CHECK_FUNCS(inet_pton, , [AC_LIBOBJ(lib/inet_pton)])
|
||||
|
||||
AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>])
|
||||
AC_HAVE_TYPE([struct sockaddr_storage], [#include <sys/types.h>
|
||||
#include <sys/socket.h>])
|
||||
|
||||
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
|
||||
# builtin getaddrinfo if one of the defines don't exist
|
||||
AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
|
||||
@@ -451,7 +459,7 @@ AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
|
||||
#endif],
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=yes,
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=no)])
|
||||
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
|
||||
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes" -a x"$ac_cv_type_struct_addrinfo" = x"yes"; then
|
||||
# Tru64 UNIX has getaddrinfo() but has it renamed in libc as
|
||||
# something else so we must include <netdb.h> to get the
|
||||
# redefinition.
|
||||
@@ -462,13 +470,11 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
|
||||
#include <netdb.h>],[getaddrinfo(NULL, NULL, NULL, NULL);],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_GETADDRINFO, 1,
|
||||
[Define to 1 if you have the "getaddrinfo" function.])],
|
||||
[Define to 1 if you have the "getaddrinfo" function and required types.])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ(lib/getaddrinfo)])])
|
||||
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
|
||||
else
|
||||
AC_LIBOBJ(lib/getaddrinfo)
|
||||
AC_LIBOBJ(lib/getnameinfo)
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
@@ -497,15 +503,6 @@ AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(struct sockaddr_storage)
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/socket.h>],
|
||||
[struct sockaddr_storage x;],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
|
||||
[Define to 1 if you have struct sockaddr_storage.] ),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
|
||||
[],
|
||||
@@ -515,8 +512,7 @@ AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(struct stat64)
|
||||
AC_TRY_COMPILE([#include <stdio.h>
|
||||
AC_HAVE_TYPE([struct stat64], [#include <stdio.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
@@ -531,10 +527,7 @@ AC_TRY_COMPILE([#include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
],[struct stat64 st;],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_STRUCT_STAT64,1,[Define to 1 if you have struct stat64.]),
|
||||
AC_MSG_RESULT(no))
|
||||
])
|
||||
|
||||
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
|
||||
#
|
||||
@@ -557,11 +550,16 @@ AC_FUNC_UTIME_NULL
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
|
||||
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
|
||||
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
|
||||
memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
|
||||
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
|
||||
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
|
||||
strerror putenv iconv_open locale_charset nl_langinfo getxattr \
|
||||
extattr_get_link sigaction sigprocmask)
|
||||
extattr_get_link sigaction sigprocmask setattrlist)
|
||||
|
||||
dnl cygwin iconv.h defines iconv_open as libiconv_open
|
||||
if test x"$ac_cv_func_iconv_open" != x"yes"; then
|
||||
AC_CHECK_FUNC(libiconv_open, [ac_cv_func_iconv_open=yes; AC_DEFINE(HAVE_ICONV_OPEN, 1)])
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
|
||||
if test $ac_cv_func_getpgrp = yes; then
|
||||
@@ -658,6 +656,15 @@ fi
|
||||
if test x"$with_included_popt" != x"yes"; then
|
||||
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
|
||||
fi
|
||||
if test x"$ac_cv_header_popt_popt_h" = x"yes"; then
|
||||
# If the system has /usr/include/popt/popt.h, we enable the
|
||||
# included popt because an attempt to "#include <popt/popt.h>"
|
||||
# would use our included header file anyway (due to -I.), and
|
||||
# might conflict with the system popt.
|
||||
with_included_popt=yes
|
||||
elif test x"$ac_cv_header_popt_h" != x"yes"; then
|
||||
with_included_popt=yes
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to use included libpopt])
|
||||
if test x"$with_included_popt" = x"yes"; then
|
||||
@@ -692,13 +699,13 @@ if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [Define to 1 if readdir() is broken])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
|
||||
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_STRUCT_UTIMBUF,[
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <utime.h>],
|
||||
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
|
||||
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no)])
|
||||
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
|
||||
rsync_cv_HAVE_STRUCT_UTIMBUF=yes,rsync_cv_HAVE_STRUCT_UTIMBUF=no)])
|
||||
if test x"$rsync_cv_HAVE_STRUCT_UTIMBUF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_STRUCT_UTIMBUF, 1, [Define to 1 if you have the "struct utimbuf" type])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
|
||||
@@ -827,8 +834,8 @@ AC_SUBST(OBJ_SAVE)
|
||||
AC_SUBST(OBJ_RESTORE)
|
||||
AC_SUBST(CC_SHOBJ_FLAG)
|
||||
AC_SUBST(BUILD_POPT)
|
||||
AC_SUBST(MAKE_MAN)
|
||||
|
||||
AC_CHECK_HEADERS(sys/acl.h acl/libacl.h)
|
||||
AC_CHECK_FUNCS(_acl __acl _facl __facl)
|
||||
#################################################
|
||||
# check for ACL support
|
||||
@@ -910,10 +917,6 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(attr/xattr.h)
|
||||
AC_CHECK_HEADERS(sys/xattr.h)
|
||||
AC_CHECK_HEADERS(sys/extattr.h)
|
||||
|
||||
#################################################
|
||||
# check for extended attribute support
|
||||
AC_MSG_CHECKING(whether to support extended attributes)
|
||||
@@ -955,6 +958,23 @@ else
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"$enable_iconv" = x"no"; then
|
||||
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wno-unused-parameter"
|
||||
AC_COMPILE_IFELSE([ ], [rsync_warn_flag=yes], [rsync_warn_flag=no])
|
||||
AC_MSG_RESULT([$rsync_warn_flag])
|
||||
if test x"$rsync_warn_flag" = x"no"; then
|
||||
CFLAGS="$OLD_CFLAGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$CC" in
|
||||
' checker'*|checker*)
|
||||
AC_DEFINE(FORCE_FD_ZERO_MEMSET, 1, [Used to make "checker" understand that FD_ZERO() clears memory.])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,7 @@
|
||||
* Error codes returned by rsync.
|
||||
*
|
||||
* Copyright (C) 1998-2000 Andrew Tridgell
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -45,6 +45,7 @@
|
||||
#define RERR_DEL_LIMIT 25 /* skipped some deletes due to --max-delete */
|
||||
|
||||
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
|
||||
#define RERR_CONTIMEOUT 35 /* timeout waiting for daemon connection */
|
||||
|
||||
/* Although it doesn't seem to be specified anywhere,
|
||||
* ssh and the shell seem to return these values:
|
||||
|
||||
122
exclude.c
122
exclude.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,8 +26,6 @@ extern int verbose;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int eol_nulls;
|
||||
extern int list_only;
|
||||
extern int recurse;
|
||||
extern int io_error;
|
||||
extern int local_server;
|
||||
extern int prune_empty_dirs;
|
||||
@@ -45,7 +43,7 @@ extern unsigned int module_dirlen;
|
||||
|
||||
struct filter_list_struct filter_list = { 0, 0, "" };
|
||||
struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" };
|
||||
struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
|
||||
struct filter_list_struct daemon_filter_list = { 0, 0, " [daemon]" };
|
||||
|
||||
/* Need room enough for ":MODS " prefix plus some room to grow. */
|
||||
#define MAX_RULE_PREFIX (16)
|
||||
@@ -54,6 +52,8 @@ struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
|
||||
#define MODIFIERS_INCL_EXCL "/!Crsp"
|
||||
#define MODIFIERS_HIDE_PROTECT "/!p"
|
||||
|
||||
#define SLASH_WILD3_SUFFIX "/***"
|
||||
|
||||
/* The dirbuf is set by push_local_filters() to the current subdirectory
|
||||
* relative to curr_dir that is being processed. The path always has a
|
||||
* trailing slash appended, and the variable dirbuf_len contains the length
|
||||
@@ -121,7 +121,7 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
|
||||
{
|
||||
struct filter_struct *ret;
|
||||
const char *cp;
|
||||
unsigned int ex_len;
|
||||
unsigned int pre_len, suf_len, slash_cnt = 0;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n",
|
||||
@@ -147,22 +147,51 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
|
||||
if (!(ret = new0(struct filter_struct)))
|
||||
out_of_memory("add_rule");
|
||||
|
||||
if (pat_len > 1 && pat[pat_len-1] == '/') {
|
||||
pat_len--;
|
||||
mflags |= MATCHFLG_DIRECTORY;
|
||||
}
|
||||
|
||||
for (cp = pat; cp < pat + pat_len; cp++) {
|
||||
if (*cp == '/')
|
||||
slash_cnt++;
|
||||
}
|
||||
|
||||
if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
|
||||
&& ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
|
||||
|| (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) {
|
||||
|| (xflags & XFLG_ABS_IF_SLASH && slash_cnt))) {
|
||||
mflags |= MATCHFLG_ABS_PATH;
|
||||
if (*pat == '/')
|
||||
ex_len = dirbuf_len - module_dirlen - 1;
|
||||
pre_len = dirbuf_len - module_dirlen - 1;
|
||||
else
|
||||
ex_len = 0;
|
||||
pre_len = 0;
|
||||
} else
|
||||
ex_len = 0;
|
||||
if (!(ret->pattern = new_array(char, ex_len + pat_len + 1)))
|
||||
pre_len = 0;
|
||||
|
||||
/* The daemon wants dir-exclude rules to get an appended "/" + "***". */
|
||||
if (xflags & XFLG_DIR2WILD3
|
||||
&& BITS_SETnUNSET(mflags, MATCHFLG_DIRECTORY, MATCHFLG_INCLUDE)) {
|
||||
mflags &= ~MATCHFLG_DIRECTORY;
|
||||
suf_len = sizeof SLASH_WILD3_SUFFIX - 1;
|
||||
} else
|
||||
suf_len = 0;
|
||||
|
||||
if (!(ret->pattern = new_array(char, pre_len + pat_len + suf_len + 1)))
|
||||
out_of_memory("add_rule");
|
||||
if (ex_len)
|
||||
memcpy(ret->pattern, dirbuf + module_dirlen, ex_len);
|
||||
strlcpy(ret->pattern + ex_len, pat, pat_len + 1);
|
||||
pat_len += ex_len;
|
||||
if (pre_len) {
|
||||
memcpy(ret->pattern, dirbuf + module_dirlen, pre_len);
|
||||
for (cp = ret->pattern; cp < ret->pattern + pre_len; cp++) {
|
||||
if (*cp == '/')
|
||||
slash_cnt++;
|
||||
}
|
||||
}
|
||||
strlcpy(ret->pattern + pre_len, pat, pat_len + 1);
|
||||
pat_len += pre_len;
|
||||
if (suf_len) {
|
||||
memcpy(ret->pattern + pat_len, SLASH_WILD3_SUFFIX, suf_len+1);
|
||||
pat_len += suf_len;
|
||||
slash_cnt++;
|
||||
}
|
||||
|
||||
if (strpbrk(ret->pattern, "*[?")) {
|
||||
mflags |= MATCHFLG_WILD;
|
||||
@@ -180,11 +209,6 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
|
||||
}
|
||||
}
|
||||
|
||||
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
|
||||
ret->pattern[pat_len-1] = 0;
|
||||
mflags |= MATCHFLG_DIRECTORY;
|
||||
}
|
||||
|
||||
if (mflags & MATCHFLG_PERDIR_MERGE) {
|
||||
struct filter_list_struct *lp;
|
||||
unsigned int len;
|
||||
@@ -228,10 +252,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
|
||||
out_of_memory("add_rule");
|
||||
}
|
||||
mergelist_parents[mergelist_cnt++] = ret;
|
||||
} else {
|
||||
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
|
||||
ret->u.slash_cnt++;
|
||||
}
|
||||
} else
|
||||
ret->u.slash_cnt = slash_cnt;
|
||||
|
||||
ret->match_flags = mflags;
|
||||
|
||||
@@ -297,7 +319,7 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
|
||||
strlcpy(to, merge_file, *len_ptr + 1);
|
||||
merge_file = to;
|
||||
}
|
||||
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
|
||||
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, SP_DEFAULT)) {
|
||||
rprintf(FERROR, "merge-file name overflows: %s\n",
|
||||
merge_file);
|
||||
return NULL;
|
||||
@@ -305,18 +327,19 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
|
||||
fn_len = strlen(fn);
|
||||
} else {
|
||||
strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
|
||||
fn_len = clean_fname(fn, 1);
|
||||
fn_len = clean_fname(fn, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
}
|
||||
|
||||
/* If the name isn't in buf yet, it's wasn't absolute. */
|
||||
if (fn != buf) {
|
||||
if (dirbuf_len + fn_len >= MAXPATHLEN) {
|
||||
int d_len = dirbuf_len - prefix_skip;
|
||||
if (d_len + fn_len >= MAXPATHLEN) {
|
||||
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
|
||||
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
|
||||
fn_len = clean_fname(buf, 1);
|
||||
memcpy(buf, dirbuf + prefix_skip, d_len);
|
||||
memcpy(buf + d_len, fn, fn_len + 1);
|
||||
fn_len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
}
|
||||
|
||||
if (len_ptr)
|
||||
@@ -338,7 +361,7 @@ void set_filter_dir(const char *dir, unsigned int dirlen)
|
||||
len = 0;
|
||||
memcpy(dirbuf + len, dir, dirlen);
|
||||
dirbuf[dirlen + len] = '\0';
|
||||
dirbuf_len = clean_fname(dirbuf, 1);
|
||||
dirbuf_len = clean_fname(dirbuf, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (dirbuf_len > 1 && dirbuf[dirbuf_len-1] == '.'
|
||||
&& dirbuf[dirbuf_len-2] == '/')
|
||||
dirbuf_len -= 2;
|
||||
@@ -374,7 +397,7 @@ static BOOL setup_merge_file(struct filter_struct *ex,
|
||||
else
|
||||
pathjoin(buf, MAXPATHLEN, dirbuf, x);
|
||||
|
||||
len = clean_fname(buf, 1);
|
||||
len = clean_fname(buf, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (len != 1 && len < MAXPATHLEN-1) {
|
||||
buf[len++] = '/';
|
||||
buf[len] = '\0';
|
||||
@@ -519,15 +542,14 @@ void change_local_filter_dir(const char *dname, int dlen, int dir_depth)
|
||||
filt_array[cur_depth] = push_local_filters(dname, dlen);
|
||||
}
|
||||
|
||||
static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
|
||||
static int rule_matches(const char *fname, struct filter_struct *ex, int name_is_dir)
|
||||
{
|
||||
int slash_handling, str_cnt = 0, anchored_match = 0;
|
||||
int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
|
||||
char *p, *pattern = ex->pattern;
|
||||
const char *strings[16]; /* more than enough */
|
||||
const char *name = fname + (*fname == '/');
|
||||
|
||||
if (*name == '/')
|
||||
name++;
|
||||
if (!*name)
|
||||
return 0;
|
||||
|
||||
@@ -537,13 +559,13 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
|
||||
* just match the name portion of the path. */
|
||||
if ((p = strrchr(name,'/')) != NULL)
|
||||
name = p+1;
|
||||
} else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
|
||||
} else if (ex->match_flags & MATCHFLG_ABS_PATH && *fname != '/'
|
||||
&& curr_dir_len > module_dirlen + 1) {
|
||||
/* If we're matching against an absolute-path pattern,
|
||||
* we need to prepend our full path info. */
|
||||
strings[str_cnt++] = curr_dir + module_dirlen + 1;
|
||||
strings[str_cnt++] = "/";
|
||||
} else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') {
|
||||
} else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *fname != '/') {
|
||||
/* Allow "**"+"/" to match at the start of the string. */
|
||||
strings[str_cnt++] = "/";
|
||||
}
|
||||
@@ -599,7 +621,7 @@ static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
|
||||
}
|
||||
|
||||
|
||||
static void report_filter_result(char const *name,
|
||||
static void report_filter_result(enum logcode code, char const *name,
|
||||
struct filter_struct const *ent,
|
||||
int name_is_dir, const char *type)
|
||||
{
|
||||
@@ -611,7 +633,7 @@ static void report_filter_result(char const *name,
|
||||
static char *actions[2][2]
|
||||
= { {"show", "hid"}, {"risk", "protect"} };
|
||||
const char *w = who_am_i();
|
||||
rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n",
|
||||
rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
|
||||
w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
|
||||
name_is_dir ? "directory" : "file", name, ent->pattern,
|
||||
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
|
||||
@@ -623,7 +645,8 @@ static void report_filter_result(char const *name,
|
||||
* Return -1 if file "name" is defined to be excluded by the specified
|
||||
* exclude list, 1 if it is included, and 0 if it was not matched.
|
||||
*/
|
||||
int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
|
||||
int check_filter(struct filter_list_struct *listp, enum logcode code,
|
||||
const char *name, int name_is_dir)
|
||||
{
|
||||
struct filter_struct *ent;
|
||||
|
||||
@@ -631,22 +654,22 @@ int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir)
|
||||
if (ignore_perishable && ent->match_flags & MATCHFLG_PERISHABLE)
|
||||
continue;
|
||||
if (ent->match_flags & MATCHFLG_PERDIR_MERGE) {
|
||||
int rc = check_filter(ent->u.mergelist, name,
|
||||
int rc = check_filter(ent->u.mergelist, code, name,
|
||||
name_is_dir);
|
||||
if (rc)
|
||||
return rc;
|
||||
continue;
|
||||
}
|
||||
if (ent->match_flags & MATCHFLG_CVS_IGNORE) {
|
||||
int rc = check_filter(&cvs_filter_list, name,
|
||||
int rc = check_filter(&cvs_filter_list, code, name,
|
||||
name_is_dir);
|
||||
if (rc)
|
||||
return rc;
|
||||
continue;
|
||||
}
|
||||
if (rule_matches(name, ent, name_is_dir)) {
|
||||
report_filter_result(name, ent, name_is_dir,
|
||||
listp->debug_type);
|
||||
report_filter_result(code, name, ent, name_is_dir,
|
||||
listp->debug_type);
|
||||
return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1;
|
||||
}
|
||||
}
|
||||
@@ -901,7 +924,7 @@ static char default_cvsignore[] =
|
||||
" *.a *.olb *.o *.obj *.so *.exe"
|
||||
" *.Z *.elc *.ln core"
|
||||
/* The rest we added to suit ourself. */
|
||||
" .svn/ .bzr/";
|
||||
" .svn/ .git/ .bzr/";
|
||||
|
||||
static void get_cvs_excludes(uint32 mflags)
|
||||
{
|
||||
@@ -1012,10 +1035,10 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
|
||||
return;
|
||||
|
||||
if (*fname != '-' || fname[1] || am_server) {
|
||||
if (server_filter_list.head) {
|
||||
if (daemon_filter_list.head) {
|
||||
strlcpy(line, fname, sizeof line);
|
||||
clean_fname(line, 1);
|
||||
if (check_filter(&server_filter_list, line, 0) < 0)
|
||||
clean_fname(line, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (check_filter(&daemon_filter_list, FLOG, line, 0) < 0)
|
||||
fp = NULL;
|
||||
else
|
||||
fp = fopen(line, "rb");
|
||||
@@ -1215,11 +1238,6 @@ void send_filter_list(int f_out)
|
||||
parse_rule(&filter_list, "-C", 0, 0);
|
||||
}
|
||||
|
||||
/* This is a complete hack - blame Rusty. FIXME!
|
||||
* Remove this hack when older rsyncs (below 2.6.4) are gone. */
|
||||
if (list_only == 1 && !recurse)
|
||||
parse_rule(&filter_list, "/*/*", MATCHFLG_NO_PREFIXES, 0);
|
||||
|
||||
send_rules(f_out, &filter_list);
|
||||
|
||||
if (f_out >= 0)
|
||||
|
||||
2
fileio.c
2
fileio.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
617
generator.c
617
generator.c
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
* `id -G` on Linux, but it's too hard to find a portable equivalent.
|
||||
*
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3 as
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Routines to provide a memory-efficient hashtable.
|
||||
*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
* Copyright (C) 2007-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,7 +24,7 @@
|
||||
struct hashtable *hashtable_create(int size, int key64)
|
||||
{
|
||||
struct hashtable *tbl;
|
||||
int node_size = key64 ? sizeof (struct ht_int64_node )
|
||||
int node_size = key64 ? sizeof (struct ht_int64_node)
|
||||
: sizeof (struct ht_int32_node);
|
||||
|
||||
/* Pick a power of 2 that can hold the requested size. */
|
||||
@@ -41,6 +41,7 @@ struct hashtable *hashtable_create(int size, int key64)
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
tbl->node_size = node_size;
|
||||
tbl->key64 = key64;
|
||||
|
||||
return tbl;
|
||||
}
|
||||
@@ -55,7 +56,7 @@ void hashtable_destroy(struct hashtable *tbl)
|
||||
* already existing. Returns NULL if not allocating and not found. */
|
||||
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
|
||||
{
|
||||
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
|
||||
int key64 = tbl->key64;
|
||||
struct ht_int32_node *node;
|
||||
uint32 ndx;
|
||||
|
||||
|
||||
160
hlink.c
160
hlink.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int list_only;
|
||||
extern int am_sender;
|
||||
extern int inc_recurse;
|
||||
extern int do_xfers;
|
||||
@@ -34,11 +35,9 @@ extern int protocol_version;
|
||||
extern int remove_source_files;
|
||||
extern int stdout_format_has_i;
|
||||
extern int maybe_ATTRS_REPORT;
|
||||
extern int unsort_ndx;
|
||||
extern char *basis_dir[];
|
||||
extern struct file_list *cur_flist;
|
||||
#ifdef ICONV_OPTION
|
||||
extern int ic_ndx;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
|
||||
@@ -126,12 +125,16 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
|
||||
prev = -1;
|
||||
} else if (CVAL(node->data, 0) == 0) {
|
||||
struct file_list *flist;
|
||||
struct file_struct *fp;
|
||||
prev = IVAL(node->data, 1);
|
||||
flist = flist_for_ndx(prev);
|
||||
assert(flist != NULL);
|
||||
fp = flist->files[prev - flist->ndx_start];
|
||||
fp->flags &= ~FLAG_HLINK_LAST;
|
||||
if (flist)
|
||||
flist->files[prev - flist->ndx_start]->flags &= ~FLAG_HLINK_LAST;
|
||||
else {
|
||||
/* We skipped all prior files in this
|
||||
* group, so mark this as a "first". */
|
||||
file->flags |= FLAG_HLINK_FIRST;
|
||||
prev = -1;
|
||||
}
|
||||
} else
|
||||
prev = -1;
|
||||
} else {
|
||||
@@ -144,12 +147,10 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
|
||||
if (gnum != gnum_next)
|
||||
break;
|
||||
F_HL_PREV(file) = prev;
|
||||
/* The linked list must use raw ndx values. */
|
||||
#ifdef ICONV_OPTION
|
||||
if (ic_ndx)
|
||||
/* The linked list uses over-the-wire ndx values. */
|
||||
if (unsort_ndx)
|
||||
prev = F_NDX(file);
|
||||
else
|
||||
#endif
|
||||
prev = ndx_list[from] + hlink_flist->ndx_start;
|
||||
}
|
||||
if (prev < 0 && !inc_recurse) {
|
||||
@@ -163,11 +164,9 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
|
||||
file->flags |= FLAG_HLINK_LAST;
|
||||
F_HL_PREV(file) = prev;
|
||||
if (inc_recurse && CVAL(node->data, 0) == 0) {
|
||||
#ifdef ICONV_OPTION
|
||||
if (ic_ndx)
|
||||
if (unsort_ndx)
|
||||
prev = F_NDX(file);
|
||||
else
|
||||
#endif
|
||||
prev = ndx_list[from] + hlink_flist->ndx_start;
|
||||
SIVAL(node->data, 1, prev);
|
||||
}
|
||||
@@ -180,23 +179,25 @@ static void match_gnums(int32 *ndx_list, int ndx_count)
|
||||
* to first when we're done. */
|
||||
void match_hard_links(struct file_list *flist)
|
||||
{
|
||||
int i, ndx_count = 0;
|
||||
int32 *ndx_list;
|
||||
if (!list_only) {
|
||||
int i, ndx_count = 0;
|
||||
int32 *ndx_list;
|
||||
|
||||
if (!(ndx_list = new_array(int32, flist->used)))
|
||||
out_of_memory("match_hard_links");
|
||||
if (!(ndx_list = new_array(int32, flist->used)))
|
||||
out_of_memory("match_hard_links");
|
||||
|
||||
for (i = 0; i < flist->used; i++) {
|
||||
if (F_IS_HLINKED(flist->sorted[i]))
|
||||
ndx_list[ndx_count++] = i;
|
||||
for (i = 0; i < flist->used; i++) {
|
||||
if (F_IS_HLINKED(flist->sorted[i]))
|
||||
ndx_list[ndx_count++] = i;
|
||||
}
|
||||
|
||||
hlink_flist = flist;
|
||||
|
||||
if (ndx_count)
|
||||
match_gnums(ndx_list, ndx_count);
|
||||
|
||||
free(ndx_list);
|
||||
}
|
||||
|
||||
hlink_flist = flist;
|
||||
|
||||
if (ndx_count)
|
||||
match_gnums(ndx_list, ndx_count);
|
||||
|
||||
free(ndx_list);
|
||||
if (protocol_version < 30)
|
||||
idev_destroy();
|
||||
}
|
||||
@@ -223,7 +224,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
|
||||
if (!make_backup(fname))
|
||||
return -1;
|
||||
} else if (robust_unlink(fname)) {
|
||||
rsyserr(FERROR, errno, "unlink %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "unlink %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
@@ -243,21 +244,42 @@ static int maybe_hard_link(struct file_struct *file, int ndx,
|
||||
}
|
||||
|
||||
/* Figure out if a prior entry is still there or if we just have a
|
||||
* cached name for it. Never called with a FLAG_HLINK_FIRST entry. */
|
||||
static char *check_prior(int prev_ndx, int gnum, struct file_list **flist_p)
|
||||
* cached name for it. */
|
||||
static char *check_prior(struct file_struct *file, int gnum,
|
||||
int *prev_ndx_p, struct file_list **flist_p)
|
||||
{
|
||||
struct file_list *flist = flist_for_ndx(prev_ndx);
|
||||
struct file_struct *fp;
|
||||
struct ht_int32_node *node;
|
||||
int prev_ndx = F_HL_PREV(file);
|
||||
|
||||
if (flist) {
|
||||
*flist_p = flist;
|
||||
return NULL;
|
||||
while (1) {
|
||||
struct file_list *flist;
|
||||
if (prev_ndx < 0
|
||||
|| (flist = flist_for_ndx(prev_ndx)) == NULL)
|
||||
break;
|
||||
fp = flist->files[prev_ndx - flist->ndx_start];
|
||||
if (!(fp->flags & FLAG_SKIP_HLINK)) {
|
||||
*prev_ndx_p = prev_ndx;
|
||||
*flist_p = flist;
|
||||
return NULL;
|
||||
}
|
||||
F_HL_PREV(file) = prev_ndx = F_HL_PREV(fp);
|
||||
}
|
||||
|
||||
node = hashtable_find(prior_hlinks, gnum, 0);
|
||||
assert(node != NULL && node->data);
|
||||
assert(CVAL(node->data, 0) != 0);
|
||||
return node->data;
|
||||
if ((node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
|
||||
assert(node->data != NULL);
|
||||
if (CVAL(node->data, 0) != 0) {
|
||||
*prev_ndx_p = -1;
|
||||
*flist_p = NULL;
|
||||
return node->data;
|
||||
}
|
||||
/* The prior file must have been skipped. */
|
||||
F_HL_PREV(file) = -1;
|
||||
}
|
||||
|
||||
*prev_ndx_p = -1;
|
||||
*flist_p = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns:
|
||||
@@ -271,20 +293,28 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|
||||
char *realname, *prev_name;
|
||||
struct file_list *flist;
|
||||
int gnum = inc_recurse ? F_HL_GNUM(file) : -1;
|
||||
int prev_ndx = F_HL_PREV(file);
|
||||
int prev_ndx;
|
||||
|
||||
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
|
||||
prev_name = realname = check_prior(file, gnum, &prev_ndx, &flist);
|
||||
|
||||
if (!prev_name) {
|
||||
struct file_struct *prev_file = flist->files[prev_ndx - flist->ndx_start];
|
||||
struct file_struct *prev_file;
|
||||
|
||||
/* Is the previous link is not complete yet? */
|
||||
if (!flist) {
|
||||
/* The previous file was skipped, so this one is
|
||||
* treated as if it were the first in its group. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
prev_file = flist->files[prev_ndx - flist->ndx_start];
|
||||
|
||||
/* Is the previous link not complete yet? */
|
||||
if (!(prev_file->flags & FLAG_HLINK_DONE)) {
|
||||
/* Is the previous link being transferred? */
|
||||
if (prev_file->flags & FLAG_FILE_SENT) {
|
||||
/* Add ourselves to the list of files that will be
|
||||
* updated when the transfer completes, and mark
|
||||
* ourself as waiting for the transfer. */
|
||||
/* Add ourselves to the list of files that will
|
||||
* be updated when the transfer completes, and
|
||||
* mark ourself as waiting for the transfer. */
|
||||
F_HL_PREV(file) = F_HL_PREV(prev_file);
|
||||
F_HL_PREV(prev_file) = ndx;
|
||||
file->flags |= FLAG_FILE_SENT;
|
||||
@@ -297,8 +327,8 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|
||||
/* There is a finished file to link with! */
|
||||
if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
|
||||
/* The previous previous is FIRST when prev is not. */
|
||||
prev_ndx = F_HL_PREV(prev_file);
|
||||
prev_name = realname = check_prior(prev_ndx, gnum, &flist);
|
||||
prev_name = realname = check_prior(prev_file, gnum, &prev_ndx, &flist);
|
||||
assert(prev_name != NULL || flist != NULL);
|
||||
/* Update our previous pointer to point to the FIRST. */
|
||||
F_HL_PREV(file) = prev_ndx;
|
||||
}
|
||||
@@ -323,7 +353,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|
||||
}
|
||||
|
||||
if (link_stat(prev_name, &prev_st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "stat %s failed",
|
||||
full_fname(prev_name));
|
||||
return -1;
|
||||
}
|
||||
@@ -345,7 +375,8 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
|
||||
|| prev_st.st_ino != alt_sx.st.st_ino)
|
||||
continue;
|
||||
statret = 1;
|
||||
if (verbose < 2 || !stdout_format_has_i) {
|
||||
if (stdout_format_has_i == 0
|
||||
|| (verbose < 2 && stdout_format_has_i < 2)) {
|
||||
itemizing = 0;
|
||||
code = FNONE;
|
||||
if (verbose > 1 && maybe_ATTRS_REPORT)
|
||||
@@ -395,10 +426,10 @@ int hard_link_one(struct file_struct *file, const char *fname,
|
||||
enum logcode code;
|
||||
if (terse) {
|
||||
if (!verbose)
|
||||
return -1;
|
||||
return 0;
|
||||
code = FINFO;
|
||||
} else
|
||||
code = FERROR;
|
||||
code = FERROR_XFER;
|
||||
rsyserr(code, errno, "link %s => %s failed",
|
||||
full_fname(fname), oldname);
|
||||
return 0;
|
||||
@@ -422,7 +453,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
|
||||
if (stp == NULL && prev_ndx >= 0) {
|
||||
if (link_stat(fname, &st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return;
|
||||
}
|
||||
@@ -476,4 +507,25 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
|
||||
out_of_memory("finish_hard_link");
|
||||
}
|
||||
}
|
||||
|
||||
int skip_hard_link(struct file_struct *file, struct file_list **flist_p)
|
||||
{
|
||||
struct file_list *flist;
|
||||
int prev_ndx;
|
||||
|
||||
file->flags |= FLAG_SKIP_HLINK;
|
||||
if (!(file->flags & FLAG_HLINK_LAST))
|
||||
return -1;
|
||||
|
||||
check_prior(file, F_HL_GNUM(file), &prev_ndx, &flist);
|
||||
if (prev_ndx >= 0) {
|
||||
file = flist->files[prev_ndx - flist->ndx_start];
|
||||
if (file->flags & (FLAG_HLINK_DONE|FLAG_FILE_SENT))
|
||||
return -1;
|
||||
file->flags |= FLAG_HLINK_LAST;
|
||||
*flist_p = flist;
|
||||
}
|
||||
|
||||
return prev_ndx;
|
||||
}
|
||||
#endif
|
||||
|
||||
12
ifuncs.h
12
ifuncs.h
@@ -1,6 +1,6 @@
|
||||
/* Inline functions for rsync.
|
||||
*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
* Copyright (C) 2007-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -57,6 +57,16 @@ from_wire_mode(int mode)
|
||||
return mode;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
d_name(struct dirent *di)
|
||||
{
|
||||
#ifdef HAVE_BROKEN_READDIR
|
||||
return (di->d_name - 2);
|
||||
#else
|
||||
return di->d_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int
|
||||
isDigit(const char *ptr)
|
||||
{
|
||||
|
||||
149
io.c
149
io.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -45,6 +45,7 @@ extern int inc_recurse;
|
||||
extern int io_error;
|
||||
extern int eol_nulls;
|
||||
extern int flist_eof;
|
||||
extern int list_only;
|
||||
extern int read_batch;
|
||||
extern int csum_length;
|
||||
extern int protect_args;
|
||||
@@ -100,10 +101,11 @@ static char ff_lastchar;
|
||||
#ifdef ICONV_OPTION
|
||||
static xbuf iconv_buf = EMPTY_XBUF;
|
||||
#endif
|
||||
static int defer_forwarding_messages = 0;
|
||||
static int defer_forwarding_messages = 0, defer_forwarding_keep = 0;
|
||||
static int select_timeout = SELECT_TIMEOUT;
|
||||
static int active_filecnt = 0;
|
||||
static OFF_T active_bytecnt = 0;
|
||||
static int first_message = 1;
|
||||
|
||||
static char int_byte_extra[64] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* (00 - 3F)/4 */
|
||||
@@ -112,6 +114,9 @@ static char int_byte_extra[64] = {
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, /* (C0 - FF)/4 */
|
||||
};
|
||||
|
||||
#define REMOTE_OPTION_ERROR "rsync: on remote machine: -"
|
||||
#define REMOTE_OPTION_ERROR2 ": unknown option"
|
||||
|
||||
enum festatus { FES_SUCCESS, FES_REDO, FES_NO_SEND };
|
||||
|
||||
static void readfd(int fd, char *buffer, size_t N);
|
||||
@@ -181,7 +186,6 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
|
||||
struct file_list *flist = flist_for_ndx(ndx);
|
||||
|
||||
assert(flist != NULL);
|
||||
assert(ndx >= flist->ndx_start);
|
||||
|
||||
if (remove_source_files) {
|
||||
active_filecnt--;
|
||||
@@ -197,8 +201,10 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
|
||||
send_msg(MSG_SUCCESS, buf, 4, 0);
|
||||
if (preserve_hard_links) {
|
||||
struct file_struct *file = flist->files[ndx - flist->ndx_start];
|
||||
if (F_IS_HLINKED(file))
|
||||
if (F_IS_HLINKED(file)) {
|
||||
flist_ndx_push(&hlink_list, ndx);
|
||||
flist->in_progress++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FES_REDO:
|
||||
@@ -320,6 +326,36 @@ static void msg_flush(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void check_for_d_option_error(const char *msg)
|
||||
{
|
||||
static char rsync263_opts[] = "BCDHIKLPRSTWabceghlnopqrtuvxz";
|
||||
char *colon;
|
||||
int saw_d = 0;
|
||||
|
||||
if (*msg != 'r'
|
||||
|| strncmp(msg, REMOTE_OPTION_ERROR, sizeof REMOTE_OPTION_ERROR - 1) != 0)
|
||||
return;
|
||||
|
||||
msg += sizeof REMOTE_OPTION_ERROR - 1;
|
||||
if (*msg == '-' || (colon = strchr(msg, ':')) == NULL
|
||||
|| strncmp(colon, REMOTE_OPTION_ERROR2, sizeof REMOTE_OPTION_ERROR2 - 1) != 0)
|
||||
return;
|
||||
|
||||
for ( ; *msg != ':'; msg++) {
|
||||
if (*msg == 'd')
|
||||
saw_d = 1;
|
||||
else if (*msg == 'e')
|
||||
break;
|
||||
else if (strchr(rsync263_opts, *msg) == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (saw_d) {
|
||||
rprintf(FWARNING,
|
||||
"*** Try using \"--old-d\" if remote rsync is <= 2.6.3 ***\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a message from the MSG_* fd and handle it. This is called either
|
||||
* during the early stages of being a local sender (up through the sending
|
||||
* of the file list) or when we're the generator (to fetch the messages
|
||||
@@ -388,6 +424,12 @@ static void read_msg_fd(void)
|
||||
goto invalid_msg;
|
||||
flist_eof = 1;
|
||||
break;
|
||||
case MSG_IO_ERROR:
|
||||
if (len != 4)
|
||||
goto invalid_msg;
|
||||
readfd(fd, buf, len);
|
||||
io_error |= IVAL(buf, 0);
|
||||
break;
|
||||
case MSG_DELETED:
|
||||
if (len >= (int)sizeof buf || !am_generator)
|
||||
goto invalid_msg;
|
||||
@@ -406,15 +448,17 @@ static void read_msg_fd(void)
|
||||
readfd(fd, buf, 4);
|
||||
got_flist_entry_status(FES_NO_SEND, buf);
|
||||
break;
|
||||
case MSG_SOCKERR:
|
||||
case MSG_ERROR_SOCKET:
|
||||
case MSG_CLIENT:
|
||||
if (!am_generator)
|
||||
goto invalid_msg;
|
||||
if (tag == MSG_SOCKERR)
|
||||
if (tag == MSG_ERROR_SOCKET)
|
||||
io_end_multiplex_out();
|
||||
/* FALL THROUGH */
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
case MSG_ERROR_XFER:
|
||||
case MSG_WARNING:
|
||||
case MSG_LOG:
|
||||
while (len) {
|
||||
n = len;
|
||||
@@ -433,7 +477,7 @@ static void read_msg_fd(void)
|
||||
|
||||
no_flush--;
|
||||
msg_fd_in = fd;
|
||||
if (!--defer_forwarding_messages)
|
||||
if (!--defer_forwarding_messages && !no_flush)
|
||||
msg_flush();
|
||||
}
|
||||
|
||||
@@ -461,46 +505,41 @@ static void mplex_write(int fd, enum msgcode code, const char *buf, size_t len,
|
||||
char buffer[BIGPATHBUFLEN]; /* Oversized for use by iconv code. */
|
||||
size_t n = len;
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert && ic_send == (iconv_t)-1)
|
||||
#endif
|
||||
convert = 0;
|
||||
/* We need to convert buf before doing anything else so that we
|
||||
* can include the (converted) byte length in the message header. */
|
||||
if (convert && ic_send != (iconv_t)-1) {
|
||||
xbuf outbuf, inbuf;
|
||||
|
||||
if (convert || n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
|
||||
n = 0;
|
||||
INIT_XBUF(outbuf, buffer + 4, 0, sizeof buffer - 4);
|
||||
INIT_XBUF(inbuf, (char*)buf, len, -1);
|
||||
|
||||
iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
|
||||
if (inbuf.len > 0) {
|
||||
rprintf(FERROR, "overflowed conversion buffer in mplex_write");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
n = len = outbuf.len;
|
||||
} else
|
||||
#endif
|
||||
if (n > 1024 - 4) /* BIGPATHBUFLEN can handle 1024 bytes */
|
||||
n = 0; /* We'd rather do 2 writes than too much memcpy(). */
|
||||
else
|
||||
memcpy(buffer + 4, buf, n);
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
defer_forwarding_keep = 1; /* defer_forwarding_messages++ on return */
|
||||
writefd_unbuffered(fd, buffer, n+4);
|
||||
defer_forwarding_keep = 0;
|
||||
|
||||
len -= n;
|
||||
buf += n;
|
||||
if (len > n)
|
||||
writefd_unbuffered(fd, buf+n, len-n);
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert) {
|
||||
xbuf outbuf, inbuf;
|
||||
|
||||
INIT_CONST_XBUF(outbuf, buffer);
|
||||
INIT_XBUF(inbuf, (char*)buf, len, -1);
|
||||
|
||||
defer_forwarding_messages++;
|
||||
do {
|
||||
iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
|
||||
writefd_unbuffered(fd, outbuf.buf, outbuf.len);
|
||||
} while (inbuf.len);
|
||||
if (!--defer_forwarding_messages)
|
||||
msg_flush();
|
||||
} else
|
||||
#endif
|
||||
if (len) {
|
||||
defer_forwarding_messages++;
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
if (!--defer_forwarding_messages)
|
||||
msg_flush();
|
||||
}
|
||||
if (!--defer_forwarding_messages && !no_flush)
|
||||
msg_flush();
|
||||
}
|
||||
|
||||
int send_msg(enum msgcode code, const char *buf, int len, int convert)
|
||||
@@ -749,7 +788,7 @@ static int read_timeout(int fd, char *buf, size_t len)
|
||||
/* Don't write errors on a dead socket. */
|
||||
if (fd == sock_f_in) {
|
||||
io_end_multiplex_out();
|
||||
rsyserr(FSOCKERR, errno, "read error");
|
||||
rsyserr(FERROR_SOCKET, errno, "read error");
|
||||
} else
|
||||
rsyserr(FERROR, errno, "read error");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
@@ -834,8 +873,8 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags)
|
||||
return s - buf;
|
||||
}
|
||||
|
||||
int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
char ***argv_p, int *argc_p, char **request_p)
|
||||
void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
char ***argv_p, int *argc_p, char **request_p)
|
||||
{
|
||||
int maxargs = MAX_ARGS;
|
||||
int dot_pos = 0;
|
||||
@@ -849,14 +888,14 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
|
||||
if (!(argv = new_array(char *, maxargs)))
|
||||
out_of_memory("read_args");
|
||||
if (mod_name)
|
||||
if (mod_name && !protect_args)
|
||||
argv[argc++] = "rsyncd";
|
||||
|
||||
while (1) {
|
||||
if (read_line(f_in, buf, bufsiz, rl_flags) == 0)
|
||||
break;
|
||||
|
||||
if (argc == maxargs) {
|
||||
if (argc == maxargs-1) {
|
||||
maxargs += MAX_ARGS;
|
||||
if (!(argv = realloc_array(argv, char *, maxargs)))
|
||||
out_of_memory("read_args");
|
||||
@@ -879,11 +918,12 @@ int read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
|
||||
dot_pos = argc;
|
||||
}
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
|
||||
glob_expand(NULL, NULL, NULL, NULL);
|
||||
|
||||
*argc_p = argc;
|
||||
*argv_p = argv;
|
||||
|
||||
return dot_pos ? dot_pos : argc;
|
||||
}
|
||||
|
||||
int io_start_buffering_out(int f_out)
|
||||
@@ -1041,6 +1081,7 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
if (msg_bytes != 4)
|
||||
goto invalid_msg;
|
||||
read_loop(fd, line, msg_bytes);
|
||||
send_msg_int(MSG_IO_ERROR, IVAL(line, 0));
|
||||
io_error |= IVAL(line, 0);
|
||||
break;
|
||||
case MSG_DELETED:
|
||||
@@ -1054,7 +1095,7 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
int pos = 0;
|
||||
|
||||
INIT_CONST_XBUF(outbuf, line);
|
||||
inbuf.buf = ibuf;
|
||||
INIT_XBUF(inbuf, ibuf, 0, -1);
|
||||
|
||||
while (msg_bytes) {
|
||||
inbuf.len = msg_bytes > sizeof ibuf
|
||||
@@ -1103,6 +1144,8 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
break;
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
case MSG_ERROR_XFER:
|
||||
case MSG_WARNING:
|
||||
if (msg_bytes >= sizeof line) {
|
||||
overflow:
|
||||
rprintf(FERROR,
|
||||
@@ -1112,6 +1155,13 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
}
|
||||
read_loop(fd, line, msg_bytes);
|
||||
rwrite((enum logcode)tag, line, msg_bytes, 1);
|
||||
if (first_message) {
|
||||
if (list_only && !am_sender && tag == 1) {
|
||||
line[msg_bytes] = '\0';
|
||||
check_for_d_option_error(line);
|
||||
}
|
||||
first_message = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rprintf(FERROR, "unexpected tag %d [%s]\n",
|
||||
@@ -1504,7 +1554,8 @@ static void writefd_unbuffered(int fd, const char *buf, size_t len)
|
||||
}
|
||||
|
||||
no_flush--;
|
||||
if (!(defer_forwarding_messages -= defer_inc))
|
||||
defer_inc -= defer_forwarding_keep;
|
||||
if (!(defer_forwarding_messages -= defer_inc) && !no_flush)
|
||||
msg_flush();
|
||||
}
|
||||
|
||||
@@ -1854,6 +1905,8 @@ void start_write_batch(int fd)
|
||||
* actual communication so far depends on whether a daemon
|
||||
* is involved. */
|
||||
write_int(batch_fd, protocol_version);
|
||||
if (protocol_version >= 30)
|
||||
write_byte(batch_fd, inc_recurse);
|
||||
write_int(batch_fd, checksum_seed);
|
||||
|
||||
if (am_sender)
|
||||
|
||||
2
io.h
2
io.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Wayne Davison
|
||||
* Copyright (C) 2007-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
dummy
|
||||
180
lib/addrinfo.h
Normal file
180
lib/addrinfo.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
PostgreSQL Database Management System
|
||||
(formerly known as Postgres, then as Postgres95)
|
||||
|
||||
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
|
||||
|
||||
Portions Copyright (c) 1994, The Regents of the University of California
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose, without fee, and without a written agreement
|
||||
is hereby granted, provided that the above copyright notice and this paragraph
|
||||
and the following two paragraphs appear in all copies.
|
||||
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
|
||||
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
|
||||
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
|
||||
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* getaddrinfo.h
|
||||
* Support getaddrinfo() on platforms that don't have it.
|
||||
*
|
||||
* Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
|
||||
* whether or not the library routine getaddrinfo() can be found. This
|
||||
* policy is needed because on some platforms a manually installed libbind.a
|
||||
* may provide getaddrinfo(), yet the system headers may not provide the
|
||||
* struct definitions needed to call it. To avoid conflict with the libbind
|
||||
* definition in such cases, we rename our routines to pg_xxx() via macros.
|
||||
*
|
||||
* This code will also work on platforms where struct addrinfo is defined
|
||||
* in the system headers but no getaddrinfo() can be located.
|
||||
*
|
||||
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ADDRINFO_H
|
||||
#define ADDRINFO_H
|
||||
|
||||
|
||||
/* Various macros that ought to be in <netdb.h>, but might not be */
|
||||
|
||||
#ifndef EAI_FAIL
|
||||
#define EAI_BADFLAGS (-1)
|
||||
#define EAI_NONAME (-2)
|
||||
#define EAI_AGAIN (-3)
|
||||
#define EAI_FAIL (-4)
|
||||
#define EAI_FAMILY (-6)
|
||||
#define EAI_SOCKTYPE (-7)
|
||||
#define EAI_SERVICE (-8)
|
||||
#define EAI_MEMORY (-10)
|
||||
#define EAI_SYSTEM (-11)
|
||||
#endif /* !EAI_FAIL */
|
||||
|
||||
#ifndef AI_PASSIVE
|
||||
#define AI_PASSIVE 0x0001
|
||||
#endif
|
||||
|
||||
#ifndef AI_NUMERICHOST
|
||||
/*
|
||||
* some platforms don't support AI_NUMERICHOST; define as zero if using
|
||||
* the system version of getaddrinfo...
|
||||
*/
|
||||
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
|
||||
#define AI_NUMERICHOST 0
|
||||
#else
|
||||
#define AI_NUMERICHOST 0x0004
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AI_CANONNAME
|
||||
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
|
||||
#define AI_CANONNAME 0
|
||||
#else
|
||||
#define AI_CANONNAME 0x0008
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AI_NUMERICSERV
|
||||
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
|
||||
#define AI_NUMERICSERV 0
|
||||
#else
|
||||
#define AI_NUMERICSERV 0x0010
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NI_NUMERICHOST
|
||||
#define NI_NUMERICHOST 1
|
||||
#endif
|
||||
|
||||
#ifndef NI_NUMERICSERV
|
||||
#define NI_NUMERICSERV 2
|
||||
#endif
|
||||
|
||||
#ifndef NI_NOFQDN
|
||||
#define NI_NOFQDN 4
|
||||
#endif
|
||||
|
||||
#ifndef NI_NAMEREQD
|
||||
#define NI_NAMEREQD 8
|
||||
#endif
|
||||
|
||||
#ifndef NI_DGRAM
|
||||
#define NI_DGRAM 16
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NI_MAXHOST
|
||||
#define NI_MAXHOST 1025
|
||||
#endif
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
#define NI_MAXSERV 32
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo
|
||||
{
|
||||
int ai_flags;
|
||||
int ai_family;
|
||||
int ai_socktype;
|
||||
int ai_protocol;
|
||||
size_t ai_addrlen;
|
||||
struct sockaddr *ai_addr;
|
||||
char *ai_canonname;
|
||||
struct addrinfo *ai_next;
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_ADDRINFO */
|
||||
|
||||
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
|
||||
struct sockaddr_storage {
|
||||
unsigned short ss_family;
|
||||
unsigned long ss_align;
|
||||
char ss_padding[128 - sizeof (unsigned long)];
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
|
||||
/* Rename private copies per comments above */
|
||||
#ifdef getaddrinfo
|
||||
#undef getaddrinfo
|
||||
#endif
|
||||
#define getaddrinfo pg_getaddrinfo
|
||||
|
||||
#ifdef freeaddrinfo
|
||||
#undef freeaddrinfo
|
||||
#endif
|
||||
#define freeaddrinfo pg_freeaddrinfo
|
||||
|
||||
#ifdef gai_strerror
|
||||
#undef gai_strerror
|
||||
#endif
|
||||
#define gai_strerror pg_gai_strerror
|
||||
|
||||
#ifdef getnameinfo
|
||||
#undef getnameinfo
|
||||
#endif
|
||||
#define getnameinfo pg_getnameinfo
|
||||
|
||||
extern int getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo * hints, struct addrinfo ** res);
|
||||
extern void freeaddrinfo(struct addrinfo * res);
|
||||
extern const char *gai_strerror(int errcode);
|
||||
extern int getnameinfo(const struct sockaddr * sa, socklen_t salen,
|
||||
char *node, size_t nodelen,
|
||||
char *service, size_t servicelen, int flags);
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
|
||||
#endif /* ADDRINFO_H */
|
||||
508
lib/getaddrinfo.c
Normal file
508
lib/getaddrinfo.c
Normal file
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
PostgreSQL Database Management System
|
||||
(formerly known as Postgres, then as Postgres95)
|
||||
|
||||
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
|
||||
|
||||
Portions Copyright (c) 1994, The Regents of the University of California
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose, without fee, and without a written agreement
|
||||
is hereby granted, provided that the above copyright notice and this paragraph
|
||||
and the following two paragraphs appear in all copies.
|
||||
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
|
||||
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
|
||||
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
|
||||
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* getaddrinfo.c
|
||||
* Support getaddrinfo() on platforms that don't have it.
|
||||
*
|
||||
* We also supply getnameinfo() here, assuming that the platform will have
|
||||
* it if and only if it has getaddrinfo(). If this proves false on some
|
||||
* platform, we'll need to split this file and provide a separate configure
|
||||
* test for getnameinfo().
|
||||
*
|
||||
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
|
||||
*
|
||||
* Copyright (C) 2007 Jeremy Allison.
|
||||
* Modified to return multiple IPv4 addresses for Samba.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifndef SMB_MALLOC
|
||||
#define SMB_MALLOC(s) malloc(s)
|
||||
#endif
|
||||
|
||||
#ifndef SMB_STRDUP
|
||||
#define SMB_STRDUP(s) strdup(s)
|
||||
#endif
|
||||
|
||||
#ifndef HOST_NAME_MAX
|
||||
#define HOST_NAME_MAX 255
|
||||
#endif
|
||||
|
||||
static int check_hostent_err(struct hostent *hp)
|
||||
{
|
||||
#ifndef INET6
|
||||
extern int h_errno;
|
||||
#endif
|
||||
if (!hp) {
|
||||
switch (h_errno) {
|
||||
case HOST_NOT_FOUND:
|
||||
case NO_DATA:
|
||||
return EAI_NONAME;
|
||||
case TRY_AGAIN:
|
||||
return EAI_AGAIN;
|
||||
case NO_RECOVERY:
|
||||
default:
|
||||
return EAI_FAIL;
|
||||
}
|
||||
}
|
||||
if (!hp->h_name || hp->h_addrtype != AF_INET) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *canon_name_from_hostent(struct hostent *hp,
|
||||
int *perr)
|
||||
{
|
||||
char *ret = NULL;
|
||||
|
||||
*perr = check_hostent_err(hp);
|
||||
if (*perr) {
|
||||
return NULL;
|
||||
}
|
||||
ret = SMB_STRDUP(hp->h_name);
|
||||
if (!ret) {
|
||||
*perr = EAI_MEMORY;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *get_my_canon_name(int *perr)
|
||||
{
|
||||
char name[HOST_NAME_MAX+1];
|
||||
|
||||
if (gethostname(name, HOST_NAME_MAX) == -1) {
|
||||
*perr = EAI_FAIL;
|
||||
return NULL;
|
||||
}
|
||||
/* Ensure null termination. */
|
||||
name[HOST_NAME_MAX] = '\0';
|
||||
return canon_name_from_hostent(gethostbyname(name), perr);
|
||||
}
|
||||
|
||||
static char *get_canon_name_from_addr(struct in_addr ip,
|
||||
int *perr)
|
||||
{
|
||||
return canon_name_from_hostent(
|
||||
gethostbyaddr((void *)&ip, sizeof ip, AF_INET),
|
||||
perr);
|
||||
}
|
||||
|
||||
static struct addrinfo *alloc_entry(const struct addrinfo *hints,
|
||||
struct in_addr ip,
|
||||
unsigned short port)
|
||||
{
|
||||
struct sockaddr_in *psin = NULL;
|
||||
struct addrinfo *ai = SMB_MALLOC(sizeof(*ai));
|
||||
|
||||
if (!ai) {
|
||||
return NULL;
|
||||
}
|
||||
memset(ai, '\0', sizeof(*ai));
|
||||
|
||||
psin = SMB_MALLOC(sizeof(*psin));
|
||||
if (!psin) {
|
||||
free(ai);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(psin, '\0', sizeof(*psin));
|
||||
|
||||
psin->sin_family = AF_INET;
|
||||
psin->sin_port = htons(port);
|
||||
psin->sin_addr = ip;
|
||||
|
||||
ai->ai_flags = 0;
|
||||
ai->ai_family = AF_INET;
|
||||
ai->ai_socktype = hints->ai_socktype;
|
||||
ai->ai_protocol = hints->ai_protocol;
|
||||
ai->ai_addrlen = sizeof(*psin);
|
||||
ai->ai_addr = (struct sockaddr *) psin;
|
||||
ai->ai_canonname = NULL;
|
||||
ai->ai_next = NULL;
|
||||
|
||||
return ai;
|
||||
}
|
||||
|
||||
/*
|
||||
* get address info for a single ipv4 address.
|
||||
*
|
||||
* Bugs: - servname can only be a number, not text.
|
||||
*/
|
||||
|
||||
static int getaddr_info_single_addr(const char *service,
|
||||
uint32 addr,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
|
||||
struct addrinfo *ai = NULL;
|
||||
struct in_addr ip;
|
||||
unsigned short port = 0;
|
||||
|
||||
if (service) {
|
||||
port = (unsigned short)atoi(service);
|
||||
}
|
||||
ip.s_addr = htonl(addr);
|
||||
|
||||
ai = alloc_entry(hints, ip, port);
|
||||
if (!ai) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
/* If we're asked for the canonical name,
|
||||
* make sure it returns correctly. */
|
||||
if (!(hints->ai_flags & AI_NUMERICSERV) &&
|
||||
hints->ai_flags & AI_CANONNAME) {
|
||||
int err;
|
||||
if (addr == INADDR_LOOPBACK || addr == INADDR_ANY) {
|
||||
ai->ai_canonname = get_my_canon_name(&err);
|
||||
} else {
|
||||
ai->ai_canonname =
|
||||
get_canon_name_from_addr(ip,&err);
|
||||
}
|
||||
if (ai->ai_canonname == NULL) {
|
||||
freeaddrinfo(ai);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
*res = ai;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get address info for multiple ipv4 addresses.
|
||||
*
|
||||
* Bugs: - servname can only be a number, not text.
|
||||
*/
|
||||
|
||||
static int getaddr_info_name(const char *node,
|
||||
const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
struct addrinfo *listp = NULL, *prevp = NULL;
|
||||
char **pptr = NULL;
|
||||
int err;
|
||||
struct hostent *hp = NULL;
|
||||
unsigned short port = 0;
|
||||
|
||||
if (service) {
|
||||
port = (unsigned short)atoi(service);
|
||||
}
|
||||
|
||||
hp = gethostbyname(node);
|
||||
err = check_hostent_err(hp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
for(pptr = hp->h_addr_list; *pptr; pptr++) {
|
||||
struct in_addr ip = *(struct in_addr *)*pptr;
|
||||
struct addrinfo *ai = alloc_entry(hints, ip, port);
|
||||
|
||||
if (!ai) {
|
||||
freeaddrinfo(listp);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
if (!listp) {
|
||||
listp = ai;
|
||||
prevp = ai;
|
||||
ai->ai_canonname = SMB_STRDUP(hp->h_name);
|
||||
if (!ai->ai_canonname) {
|
||||
freeaddrinfo(listp);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
} else {
|
||||
prevp->ai_next = ai;
|
||||
prevp = ai;
|
||||
}
|
||||
}
|
||||
*res = listp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get address info for ipv4 sockets.
|
||||
*
|
||||
* Bugs: - servname can only be a number, not text.
|
||||
*/
|
||||
|
||||
int getaddrinfo(const char *node,
|
||||
const char *service,
|
||||
const struct addrinfo * hintp,
|
||||
struct addrinfo ** res)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
|
||||
/* Setup the hints struct. */
|
||||
if (hintp == NULL) {
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
} else {
|
||||
memcpy(&hints, hintp, sizeof(hints));
|
||||
}
|
||||
|
||||
if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) {
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
|
||||
if (hints.ai_socktype == 0) {
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
}
|
||||
|
||||
if (!node && !service) {
|
||||
return EAI_NONAME;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
if (node[0] == '\0') {
|
||||
return getaddr_info_single_addr(service,
|
||||
INADDR_ANY,
|
||||
&hints,
|
||||
res);
|
||||
} else if (hints.ai_flags & AI_NUMERICHOST) {
|
||||
struct in_addr ip;
|
||||
if (!inet_aton(node, &ip)) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
return getaddr_info_single_addr(service,
|
||||
ntohl(ip.s_addr),
|
||||
&hints,
|
||||
res);
|
||||
} else {
|
||||
return getaddr_info_name(node,
|
||||
service,
|
||||
&hints,
|
||||
res);
|
||||
}
|
||||
} else if (hints.ai_flags & AI_PASSIVE) {
|
||||
return getaddr_info_single_addr(service,
|
||||
INADDR_ANY,
|
||||
&hints,
|
||||
res);
|
||||
}
|
||||
return getaddr_info_single_addr(service,
|
||||
INADDR_LOOPBACK,
|
||||
&hints,
|
||||
res);
|
||||
}
|
||||
|
||||
|
||||
void freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
struct addrinfo *next = NULL;
|
||||
|
||||
for (;res; res = next) {
|
||||
next = res->ai_next;
|
||||
if (res->ai_canonname) {
|
||||
free(res->ai_canonname);
|
||||
}
|
||||
if (res->ai_addr) {
|
||||
free(res->ai_addr);
|
||||
}
|
||||
free(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *gai_strerror(int errcode)
|
||||
{
|
||||
#ifdef HAVE_HSTRERROR
|
||||
int hcode;
|
||||
|
||||
switch (errcode)
|
||||
{
|
||||
case EAI_NONAME:
|
||||
hcode = HOST_NOT_FOUND;
|
||||
break;
|
||||
case EAI_AGAIN:
|
||||
hcode = TRY_AGAIN;
|
||||
break;
|
||||
case EAI_FAIL:
|
||||
default:
|
||||
hcode = NO_RECOVERY;
|
||||
break;
|
||||
}
|
||||
|
||||
return hstrerror(hcode);
|
||||
#else /* !HAVE_HSTRERROR */
|
||||
|
||||
switch (errcode)
|
||||
{
|
||||
case EAI_NONAME:
|
||||
return "Unknown host";
|
||||
case EAI_AGAIN:
|
||||
return "Host name lookup failure";
|
||||
#ifdef EAI_BADFLAGS
|
||||
case EAI_BADFLAGS:
|
||||
return "Invalid argument";
|
||||
#endif
|
||||
#ifdef EAI_FAMILY
|
||||
case EAI_FAMILY:
|
||||
return "Address family not supported";
|
||||
#endif
|
||||
#ifdef EAI_MEMORY
|
||||
case EAI_MEMORY:
|
||||
return "Not enough memory";
|
||||
#endif
|
||||
#ifdef EAI_NODATA
|
||||
case EAI_NODATA:
|
||||
return "No host data of that type was found";
|
||||
#endif
|
||||
#ifdef EAI_SERVICE
|
||||
case EAI_SERVICE:
|
||||
return "Class type not found";
|
||||
#endif
|
||||
#ifdef EAI_SOCKTYPE
|
||||
case EAI_SOCKTYPE:
|
||||
return "Socket type not supported";
|
||||
#endif
|
||||
default:
|
||||
return "Unknown server error";
|
||||
}
|
||||
#endif /* HAVE_HSTRERROR */
|
||||
}
|
||||
|
||||
static int gethostnameinfo(const struct sockaddr *sa,
|
||||
char *node,
|
||||
size_t nodelen,
|
||||
int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
char *p = NULL;
|
||||
|
||||
if (!(flags & NI_NUMERICHOST)) {
|
||||
struct hostent *hp = gethostbyaddr(
|
||||
(void *)&((struct sockaddr_in *)sa)->sin_addr,
|
||||
sizeof (struct in_addr),
|
||||
sa->sa_family);
|
||||
ret = check_hostent_err(hp);
|
||||
if (ret == 0) {
|
||||
/* Name looked up successfully. */
|
||||
ret = snprintf(node, nodelen, "%s", hp->h_name);
|
||||
if (ret < 0 || (size_t)ret >= nodelen) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
if (flags & NI_NOFQDN) {
|
||||
p = strchr(node,'.');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & NI_NAMEREQD) {
|
||||
/* If we require a name and didn't get one,
|
||||
* automatically fail. */
|
||||
return ret;
|
||||
}
|
||||
/* Otherwise just fall into the numeric host code... */
|
||||
}
|
||||
p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
|
||||
ret = snprintf(node, nodelen, "%s", p);
|
||||
if (ret < 0 || (size_t)ret >= nodelen) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getservicenameinfo(const struct sockaddr *sa,
|
||||
char *service,
|
||||
size_t servicelen,
|
||||
int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
int port = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||
|
||||
if (!(flags & NI_NUMERICSERV)) {
|
||||
struct servent *se = getservbyport(
|
||||
port,
|
||||
(flags & NI_DGRAM) ? "udp" : "tcp");
|
||||
if (se && se->s_name) {
|
||||
/* Service name looked up successfully. */
|
||||
ret = snprintf(service, servicelen, "%s", se->s_name);
|
||||
if (ret < 0 || (size_t)ret >= servicelen) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Otherwise just fall into the numeric service code... */
|
||||
}
|
||||
ret = snprintf(service, servicelen, "%d", port);
|
||||
if (ret < 0 || (size_t)ret >= servicelen) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an ipv4 address to a hostname.
|
||||
*
|
||||
* Bugs: - No IPv6 support.
|
||||
*/
|
||||
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
char *node, size_t nodelen,
|
||||
char *service, size_t servicelen, int flags)
|
||||
{
|
||||
|
||||
/* Invalid arguments. */
|
||||
if (sa == NULL || (node == NULL && service == NULL)) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
if (sa->sa_family != AF_INET) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
if (salen < (socklen_t)sizeof (struct sockaddr_in)) {
|
||||
return EAI_FAIL;
|
||||
}
|
||||
|
||||
/* We don't support those. */
|
||||
if ((node && !(flags & NI_NUMERICHOST))
|
||||
|| (service && !(flags & NI_NUMERICSERV)))
|
||||
return EAI_FAIL;
|
||||
|
||||
if (node) {
|
||||
return gethostnameinfo(sa, node, nodelen, flags);
|
||||
}
|
||||
|
||||
if (service) {
|
||||
return getservicenameinfo(sa, service, servicelen, flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
* An implementation of MD4 designed for use in the SMB authentication protocol.
|
||||
*
|
||||
* Copyright (C) 1997-1998 Andrew Tridgell
|
||||
* Copyright (C) 2005-2007 Wayne Davison
|
||||
* Copyright (C) 2005-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Unix SMB/CIFS implementation.
|
||||
* Based on the Samba ACL support code.
|
||||
* Copyright (C) Jeremy Allison 2000.
|
||||
* Copyright (C) 2007-2008 Wayne Davison
|
||||
*
|
||||
* The permission functions have been changed to get/set all bits via
|
||||
* one call. Some functions that rsync doesn't need were also removed.
|
||||
@@ -1100,7 +1101,7 @@ struct hpux_acl_types {
|
||||
* acl types.
|
||||
*/
|
||||
|
||||
static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
|
||||
static void hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1735,6 +1736,13 @@ int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
|
||||
struct new_acl_entry *entry;
|
||||
int keep_going;
|
||||
|
||||
if (entry_id == SMB_ACL_FIRST_ENTRY)
|
||||
theacl->count = 0;
|
||||
else if (entry_id != SMB_ACL_NEXT_ENTRY) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG(10,("This is the count: %d\n",theacl->count));
|
||||
|
||||
/* Check if count was previously set to -1. *
|
||||
@@ -1804,7 +1812,6 @@ SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
|
||||
struct acl_entry_link *acl_entry_link_head;
|
||||
int i;
|
||||
int rc = 0;
|
||||
uid_t user_id;
|
||||
|
||||
/* AIX has no DEFAULT */
|
||||
if ( type == SMB_ACL_TYPE_DEFAULT ) {
|
||||
@@ -2025,7 +2032,6 @@ SMB_ACL_T sys_acl_get_fd(int fd)
|
||||
struct acl_entry_link *acl_entry_link_head;
|
||||
int i;
|
||||
int rc = 0;
|
||||
uid_t user_id;
|
||||
|
||||
/* Get the acl using fstatacl */
|
||||
|
||||
@@ -2239,7 +2245,7 @@ int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *b
|
||||
return -1;
|
||||
|
||||
if (*tag_type_p == SMB_ACL_USER || *tag_type_p == SMB_ACL_GROUP)
|
||||
*u_g_id_p = entry->ace_id->id_data;
|
||||
memcpy(u_g_id_p, entry->ace_id->id_data, sizeof (id_t));
|
||||
|
||||
permset = &entry->ace_access;
|
||||
|
||||
@@ -2255,6 +2261,11 @@ SMB_ACL_T sys_acl_init( int count)
|
||||
{
|
||||
struct acl_entry_link *theacl = NULL;
|
||||
|
||||
if (count < 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG(10,("Entering sys_acl_init\n"));
|
||||
|
||||
theacl = SMB_MALLOC_P(struct acl_entry_link);
|
||||
@@ -2373,7 +2384,6 @@ int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl
|
||||
struct acl_entry *acl_entry = NULL;
|
||||
struct ace_id *ace_id = NULL;
|
||||
uint id_type;
|
||||
uint ace_access;
|
||||
uint user_id;
|
||||
uint acl_length;
|
||||
uint rc;
|
||||
@@ -2452,7 +2462,7 @@ int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl
|
||||
memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
|
||||
}
|
||||
|
||||
rc = chacl(name,file_acl,file_acl->acl_len);
|
||||
rc = chacl((char*)name,file_acl,file_acl->acl_len);
|
||||
DEBUG(10,("errno is %d\n",errno));
|
||||
DEBUG(10,("return code is %d\n",rc));
|
||||
SAFE_FREE(file_acl);
|
||||
@@ -2551,7 +2561,7 @@ int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
|
||||
}
|
||||
#endif
|
||||
|
||||
int sys_acl_delete_def_file(const char *name)
|
||||
int sys_acl_delete_def_file(UNUSED(const char *name))
|
||||
{
|
||||
/* AIX has no default ACL */
|
||||
return 0;
|
||||
@@ -2694,6 +2704,8 @@ int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits,
|
||||
rc = mbr_uid_to_uuid(u_g_id, uu);
|
||||
else
|
||||
rc = mbr_gid_to_uuid(u_g_id, uu);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
if (acl_set_tag_type(entry, tag_type) != 0
|
||||
|| acl_set_qualifier(entry, &uu) != 0
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Version 2.2.x
|
||||
* Portable SMB ACL interface
|
||||
* Copyright (C) Jeremy Allison 2000
|
||||
* Copyright (C) 2007-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Extended attribute support for rsync.
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc.
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
* Written by Jay Fenlason.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
31
loadparm.c
31
loadparm.c
@@ -124,6 +124,7 @@ static global Globals;
|
||||
typedef struct
|
||||
{
|
||||
char *auth_users;
|
||||
char *charset;
|
||||
char *comment;
|
||||
char *dont_compress;
|
||||
char *exclude;
|
||||
@@ -157,6 +158,8 @@ typedef struct
|
||||
BOOL ignore_errors;
|
||||
BOOL ignore_nonreadable;
|
||||
BOOL list;
|
||||
BOOL munge_symlinks;
|
||||
BOOL numeric_ids;
|
||||
BOOL read_only;
|
||||
BOOL strict_modes;
|
||||
BOOL transfer_logging;
|
||||
@@ -172,7 +175,8 @@ typedef struct
|
||||
static service sDefault =
|
||||
{
|
||||
/* auth_users; */ NULL,
|
||||
/* comment; */ NULL,
|
||||
/* charset; */ NULL,
|
||||
/* comment; */ NULL,
|
||||
/* dont_compress; */ DEFAULT_DONT_COMPRESS,
|
||||
/* exclude; */ NULL,
|
||||
/* exclude_from; */ NULL,
|
||||
@@ -205,6 +209,8 @@ static service sDefault =
|
||||
/* ignore_errors; */ False,
|
||||
/* ignore_nonreadable; */ False,
|
||||
/* list; */ True,
|
||||
/* munge_symlinks; */ (BOOL)-1,
|
||||
/* numeric_ids; */ (BOOL)-1,
|
||||
/* read_only; */ True,
|
||||
/* strict_modes; */ True,
|
||||
/* transfer_logging; */ False,
|
||||
@@ -299,6 +305,7 @@ static struct parm_struct parm_table[] =
|
||||
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
|
||||
|
||||
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
|
||||
{"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
|
||||
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
|
||||
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
|
||||
@@ -319,7 +326,9 @@ static struct parm_struct parm_table[] =
|
||||
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
|
||||
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
|
||||
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
|
||||
{"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0},
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
|
||||
{"numeric ids", P_BOOL, P_LOCAL, &sDefault.numeric_ids, NULL,0},
|
||||
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
|
||||
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
|
||||
#ifdef HAVE_PUTENV
|
||||
@@ -389,6 +398,7 @@ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
|
||||
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
|
||||
|
||||
FN_LOCAL_STRING(lp_auth_users, auth_users)
|
||||
FN_LOCAL_STRING(lp_charset, charset)
|
||||
FN_LOCAL_STRING(lp_comment, comment)
|
||||
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
|
||||
FN_LOCAL_STRING(lp_exclude, exclude)
|
||||
@@ -410,18 +420,20 @@ FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
|
||||
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
|
||||
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
|
||||
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
|
||||
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
|
||||
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
|
||||
FN_LOCAL_STRING(lp_uid, uid)
|
||||
|
||||
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
|
||||
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
|
||||
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
|
||||
FN_LOCAL_INTEGER(lp_timeout, timeout)
|
||||
|
||||
FN_LOCAL_BOOL(lp_fake_super, fake_super)
|
||||
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
|
||||
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
|
||||
FN_LOCAL_BOOL(lp_list, list)
|
||||
FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks)
|
||||
FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids)
|
||||
FN_LOCAL_BOOL(lp_read_only, read_only)
|
||||
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
|
||||
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
|
||||
@@ -558,7 +570,7 @@ static int map_parameter(char *parmname)
|
||||
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
|
||||
return(iIndex);
|
||||
|
||||
rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
|
||||
rprintf(FLOG, "Unknown Parameter encountered: \"%s\"\n", parmname);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@@ -584,7 +596,7 @@ static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
*pb = False;
|
||||
else
|
||||
{
|
||||
rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
|
||||
rprintf(FLOG, "Badly formed boolean in configuration file: \"%s\".\n",
|
||||
parmvalue);
|
||||
bRetval = False;
|
||||
}
|
||||
@@ -671,7 +683,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
|
||||
if (parmnum < 0)
|
||||
{
|
||||
rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
|
||||
rprintf(FLOG, "IGNORING unknown parameter \"%s\"\n", parmname);
|
||||
return(True);
|
||||
}
|
||||
|
||||
@@ -682,7 +694,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
parm_ptr = def_ptr;
|
||||
} else {
|
||||
if (parm_table[parmnum].class == P_GLOBAL) {
|
||||
rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
|
||||
rprintf(FLOG, "Global parameter %s found in service section!\n",parmname);
|
||||
return(True);
|
||||
}
|
||||
parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
|
||||
@@ -780,6 +792,11 @@ static BOOL do_section(char *sectionname)
|
||||
return(True);
|
||||
}
|
||||
|
||||
if (strchr(sectionname, '/') != NULL) {
|
||||
rprintf(FLOG, "Warning: invalid section name in configuration file: %s\n", sectionname);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* if we have a current service, tidy it up before moving on */
|
||||
bRetval = True;
|
||||
|
||||
@@ -794,7 +811,7 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
|
||||
{
|
||||
rprintf(FERROR,"Failed to add a new service\n");
|
||||
rprintf(FLOG, "Failed to add a new service\n");
|
||||
return(False);
|
||||
}
|
||||
}
|
||||
|
||||
67
log.c
67
log.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -41,6 +41,7 @@ extern int stdout_format_has_i;
|
||||
extern int stdout_format_has_o_or_i;
|
||||
extern int logfile_format_has_i;
|
||||
extern int logfile_format_has_o_or_i;
|
||||
extern int receiver_symlink_times;
|
||||
extern mode_t orig_umask;
|
||||
extern char *auth_user;
|
||||
extern char *stdout_format;
|
||||
@@ -61,7 +62,7 @@ static int logfile_was_closed;
|
||||
static FILE *logfile_fp;
|
||||
struct stats stats;
|
||||
|
||||
int log_got_error = 0;
|
||||
int got_xfer_error = 0;
|
||||
|
||||
struct {
|
||||
int code;
|
||||
@@ -86,6 +87,7 @@ struct {
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_VANISHED , "some files vanished before they could be transferred" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },
|
||||
{ RERR_CMD_FAILED , "remote shell failed" },
|
||||
{ RERR_CMD_KILLED , "remote shell killed" },
|
||||
{ RERR_CMD_RUN , "remote command could not be run" },
|
||||
@@ -235,8 +237,8 @@ static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
|
||||
* certain fatal conditions. */
|
||||
* it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT. Note: recursion
|
||||
* can happen with certain fatal conditions. */
|
||||
void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
{
|
||||
int trailing_CR_or_NL;
|
||||
@@ -259,7 +261,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
|
||||
if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */
|
||||
code = FERROR;
|
||||
|
||||
if (code == FCLIENT)
|
||||
@@ -267,7 +269,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
else if (am_daemon || logfile_name) {
|
||||
static int in_block;
|
||||
char msg[2048];
|
||||
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
|
||||
int priority = code == FINFO || code == FLOG ? LOG_INFO : LOG_WARNING;
|
||||
|
||||
if (in_block)
|
||||
return;
|
||||
@@ -283,12 +285,19 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
} else if (code == FLOG)
|
||||
return;
|
||||
|
||||
if (quiet && code != FERROR)
|
||||
if (quiet && code == FINFO)
|
||||
return;
|
||||
|
||||
if (am_server) {
|
||||
enum msgcode msg = (enum msgcode)code;
|
||||
if (protocol_version < 30) {
|
||||
if (msg == MSG_ERROR)
|
||||
msg = MSG_ERROR_XFER;
|
||||
else if (msg == MSG_WARNING)
|
||||
msg = MSG_INFO;
|
||||
}
|
||||
/* Pass the message to the non-server side. */
|
||||
if (send_msg((enum msgcode)code, buf, len, !is_utf8))
|
||||
if (send_msg(msg, buf, len, !is_utf8))
|
||||
return;
|
||||
if (am_daemon) {
|
||||
/* TODO: can we send the error to the user somehow? */
|
||||
@@ -297,8 +306,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case FERROR_XFER:
|
||||
got_xfer_error = 1;
|
||||
/* FALL THROUGH */
|
||||
case FERROR:
|
||||
log_got_error = 1;
|
||||
case FWARNING:
|
||||
f = stderr;
|
||||
break;
|
||||
case FINFO:
|
||||
@@ -342,8 +354,8 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR or
|
||||
* FLOG. */
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR_*,
|
||||
* FWARNING, FLOG, or FCLIENT. */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -421,10 +433,10 @@ void rflush(enum logcode code)
|
||||
if (am_daemon || code == FLOG)
|
||||
return;
|
||||
|
||||
if (code == FERROR || am_server)
|
||||
f = stderr;
|
||||
else
|
||||
if (code == FINFO && !am_server)
|
||||
f = stdout;
|
||||
else
|
||||
f = stderr;
|
||||
|
||||
fflush(f);
|
||||
}
|
||||
@@ -612,7 +624,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
|
||||
break;
|
||||
case 'i':
|
||||
if (iflags & ITEM_DELETED) {
|
||||
n = "*deleting";
|
||||
n = "*deleting ";
|
||||
break;
|
||||
}
|
||||
n = c = buf2 + MAXPATHLEN - 32;
|
||||
@@ -620,14 +632,21 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
|
||||
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
|
||||
: !(iflags & ITEM_TRANSFER) ? '.'
|
||||
: !local_server && *op == 's' ? '<' : '>';
|
||||
c[1] = S_ISDIR(file->mode) ? 'd'
|
||||
: IS_SPECIAL(file->mode) ? 'S'
|
||||
: IS_DEVICE(file->mode) ? 'D'
|
||||
: S_ISLNK(file->mode) ? 'L' : 'f';
|
||||
c[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
|
||||
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
|
||||
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
|
||||
: !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
|
||||
if (S_ISLNK(file->mode)) {
|
||||
c[1] = 'L';
|
||||
c[3] = '.';
|
||||
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
|
||||
: !preserve_times || !receiver_symlink_times
|
||||
|| (iflags & ITEM_REPORT_TIMEFAIL) ? 'T' : 't';
|
||||
} else {
|
||||
c[1] = S_ISDIR(file->mode) ? 'd'
|
||||
: IS_SPECIAL(file->mode) ? 'S'
|
||||
: IS_DEVICE(file->mode) ? 'D' : 'f';
|
||||
c[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
|
||||
c[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
|
||||
: !preserve_times ? 'T' : 't';
|
||||
}
|
||||
c[2] = !(iflags & ITEM_REPORT_CHANGE) ? '.' : 'c';
|
||||
c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
|
||||
c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
|
||||
c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
|
||||
@@ -801,7 +820,7 @@ void log_exit(int code, const char *file, int line)
|
||||
|
||||
/* VANISHED is not an error, only a warning */
|
||||
if (code == RERR_VANISHED) {
|
||||
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
name, code, file, line, who_am_i(), RSYNC_VERSION);
|
||||
} else {
|
||||
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
|
||||
|
||||
242
main.c
242
main.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -41,15 +41,17 @@ 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;
|
||||
extern int file_total;
|
||||
extern int recurse;
|
||||
extern int xfer_dirs;
|
||||
extern int protect_args;
|
||||
extern int relative_paths;
|
||||
extern int sanitize_paths;
|
||||
@@ -62,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;
|
||||
@@ -73,11 +78,9 @@ extern char *batch_name;
|
||||
extern char *password_file;
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern struct file_list *first_flist;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
#ifdef ICONV_OPTION
|
||||
extern iconv_t ic_send;
|
||||
#endif
|
||||
extern struct filter_list_struct daemon_filter_list;
|
||||
|
||||
uid_t our_uid;
|
||||
int local_server = 0;
|
||||
int daemon_over_rsh = 0;
|
||||
mode_t orig_umask = 0;
|
||||
@@ -271,9 +274,10 @@ static void output_summary(void)
|
||||
"sent %s bytes received %s bytes %s bytes/sec\n",
|
||||
human_num(total_written), human_num(total_read),
|
||||
human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
|
||||
rprintf(FINFO, "total size is %s speedup is %.2f\n",
|
||||
rprintf(FINFO, "total size is %s speedup is %.2f%s\n",
|
||||
human_num(stats.total_size),
|
||||
(double)stats.total_size / (total_written+total_read));
|
||||
(double)stats.total_size / (total_written+total_read),
|
||||
write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
@@ -327,8 +331,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
{
|
||||
int i, argc = 0;
|
||||
char *args[MAX_ARGS];
|
||||
pid_t ret;
|
||||
char *dir = NULL;
|
||||
pid_t pid;
|
||||
int dash_l_set = 0;
|
||||
|
||||
if (!read_batch && !local_server) {
|
||||
@@ -338,7 +341,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
cmd = rsh_env;
|
||||
if (!cmd)
|
||||
cmd = RSYNC_RSH;
|
||||
cmd = strdup(cmd);
|
||||
cmd = strdup(cmd); /* MEMORY LEAK */
|
||||
if (!cmd)
|
||||
goto oom;
|
||||
|
||||
@@ -439,6 +442,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
|
||||
if (read_batch) {
|
||||
int from_gen_pipe[2];
|
||||
set_allow_inc_recurse();
|
||||
if (fd_pair(from_gen_pipe) < 0) {
|
||||
rsyserr(FERROR, errno, "pipe");
|
||||
exit_cleanup(RERR_IPC);
|
||||
@@ -446,57 +450,30 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
|
||||
batch_gen_fd = from_gen_pipe[0];
|
||||
*f_out_p = from_gen_pipe[1];
|
||||
*f_in_p = batch_fd;
|
||||
ret = -1; /* no child pid */
|
||||
pid = (pid_t)-1; /* no child pid */
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
} else if (local_server) {
|
||||
/* If the user didn't request --[no-]whole-file, force
|
||||
* it on, but only if we're not batch processing. */
|
||||
if (whole_file < 0 && !write_batch)
|
||||
whole_file = 1;
|
||||
ret = local_child(argc, args, f_in_p, f_out_p, child_main);
|
||||
set_allow_inc_recurse();
|
||||
pid = local_child(argc, args, f_in_p, f_out_p, child_main);
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
} else {
|
||||
if (protect_args) {
|
||||
int fd;
|
||||
#ifdef ICONV_OPTION
|
||||
int convert = ic_send != (iconv_t)-1;
|
||||
xbuf outbuf, inbuf;
|
||||
|
||||
if (convert)
|
||||
alloc_xbuf(&outbuf, 1024);
|
||||
pid = piped_child(args, f_in_p, f_out_p);
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
|
||||
ret = piped_child(args, f_in_p, f_out_p);
|
||||
|
||||
for (i = 0; args[i]; i++) {} /* find first NULL */
|
||||
args[i] = "rsync"; /* set a new arg0 */
|
||||
if (verbose > 1)
|
||||
print_child_argv("protected args:", args + i + 1);
|
||||
fd = *f_out_p;
|
||||
do {
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert) {
|
||||
INIT_XBUF_STRLEN(inbuf, args[i]);
|
||||
iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
|
||||
outbuf.buf[outbuf.len] = '\0';
|
||||
write_buf(fd, outbuf.buf, outbuf.len + 1);
|
||||
outbuf.len = 0;
|
||||
} else
|
||||
#endif
|
||||
write_buf(fd, args[i], strlen(args[i]) + 1);
|
||||
} while (args[++i]);
|
||||
write_byte(fd, 0);
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert)
|
||||
free(outbuf.buf);
|
||||
#endif
|
||||
} else
|
||||
ret = piped_child(args, f_in_p, f_out_p);
|
||||
if (protect_args)
|
||||
send_protected_args(*f_out_p, args);
|
||||
}
|
||||
|
||||
if (dir)
|
||||
free(dir);
|
||||
|
||||
return ret;
|
||||
return pid;
|
||||
|
||||
oom:
|
||||
out_of_memory("do_cmd");
|
||||
@@ -530,12 +507,20 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
if (!dest_path || list_only)
|
||||
return NULL;
|
||||
|
||||
if (daemon_filter_list.head
|
||||
&& (check_filter(&daemon_filter_list, FLOG, dest_path, 0 != 0) < 0
|
||||
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1 != 0) < 0)) {
|
||||
rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
|
||||
dest_path);
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
/* See what currently exists at the destination. */
|
||||
if ((statret = do_stat(dest_path, &st)) == 0) {
|
||||
/* If the destination is a dir, enter it and use mode 1. */
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (!push_dir(dest_path, 0)) {
|
||||
rsyserr(FERROR, errno, "push_dir#1 %s failed",
|
||||
if (!change_dir(dest_path, CD_NORMAL)) {
|
||||
rsyserr(FERROR, errno, "change_dir#1 %s failed",
|
||||
full_fname(dest_path));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -594,8 +579,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
dry_run++;
|
||||
}
|
||||
|
||||
if (!push_dir(dest_path, dry_run > 1)) {
|
||||
rsyserr(FERROR, errno, "push_dir#2 %s failed",
|
||||
if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
|
||||
rsyserr(FERROR, errno, "change_dir#2 %s failed",
|
||||
full_fname(dest_path));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -614,8 +599,8 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
dest_path = "/";
|
||||
|
||||
*cp = '\0';
|
||||
if (!push_dir(dest_path, 0)) {
|
||||
rsyserr(FERROR, errno, "push_dir#3 %s failed",
|
||||
if (!change_dir(dest_path, CD_NORMAL)) {
|
||||
rsyserr(FERROR, errno, "change_dir#3 %s failed",
|
||||
full_fname(dest_path));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -624,36 +609,41 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
return cp + 1;
|
||||
}
|
||||
|
||||
/* Call this if the destination dir (which is assumed to be in curr_dir)
|
||||
* does not yet exist and we can't create it due to being in dry-run
|
||||
* mode. We'll fix dirs that can be relative to the non-existent dir. */
|
||||
static void fix_basis_dirs(void)
|
||||
/* This function checks on our alternate-basis directories. If we're in
|
||||
* dry-run mode and the destination dir does not yet exist, we'll try to
|
||||
* tweak any dest-relative paths to make them work for a dry-run (the
|
||||
* destination dir must be in curr_dir[] when this function is called).
|
||||
* We also warn about any arg that is non-existent or not a directory. */
|
||||
static void check_alt_basis_dirs(void)
|
||||
{
|
||||
char **dir, *new, *slash;
|
||||
int len;
|
||||
STRUCT_STAT st;
|
||||
char **dir_p, *slash = strrchr(curr_dir, '/');
|
||||
|
||||
if (dry_run <= 1)
|
||||
return;
|
||||
|
||||
slash = strrchr(curr_dir, '/');
|
||||
|
||||
for (dir = basis_dir; *dir; dir++) {
|
||||
if (**dir == '/')
|
||||
continue;
|
||||
len = curr_dir_len + 1 + strlen(*dir) + 1;
|
||||
if (!(new = new_array(char, len)))
|
||||
out_of_memory("fix_basis_dirs");
|
||||
if (slash && strncmp(*dir, "../", 3) == 0) {
|
||||
/* We want to remove only one leading "../" prefix for
|
||||
* the directory we couldn't create in dry-run mode:
|
||||
* this ensures that any other ".." references get
|
||||
* evaluated the same as they would for a live copy. */
|
||||
*slash = '\0';
|
||||
pathjoin(new, len, curr_dir, *dir + 3);
|
||||
*slash = '/';
|
||||
} else
|
||||
pathjoin(new, len, curr_dir, *dir);
|
||||
*dir = new;
|
||||
for (dir_p = basis_dir; *dir_p; dir_p++) {
|
||||
if (dry_run > 1 && **dir_p != '/') {
|
||||
int len = curr_dir_len + 1 + strlen(*dir_p) + 1;
|
||||
char *new = new_array(char, len);
|
||||
if (!new)
|
||||
out_of_memory("check_alt_basis_dirs");
|
||||
if (slash && strncmp(*dir_p, "../", 3) == 0) {
|
||||
/* We want to remove only one leading "../" prefix for
|
||||
* the directory we couldn't create in dry-run mode:
|
||||
* this ensures that any other ".." references get
|
||||
* evaluated the same as they would for a live copy. */
|
||||
*slash = '\0';
|
||||
pathjoin(new, len, curr_dir, *dir_p + 3);
|
||||
*slash = '/';
|
||||
} else
|
||||
pathjoin(new, len, curr_dir, *dir_p);
|
||||
*dir_p = new;
|
||||
}
|
||||
if (do_stat(*dir_p, &st) < 0) {
|
||||
rprintf(FWARNING, "%s arg does not exist: %s\n",
|
||||
dest_option, *dir_p);
|
||||
} else if (!S_ISDIR(st.st_mode)) {
|
||||
rprintf(FWARNING, "%s arg is not a dir: %s\n",
|
||||
dest_option, *dir_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,8 +692,8 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!relative_paths) {
|
||||
if (!push_dir(dir, 0)) {
|
||||
rsyserr(FERROR, errno, "push_dir#3 %s failed",
|
||||
if (!change_dir(dir, CD_NORMAL)) {
|
||||
rsyserr(FERROR, errno, "change_dir#3 %s failed",
|
||||
full_fname(dir));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -711,7 +701,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc == 0 && (recurse || list_only)) {
|
||||
if (argc == 0 && (recurse || xfer_dirs || list_only)) {
|
||||
argc = 1;
|
||||
argv--;
|
||||
argv[0] = ".";
|
||||
@@ -741,7 +731,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
|
||||
|
||||
/* The receiving side mustn't obey this, or an existing symlink that
|
||||
* points to an identical file won't be replaced by the referent. */
|
||||
copy_links = copy_dirlinks = 0;
|
||||
copy_links = copy_dirlinks = copy_unsafe_links = 0;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links && !inc_recurse)
|
||||
@@ -849,7 +839,6 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
|
||||
int exit_code;
|
||||
struct file_list *flist;
|
||||
char *local_name = NULL;
|
||||
char *dir = NULL;
|
||||
int save_verbose = verbose;
|
||||
|
||||
if (filesfrom_fd >= 0) {
|
||||
@@ -870,11 +859,11 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
dir = argv[0];
|
||||
char *dir = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
if (!am_daemon && !push_dir(dir, 0)) {
|
||||
rsyserr(FERROR, errno, "push_dir#4 %s failed",
|
||||
if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
|
||||
rsyserr(FERROR, errno, "change_dir#4 %s failed",
|
||||
full_fname(dir));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
@@ -911,26 +900,27 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
|
||||
/* Now that we know what our destination directory turned out to be,
|
||||
* we can sanitize the --link-/copy-/compare-dest args correctly. */
|
||||
if (sanitize_paths) {
|
||||
char **dir;
|
||||
for (dir = basis_dir; *dir; dir++) {
|
||||
*dir = sanitize_path(NULL, *dir, NULL, curr_dir_depth, NULL);
|
||||
}
|
||||
if (partial_dir) {
|
||||
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, NULL);
|
||||
}
|
||||
char **dir_p;
|
||||
for (dir_p = basis_dir; *dir_p; dir_p++)
|
||||
*dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth, SP_DEFAULT);
|
||||
if (partial_dir)
|
||||
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, SP_DEFAULT);
|
||||
}
|
||||
fix_basis_dirs();
|
||||
check_alt_basis_dirs();
|
||||
|
||||
if (server_filter_list.head) {
|
||||
char **dir;
|
||||
struct filter_list_struct *elp = &server_filter_list;
|
||||
if (daemon_filter_list.head) {
|
||||
char **dir_p;
|
||||
struct filter_list_struct *elp = &daemon_filter_list;
|
||||
|
||||
for (dir = basis_dir; *dir; dir++) {
|
||||
if (check_filter(elp, *dir, 1) < 0)
|
||||
for (dir_p = basis_dir; *dir_p; dir_p++) {
|
||||
char *dir = *dir_p;
|
||||
if (*dir == '/')
|
||||
dir += module_dirlen;
|
||||
if (check_filter(elp, FLOG, dir, 1) < 0)
|
||||
goto options_rejected;
|
||||
}
|
||||
if (partial_dir && *partial_dir == '/'
|
||||
&& check_filter(elp, partial_dir, 1) < 0) {
|
||||
&& check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
|
||||
options_rejected:
|
||||
rprintf(FERROR,
|
||||
"Your options have been rejected by the server.\n");
|
||||
@@ -1048,9 +1038,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
io_start_multiplex_out();
|
||||
}
|
||||
|
||||
if (argc == 0)
|
||||
list_only |= 1;
|
||||
|
||||
send_filter_list(read_batch ? -1 : f_out);
|
||||
|
||||
if (filesfrom_fd >= 0) {
|
||||
@@ -1067,7 +1054,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
if (flist && flist->used > 0) {
|
||||
local_name = get_local_name(flist, argv[0]);
|
||||
|
||||
fix_basis_dirs();
|
||||
check_alt_basis_dirs();
|
||||
|
||||
exit_code2 = do_recv(f_in, f_out, local_name);
|
||||
} else {
|
||||
@@ -1161,7 +1148,6 @@ static int start_client(int argc, char *argv[])
|
||||
static char *dotarg[1] = { "." };
|
||||
p = dotarg[0];
|
||||
remote_argv = dotarg;
|
||||
list_only = 1;
|
||||
}
|
||||
remote_argc = 1;
|
||||
|
||||
@@ -1233,8 +1219,6 @@ static int start_client(int argc, char *argv[])
|
||||
}
|
||||
remote_argv[i] = arg;
|
||||
}
|
||||
if (argc == 0)
|
||||
list_only |= 1;
|
||||
}
|
||||
|
||||
if (daemon_over_rsh < 0)
|
||||
@@ -1246,6 +1230,12 @@ static int start_client(int argc, char *argv[])
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (connect_timeout) {
|
||||
rprintf(FERROR, "The --contimeout option may only be "
|
||||
"used when connecting to an rsync daemon.\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (shell_machine) {
|
||||
p = strrchr(shell_machine,'@');
|
||||
if (p) {
|
||||
@@ -1292,7 +1282,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
|
||||
if (!am_server)
|
||||
output_summary();
|
||||
close_all();
|
||||
if (log_got_error)
|
||||
if (got_xfer_error)
|
||||
_exit(RERR_PARTIAL);
|
||||
_exit(0);
|
||||
}
|
||||
@@ -1399,7 +1389,8 @@ int main(int argc,char *argv[])
|
||||
#endif
|
||||
|
||||
starttime = time(NULL);
|
||||
am_root = (MY_UID() == 0);
|
||||
our_uid = MY_UID();
|
||||
am_root = our_uid == 0;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
@@ -1416,7 +1407,7 @@ int main(int argc,char *argv[])
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
|
||||
if (!parse_arguments(&argc, (const char ***) &argv)) {
|
||||
/* FIXME: We ought to call the same error-handling
|
||||
* code here, rather than relying on getopt. */
|
||||
option_error();
|
||||
@@ -1437,11 +1428,11 @@ int main(int argc,char *argv[])
|
||||
SIGACTION(SIGXFSZ, SIG_IGN);
|
||||
#endif
|
||||
|
||||
/* Initialize push_dir here because on some old systems getcwd
|
||||
/* Initialize change_dir() here because on some old systems getcwd
|
||||
* (implemented by forking "pwd" and reading its output) doesn't
|
||||
* work when there are other child processes. Also, on all systems
|
||||
* that implement getcwd that way "pwd" can't be found after chroot. */
|
||||
push_dir(NULL, 0);
|
||||
change_dir(NULL, CD_NORMAL);
|
||||
|
||||
init_flist();
|
||||
|
||||
@@ -1465,19 +1456,22 @@ int main(int argc,char *argv[])
|
||||
read_stream_flags(batch_fd);
|
||||
else
|
||||
write_stream_flags(batch_fd);
|
||||
|
||||
}
|
||||
if (write_batch < 0)
|
||||
dry_run = 1;
|
||||
|
||||
if (am_daemon && !am_server)
|
||||
if (am_server) {
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
} else if (am_daemon)
|
||||
return daemon_main();
|
||||
|
||||
if (am_server && protect_args) {
|
||||
char buf[MAXPATHLEN];
|
||||
protect_args = 2;
|
||||
read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
|
||||
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
|
||||
if (!parse_arguments(&argc, (const char ***) &argv)) {
|
||||
option_error();
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
52
match.c
52
match.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -39,29 +39,50 @@ static int total_matches;
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define TRADITIONAL_TABLESIZE (1<<16)
|
||||
|
||||
static uint32 tablesize;
|
||||
static int32 *hash_table;
|
||||
|
||||
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
|
||||
|
||||
#define BIG_SUM2HASH(sum) ((sum)%tablesize)
|
||||
|
||||
static void build_hash_table(struct sum_struct *s)
|
||||
{
|
||||
static uint32 alloc_size;
|
||||
int32 i;
|
||||
|
||||
if (!hash_table) {
|
||||
hash_table = new_array(int32, TABLESIZE);
|
||||
/* Dynamically calculate the hash table size so that the hash load
|
||||
* for big files is about 80%. A number greater than the traditional
|
||||
* size must be odd or s2 will not be able to span the entire set. */
|
||||
tablesize = (uint32)(s->count/8) * 10 + 11;
|
||||
if (tablesize < TRADITIONAL_TABLESIZE)
|
||||
tablesize = TRADITIONAL_TABLESIZE;
|
||||
if (tablesize > alloc_size || tablesize < alloc_size - 16*1024) {
|
||||
if (hash_table)
|
||||
free(hash_table);
|
||||
hash_table = new_array(int32, tablesize);
|
||||
if (!hash_table)
|
||||
out_of_memory("build_hash_table");
|
||||
alloc_size = tablesize;
|
||||
}
|
||||
|
||||
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
|
||||
memset(hash_table, 0xFF, tablesize * sizeof hash_table[0]);
|
||||
|
||||
for (i = 0; i < s->count; i++) {
|
||||
uint32 t = SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
if (tablesize == TRADITIONAL_TABLESIZE) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
uint32 t = SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
uint32 t = BIG_SUM2HASH(s->sums[i].sum1);
|
||||
s->sums[i].chain = hash_table[t];
|
||||
hash_table[t] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,11 +185,16 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
|
||||
}
|
||||
|
||||
i = hash_table[SUM2HASH2(s1,s2)];
|
||||
if (i < 0)
|
||||
goto null_hash;
|
||||
if (tablesize == TRADITIONAL_TABLESIZE) {
|
||||
if ((i = hash_table[SUM2HASH2(s1,s2)]) < 0)
|
||||
goto null_hash;
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
} else {
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
if ((i = hash_table[BIG_SUM2HASH(sum)]) < 0)
|
||||
goto null_hash;
|
||||
}
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
hash_hits++;
|
||||
do {
|
||||
int32 l;
|
||||
|
||||
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;
|
||||
}
|
||||
214
options.c
214
options.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2002-2007 Wayne Davison
|
||||
* Copyright (C) 2002-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,10 +25,12 @@
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
extern int module_id;
|
||||
extern int local_server;
|
||||
extern int sanitize_paths;
|
||||
extern int daemon_over_rsh;
|
||||
extern unsigned int module_dirlen;
|
||||
extern struct filter_list_struct filter_list;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
extern struct filter_list_struct daemon_filter_list;
|
||||
|
||||
int make_backups = 0;
|
||||
|
||||
@@ -99,6 +101,7 @@ int xfer_dirs = -1;
|
||||
int am_daemon = 0;
|
||||
int do_stats = 0;
|
||||
int do_progress = 0;
|
||||
int connect_timeout = 0;
|
||||
int keep_partial = 0;
|
||||
int safe_symlinks = 0;
|
||||
int copy_unsafe_links = 0;
|
||||
@@ -185,8 +188,8 @@ int list_only = 0;
|
||||
#define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
|
||||
char *batch_name = NULL;
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
int need_unsorted_flist = 0;
|
||||
#ifdef ICONV_OPTION
|
||||
char *iconv_opt = ICONV_OPTION;
|
||||
#endif
|
||||
|
||||
@@ -200,7 +203,7 @@ static int itemize_changes = 0;
|
||||
static int refused_delete, refused_archive_part, refused_compress;
|
||||
static int refused_partial, refused_progress, refused_delete_before;
|
||||
static int refused_delete_during;
|
||||
static int refused_inplace;
|
||||
static int refused_inplace, refused_no_iconv;
|
||||
static char *max_size_arg, *min_size_arg;
|
||||
static char tmp_partialdir[] = ".~tmp~";
|
||||
|
||||
@@ -216,6 +219,7 @@ static void print_rsync_version(enum logcode f)
|
||||
char const *got_socketpair = "no ";
|
||||
char const *have_inplace = "no ";
|
||||
char const *hardlinks = "no ";
|
||||
char const *symtimes = "no ";
|
||||
char const *acls = "no ";
|
||||
char const *xattrs = "no ";
|
||||
char const *links = "no ";
|
||||
@@ -250,10 +254,13 @@ static void print_rsync_version(enum logcode f)
|
||||
#ifdef ICONV_OPTION
|
||||
iconv = "";
|
||||
#endif
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
symtimes = "";
|
||||
#endif
|
||||
|
||||
rprintf(f, "%s version %s protocol version %d%s\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
|
||||
rprintf(f, "Copyright (C) 1996-2007 by Andrew Tridgell, Wayne Davison, and others.\n");
|
||||
rprintf(f, "Copyright (C) 1996-2008 by Andrew Tridgell, Wayne Davison, and others.\n");
|
||||
rprintf(f, "Web site: http://rsync.samba.org/\n");
|
||||
rprintf(f, "Capabilities:\n");
|
||||
rprintf(f, " %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
|
||||
@@ -263,8 +270,8 @@ static void print_rsync_version(enum logcode f)
|
||||
(int)(sizeof (int64) * 8));
|
||||
rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
|
||||
got_socketpair, hardlinks, links, ipv6, have_inplace);
|
||||
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv\n",
|
||||
have_inplace, acls, xattrs, iconv);
|
||||
rprintf(f, " %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
|
||||
have_inplace, acls, xattrs, iconv, symtimes);
|
||||
|
||||
#ifdef MAINTAINER_MODE
|
||||
rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
|
||||
@@ -351,8 +358,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --fake-super store/recover privileged attrs using xattrs\n");
|
||||
#endif
|
||||
rprintf(F," -S, --sparse handle sparse files efficiently\n");
|
||||
rprintf(F," -n, --dry-run show what would have been transferred\n");
|
||||
rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n");
|
||||
rprintf(F," -n, --dry-run perform a trial run with no changes made\n");
|
||||
rprintf(F," -W, --whole-file copy files whole (without delta-xfer algorithm)\n");
|
||||
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
|
||||
rprintf(F," -B, --block-size=SIZE force a fixed checksum block-size\n");
|
||||
rprintf(F," -e, --rsh=COMMAND specify the remote shell to use\n");
|
||||
@@ -377,7 +384,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --delay-updates put all updated files into place at transfer's end\n");
|
||||
rprintf(F," -m, --prune-empty-dirs prune empty directory chains from the file-list\n");
|
||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
|
||||
rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n");
|
||||
rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n");
|
||||
rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n");
|
||||
rprintf(F," --size-only skip files that match in size\n");
|
||||
rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n");
|
||||
@@ -421,7 +429,7 @@ void usage(enum logcode F)
|
||||
rprintf(F," --read-batch=FILE read a batched update from FILE\n");
|
||||
rprintf(F," --protocol=NUM force an older protocol version to be used\n");
|
||||
#ifdef ICONV_OPTION
|
||||
rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filesnames\n");
|
||||
rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filenames\n");
|
||||
#endif
|
||||
rprintf(F," -4, --ipv4 prefer IPv4\n");
|
||||
rprintf(F," -6, --ipv6 prefer IPv6\n");
|
||||
@@ -438,7 +446,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
|
||||
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
|
||||
OPT_NO_D, OPT_APPEND,
|
||||
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
|
||||
OPT_SERVER, OPT_REFUSED_BASE = 9000};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
@@ -467,6 +475,8 @@ static struct poptOption long_options[] = {
|
||||
{"dirs", 'd', POPT_ARG_VAL, &xfer_dirs, 2, 0, 0 },
|
||||
{"no-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 0, 0, 0 },
|
||||
{"no-d", 0, POPT_ARG_VAL, &xfer_dirs, 0, 0, 0 },
|
||||
{"old-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 },
|
||||
{"old-d", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 },
|
||||
{"perms", 'p', POPT_ARG_VAL, &preserve_perms, 1, 0, 0 },
|
||||
{"no-perms", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
|
||||
{"no-p", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
|
||||
@@ -521,14 +531,19 @@ static struct poptOption long_options[] = {
|
||||
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
|
||||
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
|
||||
{"one-file-system", 'x', POPT_ARG_NONE, 0, 'x', 0, 0 },
|
||||
{"no-one-file-system",'x',POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
|
||||
{"no-x", 'x', POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
|
||||
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
|
||||
{"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
|
||||
{"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
|
||||
{"ignore-existing", 0, POPT_ARG_NONE, &ignore_existing, 0, 0, 0 },
|
||||
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
|
||||
{"min-size", 0, POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
|
||||
{"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
|
||||
{"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
|
||||
{"sparse", 'S', POPT_ARG_VAL, &sparse_files, 1, 0, 0 },
|
||||
{"no-sparse", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
|
||||
{"no-S", 0, POPT_ARG_VAL, &sparse_files, 0, 0, 0 },
|
||||
{"inplace", 0, POPT_ARG_VAL, &inplace, 1, 0, 0 },
|
||||
{"no-inplace", 0, POPT_ARG_VAL, &inplace, 0, 0, 0 },
|
||||
{"append", 0, POPT_ARG_NONE, 0, OPT_APPEND, 0, 0 },
|
||||
{"append-verify", 0, POPT_ARG_VAL, &append_mode, 2, 0, 0 },
|
||||
{"no-append", 0, POPT_ARG_VAL, &append_mode, 0, 0, 0 },
|
||||
@@ -541,8 +556,10 @@ static struct poptOption long_options[] = {
|
||||
{"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 },
|
||||
{"remove-sent-files",0, POPT_ARG_VAL, &remove_source_files, 2, 0, 0 }, /* deprecated */
|
||||
{"remove-source-files",0,POPT_ARG_VAL, &remove_source_files, 1, 0, 0 },
|
||||
{"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
|
||||
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
|
||||
{"force", 0, POPT_ARG_VAL, &force_delete, 1, 0, 0 },
|
||||
{"no-force", 0, POPT_ARG_VAL, &force_delete, 0, 0, 0 },
|
||||
{"ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 1, 0, 0 },
|
||||
{"no-ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 0, 0, 0 },
|
||||
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
|
||||
{0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
|
||||
{"filter", 'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
|
||||
@@ -561,11 +578,13 @@ static struct poptOption long_options[] = {
|
||||
{"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
|
||||
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
|
||||
{"fuzzy", 'y', POPT_ARG_NONE, &fuzzy_basis, 0, 0, 0 },
|
||||
{"fuzzy", 'y', POPT_ARG_VAL, &fuzzy_basis, 1, 0, 0 },
|
||||
{"no-fuzzy", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 },
|
||||
{"no-y", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 },
|
||||
{"compress", 'z', POPT_ARG_NONE, 0, 'z', 0, 0 },
|
||||
{"no-compress", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 },
|
||||
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
|
||||
{"no-z", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 },
|
||||
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
|
||||
{"compress-level", 0, POPT_ARG_INT, &def_compress_level, 'z', 0, 0 },
|
||||
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
|
||||
{"progress", 0, POPT_ARG_VAL, &do_progress, 1, 0, 0 },
|
||||
@@ -575,7 +594,9 @@ static struct poptOption long_options[] = {
|
||||
{"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
|
||||
{"delay-updates", 0, POPT_ARG_VAL, &delay_updates, 1, 0, 0 },
|
||||
{"no-delay-updates", 0, POPT_ARG_VAL, &delay_updates, 0, 0, 0 },
|
||||
{"prune-empty-dirs",'m', POPT_ARG_NONE, &prune_empty_dirs, 0, 0, 0 },
|
||||
{"prune-empty-dirs",'m', POPT_ARG_VAL, &prune_empty_dirs, 1, 0, 0 },
|
||||
{"no-prune-empty-dirs",0,POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 },
|
||||
{"no-m", 0, POPT_ARG_VAL, &prune_empty_dirs, 0, 0, 0 },
|
||||
{"log-file", 0, POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
|
||||
{"log-file-format", 0, POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
|
||||
{"out-format", 0, POPT_ARG_STRING, &stdout_format, 0, 0, 0 },
|
||||
@@ -603,15 +624,20 @@ static struct poptOption long_options[] = {
|
||||
{"no-numeric-ids", 0, POPT_ARG_VAL, &numeric_ids, 0, 0, 0 },
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
|
||||
{"no-timeout", 0, POPT_ARG_VAL, &io_timeout, 0, 0, 0 },
|
||||
{"contimeout", 0, POPT_ARG_INT, &connect_timeout, 0, 0, 0 },
|
||||
{"no-contimeout", 0, POPT_ARG_VAL, &connect_timeout, 0, 0, 0 },
|
||||
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
|
||||
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
|
||||
#ifdef ICONV_OPTION
|
||||
{"iconv", 0, POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
|
||||
{"no-iconv", 0, POPT_ARG_NONE, 0, OPT_NO_ICONV, 0, 0 },
|
||||
#endif
|
||||
{"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
|
||||
{"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
|
||||
{"8-bit-output", '8', POPT_ARG_NONE, &allow_8bit_chars, 0, 0, 0 },
|
||||
{"8-bit-output", '8', POPT_ARG_VAL, &allow_8bit_chars, 1, 0, 0 },
|
||||
{"no-8-bit-output", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
|
||||
{"no-8", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
|
||||
{"qsort", 0, POPT_ARG_NONE, &use_qsort, 0, 0, 0 },
|
||||
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
|
||||
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
|
||||
@@ -754,6 +780,8 @@ static void set_refuse_options(char *bp)
|
||||
refused_progress = op->val;
|
||||
else if (wildmatch("inplace", op->longName))
|
||||
refused_inplace = op->val;
|
||||
else if (wildmatch("no-iconv", op->longName))
|
||||
refused_no_iconv = op->val;
|
||||
break;
|
||||
}
|
||||
if (!is_wild)
|
||||
@@ -864,7 +892,7 @@ static void create_refuse_error(int which)
|
||||
*
|
||||
* @retval 0 on error, with err_buf containing an explanation
|
||||
**/
|
||||
int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
int parse_arguments(int *argc_p, const char ***argv_p)
|
||||
{
|
||||
static poptContext pc;
|
||||
char *ref = lp_refuse_options(module_id);
|
||||
@@ -874,8 +902,13 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
|
||||
if (ref && *ref)
|
||||
set_refuse_options(ref);
|
||||
if (am_daemon)
|
||||
if (am_daemon) {
|
||||
set_refuse_options("log-file*");
|
||||
#ifdef ICONV_OPTION
|
||||
if (!*lp_charset(module_id))
|
||||
set_refuse_options("iconv");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (!am_daemon && !protect_args && (arg = getenv("RSYNC_ICONV")) != NULL && *arg)
|
||||
@@ -1001,16 +1034,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
case OPT_INCLUDE_FROM:
|
||||
arg = poptGetOptArg(pc);
|
||||
if (sanitize_paths)
|
||||
arg = sanitize_path(NULL, arg, NULL, 0, NULL);
|
||||
if (server_filter_list.head) {
|
||||
arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
|
||||
if (daemon_filter_list.head) {
|
||||
int rej;
|
||||
char *cp = strdup(arg);
|
||||
char *dir, *cp = strdup(arg);
|
||||
if (!cp)
|
||||
out_of_memory("parse_arguments");
|
||||
if (!*cp)
|
||||
goto options_rejected;
|
||||
clean_fname(cp, 1);
|
||||
rej = check_filter(&server_filter_list, cp, 0) < 0;
|
||||
dir = cp + (*cp == '/' ? module_dirlen : 0);
|
||||
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0;
|
||||
free(cp);
|
||||
if (rej)
|
||||
goto options_rejected;
|
||||
@@ -1063,8 +1097,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
if (frommain)
|
||||
quiet++;
|
||||
quiet++;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
@@ -1122,6 +1155,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
read_batch = 1;
|
||||
break;
|
||||
|
||||
case OPT_NO_ICONV:
|
||||
#ifdef ICONV_OPTION
|
||||
iconv_opt = NULL;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_MAX_SIZE:
|
||||
if ((max_size = parse_size_arg(&max_size_arg, 'b')) <= 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
@@ -1236,7 +1275,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
}
|
||||
}
|
||||
|
||||
if (human_readable && argc == 2) {
|
||||
if (human_readable && argc == 2 && !am_server) {
|
||||
/* Allow the old meaning of 'h' (--help) on its own. */
|
||||
usage(FINFO);
|
||||
exit_cleanup(0);
|
||||
@@ -1249,15 +1288,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
else
|
||||
need_unsorted_flist = 1;
|
||||
}
|
||||
setup_iconv();
|
||||
if (refused_no_iconv && !iconv_opt) {
|
||||
create_refuse_error(refused_no_iconv);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (protect_args == 1) {
|
||||
if (!frommain)
|
||||
protect_args = 0;
|
||||
else if (am_server)
|
||||
return 1;
|
||||
}
|
||||
if (protect_args == 1 && am_server)
|
||||
return 1;
|
||||
|
||||
*argv_p = argv = poptGetArgs(pc);
|
||||
*argc_p = argc = count_args(argv);
|
||||
|
||||
#ifndef SUPPORT_LINKS
|
||||
if (preserve_links && !am_sender) {
|
||||
@@ -1277,7 +1318,13 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SUPPORT_XATTRS
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (am_root < 0 && preserve_xattrs > 1) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--fake-super conflicts with -XX\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (am_root < 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--fake-super requires an rsync with extended attributes enabled\n");
|
||||
@@ -1302,7 +1349,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
batch_name = NULL;
|
||||
} else if (dry_run)
|
||||
write_batch = 0;
|
||||
}
|
||||
} else if (write_batch < 0 && dry_run)
|
||||
write_batch = 0;
|
||||
if (read_batch && files_from) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--read-batch cannot be used with --files-from\n");
|
||||
@@ -1339,8 +1387,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
xfer_dirs = 1;
|
||||
}
|
||||
|
||||
if (xfer_dirs < 1)
|
||||
xfer_dirs = recurse || list_only;
|
||||
if (argc < 2 && !read_batch && !am_server)
|
||||
list_only |= 1;
|
||||
|
||||
if (xfer_dirs >= 4) {
|
||||
parse_rule(&filter_list, "- /*/*", 0, 0);
|
||||
recurse = xfer_dirs = 1;
|
||||
} else if (recurse)
|
||||
xfer_dirs = 1;
|
||||
else if (xfer_dirs < 0)
|
||||
xfer_dirs = list_only ? 1 : 0;
|
||||
|
||||
if (relative_paths < 0)
|
||||
relative_paths = files_from? 1 : 0;
|
||||
@@ -1389,32 +1445,33 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
need_messages_from_generator = 1;
|
||||
}
|
||||
|
||||
*argv_p = argv = poptGetArgs(pc);
|
||||
*argc_p = argc = count_args(argv);
|
||||
|
||||
if (sanitize_paths) {
|
||||
int i;
|
||||
for (i = argc; i-- > 0; )
|
||||
argv[i] = sanitize_path(NULL, argv[i], "", 0, NULL);
|
||||
argv[i] = sanitize_path(NULL, argv[i], "", 0, SP_KEEP_DOT_DIRS);
|
||||
if (tmpdir)
|
||||
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
|
||||
tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
|
||||
if (backup_dir)
|
||||
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
|
||||
backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
|
||||
}
|
||||
if (server_filter_list.head && !am_sender) {
|
||||
struct filter_list_struct *elp = &server_filter_list;
|
||||
if (daemon_filter_list.head && !am_sender) {
|
||||
struct filter_list_struct *elp = &daemon_filter_list;
|
||||
if (tmpdir) {
|
||||
char *dir;
|
||||
if (!*tmpdir)
|
||||
goto options_rejected;
|
||||
clean_fname(tmpdir, 1);
|
||||
if (check_filter(elp, tmpdir, 1) < 0)
|
||||
dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0);
|
||||
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (check_filter(elp, FLOG, dir, 1) < 0)
|
||||
goto options_rejected;
|
||||
}
|
||||
if (backup_dir) {
|
||||
char *dir;
|
||||
if (!*backup_dir)
|
||||
goto options_rejected;
|
||||
clean_fname(backup_dir, 1);
|
||||
if (check_filter(elp, backup_dir, 1) < 0)
|
||||
dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
|
||||
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (check_filter(elp, FLOG, dir, 1) < 0)
|
||||
goto options_rejected;
|
||||
}
|
||||
}
|
||||
@@ -1566,7 +1623,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
}
|
||||
if (partial_dir) {
|
||||
if (*partial_dir)
|
||||
clean_fname(partial_dir, 1);
|
||||
clean_fname(partial_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (!*partial_dir || strcmp(partial_dir, ".") == 0)
|
||||
partial_dir = NULL;
|
||||
if (!partial_dir && refused_partial) {
|
||||
@@ -1603,12 +1660,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
}
|
||||
} else {
|
||||
if (sanitize_paths)
|
||||
files_from = sanitize_path(NULL, files_from, NULL, 0, NULL);
|
||||
if (server_filter_list.head) {
|
||||
files_from = sanitize_path(NULL, files_from, NULL, 0, SP_DEFAULT);
|
||||
if (daemon_filter_list.head) {
|
||||
char *dir;
|
||||
if (!*files_from)
|
||||
goto options_rejected;
|
||||
clean_fname(files_from, 1);
|
||||
if (check_filter(&server_filter_list, files_from, 0) < 0)
|
||||
dir = files_from + (*files_from == '/' ? module_dirlen : 0);
|
||||
clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (check_filter(&daemon_filter_list, FLOG, dir, 0) < 0)
|
||||
goto options_rejected;
|
||||
}
|
||||
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
|
||||
@@ -1645,12 +1704,8 @@ void server_options(char **args, int *argc_p)
|
||||
static char argstr[64];
|
||||
int ac = *argc_p;
|
||||
char *arg;
|
||||
|
||||
int i, x;
|
||||
|
||||
if (blocking_io == -1)
|
||||
blocking_io = 0;
|
||||
|
||||
/* This should always remain first on the server's command-line. */
|
||||
args[ac++] = "--server";
|
||||
|
||||
@@ -1682,7 +1737,8 @@ void server_options(char **args, int *argc_p)
|
||||
argstr[x++] = 'n';
|
||||
if (preserve_links)
|
||||
argstr[x++] = 'l';
|
||||
if (xfer_dirs > (recurse || !delete_mode || !am_sender ? 1 : 0))
|
||||
if ((xfer_dirs >= 2 && xfer_dirs < 4)
|
||||
|| (xfer_dirs && !recurse && (list_only || (delete_mode && am_sender))))
|
||||
argstr[x++] = 'd';
|
||||
if (am_sender) {
|
||||
if (keep_dirlinks)
|
||||
@@ -1752,25 +1808,25 @@ void server_options(char **args, int *argc_p)
|
||||
if (do_compression)
|
||||
argstr[x++] = 'z';
|
||||
|
||||
/* This is a complete hack - blame Rusty. FIXME!
|
||||
* This hack is only needed for older rsync versions that
|
||||
* don't understand the --list-only option. */
|
||||
if (list_only == 1 && !recurse)
|
||||
argstr[x++] = 'r';
|
||||
|
||||
/* We make use of the -e option to let the server know about any
|
||||
* pre-release protocol version && some behavior flags. */
|
||||
argstr[x++] = 'e';
|
||||
#if SUBPROTOCOL_VERSION != 0
|
||||
/* If we're speaking a pre-release version of a protocol, we tell
|
||||
* the server about this by (ab)using the -e option. */
|
||||
if (protocol_version == PROTOCOL_VERSION) {
|
||||
x += snprintf(argstr+x, sizeof argstr - x,
|
||||
"e%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
|
||||
}
|
||||
"%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
|
||||
} else
|
||||
#endif
|
||||
argstr[x++] = '.';
|
||||
set_allow_inc_recurse();
|
||||
if (allow_inc_recurse)
|
||||
argstr[x++] = 'i';
|
||||
#if defined HAVE_LUTIMES && defined HAVE_UTIMES
|
||||
argstr[x++] = 'L';
|
||||
#endif
|
||||
|
||||
argstr[x] = '\0';
|
||||
|
||||
if (x != 1)
|
||||
args[ac++] = argstr;
|
||||
args[ac++] = argstr;
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (iconv_opt) {
|
||||
@@ -1785,7 +1841,7 @@ void server_options(char **args, int *argc_p)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (protect_args) /* initial args break here */
|
||||
if (protect_args && !local_server) /* unprotected args stop here */
|
||||
args[ac++] = NULL;
|
||||
|
||||
if (list_only > 1)
|
||||
@@ -1931,8 +1987,8 @@ void server_options(char **args, int *argc_p)
|
||||
if (numeric_ids)
|
||||
args[ac++] = "--numeric-ids";
|
||||
|
||||
if (!allow_inc_recurse)
|
||||
args[ac++] = "--no-i-r";
|
||||
if (use_qsort)
|
||||
args[ac++] = "--use-qsort";
|
||||
|
||||
if (am_sender) {
|
||||
if (ignore_existing)
|
||||
|
||||
6
packaging/bin/gpg
Executable file
6
packaging/bin/gpg
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
# This script gets git to run gpg with a --passphrase-file option.
|
||||
|
||||
PATH=`echo $PATH | sed 's/^[^:]*://'`
|
||||
|
||||
gpg --batch --passphrase-file=$GPG_PASSFILE "${@}"
|
||||
@@ -1,9 +1,11 @@
|
||||
Summary: A program for synchronizing files over a network.
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.0.0pre1
|
||||
Release: 1
|
||||
Version: 3.0.1
|
||||
%define fullversion %{version}pre3
|
||||
Release: 0.1.pre3
|
||||
Group: Applications/Internet
|
||||
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz
|
||||
Source0: http://rsync.samba.org/ftp/rsync/%{name}-%{fullversion}.tar.gz
|
||||
Source1: http://rsync.samba.org/ftp/rsync/%{name}-patches-%{fullversion}.tar.gz
|
||||
URL: http://rsync.samba.org/
|
||||
|
||||
Prefix: %{_prefix}
|
||||
@@ -11,16 +13,25 @@ BuildRoot: /var/tmp/%{name}-root
|
||||
License: GPL
|
||||
|
||||
%description
|
||||
Rsync uses a reliable algorithm to bring remote and host files into
|
||||
sync very quickly. Rsync is fast because it just sends the differences
|
||||
in the files over the network instead of sending the complete
|
||||
files. Rsync is often used as a very powerful mirroring process or
|
||||
just as a more capable replacement for the rcp command. A technical
|
||||
report which describes the rsync algorithm is included in this
|
||||
package.
|
||||
Rsync is a fast and extraordinarily versatile file copying tool. It can
|
||||
copy locally, to/from another host over any remote shell, or to/from a
|
||||
remote rsync daemon. It offers a large number of options that control
|
||||
every aspect of its behavior and permit very flexible specification of the
|
||||
set of files to be copied. It is famous for its delta-transfer algorithm,
|
||||
which reduces the amount of data sent over the network by sending only the
|
||||
differences between the source files and the existing files in the
|
||||
destination. Rsync is widely used for backups and mirroring and as an
|
||||
improved copy command for everyday use.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
# Choose one -- setup source only, or setup source + rsync-patches:
|
||||
%setup -q -n %{name}-%{fullversion}
|
||||
#%setup -q -n %{name}-%{fullversion} -b1
|
||||
|
||||
# If you you used "%setup -q -b1", choose the patches you wish to apply:
|
||||
#patch -p1 <patches/acls.diff
|
||||
#patch -p1 <patches/xattrs.diff
|
||||
#patch -p1 <patches/checksum-reading.diff
|
||||
|
||||
%build
|
||||
%configure
|
||||
@@ -32,57 +43,24 @@ rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%makeinstall
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/xinetd.d
|
||||
install -m 644 packaging/lsb/rsync.xinetd $RPM_BUILD_ROOT/etc/xinetd.d/rsync
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc COPYING README tech_report.tex
|
||||
%config(noreplace) /etc/xinetd.d/rsync
|
||||
%{_prefix}/bin/rsync
|
||||
%{_mandir}/man1/rsync.1*
|
||||
%{_mandir}/man5/rsyncd.conf.5*
|
||||
|
||||
%changelog
|
||||
* Thu Jan 30 2003 Horst von Brand <vonbrand@inf.utfsm.cl>
|
||||
Fixed "Sept" date in %changelog here
|
||||
Use %{_mandir} to point to manpages
|
||||
Support for compressed manpages (* at end catches them in %files)
|
||||
Add doc/README-SGML and doc/rsync.sgml to %doc
|
||||
* Sun Mar 30 2008 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.1pre3.
|
||||
|
||||
* Mon Sep 11 2000 John H Terpstra <jht@turbolinux.com>
|
||||
Changed target paths to be Linux Standards Base compliant
|
||||
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
|
||||
Added installation of /etc/xinetd.d/rsync file and some commented-out
|
||||
lines that demonstrate how to use the rsync-patches tar file.
|
||||
|
||||
13
packaging/lsb/rsync.xinetd
Normal file
13
packaging/lsb/rsync.xinetd
Normal file
@@ -0,0 +1,13 @@
|
||||
# default: off
|
||||
# description: The rsync server is a good addition to an ftp server, as it
|
||||
# allows crc checksumming etc.
|
||||
service rsync
|
||||
{
|
||||
disable = yes
|
||||
socket_type = stream
|
||||
wait = no
|
||||
user = root
|
||||
server = /usr/bin/rsync
|
||||
server_args = --daemon
|
||||
log_on_failure += USERID
|
||||
}
|
||||
@@ -14,16 +14,13 @@ use strict;
|
||||
use Getopt::Long;
|
||||
use Date::Format;
|
||||
|
||||
# Choose any dir where a pristine rsync has been checked out of CVS.
|
||||
our $unpacked = $ENV{HOME} . '/release/nightly';
|
||||
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
|
||||
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
|
||||
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
|
||||
# Where the local copy of /home/ftp/pub/rsync/dev/nightly should be updated.
|
||||
our $dest = $ENV{HOME} . '/samba-rsync-ftp/dev/nightly';
|
||||
our $nightly_symlink = "$dest/rsync-HEAD.tar.gz";
|
||||
|
||||
our($cvs_update, $make_tar, $upload, $help_opt);
|
||||
our($make_tar, $upload, $help_opt);
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'cvs-update|c' => \$cvs_update,
|
||||
'make-tar|t' => \$make_tar,
|
||||
'upload|u' => \$upload,
|
||||
'help|h' => \$help_opt,
|
||||
@@ -32,70 +29,65 @@ our($cvs_update, $make_tar, $upload, $help_opt);
|
||||
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
|
||||
our $ztoday = time2str('%d %b %Y', time);
|
||||
our $today = $ztoday;
|
||||
our $gen_target = $upload ? 'gensend' : 'gen';
|
||||
|
||||
chdir($unpacked) or die $!;
|
||||
|
||||
if ($cvs_update) {
|
||||
print "Updating from cvs...\n";
|
||||
system 'cvs -q up' and die $!;
|
||||
}
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
die "There is no .git dir in the current directory.\n" unless -d '.git';
|
||||
die "There is no rsync checkout in the current directory.\n" unless -f 'rsyncd.conf.yo';
|
||||
|
||||
if ($make_tar) {
|
||||
print "Generating list of active CVS files...\n";
|
||||
my($dir, @files);
|
||||
open(CVS, '-|', 'cvs status 2>&1') or die $!;
|
||||
while (<CVS>) {
|
||||
if (/^cvs status: Examining (.*)/) {
|
||||
if ($1 eq '.') {
|
||||
$dir = '';
|
||||
} else {
|
||||
push(@files, $1);
|
||||
$dir = $1 . '/';
|
||||
}
|
||||
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
|
||||
push(@files, $dir . $1);
|
||||
if ($2 ne 'Up-to-date') {
|
||||
print "*** Not up-to-date: $dir$1\n";
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
|
||||
system "make $gen_target" and die "make $gen_target failed!\n";
|
||||
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
while (<IN>) {
|
||||
if (s/^GENFILES=//) {
|
||||
while (s/\\$//) {
|
||||
$_ .= <IN>;
|
||||
}
|
||||
@extra_files = split(' ', $_);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close CVS;
|
||||
close IN;
|
||||
|
||||
print "Creating $name.tar.gz\n";
|
||||
system "rsync -a @extra_files $name/";
|
||||
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
|
||||
system "support/git-set-file-times --prefix=$name/";
|
||||
system "fakeroot tar czf $dest/$name.tar.gz $name; rm -rf $name";
|
||||
|
||||
print "Creating $unpacked/$name.tar.gz\n";
|
||||
chdir('..') or die $!;
|
||||
rename($unpacked, $name) or die $!;
|
||||
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $nightly/$name.tar.gz $name") or die $!;
|
||||
foreach (@files) {
|
||||
print TAR "$name/$_\n";
|
||||
}
|
||||
close TAR;
|
||||
rename($name, $unpacked) or die $!;
|
||||
unlink($nightly_symlink);
|
||||
symlink("$name.tar.gz", $nightly_symlink);
|
||||
}
|
||||
|
||||
chdir($nightly) or die $!;
|
||||
|
||||
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
|
||||
my $html_fn = $fn;
|
||||
$html_fn =~ s/\.yo/.html/;
|
||||
my $yo_tmp = "$dest/$fn";
|
||||
(my $html_fn = "$dest/$fn") =~ s/\.yo/.html/;
|
||||
|
||||
open(IN, '<', "$unpacked/$fn") or die $!;
|
||||
open(IN, '<', $fn) or die $!;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
|
||||
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
|
||||
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
|
||||
|
||||
open(OUT, '>', $fn) or die $!;
|
||||
open(OUT, '>', $yo_tmp) or die $!;
|
||||
print OUT $_;
|
||||
close OUT;
|
||||
|
||||
system "yodl2html -o $html_fn $fn";
|
||||
system 'yodl2html', '-o', $html_fn, $yo_tmp;
|
||||
|
||||
unlink($fn);
|
||||
unlink($yo_tmp);
|
||||
}
|
||||
|
||||
chdir($dest) or die $!;
|
||||
|
||||
my $cnt = 0;
|
||||
open(PIPE, '-|', 'ls -1t rsync-HEAD-*') or die $!;
|
||||
while (<PIPE>) {
|
||||
@@ -112,7 +104,7 @@ if ($upload) {
|
||||
if (defined $ENV{RSYNC_PARTIAL_DIR}) {
|
||||
$opt = " -f 'R $ENV{RSYNC_PARTIAL_DIR}'";
|
||||
}
|
||||
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
|
||||
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/dev/nightly";
|
||||
}
|
||||
|
||||
exit;
|
||||
@@ -122,8 +114,7 @@ sub usage
|
||||
die <<EOT;
|
||||
Usage: nightly-rsync [OPTIONS]
|
||||
|
||||
-c, --cvs-update update $unpacked via CVS.
|
||||
-t, --make-tar create a new tar file in $nightly
|
||||
-t, --make-tar create a new tar file in $dest
|
||||
-u, --upload upload the revised nightly dir to samba.org
|
||||
-h, --help display this help
|
||||
EOT
|
||||
|
||||
@@ -1,182 +1,201 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to
|
||||
# be a copy of the /home/ftp/pub/rsync dir on samba.org. If it is run
|
||||
# in test mode, it instead expects a dir named ~/tmp/samba-rsync-ftp
|
||||
# (e.g. copy ~/samba-rsync-ftp into ~/tmp and you can do a trial-run of
|
||||
# a release without affecting the files in the ~/samba-rsync-ftp dir).
|
||||
#
|
||||
# Run this as "release-rsync live" to affect ~/samba-rsync-ftp instead
|
||||
# of ~/tmp/samba-rsync-ftp.
|
||||
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
|
||||
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
|
||||
# the git repository in the current directory will be updated, and the local
|
||||
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
|
||||
|
||||
use Cwd;
|
||||
use Term::ReadKey;
|
||||
use Date::Format;
|
||||
|
||||
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
|
||||
my $releasedir = $ENV{HOME} . '/release';
|
||||
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
|
||||
my $passfile = $ENV{HOME} . '/.rsyncpass';
|
||||
my $path = $ENV{PATH};
|
||||
|
||||
my $ztoday = time2str('%d %b %Y', time);
|
||||
my $today = $ztoday;
|
||||
$today =~ s/^0//;
|
||||
my $now = time;
|
||||
my $cl_today = time2str('* %a %b %d %Y', $now);
|
||||
my $year = time2str('%Y', $now);
|
||||
my $ztoday = time2str('%d %b %Y', $now);
|
||||
(my $today = $ztoday) =~ s/^0//;
|
||||
|
||||
my $break = <<EOT;
|
||||
==========================================================================
|
||||
EOT
|
||||
my $note = <<EOT;
|
||||
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
|
||||
EOT
|
||||
my $curdir = Cwd::cwd;
|
||||
|
||||
my $live = shift;
|
||||
my $skipping = '';
|
||||
|
||||
print $break;
|
||||
if ($live) {
|
||||
print <<EOT;
|
||||
== This will release a new version of rsync onto an unsuspecting world. ==
|
||||
EOT
|
||||
} else {
|
||||
print <<EOT;
|
||||
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
|
||||
EOT
|
||||
$dest =~ s#([^/]+$)#tmp/$1#;
|
||||
$skipping = ' ** SKIPPING **';
|
||||
}
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
|
||||
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
|
||||
|
||||
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
|
||||
chdir($releasedir) or die $!;
|
||||
|
||||
system 'rm -rf rsync';
|
||||
|
||||
my(%dirs, @files);
|
||||
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
|
||||
while (<CVS>) {
|
||||
print $_;
|
||||
next if /\.(cvs)?ignore$/;
|
||||
if (m#^[UP] rsync/(.*)#) {
|
||||
my $fn = $1;
|
||||
my($dir) = $fn =~ m#^(.+)/#;
|
||||
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
|
||||
push(@files, $fn);
|
||||
}
|
||||
END {
|
||||
unlink($passfile);
|
||||
}
|
||||
|
||||
chdir('rsync') or die $!;
|
||||
|
||||
my($version, $lastversion);
|
||||
open(IN, '<', 'configure.in') or die $!;
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$version = $lastversion = $1;
|
||||
if (s/^GENFILES=//) {
|
||||
while (s/\\$//) {
|
||||
$_ .= <IN>;
|
||||
}
|
||||
@extra_files = split(' ', $_);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
if ($lastversion =~ /cvs$/) {
|
||||
open(IN, '<', 'OLDNEWS') or die $!;
|
||||
$_ = <IN>;
|
||||
close IN;
|
||||
($lastversion) = /(\d+\.\d+\.\d+)/;
|
||||
my $break = <<EOT;
|
||||
==========================================================================
|
||||
EOT
|
||||
|
||||
print $break, <<EOT, $break, "\n";
|
||||
== This will release a new version of rsync onto an unsuspecting world. ==
|
||||
EOT
|
||||
|
||||
die "$dest does not exist\n" unless -d $dest;
|
||||
die "There is no .git dir in the current directory.\n" unless -d '.git';
|
||||
die "'a' must not exist in the current directory.\n" if -e 'a';
|
||||
die "'b' must not exist in the current directory.\n" if -e 'b';
|
||||
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
|
||||
|
||||
my $confversion;
|
||||
open(IN, '<', 'configure.in') or die $!;
|
||||
while (<IN>) {
|
||||
if (/^RSYNC_VERSION=(.*)/) {
|
||||
$confversion = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
die "Unable to find RSYNC_VERSION in configure.in\n" unless defined $confversion;
|
||||
|
||||
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
|
||||
open(IN, '<', 'OLDNEWS') or die $!;
|
||||
$_ = <IN>;
|
||||
close IN;
|
||||
my($lastversion) = /(\d+\.\d+\.\d+)/;
|
||||
|
||||
print $break, "\nPlease enter the version number of this release: [$version] ";
|
||||
my $version = $confversion;
|
||||
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
|
||||
|
||||
print "Please enter the version number of this release: [$version] ";
|
||||
chomp($_ = <STDIN>);
|
||||
if ($_ eq '.') {
|
||||
$version =~ s/pre\d+//;
|
||||
} elsif ($_ ne '') {
|
||||
$version = $_;
|
||||
}
|
||||
$version =~ s/[-.]*pre[-.]*/pre/;
|
||||
die "Invalid version: `$version'\n" unless $version =~ /^[\d.]+(pre\d+)?$/;
|
||||
|
||||
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
|
||||
if (`git tag -l v$version` ne '') {
|
||||
print "Tag v$version already exists.\n\nDelete tag or quit? [q/del] ";
|
||||
$_ = <STDIN>;
|
||||
exit 1 unless /^del/i;
|
||||
system "git tag -d v$version";
|
||||
}
|
||||
|
||||
my $cvstag = "release-$version";
|
||||
$cvstag =~ s/[.]/-/g;
|
||||
$cvstag =~ s/pre/-pre/;
|
||||
if ($version =~ s/[-.]*pre[-.]*/pre/ && $confversion !~ /dev$/) {
|
||||
$lastversion = $confversion;
|
||||
}
|
||||
|
||||
print "Enter the previous version to produce a patch against: [$lastversion] ";
|
||||
chomp($_ = <STDIN>);
|
||||
$lastversion = $_ if $_ ne '';
|
||||
$lastversion =~ s/[-.]*pre[-.]*/pre/;
|
||||
|
||||
my $release = 1;
|
||||
my $pre = $version =~ /(pre\d+)/ ? $1 : '';
|
||||
|
||||
my $release = $pre ? '0.1' : '1';
|
||||
print "Please enter the RPM release number of this release: [$release] ";
|
||||
chomp($_ = <STDIN>);
|
||||
$release = $_ if $_ ne '';
|
||||
$release .= ".$pre" if $pre;
|
||||
|
||||
my $diffdir;
|
||||
my $skipping2;
|
||||
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
|
||||
if ($lastversion =~ /pre/) {
|
||||
if ($version !~ /pre/) {
|
||||
if (!$pre) {
|
||||
die "You should not diff a release version against a pre-release version.\n";
|
||||
}
|
||||
$diffdir = "$dest/old-previews";
|
||||
$skipping2 = ' ** SKIPPING **';
|
||||
} elsif ($version =~ /pre/) {
|
||||
$diffdir = $dest;
|
||||
$skipping2 = ' ** SKIPPING **';
|
||||
$srcdir = $srcdiffdir = $lastsrcdir = 'src-previews';
|
||||
$skipping = ' ** SKIPPING **';
|
||||
} elsif ($pre) {
|
||||
$srcdir = $srcdiffdir = 'src-previews';
|
||||
$lastsrcdir = 'src';
|
||||
$skipping = ' ** SKIPPING **';
|
||||
} else {
|
||||
$diffdir = "$dest/old-versions";
|
||||
$skipping2 = '';
|
||||
$srcdir = $lastsrcdir = 'src';
|
||||
$srcdiffdir = 'src-diffs';
|
||||
$skipping = '';
|
||||
}
|
||||
|
||||
print "\n", $break, <<EOT;
|
||||
\$version is "$version"
|
||||
\$lastversion is "$lastversion"
|
||||
\$cvstag is "$cvstag"
|
||||
\$dest is "$dest"
|
||||
\$releasedir is "$releasedir"
|
||||
\$diffdir is "$diffdir"
|
||||
\$curdir is "$curdir"
|
||||
\$srcdir is "$srcdir"
|
||||
\$srcdiffdir is "$srcdiffdir"
|
||||
\$lastsrcdir is "$lastsrcdir"
|
||||
\$release is "$release"
|
||||
|
||||
About to:
|
||||
- make sure that SUBPROTOCOL_VERSION is 0$skipping2
|
||||
- tweak the version in configure.in, configure, and the spec files
|
||||
- make sure that configure, config.h.in, and proto.h are updated
|
||||
- tweak NEWS and OLDNEWS to update the release date$skipping2
|
||||
- tweak the date in the *.yo files and re-generate the man pages
|
||||
- make sure that the patches dir has been updated
|
||||
- page through the "cvs diff" output
|
||||
- make sure that SUBPROTOCOL_VERSION is 0$skipping
|
||||
- tweak the version in configure.in and the spec files
|
||||
- tweak NEWS and OLDNEWS to update the release date$skipping
|
||||
- tweak the date in the *.yo files and generate the manpages
|
||||
- generate configure.sh, config.h.in, and proto.h
|
||||
- page through the differences
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
my $f_opt = /f/ ? ' -f' : '';
|
||||
|
||||
print $break;
|
||||
system "./prepare-source && touch proto.h";
|
||||
(my $finalversion = $version) =~ s/pre\d+//;
|
||||
my %specvars = ( 'Version:' => $finalversion, 'Release:' => $release,
|
||||
'%define fullversion' => "\%{version}$pre", 'Released' => "$version." );
|
||||
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'), glob('*.yo'),
|
||||
qw( configure.in rsync.h NEWS OLDNEWS options.c ) );
|
||||
|
||||
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
|
||||
glob('*.yo'), qw( configure.in configure ) );
|
||||
if ($version !~ /pre/) {
|
||||
push(@tweak_files, qw( rsync.h NEWS OLDNEWS ));
|
||||
}
|
||||
foreach my $fn (@tweak_files) {
|
||||
open(IN, '<', $fn) or die $!;
|
||||
undef $/; $_ = <IN>; $/ = "\n";
|
||||
close IN;
|
||||
if ($fn =~ /configure/) {
|
||||
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m;
|
||||
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m
|
||||
or die "Unable to update RSYNC_VERSION in $fn\n";
|
||||
} elsif ($fn =~ /\.spec/) {
|
||||
s/^(Version:) .*/$1 $version/m;
|
||||
s/^(Release:) .*/$1 $release/m;
|
||||
while (my($str, $val) = each %specvars) {
|
||||
s/^\Q$str\E .*/$str $val/m
|
||||
or die "Unable to update $str in $fn\n";
|
||||
}
|
||||
s/^\* \w\w\w \w\w\w \d\d \d\d\d\d (.*)/$cl_today $1/m
|
||||
or die "Unable to update ChangeLog header in $fn\n";
|
||||
} elsif ($fn =~ /\.yo/) {
|
||||
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
|
||||
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
|
||||
} elsif ($fn eq 'NEWS') {
|
||||
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
|
||||
or die "Couldn't update NEWS file with release date!\n";
|
||||
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m
|
||||
or die "Unable to update date in manpage() header in $fn\n";
|
||||
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m
|
||||
or die "Unable to update current version info in $fn\n";
|
||||
} elsif ($fn eq 'rsync.h') {
|
||||
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/;
|
||||
s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/
|
||||
or die "Unable to find SUBPROTOCOL_VERSION define in $fn\n";
|
||||
next if $pre;
|
||||
} elsif ($fn eq 'NEWS') {
|
||||
s/^(NEWS for rsync \Q$finalversion\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
|
||||
or die "The first line of $fn is not in the right format. It must be:\n"
|
||||
. "NEWS for rsync $finalversion (UNRELEASED)\n";
|
||||
next if $pre;
|
||||
} elsif ($fn eq 'OLDNEWS') {
|
||||
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m
|
||||
or die "Couldn't update OLDNEWS file with release date!\n";
|
||||
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$finalversion\E)/\t$ztoday$1/m
|
||||
or die "Unable to find \"?? ??? $year\t$finalversion\" line in $fn\n";
|
||||
next if $pre;
|
||||
} elsif ($fn eq 'options.c') {
|
||||
if (s/(Copyright \(C\) 2002-)(\d+)( Wayne Davison)/$1$year$3/
|
||||
&& $2 ne $year) {
|
||||
die "Copyright comments need to be updated to $year in all files!\n";
|
||||
}
|
||||
# Adjust the year in the --version output.
|
||||
s/(rprintf\(f, "Copyright \(C\) 1996-)(\d+)/$1$year/
|
||||
or die "Unable to find Copyright string in --version output of $fn\n";
|
||||
next if $2 eq $year;
|
||||
} else {
|
||||
die "Unrecognized file in \@tweak_files: $fn\n";
|
||||
}
|
||||
@@ -185,144 +204,141 @@ foreach my $fn (@tweak_files) {
|
||||
close OUT;
|
||||
}
|
||||
|
||||
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage rsync.1";
|
||||
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage rsyncd.conf.5";
|
||||
|
||||
mkdir('patches/tmp') or die $!;
|
||||
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
|
||||
|
||||
print "\n", $break, $note, $break;
|
||||
system "patches/verify-patches -n -an$f_opt";
|
||||
|
||||
print $break;
|
||||
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
|
||||
system "git diff --color | less -p '^diff .*'";
|
||||
|
||||
my $srctar_name = "rsync-$version.tar.gz";
|
||||
my $pattar_name = "rsync-patches-$version.tar.gz";
|
||||
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
|
||||
my $srctar_file = "$dest/$srcdir/$srctar_name";
|
||||
my $pattar_file = "$dest/$srcdir/$pattar_name";
|
||||
my $diff_file = "$dest/$srcdiffdir/$diff_name";
|
||||
my $news_file = "$dest/$srcdir/rsync-$version-NEWS";
|
||||
my $lasttar_file = "$dest/$lastsrcdir/rsync-$lastversion.tar.gz";
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to:
|
||||
- "cvs commit" all changes$skipping
|
||||
- "cvs tag" this release as $cvstag$skipping
|
||||
- change the diffs in the patches dir to include generated files
|
||||
- commit all version changes
|
||||
- merge the master branch into the patch/* branches
|
||||
- update the files in the "patches" dir and OPTIONALLY
|
||||
(if you type 'y') to launch a shell for each patch
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
print "<Press Enter OR 'y' to continue> ";
|
||||
my $ans = <STDIN>;
|
||||
|
||||
if ($live) {
|
||||
system "cvs commit -m 'Preparing for release of $version'";
|
||||
system "cvs tag -F $cvstag .";
|
||||
system "git commit -a -m 'Preparing for release of $version'" and exit 1;
|
||||
|
||||
print "Updating files in \"patches\" dir ...\n";
|
||||
system "support/patch-update";
|
||||
|
||||
if ($ans =~ /^y/i) {
|
||||
print "\nVisiting all \"patch/*\" branches ...\n";
|
||||
system "support/patch-update --shell";
|
||||
}
|
||||
|
||||
if (!/skip/i) {
|
||||
print "\n", $break, $note, $break;
|
||||
system "patches/verify-patches -pun -an";
|
||||
}
|
||||
|
||||
my $tar_name = "rsync-$version.tar.gz";
|
||||
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
|
||||
my $tar_file = "$dest/$tar_name";
|
||||
my $diff_file = "$dest/$diff_name";
|
||||
|
||||
print $break, <<EOT;
|
||||
|
||||
About to do the following in the samba-rsync-ftp dir:
|
||||
- move the old tar/diff files into the appropriate old-* dirs
|
||||
- hard-link the moved tar/diff files on samba.org$skipping
|
||||
- create release tar, "$tar_name"
|
||||
About to:
|
||||
- create signed tag for this release: v$version
|
||||
- create release diffs, "$diff_name"
|
||||
- update README, *NEWS, TODO, and cvs.log
|
||||
- update rsync*.html man pages
|
||||
- gpg-sign the release files$skipping
|
||||
- create release tar, "$srctar_name"
|
||||
- generate rsync-$version/patches/* files
|
||||
- create patches tar, "$pattar_name"
|
||||
- update top-level README, *NEWS, TODO, and ChangeLog
|
||||
- update top-level rsync*.html manpages
|
||||
- gpg-sign the release files
|
||||
- update hard-linked top-level release files$skipping
|
||||
|
||||
EOT
|
||||
print "<Press Enter to continue> ";
|
||||
$_ = <STDIN>;
|
||||
|
||||
chdir($releasedir) or die $!;
|
||||
my $passphrase;
|
||||
while (1) {
|
||||
ReadMode('noecho');
|
||||
print "\nEnter your GPG pass-phrase: ";
|
||||
chomp($passphrase = <STDIN>);
|
||||
ReadMode(0);
|
||||
print "\n";
|
||||
|
||||
print $break;
|
||||
system "rm -rf rsync-$version";
|
||||
rename('rsync', "rsync-$version") or die $!;
|
||||
# Briefly create a temp file with the passphrase for git's tagging use.
|
||||
my $oldmask = umask 077;
|
||||
unlink($passfile);
|
||||
open(OUT, '>', $passfile) or die $!;
|
||||
print OUT $passphrase, "\n";
|
||||
close OUT;
|
||||
umask $oldmask;
|
||||
$ENV{'GPG_PASSFILE'} = $passfile;
|
||||
|
||||
# When creating a pre-release after a normal release, there's nothing to move.
|
||||
if ($diffdir ne $dest) {
|
||||
chdir($dest) or die $!;
|
||||
|
||||
print "Shuffling old files ...\n";
|
||||
|
||||
# We need to run this regardless of $lastversion's "pre"ness.
|
||||
my @moved_files;
|
||||
foreach my $fn (glob('rsync*pre*.tar.gz*'), glob('rsync*pre*-NEWS')) {
|
||||
link($fn, "old-previews/$fn") or die $!;
|
||||
push(@moved_files, $fn);
|
||||
}
|
||||
|
||||
if ($version !~ /pre/) {
|
||||
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
|
||||
next if $fn =~ /^rsync.*pre/;
|
||||
link($fn, "old-versions/$fn") or die $!;
|
||||
push(@moved_files, $fn);
|
||||
}
|
||||
|
||||
foreach my $fn (glob('rsync*pre*.diffs.gz*')) {
|
||||
unlink($fn);
|
||||
}
|
||||
|
||||
foreach my $fn (glob('rsync*.diffs.gz*')) {
|
||||
link($fn, "old-patches/$fn") or die $!;
|
||||
push(@moved_files, $fn);
|
||||
}
|
||||
}
|
||||
|
||||
# Optimize our future upload (in the absence of --detect-renamed) by
|
||||
# using rsync to hard-link the above files on samba.org.
|
||||
if ($live) {
|
||||
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
|
||||
}
|
||||
foreach (@moved_files) {
|
||||
unlink($_);
|
||||
}
|
||||
|
||||
chdir($releasedir) or die $!;
|
||||
# We want to use our passphrase-providing "gpg" script, so modify the PATH.
|
||||
$ENV{PATH} = "packaging/bin:$path";
|
||||
$_ = `git tag -s -m 'Version $version.' v$version 2>&1`;
|
||||
$ENV{PATH} = $path;
|
||||
unlink($passfile);
|
||||
print $_;
|
||||
next if /bad passphrase/;
|
||||
last unless /failed/;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print "Creating $tar_file ...\n";
|
||||
system "fakeroot tar czf $tar_file rsync-$version";
|
||||
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
|
||||
foreach (@files) {
|
||||
print TAR "rsync-$version/$_\n";
|
||||
}
|
||||
close TAR;
|
||||
# Extract the generated files from the old tar.
|
||||
@_ = @extra_files;
|
||||
map { s#^#rsync-$lastversion/# } @_;
|
||||
system "tar xzf $lasttar_file @_";
|
||||
rename("rsync-$lastversion", 'a');
|
||||
|
||||
print "Creating $diff_file ...\n";
|
||||
system "rm -rf rsync-$version rsync-$lastversion";
|
||||
system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
|
||||
## TWEAK THE VERSIONS AS DESIRED HERE ##
|
||||
#mkdir("rsync-$lastversion/support", 0755) or die $!;
|
||||
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
|
||||
#unlink("rsync-$lastversion/.ignore");
|
||||
## END ##
|
||||
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
|
||||
system "./config.status Makefile; make gen; rsync -a @extra_files b/";
|
||||
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
|
||||
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
|
||||
system "rm -rf a";
|
||||
rename('b', "rsync-$version");
|
||||
|
||||
print "Creating $srctar_file ...\n";
|
||||
system "git archive --format=tar --prefix=rsync-$version/ v$version | tar xf -";
|
||||
system "support/git-set-file-times --prefix=rsync-$version/";
|
||||
system "fakeroot tar czf $srctar_file rsync-$version; rm -rf rsync-$version";
|
||||
|
||||
print "Updating files in \"rsync-$version/patches\" dir ...\n";
|
||||
mkdir("rsync-$version", 0755);
|
||||
mkdir("rsync-$version/patches", 0755);
|
||||
system "support/patch-update --skip-check --gen=rsync-$version/patches";
|
||||
|
||||
print "Creating $pattar_file ...\n";
|
||||
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
|
||||
|
||||
print "Updating the other files in $dest ...\n";
|
||||
system "rsync -a rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
|
||||
unlink("$dest/rsync-$version-NEWS");
|
||||
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
|
||||
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
|
||||
system "rsync -a README NEWS OLDNEWS TODO $dest";
|
||||
unlink($news_file);
|
||||
link("$dest/NEWS", $news_file);
|
||||
system "git log --name-status | gzip -9 >$dest/ChangeLog.gz";
|
||||
|
||||
system "yodl2html -o $dest/rsync.html rsync-$version/rsync.yo";
|
||||
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
|
||||
system "yodl2html -o $dest/rsync.html rsync.yo";
|
||||
system "yodl2html -o $dest/rsyncd.conf.html rsyncd.conf.yo";
|
||||
|
||||
system "rm -rf rsync-*";
|
||||
|
||||
if ($live) {
|
||||
chdir($dest) or die $!;
|
||||
system "gpg -ba $tar_name; gpg -ba $diff_name";
|
||||
print $break, <<EOT;
|
||||
|
||||
All done. Remember to announce the release on *BOTH*
|
||||
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
|
||||
EOT
|
||||
} else {
|
||||
print $break, "All done.\n";
|
||||
foreach my $fn ($srctar_file, $pattar_file, $diff_file) {
|
||||
unlink("$fn.asc");
|
||||
open(GPG, '|-', "gpg --batch --passphrase-fd=0 -ba $fn") or die $!;
|
||||
print GPG $passphrase, "\n";
|
||||
close GPG;
|
||||
}
|
||||
|
||||
if (!$pre) {
|
||||
system "rm $dest/rsync-*{.tar.gz,.asc,-NEWS} $dest/src-preview/rsync-*diffs.gz";
|
||||
|
||||
foreach my $fn ($srctar_file, "$srctar_file.asc",
|
||||
$pattar_file, "$pattar_file.asc",
|
||||
$diff_file, "$diff_file.asc", $news_file) {
|
||||
(my $top_fn = $fn) =~ s#/src(-\w+)?/#/#;
|
||||
link($fn, $top_fn);
|
||||
}
|
||||
}
|
||||
|
||||
print $break, <<'EOT';
|
||||
|
||||
Local changes are done. When you're satisfied, push the git repository
|
||||
and rsync the release files. Remember to announce the release on *BOTH*
|
||||
rsync-announce@lists.samba.org and rsync@lists.samba.org (and the web)!
|
||||
EOT
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
17
pipe.c
17
pipe.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -133,6 +133,12 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
|
||||
filesfrom_fd = -1;
|
||||
chmod_modes = NULL; /* Let the sending side handle this. */
|
||||
|
||||
/* Let the client side handle this. */
|
||||
if (logfile_name) {
|
||||
logfile_name = NULL;
|
||||
logfile_close();
|
||||
}
|
||||
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
@@ -144,15 +150,12 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
|
||||
close(to_child_pipe[0]);
|
||||
if (from_child_pipe[1] != STDOUT_FILENO)
|
||||
close(from_child_pipe[1]);
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
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
|
||||
@@ -809,16 +809,20 @@ int poptGetNextOpt(poptContext con)
|
||||
*oe++ = '\0';
|
||||
/* XXX longArg is mapped back to persistent storage. */
|
||||
longArg = origOptString + (oe - localOptString);
|
||||
}
|
||||
} else
|
||||
oe = NULL;
|
||||
|
||||
opt = findOption(con->options, optString, '\0', &cb, &cbData,
|
||||
singleDash);
|
||||
if (!opt && !singleDash)
|
||||
return POPT_ERROR_BADOPT;
|
||||
if (!opt && oe)
|
||||
oe[-1] = '='; /* restore overwritten '=' */
|
||||
}
|
||||
|
||||
if (!opt) {
|
||||
con->os->nextCharArg = origOptString + 1;
|
||||
longArg = NULL;
|
||||
} else {
|
||||
if (con->os == con->optionStack &&
|
||||
opt->argInfo & POPT_ARGFLAG_STRIP)
|
||||
@@ -856,7 +860,7 @@ int poptGetNextOpt(poptContext con)
|
||||
|
||||
origOptString++;
|
||||
if (*origOptString != '\0')
|
||||
con->os->nextCharArg = origOptString;
|
||||
con->os->nextCharArg = origOptString + (*origOptString == '=');
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ getArgDescrip(const struct poptOption * opt,
|
||||
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
|
||||
|
||||
switch (opt->argInfo & POPT_ARG_MASK) {
|
||||
case POPT_ARG_NONE: return POPT_("NONE");
|
||||
/*case POPT_ARG_NONE: return POPT_("NONE");*/ /* impossible */
|
||||
#ifdef DYING
|
||||
case POPT_ARG_VAL: return POPT_("VAL");
|
||||
#else
|
||||
@@ -767,6 +767,9 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
|
||||
char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
|
||||
int len = 0;
|
||||
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
|
||||
/*@-boundswrite@*/
|
||||
if (opt != NULL)
|
||||
for (; (opt->longName || opt->shortName || opt->arg); opt++) {
|
||||
|
||||
@@ -163,8 +163,10 @@ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ UNUSED(int fl
|
||||
p++;
|
||||
|
||||
linelen = strlen(p);
|
||||
if (linelen >= maxlinelen-1)
|
||||
if (linelen >= maxlinelen-1) {
|
||||
free(argstr);
|
||||
return POPT_ERROR_OVERFLOW; /* XXX line too long */
|
||||
}
|
||||
|
||||
if (*p == '\0' || *p == '\n') continue; /* line is empty */
|
||||
if (*p == '#') continue; /* comment line */
|
||||
|
||||
@@ -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
|
||||
|
||||
18
progress.c
18
progress.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,8 +22,10 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern struct stats stats;
|
||||
extern int am_server;
|
||||
extern int need_unsorted_flist;
|
||||
extern struct stats stats;
|
||||
extern struct file_list *cur_flist;
|
||||
|
||||
#define PROGRESS_HISTORY_SECS 5
|
||||
|
||||
@@ -41,6 +43,7 @@ struct progress_history {
|
||||
static struct progress_history ph_start;
|
||||
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
|
||||
static int newest_hpos, oldest_hpos;
|
||||
static int current_file_index;
|
||||
|
||||
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
{
|
||||
@@ -104,7 +107,7 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
if (is_last) {
|
||||
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
|
||||
stats.num_transferred_files,
|
||||
stats.num_files - stats.current_file_index - 1,
|
||||
stats.num_files - current_file_index - 1,
|
||||
stats.num_files);
|
||||
} else
|
||||
strlcpy(eol, "\r", sizeof eol);
|
||||
@@ -112,6 +115,15 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
human_num(ofs), pct, rate, units, rembuf, eol);
|
||||
}
|
||||
|
||||
void set_current_file_index(struct file_struct *file, int ndx)
|
||||
{
|
||||
if (need_unsorted_flist)
|
||||
current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start;
|
||||
else
|
||||
current_file_index = ndx;
|
||||
current_file_index -= cur_flist->flist_num;
|
||||
}
|
||||
|
||||
void end_progress(OFF_T size)
|
||||
{
|
||||
if (!am_server) {
|
||||
|
||||
198
receiver.c
198
receiver.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -55,12 +55,12 @@ extern char *tmpdir;
|
||||
extern char *partial_dir;
|
||||
extern char *basis_dir[];
|
||||
extern struct file_list *cur_flist, *first_flist, *dir_flist;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
extern struct filter_list_struct daemon_filter_list;
|
||||
|
||||
static struct bitbag *delayed_bits = NULL;
|
||||
static int phase = 0, redoing = 0;
|
||||
/* We're either updating the basis file or an identical copy: */
|
||||
static int updating_basis;
|
||||
static int updating_basis_or_equiv;
|
||||
|
||||
/*
|
||||
* get_tmpname() - create a tmp filename for a given filename
|
||||
@@ -83,10 +83,10 @@ static int updating_basis;
|
||||
* As long as it's unique, rsync will work.
|
||||
*/
|
||||
|
||||
int get_tmpname(char *fnametmp, char *fname)
|
||||
int get_tmpname(char *fnametmp, const char *fname)
|
||||
{
|
||||
int maxname, added, length = 0;
|
||||
char *f;
|
||||
const char *f;
|
||||
|
||||
if (tmpdir) {
|
||||
/* Note: this can't overflow, so the return value is safe */
|
||||
@@ -110,7 +110,7 @@ int get_tmpname(char *fnametmp, char *fname)
|
||||
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
|
||||
|
||||
if (maxname < 1) {
|
||||
rprintf(FERROR, "temporary filename too long: %s\n", fname);
|
||||
rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
|
||||
fnametmp[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
@@ -123,6 +123,43 @@ int get_tmpname(char *fnametmp, char *fname)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Opens a temporary file for writing.
|
||||
* Success: Writes name into fnametmp, returns fd.
|
||||
* Failure: Clobbers fnametmp, returns -1.
|
||||
* Calling cleanup_set() is the caller's job. */
|
||||
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!get_tmpname(fnametmp, fname))
|
||||
return -1;
|
||||
|
||||
/* We initially set the perms without the setuid/setgid bits or group
|
||||
* access to ensure that there is no race condition. They will be
|
||||
* correctly updated after the right owner and group info is set.
|
||||
* (Thanks to snabb@epipe.fi for pointing this out.) */
|
||||
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
|
||||
#if 0
|
||||
/* In most cases parent directories will already exist because their
|
||||
* information should have been previously transferred, but that may
|
||||
* not be the case with -R */
|
||||
if (fd == -1 && relative_paths && errno == ENOENT
|
||||
&& create_directory_path(fnametmp) == 0) {
|
||||
/* Get back to name with XXXXXX in it. */
|
||||
get_tmpname(fnametmp, fname);
|
||||
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fd == -1) {
|
||||
rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
|
||||
full_fname(fnametmp));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
const char *fname, int fd, OFF_T total_size)
|
||||
@@ -174,7 +211,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
}
|
||||
offset = sum.flength;
|
||||
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
|
||||
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
|
||||
rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
|
||||
full_fname(fname), (double)j, (double)offset);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
@@ -222,14 +259,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
sum_update(map, len);
|
||||
}
|
||||
|
||||
if (updating_basis) {
|
||||
if (updating_basis_or_equiv) {
|
||||
if (offset == offset2 && fd != -1) {
|
||||
OFF_T pos;
|
||||
if (flush_write_file(fd) < 0)
|
||||
goto report_write_error;
|
||||
offset += len;
|
||||
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"lseek of %s returned %.0f, not %.0f",
|
||||
full_fname(fname),
|
||||
(double)pos, (double)offset);
|
||||
@@ -256,7 +293,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
report_write_error:
|
||||
rsyserr(FERROR, errno, "write failed on %s",
|
||||
rsyserr(FERROR_XFER, errno, "write failed on %s",
|
||||
full_fname(fname));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
@@ -298,7 +335,7 @@ static void handle_delayed_updates(char *local_name)
|
||||
/* We don't use robust_rename() here because the
|
||||
* partial-dir must be on the same drive. */
|
||||
if (do_rename(partialptr, fname) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rename failed for %s (from %s)",
|
||||
full_fname(fname), partialptr);
|
||||
} else {
|
||||
@@ -315,10 +352,11 @@ static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
|
||||
{
|
||||
while (next_gen_ndx < desired_ndx) {
|
||||
if (next_gen_ndx >= 0) {
|
||||
rprintf(FINFO,
|
||||
struct file_struct *file = cur_flist->files[next_gen_ndx];
|
||||
rprintf(FERROR_XFER,
|
||||
"(No batched update for%s \"%s\")\n",
|
||||
redoing ? " resend of" : "",
|
||||
f_name(cur_flist->files[next_gen_ndx], NULL));
|
||||
file->flags & FLAG_FILE_SENT ? " resend of" : "",
|
||||
f_name(file, NULL));
|
||||
}
|
||||
next_gen_ndx = read_int(fd);
|
||||
if (next_gen_ndx == -1) {
|
||||
@@ -364,8 +402,6 @@ int recv_files(int f_in, char *local_name)
|
||||
if (delay_updates)
|
||||
delayed_bits = bitbag_create(cur_flist->used + 1);
|
||||
|
||||
updating_basis = inplace;
|
||||
|
||||
while (1) {
|
||||
cleanup_disable();
|
||||
|
||||
@@ -446,13 +482,15 @@ int recv_files(int f_in, char *local_name)
|
||||
}
|
||||
}
|
||||
|
||||
stats.current_file_index = ndx;
|
||||
if (!am_server && do_progress)
|
||||
set_current_file_index(file, ndx);
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += F_LENGTH(file);
|
||||
|
||||
cleanup_got_literal = 0;
|
||||
|
||||
if (server_filter_list.head
|
||||
&& check_filter(&server_filter_list, fname, 0) < 0) {
|
||||
if (daemon_filter_list.head
|
||||
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) {
|
||||
rprintf(FERROR, "attempt to hack rsync failed.\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
@@ -464,7 +502,7 @@ int recv_files(int f_in, char *local_name)
|
||||
continue;
|
||||
}
|
||||
if (write_batch < 0) {
|
||||
log_item(FINFO, file, &stats, iflags, NULL);
|
||||
log_item(FCLIENT, file, &stats, iflags, NULL);
|
||||
if (!am_server)
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
continue;
|
||||
@@ -498,7 +536,6 @@ int recv_files(int f_in, char *local_name)
|
||||
fnamecmp = get_backup_name(fname);
|
||||
break;
|
||||
case FNAMECMP_FUZZY:
|
||||
updating_basis = 0;
|
||||
if (file->dirname) {
|
||||
pathjoin(fnamecmpbuf, MAXPATHLEN,
|
||||
file->dirname, xname);
|
||||
@@ -507,7 +544,6 @@ int recv_files(int f_in, char *local_name)
|
||||
fnamecmp = xname;
|
||||
break;
|
||||
default:
|
||||
updating_basis = 0;
|
||||
if (fnamecmp_type >= basis_dir_cnt) {
|
||||
rprintf(FERROR,
|
||||
"invalid basis_dir index: %d.\n",
|
||||
@@ -519,15 +555,19 @@ int recv_files(int f_in, char *local_name)
|
||||
fnamecmp = fnamecmpbuf;
|
||||
break;
|
||||
}
|
||||
if (!fnamecmp || (server_filter_list.head
|
||||
&& check_filter(&server_filter_list, fname, 0) < 0))
|
||||
if (!fnamecmp || (daemon_filter_list.head
|
||||
&& check_filter(&daemon_filter_list, FLOG, fname, 0) < 0)) {
|
||||
fnamecmp = fname;
|
||||
fnamecmp_type = FNAMECMP_FNAME;
|
||||
}
|
||||
} else {
|
||||
/* Reminder: --inplace && --partial-dir are never
|
||||
* enabled at the same time. */
|
||||
if (inplace && make_backups > 0) {
|
||||
if (!(fnamecmp = get_backup_name(fname)))
|
||||
fnamecmp = fname;
|
||||
else
|
||||
fnamecmp_type = FNAMECMP_BACKUP;
|
||||
} else if (partial_dir && partialptr)
|
||||
fnamecmp = partialptr;
|
||||
else
|
||||
@@ -554,11 +594,14 @@ int recv_files(int f_in, char *local_name)
|
||||
}
|
||||
}
|
||||
|
||||
updating_basis_or_equiv = inplace
|
||||
&& (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);
|
||||
|
||||
if (fd1 == -1) {
|
||||
st.st_mode = 0;
|
||||
st.st_size = 0;
|
||||
} else if (do_fstat(fd1,&st) != 0) {
|
||||
rsyserr(FERROR, errno, "fstat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "fstat %s failed",
|
||||
full_fname(fnamecmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
close(fd1);
|
||||
@@ -573,7 +616,7 @@ int recv_files(int f_in, char *local_name)
|
||||
* and the underlying robust_unlink could cope
|
||||
* with directories
|
||||
*/
|
||||
rprintf(FERROR,"recv_files: %s is a directory\n",
|
||||
rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
|
||||
full_fname(fnamecmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
close(fd1);
|
||||
@@ -607,54 +650,22 @@ int recv_files(int f_in, char *local_name)
|
||||
if (inplace) {
|
||||
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
|
||||
if (fd2 == -1) {
|
||||
rsyserr(FERROR, errno, "open %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "open %s failed",
|
||||
full_fname(fname));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!get_tmpname(fnametmp,fname)) {
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
fd2 = open_tmpfile(fnametmp, fname, file);
|
||||
if (fd2 != -1)
|
||||
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
|
||||
}
|
||||
|
||||
/* we initially set the perms without the
|
||||
* setuid/setgid bits to ensure that there is no race
|
||||
* condition. They are then correctly updated after
|
||||
* the lchown. Thanks to snabb@epipe.fi for pointing
|
||||
* this out. We also set it initially without group
|
||||
* access because of a similar race condition. */
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
|
||||
/* in most cases parent directories will already exist
|
||||
* because their information should have been previously
|
||||
* transferred, but that may not be the case with -R */
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT
|
||||
&& create_directory_path(fnametmp) == 0) {
|
||||
/* Get back to name with XXXXXX in it. */
|
||||
get_tmpname(fnametmp, fname);
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rsyserr(FERROR, errno, "mkstemp %s failed",
|
||||
full_fname(fnametmp));
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
|
||||
if (fd2 == -1) {
|
||||
discard_receive_data(f_in, F_LENGTH(file));
|
||||
if (fd1 != -1)
|
||||
close(fd1);
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* log the transfer */
|
||||
@@ -678,26 +689,23 @@ int recv_files(int f_in, char *local_name)
|
||||
}
|
||||
|
||||
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
|
||||
char *temp_copy_name;
|
||||
if (partialptr == fname)
|
||||
partialptr = temp_copy_name = NULL;
|
||||
else if (*partial_dir == '/')
|
||||
temp_copy_name = NULL;
|
||||
else
|
||||
temp_copy_name = partialptr;
|
||||
finish_transfer(fname, fnametmp, fnamecmp,
|
||||
temp_copy_name, file, recv_ok, 1);
|
||||
if (fnamecmp == partialptr) {
|
||||
partialptr = NULL;
|
||||
if (!finish_transfer(fname, fnametmp, fnamecmp,
|
||||
partialptr, file, recv_ok, 1))
|
||||
recv_ok = -1;
|
||||
else if (fnamecmp == partialptr) {
|
||||
do_unlink(partialptr);
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
}
|
||||
} else if (keep_partial && partialptr
|
||||
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
|
||||
finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
|
||||
file, recv_ok, !partial_dir);
|
||||
if (delay_updates && recv_ok) {
|
||||
bitbag_set_bit(delayed_bits, ndx);
|
||||
if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
|
||||
file, recv_ok, !partial_dir))
|
||||
recv_ok = -1;
|
||||
else if (delay_updates && recv_ok) {
|
||||
bitbag_set_bit(delayed_bits, ndx);
|
||||
recv_ok = 2;
|
||||
}
|
||||
} else {
|
||||
partialptr = NULL;
|
||||
@@ -706,13 +714,15 @@ int recv_files(int f_in, char *local_name)
|
||||
|
||||
cleanup_disable();
|
||||
|
||||
if (recv_ok > 0) {
|
||||
switch (recv_ok) {
|
||||
case 1:
|
||||
if (remove_source_files || inc_recurse
|
||||
|| (preserve_hard_links && F_IS_HLINKED(file)))
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
} else if (!recv_ok) {
|
||||
enum logcode msgtype = redoing || read_batch ? FERROR : FINFO;
|
||||
if (msgtype == FERROR || verbose) {
|
||||
break;
|
||||
case 0: {
|
||||
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
|
||||
if (msgtype == FERROR_XFER || verbose) {
|
||||
char *errstr, *redostr, *keptstr;
|
||||
if (!(keep_partial && partialptr) && !inplace)
|
||||
keptstr = "discarded";
|
||||
@@ -720,22 +730,30 @@ int recv_files(int f_in, char *local_name)
|
||||
keptstr = "put into partial-dir";
|
||||
else
|
||||
keptstr = "retained";
|
||||
if (msgtype == FERROR) {
|
||||
if (msgtype == FERROR_XFER) {
|
||||
errstr = "ERROR";
|
||||
redostr = "";
|
||||
} else {
|
||||
errstr = "WARNING";
|
||||
redostr = " (will try again)";
|
||||
redostr = read_batch ? " (may try again)"
|
||||
: " (will try again)";
|
||||
}
|
||||
rprintf(msgtype,
|
||||
"%s: %s failed verification -- update %s%s.\n",
|
||||
errstr, fname, keptstr, redostr);
|
||||
errstr, local_name ? f_name(file, NULL) : fname,
|
||||
keptstr, redostr);
|
||||
}
|
||||
if (!redoing) {
|
||||
send_msg_int(MSG_REDO, ndx);
|
||||
file->flags |= FLAG_FILE_SENT;
|
||||
} else if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
if (inc_recurse)
|
||||
send_msg_int(MSG_NO_SEND, ndx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (make_backups < 0)
|
||||
|
||||
38
rounding.c
Normal file
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-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, visit the http://fsf.org website.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#define ARRAY_LEN (EXTRA_ROUNDING+1)
|
||||
#define SIZEOF(x) ((long int)sizeof (x))
|
||||
|
||||
struct test {
|
||||
union file_extras extras[ARRAY_LEN];
|
||||
struct file_struct file;
|
||||
};
|
||||
|
||||
#define ACTUAL_SIZE SIZEOF(struct test)
|
||||
#define EXPECTED_SIZE (SIZEOF(union file_extras) * ARRAY_LEN + SIZEOF(struct file_struct))
|
||||
|
||||
int main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
static int test_array[1 - 2 * (ACTUAL_SIZE != EXPECTED_SIZE)];
|
||||
test_array[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
158
rsync.c
158
rsync.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -134,8 +134,6 @@ void setup_iconv(void)
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef ICONV_OPTION
|
||||
|
||||
/* This function converts the characters in the "in" xbuf into characters
|
||||
* in the "out" xbuf. The "len" of the "in" xbuf is used starting from its
|
||||
* "pos". The "size" of the "out" xbuf restricts how many characters can be
|
||||
@@ -205,16 +203,51 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
|
||||
|
||||
return errno ? -1 : 0;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void send_protected_args(int fd, char *args[])
|
||||
{
|
||||
int i;
|
||||
#ifdef ICONV_OPTION
|
||||
int convert = ic_send != (iconv_t)-1;
|
||||
xbuf outbuf, inbuf;
|
||||
|
||||
if (convert)
|
||||
alloc_xbuf(&outbuf, 1024);
|
||||
#endif
|
||||
|
||||
for (i = 0; args[i]; i++) {} /* find first NULL */
|
||||
args[i] = "rsync"; /* set a new arg0 */
|
||||
if (verbose > 1)
|
||||
print_child_argv("protected args:", args + i + 1);
|
||||
do {
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert) {
|
||||
INIT_XBUF_STRLEN(inbuf, args[i]);
|
||||
iconvbufs(ic_send, &inbuf, &outbuf,
|
||||
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
|
||||
outbuf.buf[outbuf.len] = '\0';
|
||||
write_buf(fd, outbuf.buf, outbuf.len + 1);
|
||||
outbuf.len = 0;
|
||||
} else
|
||||
#endif
|
||||
write_buf(fd, args[i], strlen(args[i]) + 1);
|
||||
} while (args[++i]);
|
||||
write_byte(fd, 0);
|
||||
|
||||
#ifdef ICONV_OPTION
|
||||
if (convert)
|
||||
free(outbuf.buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
|
||||
char *buf, int *len_ptr)
|
||||
{
|
||||
int len, iflags = 0;
|
||||
struct file_list *flist;
|
||||
uchar fnamecmp_type = FNAMECMP_FNAME;
|
||||
int ndx;
|
||||
int ndx, save_verbose = verbose;
|
||||
|
||||
read_loop:
|
||||
while (1) {
|
||||
@@ -242,15 +275,17 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
|
||||
}
|
||||
|
||||
/* Send everything read from f_in to msg_fd_out. */
|
||||
send_msg_int(MSG_FLIST, ndx);
|
||||
start_flist_forward(f_in);
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "[%s] receiving flist for dir %d\n",
|
||||
who_am_i(), ndx);
|
||||
}
|
||||
verbose = 0;
|
||||
send_msg_int(MSG_FLIST, ndx);
|
||||
start_flist_forward(f_in);
|
||||
flist = recv_file_list(f_in);
|
||||
flist->parent_ndx = ndx;
|
||||
stop_flist_forward();
|
||||
verbose = save_verbose;
|
||||
}
|
||||
|
||||
iflags = protocol_version >= 29 ? read_shortint(f_in)
|
||||
@@ -265,11 +300,13 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
|
||||
}
|
||||
|
||||
if (!(flist = flist_for_ndx(ndx))) {
|
||||
int start, used;
|
||||
invalid_ndx:
|
||||
start = first_flist ? first_flist->ndx_start : 0;
|
||||
used = first_flist ? first_flist->used : 0;
|
||||
rprintf(FERROR,
|
||||
"Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
|
||||
ndx, first_flist->ndx_start - 1, first_flist->prev->ndx_end,
|
||||
iflags, who_am_i());
|
||||
ndx, start - 1, start + used -1, iflags, who_am_i());
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
cur_flist = flist;
|
||||
@@ -350,7 +387,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
if (dry_run)
|
||||
return 1;
|
||||
if (link_stat(fname, &sx2.st, 0) < 0) {
|
||||
rsyserr(FERROR, errno, "stat %s failed",
|
||||
rsyserr(FERROR_XFER, errno, "stat %s failed",
|
||||
full_fname(fname));
|
||||
return 0;
|
||||
}
|
||||
@@ -371,16 +408,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
new_mode |= S_ISGID;
|
||||
}
|
||||
|
||||
if (daemon_chmod_modes && !S_ISLNK(new_mode))
|
||||
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
|
||||
get_acl(fname, sxp);
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (am_root < 0)
|
||||
set_stat_xattr(fname, file, new_mode);
|
||||
if (preserve_xattrs && fnamecmp)
|
||||
set_xattr(fname, file, fnamecmp, sxp);
|
||||
if (am_root < 0)
|
||||
set_stat_xattr(fname, file);
|
||||
#endif
|
||||
|
||||
if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
|
||||
@@ -389,21 +429,23 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
|
||||
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno, "failed to set times on %s",
|
||||
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
if (ret == 0) /* ret == 1 if symlink could not be set */
|
||||
updated = 1;
|
||||
else
|
||||
file->flags |= FLAG_TIME_FAILED;
|
||||
}
|
||||
|
||||
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
|
||||
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
|
||||
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
|
||||
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
|
||||
if (S_ISLNK(sxp->st.st_mode))
|
||||
if (S_ISLNK(sxp->st.st_mode)) {
|
||||
;
|
||||
else
|
||||
} else
|
||||
#endif
|
||||
if (change_uid || change_gid) {
|
||||
if (verbose > 2) {
|
||||
@@ -418,31 +460,28 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
|
||||
}
|
||||
}
|
||||
if (am_root < 0) {
|
||||
;
|
||||
} else if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
* unless have the privilege */
|
||||
rsyserr(FERROR, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
} else
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
* destination had the setuid or setgid bits set due
|
||||
* to the side effect of the chown call */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
if (am_root >= 0) {
|
||||
if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* We shouldn't have attempted to change uid
|
||||
* or gid unless have the privilege. */
|
||||
rsyserr(FERROR_XFER, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
/* A lchown had been done, so we need to re-stat if
|
||||
* the destination had the setuid or setgid bits set
|
||||
* (due to the side effect of the chown call). */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
}
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
if (daemon_chmod_modes && !S_ISLNK(new_mode))
|
||||
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
|
||||
|
||||
#ifdef SUPPORT_ACLS
|
||||
/* It's OK to call set_acl() now, even for a dir, as the generator
|
||||
* will enable owner-writability using chmod, if necessary.
|
||||
@@ -458,7 +497,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
|
||||
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to set permissions on %s",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
@@ -503,15 +542,17 @@ RETSIGTYPE sig_int(UNUSED(int val))
|
||||
}
|
||||
|
||||
/* Finish off a file transfer: renaming the file and setting the file's
|
||||
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
|
||||
* NULL and the robust_rename() call is forced to copy the temp file, we
|
||||
* stage the file into the partial-dir and then rename it into place. */
|
||||
void finish_transfer(const char *fname, const char *fnametmp,
|
||||
const char *fnamecmp, const char *partialptr,
|
||||
struct file_struct *file, int ok_to_set_time,
|
||||
int overwriting_basis)
|
||||
* attributes (e.g. permissions, ownership, etc.). If the robust_rename()
|
||||
* call is forced to copy the temp file and partialptr is both non-NULL and
|
||||
* not an absolute path, we stage the file into the partial-dir and then
|
||||
* rename it into place. This returns 1 on succcess or 0 on failure. */
|
||||
int finish_transfer(const char *fname, const char *fnametmp,
|
||||
const char *fnamecmp, const char *partialptr,
|
||||
struct file_struct *file, int ok_to_set_time,
|
||||
int overwriting_basis)
|
||||
{
|
||||
int ret;
|
||||
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
|
||||
|
||||
if (inplace) {
|
||||
if (verbose > 2)
|
||||
@@ -521,7 +562,7 @@ void finish_transfer(const char *fname, const char *fnametmp,
|
||||
}
|
||||
|
||||
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
|
||||
return;
|
||||
return 1;
|
||||
|
||||
/* Change permissions before putting the file into place. */
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
@@ -530,34 +571,39 @@ void finish_transfer(const char *fname, const char *fnametmp,
|
||||
/* move tmp file over real file */
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
|
||||
ret = robust_rename(fnametmp, fname, partialptr,
|
||||
ret = robust_rename(fnametmp, fname, temp_copy_name,
|
||||
file->mode & INITACCESSPERMS);
|
||||
if (ret < 0) {
|
||||
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
|
||||
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
|
||||
ret == -2 ? "copy" : "rename",
|
||||
full_fname(fnametmp), fname);
|
||||
do_unlink(fnametmp);
|
||||
return;
|
||||
if (!partialptr || (ret == -2 && temp_copy_name)
|
||||
|| robust_rename(fnametmp, partialptr, NULL,
|
||||
file->mode & INITACCESSPERMS) < 0)
|
||||
do_unlink(fnametmp);
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* The file was moved into place (not copied), so it's done. */
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
/* The file was copied, so tweak the perms of the copied file. If it
|
||||
* was copied to partialptr, move it into its final destination. */
|
||||
fnametmp = partialptr ? partialptr : fname;
|
||||
fnametmp = temp_copy_name ? temp_copy_name : fname;
|
||||
|
||||
do_set_file_attrs:
|
||||
set_file_attrs(fnametmp, file, NULL, fnamecmp,
|
||||
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
|
||||
|
||||
if (partialptr) {
|
||||
if (temp_copy_name) {
|
||||
if (do_rename(fnametmp, fname) < 0) {
|
||||
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
|
||||
rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
|
||||
full_fname(fnametmp), fname);
|
||||
} else
|
||||
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||
return 0;
|
||||
}
|
||||
handle_partial_dir(temp_copy_name, PDIR_DELETE);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct file_list *flist_for_ndx(int ndx)
|
||||
@@ -572,7 +618,7 @@ struct file_list *flist_for_ndx(int ndx)
|
||||
return NULL;
|
||||
flist = flist->prev;
|
||||
}
|
||||
while (ndx > flist->ndx_end) {
|
||||
while (ndx >= flist->ndx_start + flist->used) {
|
||||
if (!(flist = flist->next))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
104
rsync.h
104
rsync.h
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 1996, 2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,6 +32,9 @@
|
||||
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
|
||||
#define URL_PREFIX "rsync://"
|
||||
|
||||
#define SYMLINK_PREFIX "/rsyncd-munged/"
|
||||
#define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
|
||||
|
||||
#define BACKUP_SUFFIX "~"
|
||||
|
||||
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
|
||||
@@ -50,7 +53,7 @@
|
||||
#define XMIT_LONG_NAME (1<<6)
|
||||
#define XMIT_SAME_TIME (1<<7)
|
||||
#define XMIT_SAME_RDEV_MAJOR (1<<8) /* protocols 28 - now (devices only) */
|
||||
#define XMIT_NON_XFER_DIR (1<<8) /* protocols 30 - now (dirs only) */
|
||||
#define XMIT_NO_CONTENT_DIR (1<<8) /* protocols 30 - now (dirs only) */
|
||||
#define XMIT_HLINKED (1<<9) /* protocols 28 - now */
|
||||
#define XMIT_SAME_DEV_pre30 (1<<10) /* protocols 28 - 29 */
|
||||
#define XMIT_USER_NAME_FOLLOWS (1<<10) /* protocols 30 - now */
|
||||
@@ -63,20 +66,24 @@
|
||||
#define FLAG_TOP_DIR (1<<0) /* sender/receiver/generator */
|
||||
#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
|
||||
#define FLAG_DIR_CREATED (1<<1) /* generator */
|
||||
#define FLAG_XFER_DIR (1<<2) /* sender/receiver/generator */
|
||||
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator */
|
||||
#define FLAG_CONTENT_DIR (1<<2) /* sender/receiver/generator */
|
||||
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator (dirs only) */
|
||||
#define FLAG_SKIP_HLINK (1<<3) /* receiver/generator (w/FLAG_HLINKED) */
|
||||
#define FLAG_DUPLICATE (1<<4) /* sender */
|
||||
#define FLAG_MISSING_DIR (1<<4) /* generator */
|
||||
#define FLAG_HLINKED (1<<5) /* receiver/generator */
|
||||
#define FLAG_HLINK_FIRST (1<<6) /* receiver/generator */
|
||||
#define FLAG_HLINKED (1<<5) /* receiver/generator (checked on all types) */
|
||||
#define FLAG_HLINK_FIRST (1<<6) /* receiver/generator (w/FLAG_HLINKED) */
|
||||
#define FLAG_IMPLIED_DIR (1<<6) /* sender/receiver/generator (dirs only) */
|
||||
#define FLAG_HLINK_LAST (1<<7) /* receiver/generator */
|
||||
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator */
|
||||
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator (checked on all types) */
|
||||
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
|
||||
#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
|
||||
#define FLAG_TIME_FAILED (1<<11)/* generator */
|
||||
|
||||
/* These flags are passed to functions but not stored. */
|
||||
|
||||
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
|
||||
#define FLAG_DOTDIR_NAME (1<<17)/* sender */
|
||||
|
||||
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
|
||||
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
|
||||
@@ -89,7 +96,7 @@
|
||||
/* This is used when working on a new protocol version in CVS, and should
|
||||
* be a new non-zero value for each CVS change that affects the protocol.
|
||||
* It must ALWAYS be 0 when the protocol goes final! */
|
||||
#define SUBPROTOCOL_VERSION 9
|
||||
#define SUBPROTOCOL_VERSION 0
|
||||
|
||||
/* We refuse to interoperate with versions that are not in this range.
|
||||
* Note that we assume we'll work with later versions: the onus is on
|
||||
@@ -121,7 +128,7 @@
|
||||
#define CHUNK_SIZE (32*1024)
|
||||
#define MAX_MAP_SIZE (256*1024)
|
||||
#define IO_BUFFER_SIZE (4092)
|
||||
#define MAX_BLOCK_SIZE ((int32)1 << 29)
|
||||
#define MAX_BLOCK_SIZE ((int32)1 << 17)
|
||||
|
||||
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
|
||||
#define IOERR_VANISHED (1<<1)
|
||||
@@ -139,8 +146,9 @@
|
||||
|
||||
#define XFLG_FATAL_ERRORS (1<<0)
|
||||
#define XFLG_OLD_PREFIXES (1<<1)
|
||||
#define XFLG_ANCHORED2ABS (1<<2)
|
||||
#define XFLG_ABS_IF_SLASH (1<<3)
|
||||
#define XFLG_ANCHORED2ABS (1<<2) /* leading slash indicates absolute */
|
||||
#define XFLG_ABS_IF_SLASH (1<<3) /* leading or interior slash is absolute */
|
||||
#define XFLG_DIR2WILD3 (1<<4) /* dir/ match gets trailing *** added */
|
||||
|
||||
#define ATTRS_REPORT (1<<0)
|
||||
#define ATTRS_SKIP_MTIME (1<<1)
|
||||
@@ -161,8 +169,9 @@
|
||||
|
||||
/* For use by the itemize_changes code */
|
||||
#define ITEM_REPORT_ATIME (1<<0)
|
||||
#define ITEM_REPORT_CHECKSUM (1<<1)
|
||||
#define ITEM_REPORT_SIZE (1<<2)
|
||||
#define ITEM_REPORT_CHANGE (1<<1)
|
||||
#define ITEM_REPORT_SIZE (1<<2) /* regular files only */
|
||||
#define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
|
||||
#define ITEM_REPORT_TIME (1<<3)
|
||||
#define ITEM_REPORT_PERMS (1<<4)
|
||||
#define ITEM_REPORT_OWNER (1<<5)
|
||||
@@ -182,18 +191,35 @@
|
||||
#define SIGNIFICANT_ITEM_FLAGS (~(\
|
||||
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
|
||||
|
||||
#define CFN_KEEP_DOT_DIRS (1<<0)
|
||||
#define CFN_KEEP_TRAILING_SLASH (1<<1)
|
||||
#define CFN_DROP_TRAILING_DOT_DIR (1<<2)
|
||||
#define CFN_COLLAPSE_DOT_DOT_DIRS (1<<3)
|
||||
|
||||
/* Log-message categories. Only FERROR and FINFO get sent over the socket,
|
||||
* but FLOG and FSOCKERR can be sent over the receiver -> generator pipe.
|
||||
* FLOG only goes to the log file, not the client; FCLIENT is the opposite. */
|
||||
enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
|
||||
#define SP_DEFAULT 0
|
||||
#define SP_KEEP_DOT_DIRS (1<<0)
|
||||
|
||||
#define CD_NORMAL 0
|
||||
#define CD_SKIP_CHDIR 1
|
||||
|
||||
/* Log-message categories. FLOG only goes to the log file, not the client;
|
||||
* FCLIENT is the opposite. */
|
||||
enum logcode {
|
||||
FNONE=0, /* never sent */
|
||||
FERROR_XFER=1, FINFO=2, /* sent over socket for any protocol */
|
||||
FERROR=3, FWARNING=4, /* sent over socket for protocols >= 30 */
|
||||
FERROR_SOCKET=5, FLOG=6, /* only sent via receiver -> generator pipe */
|
||||
FCLIENT=7 /* never transmitted (e.g. server converts to FINFO) */
|
||||
};
|
||||
|
||||
/* Messages types that are sent over the message channel. The logcode
|
||||
* values must all be present here with identical numbers. */
|
||||
enum msgcode {
|
||||
MSG_DATA=0, /* raw data on the multiplexed stream */
|
||||
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
|
||||
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, MSG_SOCKERR=FSOCKERR, /* sibling logging */
|
||||
MSG_ERROR_XFER=FERROR_XFER, MSG_INFO=FINFO, /* remote logging */
|
||||
MSG_ERROR=FERROR, MSG_WARNING=FWARNING, /* protocol-30 remote logging */
|
||||
MSG_ERROR_SOCKET=FERROR_SOCKET, /* sibling logging */
|
||||
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, /* sibling logging */
|
||||
MSG_REDO=9, /* reprocess indicated flist index */
|
||||
MSG_FLIST=20, /* extra file list over sibling socket */
|
||||
MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
|
||||
@@ -315,10 +341,6 @@ enum msgcode {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
/* these are needed for the uid/gid mapping code */
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
@@ -326,7 +348,9 @@ enum msgcode {
|
||||
#include <stdarg.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <syslog.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
@@ -377,6 +401,9 @@ enum msgcode {
|
||||
#ifdef ICONV_CONST
|
||||
#undef ICONV_CONST
|
||||
#endif
|
||||
#ifdef ICONV_OPTION
|
||||
#undef ICONV_OPTION
|
||||
#endif
|
||||
#ifdef iconv_t
|
||||
#undef iconv_t
|
||||
#endif
|
||||
@@ -387,6 +414,22 @@ enum msgcode {
|
||||
|
||||
#include "lib/pool_alloc.h"
|
||||
|
||||
#ifndef HAVE_ID_T
|
||||
typedef unsigned int id_t;
|
||||
#endif
|
||||
#ifndef HAVE_PID_T
|
||||
typedef int pid_t;
|
||||
#endif
|
||||
#ifndef HAVE_MODE_T
|
||||
typedef unsigned int mode_t;
|
||||
#endif
|
||||
#ifndef HAVE_OFF_T
|
||||
typedef long off_t;
|
||||
#endif
|
||||
#ifndef HAVE_SIZE_T
|
||||
typedef unsigned int size_t;
|
||||
#endif
|
||||
|
||||
#define BOOL int
|
||||
|
||||
#ifndef uchar
|
||||
@@ -504,6 +547,7 @@ struct hashtable {
|
||||
void *nodes;
|
||||
int32 size, entries;
|
||||
uint32 node_size;
|
||||
int key64;
|
||||
};
|
||||
|
||||
struct ht_int32_node {
|
||||
@@ -621,7 +665,7 @@ extern int xattrs_ndx;
|
||||
#define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
|
||||
#define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
|
||||
#define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
|
||||
#define F_NDX(f) REQ_EXTRA(f, ic_ndx)->num
|
||||
#define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
|
||||
|
||||
/* These items are per-entry optional: */
|
||||
#define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num /* non-dirs */
|
||||
@@ -636,7 +680,7 @@ extern int xattrs_ndx;
|
||||
|
||||
/* This optional item might follow an F_HL_*() item.
|
||||
* (Note: a device doesn't need to check LEN64_BUMP(f).) */
|
||||
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + 2 - 1)->unum)
|
||||
#define F_RDEV_P(f) (&OPT_EXTRA(f, HLINK_BUMP(f) + DEV_EXTRA_CNT - 1)->unum)
|
||||
|
||||
/* The sum is only present on regular files. */
|
||||
#define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
|
||||
@@ -687,7 +731,7 @@ struct file_list {
|
||||
int used, malloced;
|
||||
int low, high; /* 0-relative index values excluding empties */
|
||||
int ndx_start; /* the start offset for inc_recurse mode */
|
||||
int ndx_end; /* the end offset for inc_recurse mode */
|
||||
int flist_num; /* 1-relative file_list number or 0 */
|
||||
int parent_ndx; /* dir_flist index of parent directory */
|
||||
int in_progress, to_redo;
|
||||
};
|
||||
@@ -778,7 +822,6 @@ struct stats {
|
||||
int64 flist_size;
|
||||
int num_files;
|
||||
int num_transferred_files;
|
||||
int current_file_index;
|
||||
};
|
||||
|
||||
struct chmod_mode_struct;
|
||||
@@ -817,7 +860,7 @@ typedef struct {
|
||||
#define RL_CONVERT (1<<2)
|
||||
|
||||
typedef struct {
|
||||
char is_dot_dir;
|
||||
char name_type;
|
||||
char fname[1]; /* has variable size */
|
||||
} relnamecache;
|
||||
|
||||
@@ -1068,6 +1111,11 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
|
||||
#define MY_GID() getgid()
|
||||
#endif
|
||||
|
||||
#ifdef FORCE_FD_ZERO_MEMSET
|
||||
#undef FD_ZERO
|
||||
#define FD_ZERO(fdsetp) memset(fdsetp, 0, sizeof (fd_set))
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
|
||||
249
rsync.yo
249
rsync.yo
@@ -1,41 +1,40 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(4 Oct 2007)()()
|
||||
manpagename(rsync)(faster, flexible replacement for rcp)
|
||||
manpage(rsync)(1)(30 Mar 2008)()()
|
||||
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
|
||||
manpagesynopsis()
|
||||
|
||||
rsync [OPTION]... SRC [SRC]... DEST
|
||||
verb(Local: rsync [OPTION...] SRC... [DEST]
|
||||
|
||||
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
|
||||
Access via remote shell:
|
||||
Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
|
||||
Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
|
||||
|
||||
rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
|
||||
Access via rsync daemon:
|
||||
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
|
||||
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
|
||||
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
|
||||
rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST)
|
||||
|
||||
rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST
|
||||
|
||||
rsync [OPTION]... SRC
|
||||
|
||||
rsync [OPTION]... [USER@]HOST:SRC [DEST]
|
||||
|
||||
rsync [OPTION]... [USER@]HOST::SRC [DEST]
|
||||
|
||||
rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
|
||||
Usages with just one SRC arg and no DEST arg will list the source files
|
||||
instead of copying.
|
||||
|
||||
manpagedescription()
|
||||
|
||||
Rsync is a program that behaves in much the same way that rcp does,
|
||||
but has many more options and uses the rsync remote-update protocol to
|
||||
greatly speed up file transfers when the destination file is being
|
||||
updated.
|
||||
Rsync is a fast and extraordinarily versatile file copying tool. It can
|
||||
copy locally, to/from another host over any remote shell, or to/from a
|
||||
remote rsync daemon. It offers a large number of options that control
|
||||
every aspect of its behavior and permit very flexible specification of the
|
||||
set of files to be copied. It is famous for its delta-transfer algorithm,
|
||||
which reduces the amount of data sent over the network by sending only the
|
||||
differences between the source files and the existing files in the
|
||||
destination. Rsync is widely used for backups and mirroring and as an
|
||||
improved copy command for everyday use.
|
||||
|
||||
The rsync remote-update protocol allows rsync to transfer just the
|
||||
differences between two sets of files across the network connection, using
|
||||
an efficient checksum-search algorithm described in the technical
|
||||
report that accompanies this package.
|
||||
|
||||
Rsync finds files that need to be transferred using a "quick check" algorithm
|
||||
that looks for files that have changed in size or in last-modified time (by
|
||||
default). Any changes in the other preserved attributes (as requested by
|
||||
options) are made on the destination file directly when the quick check
|
||||
indicates that the file's data does not need to be updated.
|
||||
Rsync finds files that need to be transferred using a "quick check"
|
||||
algorithm (by default) that looks for files that have changed in size or
|
||||
in last-modified time. Any changes in the other preserved attributes (as
|
||||
requested by options) are made on the destination file directly when the
|
||||
quick check indicates that the file's data does not need to be updated.
|
||||
|
||||
Some of the additional features of rsync are:
|
||||
|
||||
@@ -226,7 +225,7 @@ verb( export RSYNC_CONNECT_PROG='ssh proxyhost nc %H 873'
|
||||
rsync -av targethost1::module/src/ /dest/
|
||||
rsync -av rsync:://targethost2/module/src/ /dest/ )
|
||||
|
||||
The command specifed above uses ssh to run nc (netcat) on a proxyhost,
|
||||
The command specified above uses ssh to run nc (netcat) on a proxyhost,
|
||||
which forwards all data to port 873 (the rsync daemon) on the targethost
|
||||
(%H).
|
||||
|
||||
@@ -329,7 +328,7 @@ to the detailed description below for a complete description. verb(
|
||||
-u, --update skip files that are newer on the receiver
|
||||
--inplace update destination files in-place
|
||||
--append append data onto shorter files
|
||||
--append-verify --append w/old data in file cheksum
|
||||
--append-verify --append w/old data in file checksum
|
||||
-d, --dirs transfer directories without recursing
|
||||
-l, --links copy symlinks as symlinks
|
||||
-L, --copy-links transform symlink into referent file/dir
|
||||
@@ -353,8 +352,8 @@ to the detailed description below for a complete description. verb(
|
||||
--super receiver attempts super-user activities
|
||||
--fake-super store/recover privileged attrs using xattrs
|
||||
-S, --sparse handle sparse files efficiently
|
||||
-n, --dry-run show what would have been transferred
|
||||
-W, --whole-file copy files whole (without rsync algorithm)
|
||||
-n, --dry-run perform a trial run with no changes made
|
||||
-W, --whole-file copy files whole (w/o delta-xfer algorithm)
|
||||
-x, --one-file-system don't cross filesystem boundaries
|
||||
-B, --block-size=SIZE force a fixed checksum block-size
|
||||
-e, --rsh=COMMAND specify the remote shell to use
|
||||
@@ -379,7 +378,8 @@ to the detailed description below for a complete description. verb(
|
||||
--delay-updates put all updated files into place at end
|
||||
-m, --prune-empty-dirs prune empty directory chains from file-list
|
||||
--numeric-ids don't map uid/gid values by user/group name
|
||||
--timeout=TIME set I/O timeout in seconds
|
||||
--timeout=SECONDS set I/O timeout in seconds
|
||||
--contimeout=SECONDS set daemon connection timeout in seconds
|
||||
-I, --ignore-times don't skip files that match size and time
|
||||
--size-only skip files that match in size
|
||||
--modify-window=NUM compare mod-times with reduced accuracy
|
||||
@@ -422,7 +422,7 @@ to the detailed description below for a complete description. verb(
|
||||
--only-write-batch=FILE like --write-batch but w/o updating dest
|
||||
--read-batch=FILE read a batched update from FILE
|
||||
--protocol=NUM force an older protocol version to be used
|
||||
--iconv=CONVERT_SPEC request charset conversion of filesnames
|
||||
--iconv=CONVERT_SPEC request charset conversion of filenames
|
||||
--checksum-seed=NUM set block/file checksum seed (advanced)
|
||||
-4, --ipv4 prefer IPv4
|
||||
-6, --ipv6 prefer IPv6
|
||||
@@ -528,7 +528,7 @@ either a changed size or a changed checksum are selected for transfer.
|
||||
|
||||
Note that rsync always verifies that each em(transferred) file was
|
||||
correctly reconstructed on the receiving side by checking a whole-file
|
||||
checksum that is generated when as the file is transferred, but that
|
||||
checksum that is generated as the file is transferred, but that
|
||||
automatic after-the-transfer verification has nothing to do with this
|
||||
option's before-the-transfer "Does this file need to be updated?" check.
|
||||
|
||||
@@ -723,9 +723,12 @@ receiving user.
|
||||
dit(bf(--append)) This causes rsync to update a file by appending data onto
|
||||
the end of the file, which presumes that the data that already exists on
|
||||
the receiving side is identical with the start of the file on the sending
|
||||
side. Any files that are the same size or shorter on the receiving size
|
||||
are skipped. Files that do not yet exist on the receiving side are also
|
||||
sent, since they are considered to have 0 length. Implies bf(--inplace),
|
||||
side. If a file needs to be transferred and its size on the receiver is
|
||||
the same or longer than the size on the sender, the file is skipped. This
|
||||
does not interfere with the updating of a file's non-content attributes
|
||||
(e.g. permissions, ownership, etc.) when the file does not need to be
|
||||
transferred, nor does it affect the updating of any non-regular files.
|
||||
Implies bf(--inplace),
|
||||
but does not conflict with bf(--sparse) (since it is always extending a
|
||||
file's length).
|
||||
|
||||
@@ -748,6 +751,16 @@ bf(--recursive) option, rsync will skip all directories it encounters (and
|
||||
output a message to that effect for each one). If you specify both
|
||||
bf(--dirs) and bf(--recursive), bf(--recursive) takes precedence.
|
||||
|
||||
The bf(--dirs) option is implied by the bf(--files-from) option
|
||||
or the bf(--list-only) option (including an implied
|
||||
bf(--list-only) usage) if bf(--recursive) wasn't specified (so that
|
||||
directories are seen in the listing). Specify bf(--no-dirs) (or bf(--no-d))
|
||||
if you want to turn this off.
|
||||
|
||||
There is also a backward-compatibility helper option, bf(--old-dirs) (or
|
||||
bf(--old-d)) that tells rsync to use a hack of "-r --exclude='/*/*'" to get
|
||||
an older rsync to list a single directory without recursing.
|
||||
|
||||
dit(bf(-l, --links)) When symlinks are encountered, recreate the
|
||||
symlink on the destination.
|
||||
|
||||
@@ -796,6 +809,14 @@ directory, and receives the file into the new directory. With
|
||||
bf(--keep-dirlinks), the receiver keeps the symlink and "file" ends up in
|
||||
"bar".
|
||||
|
||||
One note of caution: if you use bf(--keep-dirlinks), you must trust all
|
||||
the symlinks in the copy! If it is possible for an untrusted user to
|
||||
create their own symlink to any directory, the user could then (on a
|
||||
subsequent copy) replace the symlink with a real directory and affect the
|
||||
content of whatever directory the symlink references. For backup copies,
|
||||
you are better off using something like a bind mount instead of a symlink
|
||||
to modify your receiving hierarchy.
|
||||
|
||||
See also bf(--copy-dirlinks) for an analogous option for the sending side.
|
||||
|
||||
dit(bf(-H, --hard-links)) This tells rsync to look for hard-linked files in
|
||||
@@ -803,11 +824,24 @@ the transfer and link together the corresponding files on the receiving
|
||||
side. Without this option, hard-linked files in the transfer are treated
|
||||
as though they were separate files.
|
||||
|
||||
Note that rsync can only detect hard links if both parts of the link
|
||||
are in the list of files being sent.
|
||||
When you are updating a non-empty destination, this option only ensures
|
||||
that files that are hard-linked together on the source are hard-linked
|
||||
together on the destination. It does NOT currently endeavor to break
|
||||
already existing hard links on the destination that do not exist between
|
||||
the source files. Note, however, that if one or more extra-linked files
|
||||
have content changes, they will become unlinked when updated (assuming you
|
||||
are not using the bf(--inplace) option).
|
||||
|
||||
Note that rsync can only detect hard links between files that are inside
|
||||
the transfer set. If rsync updates a file that has extra hard-link
|
||||
connections to files outside the transfer, that linkage will be broken. If
|
||||
you are tempted to use the bf(--inplace) option to avoid this breakage, be
|
||||
very careful that you know how your files are being updated so that you are
|
||||
certain that no unintended changes happen due to lingering hard links (and
|
||||
see the bf(--inplace) option for more caveats).
|
||||
|
||||
If incremental recursion is active (see bf(--recursive)), rsync may transfer
|
||||
a missing hard-linked file before it finds that another link for the file
|
||||
a missing hard-linked file before it finds that another link for that contents
|
||||
exists elsewhere in the hierarchy. This does not affect the accuracy of
|
||||
the transfer, just its efficiency. One way to avoid this is to disable
|
||||
incremental recursion using the bf(--no-inc-recursive) option.
|
||||
@@ -841,17 +875,17 @@ permissions (while leaving existing files unchanged), make sure that the
|
||||
bf(--perms) option is off and use bf(--chmod=ugo=rwX) (which ensures that
|
||||
all non-masked bits get enabled). If you'd care to make this latter
|
||||
behavior easier to type, you could define a popt alias for it, such as
|
||||
putting this line in the file ~/.popt (this defines the bf(-s) option,
|
||||
putting this line in the file ~/.popt (the following defines the bf(-Z) option,
|
||||
and includes --no-g to use the default group of the destination dir):
|
||||
|
||||
quote(tt( rsync alias -s --no-p --no-g --chmod=ugo=rwX))
|
||||
quote(tt( rsync alias -Z --no-p --no-g --chmod=ugo=rwX))
|
||||
|
||||
You could then use this new option in a command such as this one:
|
||||
|
||||
quote(tt( rsync -asv src/ dest/))
|
||||
quote(tt( rsync -avZ src/ dest/))
|
||||
|
||||
(Caveat: make sure that bf(-a) does not follow bf(-s), or it will re-enable
|
||||
the "--no-*" options.)
|
||||
(Caveat: make sure that bf(-a) does not follow bf(-Z), or it will re-enable
|
||||
the two "--no-*" options mentioned above.)
|
||||
|
||||
The preservation of the destination's setgid bit on newly-created
|
||||
directories when bf(--perms) is off was added in rsync 2.6.7. Older rsync
|
||||
@@ -982,7 +1016,7 @@ files we create can always be accessed/changed by the creating user).
|
||||
This option also handles ACLs (if bf(--acls) was specified) and non-user
|
||||
extended attributes (if bf(--xattrs) was specified).
|
||||
|
||||
This is a good way to backup data withou using a super-user, and to store
|
||||
This is a good way to backup data without using a super-user, and to store
|
||||
ACLs from incompatible systems.
|
||||
|
||||
The bf(--fake-super) option only affects the side where the option is used.
|
||||
@@ -992,7 +1026,7 @@ path:
|
||||
quote(tt( rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
|
||||
|
||||
Since there is only one "side" in a local copy, this option affects both
|
||||
the sending and recieving of files. You'll need to specify a copy using
|
||||
the sending and receiving of files. You'll need to specify a copy using
|
||||
"localhost" if you need to avoid this, possibly using the "lsh" shell
|
||||
script (from the support directory) as a substitute for an actual remote
|
||||
shell (see bf(--rsh)).
|
||||
@@ -1009,10 +1043,22 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
|
||||
filesystem. It doesn't seem to handle seeks over null regions
|
||||
correctly and ends up corrupting the files.
|
||||
|
||||
dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
|
||||
instead it will just report the actions it would have taken.
|
||||
dit(bf(-n, --dry-run)) This makes rsync perform a trial run that doesn't
|
||||
make any changes (and produces mostly the same output as a real run). It
|
||||
is most commonly used in combination with the bf(-v, --verbose) and/or
|
||||
bf(-i, --itemize-changes) options to see what an rsync command is going
|
||||
to do before one actually runs it.
|
||||
|
||||
dit(bf(-W, --whole-file)) With this option the delta transfer algorithm
|
||||
The output of bf(--itemize-changes) is supposed to be exactly the same on a
|
||||
dry run and a subsequent real run (barring intentional trickery and system
|
||||
call failures); if it isn't, that's a bug. Other output is the same to the
|
||||
extent practical, but may differ in some areas. Notably, a dry run does not
|
||||
send the actual data for file transfers, so bf(--progress) has no effect,
|
||||
the "bytes sent", "bytes received", "literal data", and "matched data"
|
||||
statistics are too small, and the "speedup" value is equivalent to a run
|
||||
where no file transfers are needed.
|
||||
|
||||
dit(bf(-W, --whole-file)) With this option the delta-transfer algorithm
|
||||
is not used and the whole file is sent as-is instead. The transfer may be
|
||||
faster if this option is used when the bandwidth between the source and
|
||||
destination machines is higher than the bandwidth to disk (especially when the
|
||||
@@ -1074,9 +1120,9 @@ Prior to rsync 2.6.7, this option would have no effect unless bf(--recursive)
|
||||
was enabled. Beginning with 2.6.7, deletions will also occur when bf(--dirs)
|
||||
(bf(-d)) is enabled, but only for directories whose contents are being copied.
|
||||
|
||||
This option can be dangerous if used incorrectly! It is a very good idea
|
||||
to run first using the bf(--dry-run) option (bf(-n)) to see what files would be
|
||||
deleted to make sure important files aren't listed.
|
||||
This option can be dangerous if used incorrectly! It is a very good idea to
|
||||
first try a run using the bf(--dry-run) option (bf(-n)) to see what files are
|
||||
going to be deleted.
|
||||
|
||||
If the sending side detects any I/O errors, then the deletion of any
|
||||
files at the destination will be automatically disabled. This is to
|
||||
@@ -1238,8 +1284,8 @@ The exclude list is initialized to exclude the following items (these
|
||||
initial items are marked as perishable -- see the FILTER RULES section):
|
||||
|
||||
quote(quote(tt(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
|
||||
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej
|
||||
.del-* *.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .bzr/)))
|
||||
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej .del-*
|
||||
*.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/ .git/ .bzr/)))
|
||||
|
||||
then, files listed in a $HOME/.cvsignore are added to the list and any
|
||||
files listed in the CVSIGNORE environment variable (all cvsignore names
|
||||
@@ -1267,7 +1313,10 @@ exclude certain files from the list of files to be transferred. This is
|
||||
most useful in combination with a recursive transfer.
|
||||
|
||||
You may use as many bf(--filter) options on the command line as you like
|
||||
to build up the list of files to exclude.
|
||||
to build up the list of files to exclude. If the filter contains whitespace,
|
||||
be sure to quote it so that the shell gives the rule to rsync as a single
|
||||
argument. The text below also mentions that you can use an underscore to
|
||||
replace the space that separates a rule from its arg.
|
||||
|
||||
See the FILTER RULES section for detailed information on this option.
|
||||
|
||||
@@ -1380,7 +1429,7 @@ characters are not translated (such as ~, $, ;, &, etc.). Wildcards are
|
||||
expanded on the remote host by rsync (instead of the shell doing it).
|
||||
|
||||
If you use this option with bf(--iconv), the args will also be translated
|
||||
from the local to the remote character set. The translation happens before
|
||||
from the local to the remote character-set. The translation happens before
|
||||
wild-cards are expanded. See also the bf(--files-from) option.
|
||||
|
||||
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
|
||||
@@ -1390,7 +1439,7 @@ file in the same directory as the associated destination file.
|
||||
|
||||
This option is most often used when the receiving disk partition does not
|
||||
have enough free space to hold a copy of the largest file in the transfer.
|
||||
In this case (i.e. when the scratch directory in on a different disk
|
||||
In this case (i.e. when the scratch directory is on a different disk
|
||||
partition), rsync will not be able to rename each received temporary file
|
||||
over the top of the associated destination file, but instead must copy it
|
||||
into place. Rsync does this by copying the file over the top of the
|
||||
@@ -1557,6 +1606,10 @@ dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
|
||||
timeout in seconds. If no data is transferred for the specified time
|
||||
then rsync will exit. The default is 0, which means no timeout.
|
||||
|
||||
dit(bf(--contimeout)) This option allows you to set the amount of time
|
||||
that rsync will wait for its connection to an rsync daemon to succeed.
|
||||
If the timeout is reached, rsync exits with an error.
|
||||
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address when
|
||||
connecting to an rsync daemon. The bf(--address) option allows you to
|
||||
specify a specific IP address (or hostname) to bind to. See also this
|
||||
@@ -1610,6 +1663,8 @@ quote(itemization(
|
||||
bf(--hard-links)).
|
||||
it() A bf(.) means that the item is not being updated (though it might
|
||||
have attributes that are being modified).
|
||||
it() A bf(*) means that the rest of the itemized-output area contains
|
||||
a message (e.g. "deleting").
|
||||
))
|
||||
|
||||
The file-types that replace the bf(X) are: bf(f) for a file, a bf(d) for a
|
||||
@@ -1626,26 +1681,29 @@ a "?" (this can happen when talking to an older rsync).
|
||||
The attribute that is associated with each letter is as follows:
|
||||
|
||||
quote(itemization(
|
||||
it() A bf(c) means the checksum of the file is different and will be
|
||||
updated by the file transfer (requires bf(--checksum)).
|
||||
it() A bf(s) means the size of the file is different and will be updated
|
||||
it() A bf(c) means either that a regular file has a different checksum
|
||||
(requires bf(--checksum)) or that a symlink, device, or special file has
|
||||
a changed value.
|
||||
Note that if you are sending files to an rsync prior to 3.0.1, this
|
||||
change flag will be present only for checksum-differing regular files.
|
||||
it() A bf(s) means the size of a regular file is different and will be updated
|
||||
by the file transfer.
|
||||
it() A bf(t) means the modification time is different and is being updated
|
||||
to the sender's value (requires bf(--times)). An alternate value of bf(T)
|
||||
means that the modification time will be set to the transfer time, which happens
|
||||
anytime a symlink is transferred, or when a regular file or device is
|
||||
transferred without bf(--times).
|
||||
when a file/symlink/device is updated without bf(--times) and when a
|
||||
symlink is changed and the receiver can't set its time.
|
||||
(Note: when using an rsync 3.0.0 client, you might see the bf(s) flag combined
|
||||
with bf(t) instead of the proper bf(T) flag for this time-setting failure.)
|
||||
it() A bf(p) means the permissions are different and are being updated to
|
||||
the sender's value (requires bf(--perms)).
|
||||
it() An bf(o) means the owner is different and is being updated to the
|
||||
sender's value (requires bf(--owner) and super-user privileges).
|
||||
it() A bf(g) means the group is different and is being updated to the
|
||||
sender's value (requires bf(--group) and the authority to set the group).
|
||||
it() The bf(u) slot is reserved for reporting update (access) time changes
|
||||
(a feature that is not yet released).
|
||||
it() The bf(u) slot is reserved for future use.
|
||||
it() The bf(a) means that the ACL information changed.
|
||||
it() The bf(x) slot is reserved for reporting extended attribute changes
|
||||
(a feature that is not yet released).
|
||||
it() The bf(x) means that the extended attribute information changed.
|
||||
))
|
||||
|
||||
One other output is possible: when deleting files, the "%i" will output
|
||||
@@ -1914,6 +1972,8 @@ dit(bf(--password-file)) This option allows you to provide a password in a
|
||||
file for accessing an rsync daemon. The file must not be world readable.
|
||||
It should contain just the password as a single line.
|
||||
|
||||
This option does not supply a password to a remote shell transport such as
|
||||
ssh; to learn how to do that, consult the remote shell's documentation.
|
||||
When accessing an rsync daemon using a remote shell as the transport, this
|
||||
option only comes into effect after the remote shell finishes its
|
||||
authentication (i.e. if you have also specified a password in the daemon's
|
||||
@@ -1923,16 +1983,22 @@ dit(bf(--list-only)) This option will cause the source files to be listed
|
||||
instead of transferred. This option is inferred if there is a single source
|
||||
arg and no destination specified, so its main uses are: (1) to turn a copy
|
||||
command that includes a
|
||||
destination arg into a file-listing command, (2) to be able to specify more
|
||||
than one local source arg (note: be sure to include the destination), or
|
||||
(3) to avoid the automatically added "bf(-r --exclude='/*/*')" options that
|
||||
rsync usually uses as a compatibility kluge when generating a non-recursive
|
||||
listing. Caution: keep in mind that a source arg with a wild-card is expanded
|
||||
by the shell into multiple args, so it is never safe to try to list such an arg
|
||||
destination arg into a file-listing command, or (2) to be able to specify
|
||||
more than one source arg (note: be sure to include the destination).
|
||||
Caution: keep in mind that a source arg with a wild-card is expanded by the
|
||||
shell into multiple args, so it is never safe to try to list such an arg
|
||||
without using this option. For example:
|
||||
|
||||
verb( rsync -av --list-only foo* dest/)
|
||||
|
||||
Compatibility note: when requesting a remote listing of files from an rsync
|
||||
that is version 2.6.3 or older, you may encounter an error if you ask for a
|
||||
non-recursive listing. This is because a file listing implies the bf(--dirs)
|
||||
option w/o bf(--recursive), and older rsyncs don't have that option. To
|
||||
avoid this problem, either specify the bf(--no-dirs) option (if you don't
|
||||
need to expand a directory's content), or turn on recursion and exclude
|
||||
the content of subdirectories: bf(-r --exclude='/*/*').
|
||||
|
||||
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
|
||||
transfer rate in kilobytes per second. This option is most effective when
|
||||
using rsync with large files (several megabytes and up). Due to the nature
|
||||
@@ -1979,11 +2045,17 @@ dit(bf(--iconv=CONVERT_SPEC)) Rsync can convert filenames between character
|
||||
sets using this option. Using a CONVERT_SPEC of "." tells rsync to look up
|
||||
the default character-set via the locale setting. Alternately, you can
|
||||
fully specify what conversion to do by giving a local and a remote charset
|
||||
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591).
|
||||
Finally, you can specify a CONVERT_SPEC of "-" to turn off any conversion.
|
||||
separated by a comma in the order bf(--iconv=LOCAL,REMOTE), e.g.
|
||||
bf(--iconv=utf8,iso88591). This order ensures that the option
|
||||
will stay the same whether you're pushing or pulling files.
|
||||
Finally, you can specify either bf(--no-iconv) or a CONVERT_SPEC of "-"
|
||||
to turn off any conversion.
|
||||
The default setting of this option is site-specific, and can also be
|
||||
affected via the RSYNC_ICONV environment variable.
|
||||
|
||||
For a list of what charset names your local iconv library supports, you can
|
||||
run "iconv --list".
|
||||
|
||||
If you specify the bf(--protect-args) option (bf(-s)), rsync will translate
|
||||
the filenames you specify on the command-line that are being sent to the
|
||||
remote host. See also the bf(--files-from) option.
|
||||
@@ -1994,6 +2066,11 @@ specifying matching rules that can match on both sides of the transfer.
|
||||
For instance, you can specify extra include/exclude rules if there are
|
||||
filename differences on the two sides that need to be accounted for.
|
||||
|
||||
When you pass an bf(--iconv) option to an rsync daemon that allows it, the
|
||||
daemon uses the charset specified in its "charset" configuration parameter
|
||||
regardless of the remote charset you actually pass. Thus, you may feel free to
|
||||
specify just the local charset for a daemon transfer (e.g. bf(--iconv=utf8)).
|
||||
|
||||
dit(bf(-4, --ipv4) or bf(-6, --ipv6)) Tells rsync to prefer IPv4/IPv6
|
||||
when creating sockets. This only affects sockets that rsync has direct
|
||||
control over, such as the outgoing socket when directly contacting an
|
||||
@@ -2744,6 +2821,7 @@ dit(bf(23)) Partial transfer due to error
|
||||
dit(bf(24)) Partial transfer due to vanished source files
|
||||
dit(bf(25)) The --max-delete limit stopped deletions
|
||||
dit(bf(30)) Timeout in data send/receive
|
||||
dit(bf(35)) Timeout waiting for daemon connection
|
||||
enddit()
|
||||
|
||||
manpagesection(ENVIRONMENT VARIABLES)
|
||||
@@ -2763,7 +2841,8 @@ rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
|
||||
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
|
||||
password allows you to run authenticated rsync connections to an rsync
|
||||
daemon without user intervention. Note that this does not supply a
|
||||
password to a shell transport such as ssh.
|
||||
password to a remote shell transport such as ssh; to learn how to do that,
|
||||
consult the remote shell's documentation.
|
||||
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
|
||||
are used to determine the default username sent to an rsync daemon.
|
||||
If neither is set, the username defaults to "nobody".
|
||||
@@ -2797,7 +2876,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.0pre1 of rsync.
|
||||
This man page is current for version 3.0.1pre3 of rsync.
|
||||
|
||||
manpagesection(INTERNAL OPTIONS)
|
||||
|
||||
@@ -2823,23 +2902,25 @@ The primary ftp site for rsync is
|
||||
url(ftp://rsync.samba.org/pub/rsync)(ftp://rsync.samba.org/pub/rsync).
|
||||
|
||||
We would be delighted to hear from you if you like this program.
|
||||
Please contact the mailing-list at rsync@lists.samba.org.
|
||||
|
||||
This program uses the excellent zlib compression library written by
|
||||
Jean-loup Gailly and Mark Adler.
|
||||
|
||||
manpagesection(THANKS)
|
||||
|
||||
Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
|
||||
and David Bell for helpful suggestions, patches and testing of rsync.
|
||||
I've probably missed some people, my apologies if I have.
|
||||
Especial thanks go out to: John Van Essen, Matt McCutchen, Wesley W. Terpstra,
|
||||
David Dykstra, Jos Backus, Sebastian Krahmer, Martin Pool, and our
|
||||
gone-but-not-forgotten compadre, J.W. Schultz.
|
||||
|
||||
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer,
|
||||
Martin Pool, Wayne Davison, J.W. Schultz.
|
||||
Thanks also to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
|
||||
and David Bell. I've probably missed some people, my apologies if I have.
|
||||
|
||||
manpageauthor()
|
||||
|
||||
rsync was originally written by Andrew Tridgell and Paul Mackerras.
|
||||
Many people have later contributed to it.
|
||||
Many people have later contributed to it. It is currently maintained
|
||||
by Wayne Davison.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
url(http://lists.samba.org)(lists.samba.org)
|
||||
|
||||
232
rsyncd.conf.yo
232
rsyncd.conf.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(4 Oct 2007)()()
|
||||
manpage(rsyncd.conf)(5)(30 Mar 2008)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -113,6 +113,10 @@ After the global options you should define a number of modules, each
|
||||
module exports a directory tree as a symbolic name. Modules are
|
||||
exported by specifying a module name in square brackets [module]
|
||||
followed by the options for that module.
|
||||
The module name cannot contain a slash or a closing square bracket. If the
|
||||
name contains whitespace, each internal sequence of whitespace will be
|
||||
changed into a single space, while leading or trailing whitespace will be
|
||||
discarded.
|
||||
|
||||
startdit()
|
||||
|
||||
@@ -129,35 +133,112 @@ to the "path" before starting the file transfer with the client. This has
|
||||
the advantage of extra protection against possible implementation security
|
||||
holes, but it has the disadvantages of requiring super-user privileges,
|
||||
of not being able to follow symbolic links that are either absolute or outside
|
||||
of the new root path, and of complicating the preservation of usernames and groups
|
||||
(see below). When "use chroot" is false, for security reasons,
|
||||
symlinks may only be relative paths pointing to other files within the root
|
||||
path, and leading slashes are removed from most absolute paths (options
|
||||
such as bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
|
||||
rooted in the module's "path" dir, just as if chroot was specified).
|
||||
The default for "use chroot" is true.
|
||||
of the new root path, and of complicating the preservation of users and groups
|
||||
by name (see below).
|
||||
|
||||
In order to preserve usernames and groupnames, rsync needs to be able to
|
||||
As an additional safety feature, you can specify a dot-dir in the module's
|
||||
"path" to indicate the point where the chroot should occur. This allows rsync
|
||||
to run in a chroot with a non-"/" path for the top of the transfer hierarchy.
|
||||
Doing this guards against unintended library loading (since those absolute
|
||||
paths will not be inside the transfer hierarchy unless you have used an unwise
|
||||
pathname), and lets you setup libraries for the chroot that are outside of the
|
||||
transfer. For example, specifying "/var/rsync/./module1" will chroot to the
|
||||
"/var/rsync" directory and set the inside-chroot path to "/module1". If you
|
||||
had omitted the dot-dir, the chroot would have used the whole path, and the
|
||||
inside-chroot path would have been "/".
|
||||
|
||||
When "use chroot" is false or the inside-chroot path is not "/", rsync will:
|
||||
(1) munge symlinks by
|
||||
default for security reasons (see "munge symlinks" for a way to turn this
|
||||
off, but only if you trust your users), (2) substitute leading slashes in
|
||||
absolute paths with the module's path (so that options such as
|
||||
bf(--backup-dir), bf(--compare-dest), etc. interpret an absolute path as
|
||||
rooted in the module's "path" dir), and (3) trim ".." path elements from
|
||||
args if rsync believes they would escape the module hierarchy.
|
||||
The default for "use chroot" is true, and is the safer choice (especially
|
||||
if the module is not read-only).
|
||||
|
||||
When this option is enabled, rsync will not attempt to map users and groups
|
||||
by name (by default), but instead copy IDs as though bf(--numeric-ids) had
|
||||
been specified. In order to enable name-mapping, rsync needs to be able to
|
||||
use the standard library functions for looking up names and IDs (i.e.
|
||||
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
|
||||
process in the chroot namespace will need to have access to the resources
|
||||
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())).
|
||||
This means the rsync
|
||||
process in the chroot hierarchy will need to have access to the resources
|
||||
used by these library functions (traditionally /etc/passwd and
|
||||
/etc/group). If these resources are not available, rsync will only be
|
||||
able to copy the IDs, just as if the bf(--numeric-ids) option had been
|
||||
specified.
|
||||
/etc/group, but perhaps additional dynamic libraries as well).
|
||||
|
||||
Note that you are free to setup user/group information in the chroot area
|
||||
differently from your normal system. For example, you could abbreviate
|
||||
the list of users and groups. Also, you can protect this information from
|
||||
being downloaded/uploaded by adding an exclude rule to the rsyncd.conf file
|
||||
(e.g. "bf(exclude = /etc/**)"). Note that having the exclusion affect uploads
|
||||
is a relatively new feature in rsync, so make sure your daemon is
|
||||
at least 2.6.3 to effect this. Also note that it is safest to exclude a
|
||||
directory and all its contents combining the rule "/some/dir/" with the
|
||||
rule "/some/dir/**" just to be sure that rsync will not allow deeper
|
||||
access to some of the excluded files inside the directory (rsync tries to
|
||||
do this automatically, but you might as well specify both to be extra
|
||||
sure).
|
||||
If you copy the necessary resources into the module's chroot area, you
|
||||
should protect them through your OS's normal user/group or ACL settings (to
|
||||
prevent the rsync module's user from being able to change them), and then
|
||||
hide them from the user's view via "exclude" (see how in the discussion of
|
||||
that option). At that point it will be safe to enable the mapping of users
|
||||
and groups by name using the "numeric ids" daemon option (see below).
|
||||
|
||||
Note also that you are free to setup custom user/group information in the
|
||||
chroot area that is different from your normal system. For example, you
|
||||
could abbreviate the list of users and groups.
|
||||
|
||||
dit(bf(numeric ids)) Enabling the "numeric ids" option disables the mapping
|
||||
of users and groups by name for the current daemon module. This prevents
|
||||
the daemon from trying to load any user/group-related files or libraries.
|
||||
Enabling this option makes the transfer behave as if the client had passed
|
||||
the bf(--numeric-ids) command-line option. By default, this parameter is
|
||||
enabled for chroot modules and disabled for non-chroot modules.
|
||||
|
||||
A chroot-enabled module should not have this option enabled unless you've
|
||||
taken steps to ensure that the module has the necessary resources it needs
|
||||
to translate names, and that it is not possible for a user to change those
|
||||
resources.
|
||||
|
||||
dit(bf(munge symlinks)) The "munge symlinks" option tells rsync to modify
|
||||
all incoming symlinks in a way that makes them unusable but recoverable
|
||||
(see below). This should help protect your files from user trickery when
|
||||
your daemon module is writable. The default is disabled when "use chroot"
|
||||
is on and the inside-chroot path is "/", otherwise it is enabled.
|
||||
|
||||
If you disable this option on a daemon that is not read-only, there
|
||||
are tricks that a user can play with uploaded symlinks to access
|
||||
daemon-excluded items (if your module has any), and, if "use chroot"
|
||||
is off, rsync can even be tricked into showing or changing data that
|
||||
is outside the module's path (as access-permissions allow).
|
||||
|
||||
The way rsync disables the use of symlinks is to prefix each one with
|
||||
the string "/rsyncd-munged/". This prevents the links from being used
|
||||
as long as that directory does not exist. When this option is enabled,
|
||||
rsync will refuse to run if that path is a directory or a symlink to
|
||||
a directory. When using the "munge symlinks" option in a chroot area
|
||||
that has an inside-chroot path of "/", you should add "/rsyncd-munged/"
|
||||
to the exclude setting for the module so that
|
||||
a user can't try to create it.
|
||||
|
||||
Note: rsync makes no attempt to verify that any pre-existing symlinks in
|
||||
the hierarchy are as safe as you want them to be. If you setup an rsync
|
||||
daemon on a new area or locally add symlinks, you can manually protect your
|
||||
symlinks from being abused by prefixing "/rsyncd-munged/" to the start of
|
||||
every symlink's value. There is a perl script in the support directory
|
||||
of the source code named "munge-symlinks" that can be used to add or remove
|
||||
this prefix from your symlinks.
|
||||
|
||||
When this option is disabled on a writable module and "use chroot" is off
|
||||
(or the inside-chroot path is not "/"),
|
||||
incoming symlinks will be modified to drop a leading slash and to remove ".."
|
||||
path elements that rsync believes will allow a symlink to escape the module's
|
||||
hierarchy. There are tricky ways to work around this, though, so you had
|
||||
better trust your users if you choose this combination of options.
|
||||
|
||||
dit(bf(charset)) This specifies the name of the character set in which the
|
||||
module's filenames are stored. If the client uses an bf(--iconv) option,
|
||||
the daemon will use the value of the "charset" parameter regardless of the
|
||||
character set the client actually passed. This allows the daemon to
|
||||
support charset conversion in a chroot module without extra files in the
|
||||
chroot area, and also ensures that name-translation is done in a consistent
|
||||
manner. If the "charset" parameter is not set, the bf(--iconv) option is
|
||||
refused, just as if "iconv" had been specified via "refuse options".
|
||||
|
||||
If you wish to force users to always use bf(--iconv) for a particular
|
||||
module, add "no-iconv" to the "refuse options" parameter. Keep in mind
|
||||
that this will restrict access to your module to very new rsync clients.
|
||||
|
||||
dit(bf(max connections)) The "max connections" option allows you to
|
||||
specify the maximum number of simultaneous connections you will allow.
|
||||
@@ -233,49 +314,54 @@ daemon side to behave as if the bf(--fake-user) command-line option had
|
||||
been specified. This allows the full attributes of a file to be stored
|
||||
without having to have the daemon actually running as root.
|
||||
|
||||
dit(bf(filter)) The "filter" option allows you to specify a space-separated
|
||||
list of filter rules that the daemon will not allow to be read or written.
|
||||
This is only superficially equivalent to the client specifying these
|
||||
patterns with the bf(--filter) option. Only one "filter" option may be
|
||||
specified, but it may contain as many rules as you like, including
|
||||
merge-file rules. Note that per-directory merge-file rules do not provide
|
||||
as much protection as global rules, but they can be used to make bf(--delete)
|
||||
work better when a client downloads the daemon's files (if the per-dir
|
||||
merge files are included in the transfer).
|
||||
dit(bf(filter)) The daemon has its own filter chain that determines what files
|
||||
it will let the client access. This chain is not sent to the client and is
|
||||
independent of any filters the client may have specified. Files excluded by
|
||||
the daemon filter chain (bf(daemon-excluded) files) are treated as non-existent
|
||||
if the client tries to pull them, are skipped with an error message if the
|
||||
client tries to push them (triggering exit code 23), and are never deleted from
|
||||
the module. You can use daemon filters to prevent clients from downloading or
|
||||
tampering with private administrative files, such as files you may add to
|
||||
support uid/gid name translations.
|
||||
|
||||
dit(bf(exclude)) The "exclude" option allows you to specify a
|
||||
space-separated list of patterns that the daemon will not allow to be read
|
||||
or written. This is only superficially equivalent to the client
|
||||
specifying these patterns with the bf(--exclude) option. Only one "exclude"
|
||||
option may be specified, but you can use "-" and "+" before patterns to
|
||||
specify exclude/include.
|
||||
The daemon filter chain is built from the "filter", "include from", "include",
|
||||
"exclude from", and "exclude" parameters, in that order of priority. Anchored
|
||||
patterns are anchored at the root of the module. To prevent access to an
|
||||
entire subtree, for example, "/secret", you em(must) exclude everything in the
|
||||
subtree; the easiest way to do this is with a triple-star pattern like
|
||||
"/secret/***".
|
||||
|
||||
Because this exclude list is not passed to the client it only applies on
|
||||
the daemon: that is, it excludes files received by a client when receiving
|
||||
from a daemon and files deleted on a daemon when sending to a daemon, but
|
||||
it doesn't exclude files from being deleted on a client when receiving
|
||||
from a daemon.
|
||||
The "filter" parameter takes a space-separated list of daemon filter rules,
|
||||
though it is smart enough to know not to split a token at an internal space in
|
||||
a rule (e.g. "- /foo - /bar" is parsed as two rules). You may specify one or
|
||||
more merge-file rules using the normal syntax. Only one "filter" parameter can
|
||||
apply to a given module in the config file, so put all the rules you want in a
|
||||
single parameter. Note that per-directory merge-file rules do not provide as
|
||||
much protection as global rules, but they can be used to make bf(--delete) work
|
||||
better during a client download operation if the per-dir merge files are
|
||||
included in the transfer and the client requests that they be used.
|
||||
|
||||
dit(bf(exclude from)) The "exclude from" option specifies a filename
|
||||
on the daemon that contains exclude patterns, one per line.
|
||||
This is only superficially equivalent
|
||||
to the client specifying the bf(--exclude-from) option with an equivalent file.
|
||||
See the "exclude" option above.
|
||||
dit(bf(exclude)) The "exclude" parameter takes a space-separated list of daemon
|
||||
exclude patterns. As with the client bf(--exclude) option, patterns can be
|
||||
qualified with "- " or "+ " to explicitly indicate exclude/include. Only one
|
||||
"exclude" parameter can apply to a given module. See the "filter" parameter
|
||||
for a description of how excluded files affect the daemon.
|
||||
|
||||
dit(bf(include)) The "include" option allows you to specify a
|
||||
space-separated list of patterns which rsync should not exclude. This is
|
||||
only superficially equivalent to the client specifying these patterns with
|
||||
the bf(--include) option because it applies only on the daemon. This is
|
||||
useful as it allows you to build up quite complex exclude/include rules.
|
||||
Only one "include" option may be specified, but you can use "+" and "-"
|
||||
before patterns to switch include/exclude. See the "exclude" option
|
||||
above.
|
||||
dit(bf(include)) Use an "include" to override the effects of the "exclude"
|
||||
parameter. Only one "include" parameter can apply to a given module. See the
|
||||
"filter" parameter for a description of how excluded files affect the daemon.
|
||||
|
||||
dit(bf(include from)) The "include from" option specifies a filename
|
||||
on the daemon that contains include patterns, one per line. This is
|
||||
only superficially equivalent to the client specifying the
|
||||
bf(--include-from) option with a equivalent file.
|
||||
See the "exclude" option above.
|
||||
dit(bf(exclude from)) The "exclude from" parameter specifies the name of a file
|
||||
on the daemon that contains daemon exclude patterns, one per line. Only one
|
||||
"exclude from" parameter can apply to a given module; if you have multiple
|
||||
exclude-from files, you can specify them as a merge file in the "filter"
|
||||
parameter. See the "filter" parameter for a description of how excluded files
|
||||
affect the daemon.
|
||||
|
||||
dit(bf(include from)) Analogue of "exclude from" for a file of daemon include
|
||||
patterns. Only one "include from" parameter can apply to a given module. See
|
||||
the "filter" parameter for a description of how excluded files affect the
|
||||
daemon.
|
||||
|
||||
dit(bf(incoming chmod)) This option allows you to specify a set of
|
||||
comma-separated chmod strings that will affect the permissions of all
|
||||
@@ -368,7 +454,7 @@ tt( fe80::%link1/ffff:ffff:ffff:ffff::)nl()
|
||||
)
|
||||
|
||||
You can also combine "hosts allow" with a separate "hosts deny"
|
||||
option. If both options are specified then the "hosts allow" option s
|
||||
option. If both options are specified then the "hosts allow" option is
|
||||
checked first and a match results in the client being able to
|
||||
connect. The "hosts deny" option is then checked and a match means
|
||||
that the host is rejected. If the host does not match either the
|
||||
@@ -468,9 +554,9 @@ quote(tt( refuse options = c delete))
|
||||
The reason the above refuses all delete options is that the options imply
|
||||
bf(--delete), and implied options are refused just like explicit options.
|
||||
As an additional safety feature, the refusal of "delete" also refuses
|
||||
bf(remove-sent-files) when the daemon is the sender; if you want the latter
|
||||
bf(remove-source-files) when the daemon is the sender; if you want the latter
|
||||
without the former, instead refuse "delete-*" -- that refuses all the
|
||||
delete modes without affecting bf(--remove-sent-files).
|
||||
delete modes without affecting bf(--remove-source-files).
|
||||
|
||||
When an option is refused, the daemon prints an error message and exits.
|
||||
To prevent all compression when serving files,
|
||||
@@ -492,7 +578,7 @@ of the patterns will not be compressed during transfer.
|
||||
|
||||
See the bf(--skip-compress) option in the bf(rsync)(1) manpage for the list
|
||||
of file suffixes that are not compressed by default. Specifying a value
|
||||
for the bf(dont compress) option changes the default when the daemon is
|
||||
for the "dont compress" option changes the default when the daemon is
|
||||
the sender.
|
||||
|
||||
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
|
||||
@@ -562,21 +648,21 @@ A more sophisticated example would be:
|
||||
verb(
|
||||
uid = nobody
|
||||
gid = nobody
|
||||
use chroot = no
|
||||
use chroot = yes
|
||||
max connections = 4
|
||||
syslog facility = local5
|
||||
pid file = /var/run/rsyncd.pid
|
||||
|
||||
[ftp]
|
||||
path = /var/ftp/pub
|
||||
path = /var/ftp/./pub
|
||||
comment = whole ftp area (approx 6.1 GB)
|
||||
|
||||
[sambaftp]
|
||||
path = /var/ftp/pub/samba
|
||||
path = /var/ftp/./pub/samba
|
||||
comment = Samba ftp area (approx 300 MB)
|
||||
|
||||
[rsyncftp]
|
||||
path = /var/ftp/pub/rsync
|
||||
path = /var/ftp/./pub/rsync
|
||||
comment = rsync ftp area (approx 6 MB)
|
||||
|
||||
[sambawww]
|
||||
@@ -614,7 +700,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.0pre1 of rsync.
|
||||
This man page is current for version 3.0.1pre3 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
|
||||
17
sender.c
17
sender.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -135,7 +135,7 @@ void successful_send(int ndx)
|
||||
}
|
||||
|
||||
file = flist->files[ndx - flist->ndx_start];
|
||||
if (!push_pathname(F_PATHNAME(file), -1))
|
||||
if (!change_pathname(file, NULL, 0))
|
||||
return;
|
||||
f_name(file, fname);
|
||||
|
||||
@@ -221,7 +221,7 @@ void send_files(int f_in, int f_out)
|
||||
} else {
|
||||
path = slash = "";
|
||||
}
|
||||
if (!push_pathname(F_PATHNAME(file), -1))
|
||||
if (!change_pathname(file, NULL, 0))
|
||||
continue;
|
||||
f_name(file, fname);
|
||||
|
||||
@@ -229,7 +229,7 @@ void send_files(int f_in, int f_out)
|
||||
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
|
||||
recv_xattr_request(file, f_in);
|
||||
#endif
|
||||
|
||||
@@ -265,7 +265,8 @@ void send_files(int f_in, int f_out)
|
||||
updating_basis_file = inplace && (protocol_version >= 29
|
||||
? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
|
||||
|
||||
stats.current_file_index = ndx;
|
||||
if (!am_server && do_progress)
|
||||
set_current_file_index(file, ndx);
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += F_LENGTH(file);
|
||||
|
||||
@@ -289,13 +290,13 @@ void send_files(int f_in, int f_out)
|
||||
if (errno == ENOENT) {
|
||||
enum logcode c = am_daemon
|
||||
&& protocol_version < 28 ? FERROR
|
||||
: FINFO;
|
||||
: FWARNING;
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"send_files failed to open %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
@@ -349,7 +350,7 @@ void send_files(int f_in, int f_out)
|
||||
j = unmap_file(mbuf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rsyserr(FERROR, j,
|
||||
rsyserr(FERROR_XFER, j,
|
||||
"read errors mapping %s",
|
||||
full_fname(fname));
|
||||
}
|
||||
|
||||
28
socket.c
28
socket.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
extern int connect_timeout;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
@@ -157,6 +158,11 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* connect() timeout handler based on alarm() */
|
||||
static RETSIGTYPE contimeout_handler(UNUSED(int val))
|
||||
{
|
||||
connect_timeout = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a socket to a tcp remote host with the specified port .
|
||||
@@ -261,11 +267,27 @@ int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
if (connect_timeout > 0) {
|
||||
SIGACTION(SIGALRM, contimeout_handler);
|
||||
alarm(connect_timeout);
|
||||
}
|
||||
|
||||
while (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
if (connect_timeout < 0)
|
||||
exit_cleanup(RERR_CONTIMEOUT);
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (connect_timeout > 0)
|
||||
alarm(0);
|
||||
|
||||
if (s < 0)
|
||||
continue;
|
||||
|
||||
if (proxied
|
||||
&& establish_proxy_connection(s, host, port,
|
||||
proxy_user, proxy_pass) != 0) {
|
||||
|
||||
@@ -4,13 +4,19 @@
|
||||
# is included in the rrsync script.
|
||||
use strict;
|
||||
|
||||
our(%short_no_arg, %short_with_num, %long_opt);
|
||||
our %short_no_arg;
|
||||
our %short_with_num;
|
||||
our %long_opt = (
|
||||
'no-i-r' => 0,
|
||||
'fake-super' => 0,
|
||||
'log-file' => 3,
|
||||
);
|
||||
our $last_long_opt;
|
||||
|
||||
open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
|
||||
|
||||
while (<IN>) {
|
||||
if (/\Qargstr[x++]\E = '(.)'/) {
|
||||
if (/\Qargstr[x++]\E = '([^.ie])'/) {
|
||||
$short_no_arg{$1} = 1;
|
||||
undef $last_long_opt;
|
||||
} elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {
|
||||
|
||||
18
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
|
||||
}
|
||||
213
support/patch-update
Executable file
213
support/patch-update
Executable file
@@ -0,0 +1,213 @@
|
||||
#!/usr/bin/perl -w
|
||||
# This script is used to turn one or more of the "patch/*" branches
|
||||
# into one or more diffs in the "patches" directory. Pass the option
|
||||
# --gen if you want generated files in the diffs. Pass the name of
|
||||
# one or more diffs if you want to just update a subset of all the
|
||||
# diffs.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
my $patches_dir = 'patches';
|
||||
my $tmp_dir = "patches.$$";
|
||||
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'skip-check' => \( my $skip_branch_check ),
|
||||
'shell|s' => \( my $launch_shell ),
|
||||
'gen:s' => \( my $incl_generated_files ),
|
||||
'help|h' => \( my $help_opt ),
|
||||
);
|
||||
&usage if $help_opt;
|
||||
|
||||
if (defined $incl_generated_files) {
|
||||
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
|
||||
$incl_generated_files = 1;
|
||||
}
|
||||
|
||||
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
|
||||
die "No '.git' directory present in the current dir.\n" unless -d '.git';
|
||||
|
||||
my($status, $is_clean, $starting_branch) = &check_git_status;
|
||||
if (!$skip_branch_check && !$is_clean) {
|
||||
die "The checkout is not clean:\n", $status;
|
||||
}
|
||||
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
while (<IN>) {
|
||||
if (s/^GENFILES=//) {
|
||||
while (s/\\$//) {
|
||||
$_ .= <IN>;
|
||||
}
|
||||
@extra_files = split(' ', $_);
|
||||
last;
|
||||
}
|
||||
}
|
||||
close IN;
|
||||
|
||||
if ($incl_generated_files) {
|
||||
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
|
||||
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
|
||||
}
|
||||
my $last_touch = time;
|
||||
|
||||
my(%patches, %local_patch);
|
||||
|
||||
# Start by finding all patches so that we can load all possible parents.
|
||||
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
|
||||
while (<PIPE>) {
|
||||
if (m# origin/patch/(.*)#) {
|
||||
$patches{$1} = 1;
|
||||
} elsif (m# patch/(.*)#) {
|
||||
$patches{$1} = $local_patch{$1} = 1;
|
||||
}
|
||||
}
|
||||
close PIPE;
|
||||
|
||||
my @patches = sort keys %patches;
|
||||
|
||||
my(%parent, %description);
|
||||
foreach my $patch (@patches) {
|
||||
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
|
||||
my $desc = '';
|
||||
open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
|
||||
while (<PIPE>) {
|
||||
last if /^@@ /;
|
||||
}
|
||||
while (<PIPE>) {
|
||||
next unless s/^[ +]//;
|
||||
if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
|
||||
$parent{$patch} = $1;
|
||||
}
|
||||
$desc .= $_;
|
||||
}
|
||||
$description{$patch} = $desc;
|
||||
}
|
||||
|
||||
if (@ARGV) {
|
||||
# Limit the list of patches to actually process based on @ARGV.
|
||||
@patches = ( );
|
||||
foreach (@ARGV) {
|
||||
s{^(patches|patch|origin/patch)/} {};
|
||||
s{\.diff$} {};
|
||||
push(@patches, $_);
|
||||
}
|
||||
}
|
||||
|
||||
my %completed;
|
||||
foreach my $patch (@patches) {
|
||||
next if $completed{$patch}++;
|
||||
last unless update_patch($patch);
|
||||
}
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "rm -rf $tmp_dir";
|
||||
}
|
||||
|
||||
sleep 1 if $last_touch == time;
|
||||
system "git checkout $starting_branch" and exit 1;
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
sub update_patch
|
||||
{
|
||||
my($patch) = @_;
|
||||
|
||||
my $parent = $parent{$patch};
|
||||
if (defined $parent) {
|
||||
unless ($completed{$parent}++) {
|
||||
update_patch($parent);
|
||||
}
|
||||
$parent = "patch/$parent";
|
||||
} else {
|
||||
$parent = 'master';
|
||||
}
|
||||
|
||||
print "======== $patch ========\n";
|
||||
|
||||
sleep 1 if $incl_generated_files && $last_touch == time;
|
||||
if ($local_patch{$patch}) {
|
||||
system "git checkout patch/$patch" and return 0;
|
||||
} else {
|
||||
system "git checkout --track -b patch/$patch origin/patch/$patch" and return 0;
|
||||
}
|
||||
|
||||
my $ok = system("git merge $parent") == 0;
|
||||
if (!$ok || $launch_shell) {
|
||||
print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
|
||||
$ENV{PS1} = "[$parent] patch/$patch: ";
|
||||
while (1) {
|
||||
if (system($ENV{SHELL}) != 0) {
|
||||
print "Abort? [n/y] ";
|
||||
$_ = <STDIN>;
|
||||
next unless /^y/i;
|
||||
return 0;
|
||||
}
|
||||
($status, $is_clean) = &check_git_status;
|
||||
last if $is_clean;
|
||||
print $status;
|
||||
}
|
||||
}
|
||||
|
||||
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
|
||||
print OUT $description{$patch}, "\n";
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/";
|
||||
}
|
||||
$last_touch = time;
|
||||
|
||||
open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
|
||||
DIFF: while (<PIPE>) {
|
||||
while (m{^diff --git a/PATCH}) {
|
||||
while (<PIPE>) {
|
||||
last if m{^diff --git a/};
|
||||
}
|
||||
last DIFF if !defined $_;
|
||||
}
|
||||
next if /^index /;
|
||||
print OUT $_;
|
||||
}
|
||||
close PIPE;
|
||||
|
||||
if ($incl_generated_files) {
|
||||
$parent =~ s#.*/##;
|
||||
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
|
||||
while (<PIPE>) {
|
||||
s#^(diff -up) $tmp_dir/[^/]+/(.*?) $tmp_dir/[^/]+/(.*)#$1 a/$2 b/$3#o;
|
||||
s#^\Q---\E $tmp_dir/[^/]+/([^\t]+)\t.*#--- a/$1#o;
|
||||
s#^\Q+++\E $tmp_dir/[^/]+/([^\t]+)\t.*#+++ b/$1#o;
|
||||
print OUT $_;
|
||||
}
|
||||
close PIPE;
|
||||
}
|
||||
|
||||
close OUT;
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
sub check_git_status
|
||||
{
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
my($starting_branch) = $status =~ /^# On branch (.+)\n/;
|
||||
($status, $is_clean, $starting_branch);
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: patch-update [OPTIONS]
|
||||
|
||||
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
|
||||
--skip-check Skip the check that ensures starting with a clean branch.
|
||||
EOT
|
||||
}
|
||||
@@ -39,6 +39,7 @@ die "$0: Restricted directory does not exist!\n" if $subdir ne '/' && !-d $subdi
|
||||
my $command = $ENV{SSH_ORIGINAL_COMMAND};
|
||||
die "$0: Not invoked via sshd\n$Usage" unless defined $command;
|
||||
die "$0: SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ s/^rsync\s+//;
|
||||
die "$0: --server option is not first\n" unless $command =~ /^--server\s/;
|
||||
our $am_sender = $command =~ /^--server\s+--sender\s/; # Restrictive on purpose!
|
||||
die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
|
||||
|
||||
@@ -65,7 +66,7 @@ our %long_opt = (
|
||||
'compress-level' => 1,
|
||||
'copy-dest' => 2,
|
||||
'copy-unsafe-links' => 0,
|
||||
'daemon' => 0,
|
||||
'daemon' => -1,
|
||||
'delay-updates' => 0,
|
||||
'delete' => 0,
|
||||
'delete-after' => 0,
|
||||
@@ -74,6 +75,7 @@ our %long_opt = (
|
||||
'delete-during' => 0,
|
||||
'delete-excluded' => 0,
|
||||
'existing' => 0,
|
||||
'fake-super' => 0,
|
||||
'files-from' => 3,
|
||||
'force' => 0,
|
||||
'from0' => 0,
|
||||
@@ -84,6 +86,7 @@ our %long_opt = (
|
||||
'inplace' => 0,
|
||||
'link-dest' => 2,
|
||||
'list-only' => 0,
|
||||
'log-file' => 3,
|
||||
'log-format' => 1,
|
||||
'max-delete' => 1,
|
||||
'max-size' => 1,
|
||||
@@ -110,6 +113,7 @@ our %long_opt = (
|
||||
'super' => 0,
|
||||
'temp-dir' => 2,
|
||||
'timeout' => 1,
|
||||
'use-qsort' => 0,
|
||||
);
|
||||
|
||||
### END of options data produced by the cull_options script. ###
|
||||
@@ -139,7 +143,7 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
|
||||
if ($_ eq '.') {
|
||||
$in_options = 0;
|
||||
} else {
|
||||
next if /^-$short_no_arg+(e\d+\.\d+)?$/o || /^-$short_with_num\d+$/o;
|
||||
next if /^-$short_no_arg+(e\d*\.\w*)?$/o || /^-$short_with_num\d+$/o;
|
||||
|
||||
my($opt,$arg) = /^--([^=]+)(?:=(.*))?$/;
|
||||
my $disabled;
|
||||
|
||||
30
syscall.c
30
syscall.c
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Tridgell
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,12 +25,16 @@
|
||||
#if !defined MKNOD_CREATES_SOCKETS && defined HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ATTR_H
|
||||
#include <sys/attr.h>
|
||||
#endif
|
||||
|
||||
extern int dry_run;
|
||||
extern int am_root;
|
||||
extern int read_only;
|
||||
extern int list_only;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_executability;
|
||||
|
||||
#define RETURN_ERROR_IF(x,e) \
|
||||
do { \
|
||||
@@ -151,13 +155,21 @@ int do_chmod(const char *path, mode_t mode)
|
||||
if (S_ISLNK(mode)) {
|
||||
#ifdef HAVE_LCHMOD
|
||||
code = lchmod(path, mode & CHMOD_BITS);
|
||||
#elif defined HAVE_SETATTRLIST
|
||||
struct attrlist attrList;
|
||||
uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
|
||||
|
||||
memset(&attrList, 0, sizeof attrList);
|
||||
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
attrList.commonattr = ATTR_CMN_ACCESSMASK;
|
||||
code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
|
||||
#else
|
||||
code = 1;
|
||||
#endif
|
||||
} else
|
||||
code = chmod(path, mode & CHMOD_BITS);
|
||||
if (code != 0 && preserve_perms)
|
||||
return code;
|
||||
code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
|
||||
if (code != 0 && (preserve_perms || preserve_executability))
|
||||
return code;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -200,6 +212,7 @@ int do_mkstemp(char *template, mode_t perms)
|
||||
{
|
||||
RETURN_ERROR_IF(dry_run, 0);
|
||||
RETURN_ERROR_IF(read_only, EROFS);
|
||||
perms |= S_IWUSR;
|
||||
|
||||
#if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
|
||||
{
|
||||
@@ -269,12 +282,3 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
|
||||
return lseek(fd, offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *d_name(struct dirent *di)
|
||||
{
|
||||
#ifdef HAVE_BROKEN_READDIR
|
||||
return (di->d_name - 2);
|
||||
#else
|
||||
return di->d_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
8
t_stub.c
8
t_stub.c
@@ -3,7 +3,7 @@
|
||||
* functions, so that module test harnesses can run standalone.
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,7 +29,7 @@ int module_dirlen = 0;
|
||||
mode_t orig_umask = 002;
|
||||
char *partial_dir;
|
||||
char *module_dir;
|
||||
struct filter_list_struct server_filter_list;
|
||||
struct filter_list_struct daemon_filter_list;
|
||||
|
||||
void rprintf(UNUSED(enum logcode code), const char *format, ...)
|
||||
{
|
||||
@@ -56,8 +56,8 @@ struct filter_list_struct server_filter_list;
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(char *name),
|
||||
UNUSED(int name_is_dir))
|
||||
int check_filter(UNUSED(struct filter_list_struct *listp), UNUSED(enum logcode code),
|
||||
UNUSED(const char *name), UNUSED(int name_is_dir))
|
||||
{
|
||||
/* This function doesn't really get called in this test context, so
|
||||
* just return 0. */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Test harness for unsafe_symlink(). Not linked into rsync itself.
|
||||
*
|
||||
* Copyright (C) 2002 Martin Pool
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,7 @@ int read_only = 0;
|
||||
int list_only = 0;
|
||||
int verbose = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,8 +24,29 @@
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
SSH="$scratchdir/pretend-ssh"
|
||||
|
||||
cat >"$SSH" <<'EOT'
|
||||
while : ; do
|
||||
case "$1" in
|
||||
-*) shift ;;
|
||||
localhost) shift; break ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
eval "${@}"
|
||||
EOT
|
||||
chmod +x "$SSH"
|
||||
|
||||
build_rsyncd_conf
|
||||
|
||||
cd "$scratchdir"
|
||||
|
||||
ln -s test-rsyncd.conf rsyncd.conf
|
||||
|
||||
$RSYNC -ve $SSH --rsync-path="$RSYNC" localhost::
|
||||
|
||||
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
|
||||
export RSYNC_CONNECT_PROG
|
||||
|
||||
|
||||
@@ -81,14 +81,14 @@ touch -r "$fromdir/block" "$fromdir/block2"
|
||||
$RSYNC -ai "$fromdir/block" "$todir/block2" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cD+++++++++ block
|
||||
cD$all_plus block
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
|
||||
|
||||
$RSYNC -ai "$fromdir/block2" "$todir/block" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cD+++++++++ block2
|
||||
cD$all_plus block2
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
|
||||
|
||||
@@ -97,7 +97,7 @@ sleep 1
|
||||
$RSYNC -Di "$fromdir/block3" "$todir/block" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cD..T...... block3
|
||||
cDc.T.$dots block3
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
@@ -105,15 +105,15 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
filter_outfile
|
||||
cat <<EOT >"$chkfile"
|
||||
.d..t...... ./
|
||||
cD..t...... block
|
||||
cD block2
|
||||
cD+++++++++ block3
|
||||
hD+++++++++ block2.5 => block3
|
||||
cD+++++++++ char
|
||||
cD+++++++++ char2
|
||||
cD+++++++++ char3
|
||||
cS+++++++++ fifo
|
||||
.d..t.$dots ./
|
||||
cDc.t.$dots block
|
||||
cDc...$dots block2
|
||||
cD$all_plus block3
|
||||
hD$all_plus block2.5 => block3
|
||||
cD$all_plus char
|
||||
cD$all_plus char2
|
||||
cD$all_plus char3
|
||||
cS$all_plus fifo
|
||||
EOT
|
||||
if test ! -r "$fromdir/block2.5"; then
|
||||
sed -e '/block2\.5/d' <"$chkfile" >"$chkfile.new"
|
||||
@@ -132,15 +132,15 @@ if test -b "$fromdir/block2.5"; then
|
||||
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cd ./
|
||||
hD block
|
||||
hD block2
|
||||
hD block2.5
|
||||
hD block3
|
||||
hD char
|
||||
hD char2
|
||||
hD char3
|
||||
hS fifo
|
||||
cd$allspace ./
|
||||
hD$allspace block
|
||||
hD$allspace block2
|
||||
hD$allspace block2.5
|
||||
hD$allspace block3
|
||||
hD$allspace char
|
||||
hD$allspace char2
|
||||
hD$allspace char3
|
||||
hS$allspace fifo
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
|
||||
fi
|
||||
|
||||
@@ -38,9 +38,20 @@ echo "extra extra" >>"$todir/name1"
|
||||
checkit "$RSYNC -aHivv --no-whole-file '$fromdir/' '$todir/'" "$fromdir" "$todir"
|
||||
|
||||
# Add a new link in a new subdirectory to test that we don't try to link
|
||||
# the files before the directory gets created.
|
||||
mkdir "$fromdir/subdir"
|
||||
ln "$name1" "$fromdir/subdir/new-file"
|
||||
# the files before the directory gets created. We also create a bunch of
|
||||
# extra files to ensure that an incremental-recursion transfer works across
|
||||
# distant files.
|
||||
makepath "$fromdir/subdir/down/deep"
|
||||
|
||||
files=''
|
||||
for x in 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z; do
|
||||
for y in 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z; do
|
||||
files="$files $x$y"
|
||||
done
|
||||
done
|
||||
(cd "$fromdir/subdir"; touch $files)
|
||||
|
||||
ln "$name1" "$fromdir/subdir/down/deep/new-file"
|
||||
rm "$todir/text"
|
||||
|
||||
checkit "$RSYNC -aHivv '$fromdir/' '$todir/'" "$fromdir" "$todir"
|
||||
|
||||
@@ -25,28 +25,42 @@ umask 0
|
||||
ln -s ../bar/baz/rsync "$fromdir/foo/sym"
|
||||
umask 022
|
||||
ln "$fromdir/foo/config1" "$fromdir/foo/extra"
|
||||
rm -f "$to2dir"
|
||||
|
||||
# Check if the OS can hard-link symlinks or not
|
||||
ln -s no-such-dir "$to2dir"
|
||||
if ln "$to2dir" "$to2dir.test" 2>/dev/null; then
|
||||
# Check if rsync is set to hard-link symlinks.
|
||||
confile=`echo "$scratchdir" | sed 's;/testtmp/itemize$;/config.h;'`
|
||||
if egrep '^#define CAN_HARDLINK_SYMLINK 1' "$confile" >/dev/null; then
|
||||
L=hL
|
||||
else
|
||||
L=cL
|
||||
fi
|
||||
rm -f "$to2dir" "$to2dir.test"
|
||||
|
||||
# Check if rsync can preserve time on symlinks
|
||||
case "$RSYNC" in
|
||||
*protocol=2*)
|
||||
T=.T
|
||||
;;
|
||||
*)
|
||||
if $RSYNC --version | grep ", symtimes" >/dev/null; then
|
||||
T=.t
|
||||
else
|
||||
T=.T
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
$RSYNC -iplr "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cd+++++++++ ./
|
||||
cd+++++++++ bar/
|
||||
cd+++++++++ bar/baz/
|
||||
>f+++++++++ bar/baz/rsync
|
||||
cd+++++++++ foo/
|
||||
>f+++++++++ foo/config1
|
||||
>f+++++++++ foo/config2
|
||||
>f+++++++++ foo/extra
|
||||
cL+++++++++ foo/sym -> ../bar/baz/rsync
|
||||
cd$all_plus ./
|
||||
cd$all_plus bar/
|
||||
cd$all_plus bar/baz/
|
||||
>f$all_plus bar/baz/rsync
|
||||
cd$all_plus foo/
|
||||
>f$all_plus foo/config1
|
||||
>f$all_plus foo/config2
|
||||
>f$all_plus foo/extra
|
||||
cL$all_plus foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
|
||||
|
||||
@@ -58,10 +72,10 @@ chmod 601 "$fromdir/foo/config2"
|
||||
$RSYNC -iplrH "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
>f..T...... bar/baz/rsync
|
||||
>f..T...... foo/config1
|
||||
>f.sTp..... foo/config2
|
||||
hf..T...... foo/extra => foo/config1
|
||||
>f..T.$dots bar/baz/rsync
|
||||
>f..T.$dots foo/config1
|
||||
>f.sTp$dots foo/config2
|
||||
hf..T.$dots foo/extra => foo/config1
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
|
||||
|
||||
@@ -78,11 +92,11 @@ chmod 777 "$todir/bar/baz/rsync"
|
||||
$RSYNC -iplrtc "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
.f..tp..... bar/baz/rsync
|
||||
.d..t...... foo/
|
||||
.f..t...... foo/config1
|
||||
>fcstp..... foo/config2
|
||||
cL..T...... foo/sym -> ../bar/baz/rsync
|
||||
.f..tp$dots bar/baz/rsync
|
||||
.d..t.$dots foo/
|
||||
.f..t.$dots foo/config1
|
||||
>fcstp$dots foo/config2
|
||||
cLc$T.$dots foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
||||
|
||||
@@ -107,15 +121,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
filter_outfile
|
||||
cat <<EOT >"$chkfile"
|
||||
.d ./
|
||||
.d bar/
|
||||
.d bar/baz/
|
||||
.f...p..... bar/baz/rsync
|
||||
.d foo/
|
||||
.f foo/config1
|
||||
>f..t...... foo/config2
|
||||
hf foo/extra
|
||||
.L foo/sym -> ../bar/baz/rsync
|
||||
.d$allspace ./
|
||||
.d$allspace bar/
|
||||
.d$allspace bar/baz/
|
||||
.f...p$dots bar/baz/rsync
|
||||
.d$allspace foo/
|
||||
.f$allspace foo/config1
|
||||
>f..t.$dots foo/config2
|
||||
hf$allspace foo/extra
|
||||
.L$allspace foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
|
||||
|
||||
@@ -134,32 +148,47 @@ touch "$todir/foo/config2"
|
||||
$RSYNC -iplrtH "$fromdir/" "$todir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
.f...p..... foo/config1
|
||||
>f..t...... foo/config2
|
||||
.f...p$dots foo/config1
|
||||
>f..t.$dots foo/config2
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
|
||||
|
||||
$RSYNC -ivvplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
filter_outfile
|
||||
case `tail -1 "$outfile"` in
|
||||
cLc.t*)
|
||||
sym_dots="c.t.$dots"
|
||||
L_sym_dots="cL$sym_dots"
|
||||
is_uptodate='-> ../bar/baz/rsync'
|
||||
echo "cL$sym_dots foo/sym $is_uptodate" >"$chkfile.extra"
|
||||
L=cL
|
||||
;;
|
||||
*)
|
||||
sym_dots="$allspace"
|
||||
L_sym_dots=".L$allspace"
|
||||
is_uptodate='is uptodate'
|
||||
touch "$chkfile.extra"
|
||||
;;
|
||||
esac
|
||||
cat <<EOT >"$chkfile"
|
||||
cd ./
|
||||
cd bar/
|
||||
cd bar/baz/
|
||||
cf bar/baz/rsync
|
||||
cd foo/
|
||||
cf foo/config1
|
||||
cf foo/config2
|
||||
hf foo/extra => foo/config1
|
||||
cL foo/sym -> ../bar/baz/rsync
|
||||
cd$allspace ./
|
||||
cd$allspace bar/
|
||||
cd$allspace bar/baz/
|
||||
cf$allspace bar/baz/rsync
|
||||
cd$allspace foo/
|
||||
cf$allspace foo/config1
|
||||
cf$allspace foo/config2
|
||||
hf$allspace foo/extra => foo/config1
|
||||
cL$sym_dots foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
|
||||
|
||||
rm -rf "$to2dir"
|
||||
$RSYNC -iplrtH --copy-dest=../to "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
hf foo/extra => foo/config1
|
||||
cat - "$chkfile.extra" <<EOT >"$chkfile"
|
||||
hf$allspace foo/extra => foo/config1
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
|
||||
|
||||
@@ -176,7 +205,7 @@ foo/ is uptodate
|
||||
foo/config1 is uptodate
|
||||
foo/config2 is uptodate
|
||||
foo/extra => foo/config1
|
||||
foo/sym is uptodate
|
||||
foo/sym $is_uptodate
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 10 failed"
|
||||
|
||||
@@ -185,29 +214,29 @@ $RSYNC -ivvplrtH --link-dest="$todir" "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
filter_outfile
|
||||
cat <<EOT >"$chkfile"
|
||||
cd ./
|
||||
cd bar/
|
||||
cd bar/baz/
|
||||
hf bar/baz/rsync
|
||||
cd foo/
|
||||
hf foo/config1
|
||||
hf foo/config2
|
||||
hf foo/extra => foo/config1
|
||||
$L foo/sym -> ../bar/baz/rsync
|
||||
cd$allspace ./
|
||||
cd$allspace bar/
|
||||
cd$allspace bar/baz/
|
||||
hf$allspace bar/baz/rsync
|
||||
cd$allspace foo/
|
||||
hf$allspace foo/config1
|
||||
hf$allspace foo/config2
|
||||
hf$allspace foo/extra => foo/config1
|
||||
$L$sym_dots foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
|
||||
|
||||
rm -rf "$to2dir"
|
||||
$RSYNC -iplrtH --dry-run --link-dest=../to "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cat - "$chkfile.extra" <<EOT >"$chkfile"
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
|
||||
|
||||
rm -rf "$to2dir"
|
||||
$RSYNC -iplrtH --link-dest=../to "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cat - "$chkfile.extra" <<EOT >"$chkfile"
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 13 failed"
|
||||
|
||||
@@ -224,7 +253,7 @@ foo/ is uptodate
|
||||
foo/config1 is uptodate
|
||||
foo/config2 is uptodate
|
||||
foo/extra is uptodate
|
||||
foo/sym is uptodate
|
||||
foo/sym $is_uptodate
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
|
||||
|
||||
@@ -233,22 +262,22 @@ $RSYNC -ivvplrtH --compare-dest="$todir" "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
filter_outfile
|
||||
cat <<EOT >"$chkfile"
|
||||
cd ./
|
||||
cd bar/
|
||||
cd bar/baz/
|
||||
.f bar/baz/rsync
|
||||
cd foo/
|
||||
.f foo/config1
|
||||
.f foo/config2
|
||||
.f foo/extra
|
||||
.L foo/sym -> ../bar/baz/rsync
|
||||
cd$allspace ./
|
||||
cd$allspace bar/
|
||||
cd$allspace bar/baz/
|
||||
.f$allspace bar/baz/rsync
|
||||
cd$allspace foo/
|
||||
.f$allspace foo/config1
|
||||
.f$allspace foo/config2
|
||||
.f$allspace foo/extra
|
||||
$L_sym_dots foo/sym -> ../bar/baz/rsync
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
|
||||
|
||||
rm -rf "$to2dir"
|
||||
$RSYNC -iplrtH --compare-dest="$todir" "$fromdir/" "$to2dir/" \
|
||||
| tee "$outfile"
|
||||
cat <<EOT >"$chkfile"
|
||||
cat - "$chkfile.extra" <<EOT >"$chkfile"
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 16 failed"
|
||||
|
||||
@@ -265,7 +294,7 @@ foo/ is uptodate
|
||||
foo/config1 is uptodate
|
||||
foo/config2 is uptodate
|
||||
foo/extra is uptodate
|
||||
foo/sym is uptodate
|
||||
foo/sym $is_uptodate
|
||||
EOT
|
||||
diff $diffopt "$chkfile" "$outfile" || test_fail "test 17 failed"
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ $RSYNC -av --existing -f 'exclude,! */' from2/ from3/
|
||||
$RSYNC -av --existing -f 'exclude,! */' from1/ chk/
|
||||
$RSYNC -av --existing -f 'exclude,! */' from3/ chk/
|
||||
|
||||
checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" chk to
|
||||
checkit "$RSYNC -avv deep/arg-test shallow from1/ from2/ from3/ to/" "$chkdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
27
testsuite/missing.test
Normal file
27
testsuite/missing.test
Normal file
@@ -0,0 +1,27 @@
|
||||
#! /bin/sh
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test three bugs fixed by my redoing of the missing_below logic.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
makepath "$fromdir/subdir" "$todir"
|
||||
echo data >"$fromdir/subdir/file"
|
||||
echo data >"$todir/other"
|
||||
|
||||
# Test 1: Too much "not creating new..." output on a dry run
|
||||
$RSYNC -n -r --ignore-non-existing -vv "$fromdir/" "$todir/" | tee "$scratchdir/out"
|
||||
if grep 'not creating new.*subdir/file' "$scratchdir/out" >/dev/null; then
|
||||
test_fail 'test 1 failed'
|
||||
fi
|
||||
|
||||
# Test 2: Attempt to make a fuzzy dirlist for a dir not created on a dry run
|
||||
$RSYNC -n -r -R --no-implied-dirs -y "$fromdir/./subdir/file" "$todir/" \
|
||||
|| test_fail 'test 2 failed'
|
||||
|
||||
# Test 3: --delete-after pass skipped when last dir is dry-missing
|
||||
$RSYNC -n -r --delete-after -i "$fromdir/" "$todir/" | tee "$scratchdir/out"
|
||||
grep '^\*deleting * other' "$scratchdir/out" >/dev/null \
|
||||
|| test_fail 'test 3 failed'
|
||||
@@ -23,6 +23,11 @@ fromdir="$tmpdir/from"
|
||||
todir="$tmpdir/to"
|
||||
chkdir="$tmpdir/chk"
|
||||
|
||||
# For itemized output:
|
||||
all_plus='+++++++++'
|
||||
allspace=' '
|
||||
dots='.....' # trailing dots after changes
|
||||
|
||||
# Berkley's nice.
|
||||
PATH="$PATH:/usr/ucb"
|
||||
|
||||
@@ -234,6 +239,7 @@ build_rsyncd_conf() {
|
||||
|
||||
pid file = $pidfile
|
||||
use chroot = no
|
||||
munge symlinks = no
|
||||
hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
|
||||
log file = $logfile
|
||||
log format = %i %h [%a] %m (%u) %l %f%L
|
||||
@@ -255,6 +261,25 @@ gid = 0
|
||||
path = $scratchdir
|
||||
read only = no
|
||||
EOF
|
||||
|
||||
# Build a helper script to ignore exit code 23
|
||||
ignore23="$scratchdir/ignore23"
|
||||
echo "building help script $ignore23"
|
||||
|
||||
cat >"$ignore23" <<'EOT'
|
||||
if "${@}"; then
|
||||
exit
|
||||
fi
|
||||
|
||||
ret=$?
|
||||
|
||||
if test $ret = 23; then
|
||||
exit
|
||||
fi
|
||||
|
||||
exit $ret
|
||||
EOT
|
||||
chmod +x "$ignore23"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ case "`xattr 2>&1`" in
|
||||
xls() {
|
||||
xattr -l "${@}"
|
||||
}
|
||||
RUSR='rsync.nonuser'
|
||||
;;
|
||||
*)
|
||||
xset() {
|
||||
@@ -31,21 +32,23 @@ case "`xattr 2>&1`" in
|
||||
xls() {
|
||||
getfattr -d "${@}"
|
||||
}
|
||||
RUSR='user.rsync'
|
||||
;;
|
||||
esac
|
||||
|
||||
makepath "$fromdir/foo"
|
||||
makepath "$fromdir/foo/bar"
|
||||
echo now >"$fromdir/file0"
|
||||
echo something >"$fromdir/file1"
|
||||
echo else >"$fromdir/file2"
|
||||
echo deep >"$fromdir/foo/file3"
|
||||
echo normal >"$fromdir/file4"
|
||||
echo deeper >"$fromdir/foo/bar/file5"
|
||||
|
||||
makepath "$chkdir/foo"
|
||||
echo wow >"$chkdir/file1"
|
||||
cp -p "$fromdir/foo/file3" "$chkdir/foo"
|
||||
|
||||
files='foo file0 file1 file2 foo/file3 file4'
|
||||
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
|
||||
|
||||
cd "$fromdir"
|
||||
|
||||
@@ -61,28 +64,28 @@ xset user.foo foo file2
|
||||
xset user.bar bar file2
|
||||
xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
|
||||
|
||||
xset user.foo 'new foo' foo/file3
|
||||
xset user.bar 'new bar' foo/file3
|
||||
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3
|
||||
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3
|
||||
xset user.foo 'new foo' foo/file3 foo/bar/file5
|
||||
xset user.bar 'new bar' foo/file3 foo/bar/file5
|
||||
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3 foo/bar/file5
|
||||
xset $RUSR.equal 'this long attribute should remain the same and not need to be transferred' foo/file3 foo/bar/file5
|
||||
|
||||
xset user.short 'old short' "$chkdir/file1"
|
||||
xset user.extra 'remove me' "$chkdir/file1"
|
||||
|
||||
xset user.foo 'old foo' "$chkdir/foo/file3"
|
||||
xset user.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
|
||||
xset $RUSR.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
|
||||
|
||||
xls $files >"$scratchdir/xattrs.txt"
|
||||
|
||||
# OK, let's try a simple xattr copy.
|
||||
checkit "$RSYNC -avX . '$chkdir/'" "$fromdir" "$chkdir"
|
||||
checkit "$RSYNC -avX --super . '$chkdir/'" "$fromdir" "$chkdir"
|
||||
|
||||
cd "$chkdir"
|
||||
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
cd "$fromdir"
|
||||
|
||||
checkit "$RSYNC -aiX --copy-dest=../chk . ../to" "$fromdir" "$todir"
|
||||
checkit "$RSYNC -aiX --super --copy-dest=../chk . ../to" "$fromdir" "$todir"
|
||||
|
||||
cd "$todir"
|
||||
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
@@ -94,10 +97,17 @@ xls $files >"$scratchdir/xattrs.txt"
|
||||
|
||||
rm -rf "$todir"
|
||||
|
||||
checkit "$RSYNC -aiX --link-dest=../chk . ../to" "$chkdir" "$todir"
|
||||
checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
|
||||
|
||||
cd "$todir"
|
||||
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
|
||||
|
||||
sed -n -e '/\.\/file1$/d' -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff"
|
||||
if [ -s "$scratchdir/ls-diff" ]; then
|
||||
echo "Missing hard links on:"
|
||||
cat "$scratchdir/ls-diff"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
5
tls.c
5
tls.c
@@ -2,7 +2,7 @@
|
||||
* Trivial ls for comparing two directories after running an rsync.
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -35,7 +35,7 @@
|
||||
* change. */
|
||||
|
||||
#include "rsync.h"
|
||||
#include "popt.h"
|
||||
#include <popt.h>
|
||||
#include "lib/sysxattrs.h"
|
||||
|
||||
#define PROGRAM "tls"
|
||||
@@ -46,6 +46,7 @@ int am_root = 0;
|
||||
int read_only = 1;
|
||||
int list_only = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
|
||||
|
||||
2
token.c
2
token.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -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)
|
||||
|
||||
34
uidlist.c
34
uidlist.c
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 1996 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2004-2007 Wayne Davison
|
||||
* Copyright (C) 2004-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -43,7 +43,7 @@ extern int numeric_ids;
|
||||
|
||||
struct idlist {
|
||||
struct idlist *next;
|
||||
char *name;
|
||||
const char *name;
|
||||
id_t id, id2;
|
||||
uint16 flags;
|
||||
};
|
||||
@@ -51,7 +51,7 @@ struct idlist {
|
||||
static struct idlist *uidlist;
|
||||
static struct idlist *gidlist;
|
||||
|
||||
static struct idlist *add_to_list(struct idlist **root, id_t id, char *name,
|
||||
static struct idlist *add_to_list(struct idlist **root, id_t id, const char *name,
|
||||
id_t id2, uint16 flags)
|
||||
{
|
||||
struct idlist *node = new(struct idlist);
|
||||
@@ -67,7 +67,7 @@ static struct idlist *add_to_list(struct idlist **root, id_t id, char *name,
|
||||
}
|
||||
|
||||
/* turn a uid into a user name */
|
||||
static char *uid_to_name(uid_t uid)
|
||||
static const char *uid_to_name(uid_t uid)
|
||||
{
|
||||
struct passwd *pass = getpwuid(uid);
|
||||
if (pass)
|
||||
@@ -76,7 +76,7 @@ static char *uid_to_name(uid_t uid)
|
||||
}
|
||||
|
||||
/* turn a gid into a group name */
|
||||
static char *gid_to_name(gid_t gid)
|
||||
static const char *gid_to_name(gid_t gid)
|
||||
{
|
||||
struct group *grp = getgrgid(gid);
|
||||
if (grp)
|
||||
@@ -84,7 +84,7 @@ static char *gid_to_name(gid_t gid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uid_t map_uid(uid_t id, char *name)
|
||||
static uid_t map_uid(uid_t id, const char *name)
|
||||
{
|
||||
uid_t uid;
|
||||
if (id != 0 && name_to_uid(name, &uid))
|
||||
@@ -92,7 +92,7 @@ static uid_t map_uid(uid_t id, char *name)
|
||||
return id;
|
||||
}
|
||||
|
||||
static gid_t map_gid(gid_t id, char *name)
|
||||
static gid_t map_gid(gid_t id, const char *name)
|
||||
{
|
||||
gid_t gid;
|
||||
if (id != 0 && name_to_gid(name, &gid))
|
||||
@@ -160,7 +160,7 @@ static int is_in_group(gid_t gid)
|
||||
}
|
||||
|
||||
/* Add a uid to the list of uids. Only called on receiving side. */
|
||||
static struct idlist *recv_add_uid(uid_t id, char *name)
|
||||
static struct idlist *recv_add_uid(uid_t id, const char *name)
|
||||
{
|
||||
uid_t id2 = name ? map_uid(id, name) : id;
|
||||
struct idlist *node;
|
||||
@@ -176,7 +176,7 @@ static struct idlist *recv_add_uid(uid_t id, char *name)
|
||||
}
|
||||
|
||||
/* Add a gid to the list of gids. Only called on receiving side. */
|
||||
static struct idlist *recv_add_gid(gid_t id, char *name)
|
||||
static struct idlist *recv_add_gid(gid_t id, const char *name)
|
||||
{
|
||||
gid_t id2 = name ? map_gid(id, name) : id;
|
||||
struct idlist *node;
|
||||
@@ -237,7 +237,7 @@ gid_t match_gid(gid_t gid, uint16 *flags_ptr)
|
||||
}
|
||||
|
||||
/* Add a uid to the list of uids. Only called on sending side. */
|
||||
char *add_uid(uid_t uid)
|
||||
const char *add_uid(uid_t uid)
|
||||
{
|
||||
struct idlist *list;
|
||||
struct idlist *node;
|
||||
@@ -255,7 +255,7 @@ char *add_uid(uid_t uid)
|
||||
}
|
||||
|
||||
/* Add a gid to the list of gids. Only called on sending side. */
|
||||
char *add_gid(gid_t gid)
|
||||
const char *add_gid(gid_t gid)
|
||||
{
|
||||
struct idlist *list;
|
||||
struct idlist *node;
|
||||
@@ -316,6 +316,10 @@ uid_t recv_user_name(int f, uid_t uid)
|
||||
if (!name)
|
||||
out_of_memory("recv_user_name");
|
||||
read_sbuf(f, name, len);
|
||||
if (numeric_ids < 0) {
|
||||
free(name);
|
||||
name = NULL;
|
||||
}
|
||||
node = recv_add_uid(uid, name); /* node keeps name's memory */
|
||||
return node->id2;
|
||||
}
|
||||
@@ -328,6 +332,10 @@ gid_t recv_group_name(int f, gid_t gid, uint16 *flags_ptr)
|
||||
if (!name)
|
||||
out_of_memory("recv_group_name");
|
||||
read_sbuf(f, name, len);
|
||||
if (numeric_ids < 0) {
|
||||
free(name);
|
||||
name = NULL;
|
||||
}
|
||||
node = recv_add_gid(gid, name); /* node keeps name's memory */
|
||||
if (flags_ptr && node->flags & FLAG_SKIP_GROUP)
|
||||
*flags_ptr |= FLAG_SKIP_GROUP;
|
||||
@@ -341,13 +349,13 @@ void recv_id_list(int f, struct file_list *flist)
|
||||
id_t id;
|
||||
int i;
|
||||
|
||||
if ((preserve_uid || preserve_acls) && !numeric_ids) {
|
||||
if ((preserve_uid || preserve_acls) && numeric_ids <= 0) {
|
||||
/* read the uid list */
|
||||
while ((id = read_varint30(f)) != 0)
|
||||
recv_user_name(f, id);
|
||||
}
|
||||
|
||||
if ((preserve_gid || preserve_acls) && !numeric_ids) {
|
||||
if ((preserve_gid || preserve_acls) && numeric_ids <= 0) {
|
||||
/* read the gid list */
|
||||
while ((id = read_varint30(f)) != 0)
|
||||
recv_group_name(f, id, NULL);
|
||||
|
||||
434
util.c
434
util.c
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1996-2000 Andrew Tridgell
|
||||
* Copyright (C) 1996 Paul Mackerras
|
||||
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@ extern char *module_dir;
|
||||
extern unsigned int module_dirlen;
|
||||
extern mode_t orig_umask;
|
||||
extern char *partial_dir;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
extern struct filter_list_struct daemon_filter_list;
|
||||
|
||||
int sanitize_paths = 0;
|
||||
|
||||
@@ -147,12 +147,13 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
|
||||
t[1].tv_usec = 0;
|
||||
# ifdef HAVE_LUTIMES
|
||||
if (S_ISLNK(mode)) {
|
||||
lutimes(fname, t);
|
||||
return 0; /* ignore errors */
|
||||
if (lutimes(fname, t) < 0)
|
||||
return errno == ENOSYS ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
return utimes(fname, t);
|
||||
#elif defined HAVE_UTIMBUF
|
||||
#elif defined HAVE_STRUCT_UTIMBUF
|
||||
struct utimbuf tbuf;
|
||||
tbuf.actime = time(NULL);
|
||||
tbuf.modtime = modtime;
|
||||
@@ -261,38 +262,41 @@ static int safe_read(int desc, char *ptr, size_t len)
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
/** Copy a file.
|
||||
/* Copy a file. If ofd < 0, copy_file unlinks and opens the "dest" file.
|
||||
* Otherwise, it just writes to and closes the provided file descriptor.
|
||||
*
|
||||
* This is used in conjunction with the --temp-dir, --backup, and
|
||||
* --copy-dest options. */
|
||||
int copy_file(const char *source, const char *dest, mode_t mode, int create_bak_dir)
|
||||
int copy_file(const char *source, const char *dest, int ofd,
|
||||
mode_t mode, int create_bak_dir)
|
||||
{
|
||||
int ifd;
|
||||
int ofd;
|
||||
char buf[1024 * 8];
|
||||
int len; /* Number of bytes read into `buf'. */
|
||||
|
||||
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
|
||||
rsyserr(FERROR, errno, "open %s", full_fname(source));
|
||||
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (robust_unlink(dest) && errno != ENOENT) {
|
||||
rsyserr(FERROR, errno, "unlink %s", full_fname(dest));
|
||||
return -1;
|
||||
}
|
||||
if (ofd < 0) {
|
||||
if (robust_unlink(dest) && errno != ENOENT) {
|
||||
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
|
||||
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|
||||
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
|
||||
rsyserr(FERROR, errno, "open %s", full_fname(dest));
|
||||
close(ifd);
|
||||
return -1;
|
||||
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
|
||||
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|
||||
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
|
||||
rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest));
|
||||
close(ifd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
|
||||
if (full_write(ofd, buf, len) < 0) {
|
||||
rsyserr(FERROR, errno, "write %s", full_fname(dest));
|
||||
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
return -1;
|
||||
@@ -300,19 +304,19 @@ int copy_file(const char *source, const char *dest, mode_t mode, int create_bak_
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
rsyserr(FERROR, errno, "read %s", full_fname(source));
|
||||
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(ifd) < 0) {
|
||||
rsyserr(FINFO, errno, "close failed on %s",
|
||||
rsyserr(FWARNING, errno, "close failed on %s",
|
||||
full_fname(source));
|
||||
}
|
||||
|
||||
if (close(ofd) < 0) {
|
||||
rsyserr(FERROR, errno, "close failed on %s",
|
||||
rsyserr(FERROR_XFER, errno, "close failed on %s",
|
||||
full_fname(dest));
|
||||
return -1;
|
||||
}
|
||||
@@ -368,7 +372,7 @@ int robust_unlink(const char *fname)
|
||||
} while ((rc = access(path, 0)) == 0 && counter != start);
|
||||
|
||||
if (verbose > 0) {
|
||||
rprintf(FINFO,"renaming %s to %s because of text busy\n",
|
||||
rprintf(FWARNING, "renaming %s to %s because of text busy\n",
|
||||
fname, path);
|
||||
}
|
||||
|
||||
@@ -407,7 +411,7 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
|
||||
return -1;
|
||||
to = partialptr;
|
||||
}
|
||||
if (copy_file(from, to, mode, 0) != 0)
|
||||
if (copy_file(from, to, -1, mode, 0) != 0)
|
||||
return -2;
|
||||
do_unlink(from);
|
||||
return 1;
|
||||
@@ -462,31 +466,27 @@ void kill_all(int sig)
|
||||
}
|
||||
|
||||
/** Turn a user name into a uid */
|
||||
int name_to_uid(const char *name, uid_t *uid)
|
||||
int name_to_uid(const char *name, uid_t *uid_p)
|
||||
{
|
||||
struct passwd *pass;
|
||||
if (!name || !*name)
|
||||
return 0;
|
||||
pass = getpwnam(name);
|
||||
if (pass) {
|
||||
*uid = pass->pw_uid;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (!(pass = getpwnam(name)))
|
||||
return 0;
|
||||
*uid_p = pass->pw_uid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Turn a group name into a gid */
|
||||
int name_to_gid(const char *name, gid_t *gid)
|
||||
int name_to_gid(const char *name, gid_t *gid_p)
|
||||
{
|
||||
struct group *grp;
|
||||
if (!name || !*name)
|
||||
return 0;
|
||||
grp = getgrnam(name);
|
||||
if (grp) {
|
||||
*gid = grp->gr_gid;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (!(grp = getgrnam(name)))
|
||||
return 0;
|
||||
*gid_p = grp->gr_gid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Lock a byte range in a open file */
|
||||
@@ -503,82 +503,172 @@ int lock_range(int fd, int offset, int len)
|
||||
return fcntl(fd,F_SETLK,&lock) == 0;
|
||||
}
|
||||
|
||||
static int filter_server_path(char *arg)
|
||||
{
|
||||
char *s;
|
||||
#define ENSURE_MEMSPACE(buf, type, sz, req) \
|
||||
if ((req) > sz && !(buf = realloc_array(buf, type, sz = MAX(sz * 2, req)))) \
|
||||
out_of_memory("glob_expand")
|
||||
|
||||
if (server_filter_list.head) {
|
||||
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
|
||||
*s = '\0';
|
||||
if (check_filter(&server_filter_list, arg, 1) < 0) {
|
||||
/* We must leave arg truncated! */
|
||||
return 1;
|
||||
}
|
||||
*s++ = '/';
|
||||
static inline void call_glob_match(const char *name, int len, int from_glob,
|
||||
char *arg, int abpos, int fbpos);
|
||||
|
||||
static struct glob_data {
|
||||
char *arg_buf, *filt_buf, **argv;
|
||||
int absize, fbsize, maxargs, argc;
|
||||
} glob;
|
||||
|
||||
static void glob_match(char *arg, int abpos, int fbpos)
|
||||
{
|
||||
int len;
|
||||
char *slash;
|
||||
|
||||
while (*arg == '.' && arg[1] == '/') {
|
||||
if (fbpos < 0) {
|
||||
ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, glob.absize);
|
||||
memcpy(glob.filt_buf, glob.arg_buf, abpos + 1);
|
||||
fbpos = abpos;
|
||||
}
|
||||
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + 3);
|
||||
glob.arg_buf[abpos++] = *arg++;
|
||||
glob.arg_buf[abpos++] = *arg++;
|
||||
glob.arg_buf[abpos] = '\0';
|
||||
}
|
||||
return 0;
|
||||
if ((slash = strchr(arg, '/')) != NULL) {
|
||||
*slash = '\0';
|
||||
len = slash - arg;
|
||||
} else
|
||||
len = strlen(arg);
|
||||
if (strpbrk(arg, "*?[")) {
|
||||
struct dirent *di;
|
||||
DIR *d;
|
||||
|
||||
if (!(d = opendir(abpos ? glob.arg_buf : ".")))
|
||||
return;
|
||||
while ((di = readdir(d)) != NULL) {
|
||||
char *dname = d_name(di);
|
||||
if (dname[0] == '.' && (dname[1] == '\0'
|
||||
|| (dname[1] == '.' && dname[2] == '\0')))
|
||||
continue;
|
||||
if (!wildmatch(arg, dname))
|
||||
continue;
|
||||
call_glob_match(dname, strlen(dname), 1,
|
||||
slash ? arg + len + 1 : NULL,
|
||||
abpos, fbpos);
|
||||
}
|
||||
closedir(d);
|
||||
} else {
|
||||
call_glob_match(arg, len, 0,
|
||||
slash ? arg + len + 1 : NULL,
|
||||
abpos, fbpos);
|
||||
}
|
||||
if (slash)
|
||||
*slash = '/';
|
||||
}
|
||||
|
||||
void glob_expand(char *s, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
|
||||
static inline void call_glob_match(const char *name, int len, int from_glob,
|
||||
char *arg, int abpos, int fbpos)
|
||||
{
|
||||
char **argv = *argv_ptr;
|
||||
int argc = *argc_ptr;
|
||||
int maxargs = *maxargs_ptr;
|
||||
#if !defined HAVE_GLOB || !defined HAVE_GLOB_H
|
||||
if (argc == maxargs) {
|
||||
maxargs += MAX_ARGS;
|
||||
if (!(argv = realloc_array(argv, char *, maxargs)))
|
||||
out_of_memory("glob_expand");
|
||||
*argv_ptr = argv;
|
||||
*maxargs_ptr = maxargs;
|
||||
}
|
||||
if (!*s)
|
||||
s = ".";
|
||||
s = argv[argc++] = strdup(s);
|
||||
filter_server_path(s);
|
||||
#else
|
||||
glob_t globbuf;
|
||||
char *use_buf;
|
||||
|
||||
if (maxargs <= argc)
|
||||
return;
|
||||
if (!*s)
|
||||
s = ".";
|
||||
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + len + 2);
|
||||
memcpy(glob.arg_buf + abpos, name, len);
|
||||
abpos += len;
|
||||
glob.arg_buf[abpos] = '\0';
|
||||
|
||||
if (fbpos >= 0) {
|
||||
ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, fbpos + len + 2);
|
||||
memcpy(glob.filt_buf + fbpos, name, len);
|
||||
fbpos += len;
|
||||
glob.filt_buf[fbpos] = '\0';
|
||||
use_buf = glob.filt_buf;
|
||||
} else
|
||||
use_buf = glob.arg_buf;
|
||||
|
||||
if (from_glob || arg) {
|
||||
STRUCT_STAT st;
|
||||
int is_dir;
|
||||
|
||||
if (do_stat(glob.arg_buf, &st) != 0)
|
||||
return;
|
||||
is_dir = S_ISDIR(st.st_mode) != 0;
|
||||
if (arg && !is_dir)
|
||||
return;
|
||||
|
||||
if (daemon_filter_list.head
|
||||
&& check_filter(&daemon_filter_list, FLOG, use_buf, is_dir) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg) {
|
||||
glob.arg_buf[abpos++] = '/';
|
||||
glob.arg_buf[abpos] = '\0';
|
||||
if (fbpos >= 0) {
|
||||
glob.filt_buf[fbpos++] = '/';
|
||||
glob.filt_buf[fbpos] = '\0';
|
||||
}
|
||||
glob_match(arg, abpos, fbpos);
|
||||
} else {
|
||||
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
|
||||
if (!(glob.argv[glob.argc++] = strdup(glob.arg_buf)))
|
||||
out_of_memory("glob_match");
|
||||
}
|
||||
}
|
||||
|
||||
/* This routine performs wild-card expansion of the pathname in "arg". Any
|
||||
* daemon-excluded files/dirs will not be matched by the wildcards. Returns 0
|
||||
* if a wild-card string is the only returned item (due to matching nothing). */
|
||||
int glob_expand(const char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
|
||||
{
|
||||
int ret, save_argc;
|
||||
char *s;
|
||||
|
||||
if (!arg) {
|
||||
if (glob.filt_buf)
|
||||
free(glob.filt_buf);
|
||||
free(glob.arg_buf);
|
||||
memset(&glob, 0, sizeof glob);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sanitize_paths)
|
||||
s = sanitize_path(NULL, s, "", 0, NULL);
|
||||
else
|
||||
s = strdup(s);
|
||||
if (!s)
|
||||
out_of_memory("glob_expand");
|
||||
|
||||
memset(&globbuf, 0, sizeof globbuf);
|
||||
if (!filter_server_path(s))
|
||||
glob(s, 0, NULL, &globbuf);
|
||||
if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) {
|
||||
maxargs += globbuf.gl_pathc + MAX_ARGS;
|
||||
if (!(argv = realloc_array(argv, char *, maxargs)))
|
||||
out_of_memory("glob_expand");
|
||||
*argv_ptr = argv;
|
||||
*maxargs_ptr = maxargs;
|
||||
}
|
||||
if (globbuf.gl_pathc == 0)
|
||||
argv[argc++] = s;
|
||||
s = sanitize_path(NULL, arg, "", 0, SP_KEEP_DOT_DIRS);
|
||||
else {
|
||||
int i;
|
||||
free(s);
|
||||
for (i = 0; i < (int)globbuf.gl_pathc; i++) {
|
||||
if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
|
||||
out_of_memory("glob_expand");
|
||||
}
|
||||
s = strdup(arg);
|
||||
if (!s)
|
||||
out_of_memory("glob_expand");
|
||||
clean_fname(s, CFN_KEEP_DOT_DIRS
|
||||
| CFN_KEEP_TRAILING_SLASH
|
||||
| CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
}
|
||||
globfree(&globbuf);
|
||||
#endif
|
||||
*argc_ptr = argc;
|
||||
|
||||
ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, MAXPATHLEN);
|
||||
*glob.arg_buf = '\0';
|
||||
|
||||
glob.argc = save_argc = *argc_p;
|
||||
glob.argv = *argv_p;
|
||||
glob.maxargs = *maxargs_p;
|
||||
|
||||
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, 100);
|
||||
|
||||
glob_match(s, 0, -1);
|
||||
|
||||
/* The arg didn't match anything, so add the failed arg to the list. */
|
||||
if (glob.argc == save_argc) {
|
||||
ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
|
||||
glob.argv[glob.argc++] = s;
|
||||
ret = 0;
|
||||
} else {
|
||||
free(s);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
*maxargs_p = glob.maxargs;
|
||||
*argv_p = glob.argv;
|
||||
*argc_p = glob.argc;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This routine is only used in daemon mode. */
|
||||
void glob_expand_module(char *base1, char *arg, char ***argv_ptr, int *argc_ptr, int *maxargs_ptr)
|
||||
void glob_expand_module(char *base1, char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
|
||||
{
|
||||
char *p, *s;
|
||||
char *base = base1;
|
||||
@@ -600,7 +690,7 @@ void glob_expand_module(char *base1, char *arg, char ***argv_ptr, int *argc_ptr,
|
||||
for (s = arg; *s; s = p + base_len) {
|
||||
if ((p = strstr(s, base)) != NULL)
|
||||
*p = '\0'; /* split it at this point */
|
||||
glob_expand(s, argv_ptr, argc_ptr, maxargs_ptr);
|
||||
glob_expand(s, argv_p, argc_p, maxargs_p);
|
||||
if (!p)
|
||||
break;
|
||||
}
|
||||
@@ -687,11 +777,14 @@ int count_dir_elements(const char *p)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Turns multiple adjacent slashes into a single slash, gets rid of "./"
|
||||
* elements (but not a trailing dot dir), removes a trailing slash, and
|
||||
* optionally collapses ".." elements (except for those at the start of the
|
||||
* string). If the resulting name would be empty, change it into a ".". */
|
||||
unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
|
||||
/* Turns multiple adjacent slashes into a single slash, drops all leading or
|
||||
* interior "." elements unless CFN_KEEP_DOT_DIRS is flagged. Will also drop
|
||||
* a trailing '.' after a '/' if CFN_DROP_TRAILING_DOT_DIR is flagged, removes
|
||||
* a trailing slash (perhaps after removing the aforementioned dot) unless
|
||||
* CFN_KEEP_TRAILING_SLASH is flagged, and will also collapse ".." elements
|
||||
* (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged. If the
|
||||
* resulting name would be empty, returns ".". */
|
||||
unsigned int clean_fname(char *name, int flags)
|
||||
{
|
||||
char *limit = name - 1, *t = name, *f = name;
|
||||
int anchored;
|
||||
@@ -701,6 +794,10 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
|
||||
|
||||
if ((anchored = *f == '/') != 0)
|
||||
*t++ = *f++;
|
||||
else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {
|
||||
*t++ = *f++;
|
||||
*t++ = *f++;
|
||||
}
|
||||
while (*f) {
|
||||
/* discard extra slashes */
|
||||
if (*f == '/') {
|
||||
@@ -708,14 +805,16 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
|
||||
continue;
|
||||
}
|
||||
if (*f == '.') {
|
||||
/* discard "." dirs (but NOT a trailing '.'!) */
|
||||
if (f[1] == '/') {
|
||||
/* discard interior "." dirs */
|
||||
if (f[1] == '/' && !(flags & CFN_KEEP_DOT_DIRS)) {
|
||||
f += 2;
|
||||
continue;
|
||||
}
|
||||
if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR)
|
||||
break;
|
||||
/* collapse ".." dirs */
|
||||
if (collapse_dot_dot
|
||||
&& f[1] == '.' && (f[2] == '/' || !f[2])) {
|
||||
if (flags & CFN_COLLAPSE_DOT_DOT_DIRS
|
||||
&& f[1] == '.' && (f[2] == '/' || !f[2])) {
|
||||
char *s = t - 1;
|
||||
if (s == name && anchored) {
|
||||
f += 2;
|
||||
@@ -733,7 +832,7 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
|
||||
while (*f && (*t++ = *f++) != '/') {}
|
||||
}
|
||||
|
||||
if (t > name+anchored && t[-1] == '/')
|
||||
if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
|
||||
t--;
|
||||
if (t == name)
|
||||
*t++ = '.';
|
||||
@@ -754,8 +853,7 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
|
||||
* Specify NULL to get the default of "module_dir".
|
||||
*
|
||||
* The depth var is a count of how many '..'s to allow at the start of the
|
||||
* path. If symlink is set, combine its value with the "p" value to get
|
||||
* the target path, and **return NULL if any '..'s try to escape**.
|
||||
* path.
|
||||
*
|
||||
* We also clean the path in a manner similar to clean_fname() but with a
|
||||
* few differences:
|
||||
@@ -766,15 +864,10 @@ unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
|
||||
* string up to "depth" deep). If the resulting name would be empty,
|
||||
* change it into a ".". */
|
||||
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
const char *symlink)
|
||||
int flags)
|
||||
{
|
||||
char *start, *sanp, *save_dest = dest;
|
||||
int rlen = 0, leave_one_dotdir = relative_paths;
|
||||
|
||||
if (symlink && *symlink == '/') {
|
||||
p = symlink;
|
||||
symlink = "";
|
||||
}
|
||||
char *start, *sanp;
|
||||
int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
|
||||
|
||||
if (dest != p) {
|
||||
int plen = strlen(p);
|
||||
@@ -797,32 +890,22 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_dot_dirs) {
|
||||
while (*p == '.' && p[1] == '/')
|
||||
p += 2;
|
||||
}
|
||||
|
||||
start = sanp = dest + rlen;
|
||||
while (1) {
|
||||
if (*p == '\0') {
|
||||
if (!symlink || !*symlink)
|
||||
break;
|
||||
while (sanp != start && sanp[-1] != '/') {
|
||||
/* strip last element */
|
||||
sanp--;
|
||||
}
|
||||
/* Append a relative symlink */
|
||||
p = symlink;
|
||||
symlink = "";
|
||||
}
|
||||
/* This loop iterates once per filename component in p, pointing at
|
||||
* the start of the name (past any prior slash) for each iteration. */
|
||||
while (*p) {
|
||||
/* discard leading or extra slashes */
|
||||
if (*p == '/') {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
/* this loop iterates once per filename component in p.
|
||||
* both p (and sanp if the original had a slash) should
|
||||
* always be left pointing after a slash
|
||||
*/
|
||||
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
|
||||
if (leave_one_dotdir && p[1])
|
||||
leave_one_dotdir = 0;
|
||||
else {
|
||||
if (drop_dot_dirs) {
|
||||
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
|
||||
/* skip "." component */
|
||||
p++;
|
||||
continue;
|
||||
@@ -831,19 +914,12 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
|
||||
/* ".." component followed by slash or end */
|
||||
if (depth <= 0 || sanp != start) {
|
||||
if (symlink && sanp == start) {
|
||||
if (!save_dest)
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
p += 2;
|
||||
if (sanp != start) {
|
||||
/* back up sanp one level */
|
||||
--sanp; /* now pointing at slash */
|
||||
while (sanp > start && sanp[-1] != '/') {
|
||||
/* skip back up to slash */
|
||||
while (sanp > start && sanp[-1] != '/')
|
||||
sanp--;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -867,7 +943,7 @@ char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth,
|
||||
/* Like chdir(), but it keeps track of the current directory (in the
|
||||
* global "curr_dir"), and ensures that the path size doesn't overflow.
|
||||
* Also cleans the path using the clean_fname() function. */
|
||||
int push_dir(const char *dir, int set_path_only)
|
||||
int change_dir(const char *dir, int set_path_only)
|
||||
{
|
||||
static int initialised;
|
||||
unsigned int len;
|
||||
@@ -885,47 +961,37 @@ int push_dir(const char *dir, int set_path_only)
|
||||
if (len == 1 && *dir == '.')
|
||||
return 1;
|
||||
|
||||
if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir) {
|
||||
errno = ENAMETOOLONG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!set_path_only && chdir(dir))
|
||||
return 0;
|
||||
|
||||
if (*dir == '/') {
|
||||
if (len >= sizeof curr_dir) {
|
||||
errno = ENAMETOOLONG;
|
||||
return 0;
|
||||
}
|
||||
if (!set_path_only && chdir(dir))
|
||||
return 0;
|
||||
memcpy(curr_dir, dir, len + 1);
|
||||
curr_dir_len = len;
|
||||
} else {
|
||||
curr_dir[curr_dir_len++] = '/';
|
||||
memcpy(curr_dir + curr_dir_len, dir, len + 1);
|
||||
curr_dir_len += len;
|
||||
if (curr_dir_len + 1 + len >= sizeof curr_dir) {
|
||||
errno = ENAMETOOLONG;
|
||||
return 0;
|
||||
}
|
||||
curr_dir[curr_dir_len] = '/';
|
||||
memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
|
||||
|
||||
if (!set_path_only && chdir(curr_dir)) {
|
||||
curr_dir[curr_dir_len] = '\0';
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
curr_dir_len = clean_fname(curr_dir, 1);
|
||||
curr_dir_len = clean_fname(curr_dir, CFN_COLLAPSE_DOT_DOT_DIRS);
|
||||
if (sanitize_paths) {
|
||||
if (module_dirlen > curr_dir_len)
|
||||
module_dirlen = curr_dir_len;
|
||||
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse a push_dir() call. You must pass in an absolute path
|
||||
* that was copied from a prior value of "curr_dir".
|
||||
**/
|
||||
int pop_dir(const char *dir)
|
||||
{
|
||||
if (chdir(dir))
|
||||
return 0;
|
||||
|
||||
curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
|
||||
if (curr_dir_len >= sizeof curr_dir)
|
||||
curr_dir_len = sizeof curr_dir - 1;
|
||||
if (sanitize_paths)
|
||||
curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
|
||||
if (verbose >= 5 && !set_path_only)
|
||||
rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -985,13 +1051,13 @@ char *partial_dir_fname(const char *fname)
|
||||
fn = fname;
|
||||
if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
|
||||
return NULL;
|
||||
if (server_filter_list.head) {
|
||||
if (daemon_filter_list.head) {
|
||||
t = strrchr(partial_fname, '/');
|
||||
*t = '\0';
|
||||
if (check_filter(&server_filter_list, partial_fname, 1) < 0)
|
||||
if (check_filter(&daemon_filter_list, FLOG, partial_fname, 1) < 0)
|
||||
return NULL;
|
||||
*t = '/';
|
||||
if (check_filter(&server_filter_list, partial_fname, 0) < 0)
|
||||
if (check_filter(&daemon_filter_list, FLOG, partial_fname, 0) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Test suite for the wildmatch code.
|
||||
*
|
||||
* Copyright (C) 2003-2007 Wayne Davison
|
||||
* Copyright (C) 2003-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
285
xattrs.c
285
xattrs.c
@@ -3,7 +3,7 @@
|
||||
* Written by Jay Fenlason, vaguely based on the ACLs patch.
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc.
|
||||
* Copyright (C) 2006, 2007 Wayne Davison
|
||||
* Copyright (C) 2006-2008 Wayne Davison
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -47,7 +47,6 @@ extern int checksum_seed;
|
||||
#define XSTATE_ABBREV 0
|
||||
#define XSTATE_DONE 1
|
||||
#define XSTATE_TODO 2
|
||||
#define XSTATE_LOCAL 3
|
||||
|
||||
#define USER_PREFIX "user."
|
||||
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
|
||||
@@ -63,13 +62,17 @@ extern int checksum_seed;
|
||||
#endif
|
||||
#define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1)
|
||||
|
||||
#define XSTAT_ATTR RSYNC_PREFIX "%stat"
|
||||
#define XACC_ACL_ATTR RSYNC_PREFIX "%aacl"
|
||||
#define XDEF_ACL_ATTR RSYNC_PREFIX "%dacl"
|
||||
#define XSTAT_SUFFIX "stat"
|
||||
#define XSTAT_ATTR RSYNC_PREFIX "%" XSTAT_SUFFIX
|
||||
#define XACC_ACL_SUFFIX "aacl"
|
||||
#define XACC_ACL_ATTR RSYNC_PREFIX "%" XACC_ACL_SUFFIX
|
||||
#define XDEF_ACL_SUFFIX "dacl"
|
||||
#define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX
|
||||
|
||||
typedef struct {
|
||||
char *datum, *name;
|
||||
size_t datum_len, name_len;
|
||||
int num;
|
||||
} rsync_xa;
|
||||
|
||||
static size_t namebuf_len = 0;
|
||||
@@ -111,6 +114,7 @@ static int rsync_xal_compare_names(const void *x1, const void *x2)
|
||||
static ssize_t get_xattr_names(const char *fname)
|
||||
{
|
||||
ssize_t list_len;
|
||||
double arg;
|
||||
|
||||
if (!namebuf) {
|
||||
namebuf_len = 1024;
|
||||
@@ -119,23 +123,26 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
out_of_memory("get_xattr_names");
|
||||
}
|
||||
|
||||
/* The length returned includes all the '\0' terminators. */
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len > (ssize_t)namebuf_len) {
|
||||
list_len = -1;
|
||||
errno = ERANGE;
|
||||
}
|
||||
if (list_len >= 0)
|
||||
return list_len;
|
||||
if (errno == ENOTSUP)
|
||||
return 0;
|
||||
if (errno == ERANGE) {
|
||||
while (1) {
|
||||
/* The length returned includes all the '\0' terminators. */
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len >= 0) {
|
||||
if ((size_t)list_len <= namebuf_len)
|
||||
break;
|
||||
} else if (errno == ENOTSUP)
|
||||
return 0;
|
||||
else if (errno != ERANGE) {
|
||||
arg = (double)namebuf_len;
|
||||
got_error:
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
|
||||
fname, arg);
|
||||
return -1;
|
||||
}
|
||||
list_len = sys_llistxattr(fname, NULL, 0);
|
||||
if (list_len < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",0) failed",
|
||||
fname);
|
||||
return -1;
|
||||
arg = 0;
|
||||
goto got_error;
|
||||
}
|
||||
if (namebuf_len)
|
||||
free(namebuf);
|
||||
@@ -143,15 +150,9 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
namebuf = new_array(char, namebuf_len);
|
||||
if (!namebuf)
|
||||
out_of_memory("get_xattr_names");
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len >= 0)
|
||||
return list_len;
|
||||
}
|
||||
|
||||
rsyserr(FERROR, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%ld) failed",
|
||||
fname, (long)namebuf_len);
|
||||
return -1;
|
||||
return list_len;
|
||||
}
|
||||
|
||||
/* On entry, the *len_ptr parameter contains the size of the extra space we
|
||||
@@ -161,32 +162,35 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
|
||||
int no_missing_error)
|
||||
{
|
||||
size_t datum_len = sys_lgetxattr(fname, name, NULL, 0);
|
||||
size_t extra_len = *len_ptr;
|
||||
char *ptr;
|
||||
|
||||
*len_ptr = datum_len;
|
||||
|
||||
if (datum_len == (size_t)-1) {
|
||||
if (errno == ENOTSUP || no_missing_error)
|
||||
return NULL;
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
|
||||
fname, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (datum_len + *len_ptr < datum_len /* checks for overflow */
|
||||
|| !(ptr = new_array(char, datum_len + *len_ptr)))
|
||||
if (!datum_len && !extra_len)
|
||||
extra_len = 1; /* request non-zero amount of memory */
|
||||
if (datum_len + extra_len < datum_len /* checks for overflow */
|
||||
|| !(ptr = new_array(char, datum_len + extra_len)))
|
||||
out_of_memory("get_xattr_data");
|
||||
|
||||
*len_ptr = datum_len;
|
||||
|
||||
if (datum_len) {
|
||||
size_t len = sys_lgetxattr(fname, name, ptr, datum_len);
|
||||
if (len != datum_len) {
|
||||
if (len == (size_t)-1) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
|
||||
" failed", fname, name, (long)datum_len);
|
||||
} else {
|
||||
rprintf(FERROR,
|
||||
rprintf(FERROR_XFER,
|
||||
"get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
|
||||
" returned %ld\n", fname, name,
|
||||
(long)datum_len, (long)len);
|
||||
@@ -207,14 +211,14 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
|
||||
#ifdef HAVE_LINUX_XATTRS
|
||||
int user_only = am_sender ? 0 : !am_root;
|
||||
#endif
|
||||
rsync_xa *rxa;
|
||||
int count;
|
||||
|
||||
/* This puts the name list into the "namebuf" buffer. */
|
||||
if ((list_len = get_xattr_names(fname)) < 0)
|
||||
return -1;
|
||||
|
||||
for (name = namebuf; list_len > 0; name += name_len) {
|
||||
rsync_xa *rxas;
|
||||
|
||||
name_len = strlen(name) + 1;
|
||||
list_len -= name_len;
|
||||
|
||||
@@ -227,9 +231,15 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
|
||||
#endif
|
||||
|
||||
/* No rsync.%FOO attributes are copied w/o 2 -X options. */
|
||||
if (preserve_xattrs < 2 && name_len > RPRE_LEN
|
||||
&& name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX))
|
||||
continue;
|
||||
if (name_len > RPRE_LEN && name[RPRE_LEN] == '%'
|
||||
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
|
||||
if ((am_sender && preserve_xattrs < 2)
|
||||
|| (am_root < 0
|
||||
&& (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
|
||||
|| strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
|
||||
|| strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
|
||||
continue;
|
||||
}
|
||||
|
||||
datum_len = name_len; /* Pass extra size to get_xattr_data() */
|
||||
if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
|
||||
@@ -249,23 +259,19 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
|
||||
} else
|
||||
name_offset = datum_len;
|
||||
|
||||
#ifdef HAVE_LINUX_XATTRS
|
||||
if (am_root < 0 && name_len > RPRE_LEN
|
||||
&& HAS_PREFIX(name, RSYNC_PREFIX)) {
|
||||
name += RPRE_LEN;
|
||||
name_len -= RPRE_LEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
|
||||
rxas->name = ptr + name_offset;
|
||||
memcpy(rxas->name, name, name_len);
|
||||
rxas->datum = ptr;
|
||||
rxas->name_len = name_len;
|
||||
rxas->datum_len = datum_len;
|
||||
rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
|
||||
rxa->name = ptr + name_offset;
|
||||
memcpy(rxa->name, name, name_len);
|
||||
rxa->datum = ptr;
|
||||
rxa->name_len = name_len;
|
||||
rxa->datum_len = datum_len;
|
||||
}
|
||||
if (xalp->count > 1)
|
||||
qsort(xalp->items, xalp->count, sizeof (rsync_xa), rsync_xal_compare_names);
|
||||
count = xalp->count;
|
||||
rxa = xalp->items;
|
||||
if (count > 1)
|
||||
qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names);
|
||||
for (rxa += count-1; count; count--, rxa--)
|
||||
rxa->num = count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -344,25 +350,32 @@ int send_xattr(stat_x *sxp, int f)
|
||||
int count = sxp->xattr->count;
|
||||
write_varint(f, count);
|
||||
for (rxa = sxp->xattr->items; count--; rxa++) {
|
||||
size_t name_len = rxa->name_len;
|
||||
const char *name = rxa->name;
|
||||
/* Strip the rsync prefix from disguised namespaces. */
|
||||
if (name_len > RPRE_LEN
|
||||
#ifdef HAVE_LINUX_XATTRS
|
||||
write_varint(f, rxa->name_len);
|
||||
write_varint(f, rxa->datum_len);
|
||||
write_buf(f, rxa->name, rxa->name_len);
|
||||
#else
|
||||
/* We strip the rsync prefix from disguised namespaces
|
||||
* and put everything else in the user namespace. */
|
||||
if (HAS_PREFIX(rxa->name, RSYNC_PREFIX)
|
||||
&& rxa->name[RPRE_LEN] != '%') {
|
||||
write_varint(f, rxa->name_len - RPRE_LEN);
|
||||
write_varint(f, rxa->datum_len);
|
||||
write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN);
|
||||
} else {
|
||||
write_varint(f, rxa->name_len + UPRE_LEN);
|
||||
write_varint(f, rxa->datum_len);
|
||||
write_buf(f, USER_PREFIX, UPRE_LEN);
|
||||
write_buf(f, rxa->name, rxa->name_len);
|
||||
&& am_root < 0
|
||||
#endif
|
||||
&& name[RPRE_LEN] != '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
|
||||
name += RPRE_LEN;
|
||||
name_len -= RPRE_LEN;
|
||||
}
|
||||
#ifndef HAVE_LINUX_XATTRS
|
||||
else {
|
||||
/* Put everything else in the user namespace. */
|
||||
name_len += UPRE_LEN;
|
||||
}
|
||||
#endif
|
||||
write_varint(f, name_len);
|
||||
write_varint(f, rxa->datum_len);
|
||||
#ifndef HAVE_LINUX_XATTRS
|
||||
if (name_len > rxa->name_len) {
|
||||
write_buf(f, USER_PREFIX, UPRE_LEN);
|
||||
name_len -= UPRE_LEN;
|
||||
}
|
||||
#endif
|
||||
write_buf(f, name, name_len);
|
||||
if (rxa->datum_len > MAX_FULL_DATUM)
|
||||
write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
|
||||
else
|
||||
@@ -453,18 +466,19 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
|
||||
void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
{
|
||||
item_list *lst = rsync_xal_l.items;
|
||||
int j, cnt, prior_req = -1;
|
||||
int cnt, prior_req = 0;
|
||||
rsync_xa *rxa;
|
||||
|
||||
lst += F_XATTR(file);
|
||||
cnt = lst->count;
|
||||
for (rxa = lst->items, j = 0; j < cnt; rxa++, j++) {
|
||||
for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) {
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM)
|
||||
continue;
|
||||
switch (rxa->datum[0]) {
|
||||
case XSTATE_LOCAL:
|
||||
/* Items set locally will get cached by receiver. */
|
||||
rxa->datum[0] = XSTATE_DONE;
|
||||
case XSTATE_ABBREV:
|
||||
/* Items left abbreviated matched the sender's checksum, so
|
||||
* the receiver will cache the local data for future use. */
|
||||
if (am_generator)
|
||||
rxa->datum[0] = XSTATE_DONE;
|
||||
continue;
|
||||
case XSTATE_TODO:
|
||||
break;
|
||||
@@ -475,16 +489,19 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
/* Flag that we handled this abbreviated item. */
|
||||
rxa->datum[0] = XSTATE_DONE;
|
||||
|
||||
write_varint(f_out, j - prior_req);
|
||||
prior_req = j;
|
||||
write_varint(f_out, rxa->num - prior_req);
|
||||
prior_req = rxa->num;
|
||||
|
||||
if (fname) {
|
||||
size_t len = 0;
|
||||
char *ptr;
|
||||
|
||||
/* Re-read the long datum. */
|
||||
if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0)))
|
||||
if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) {
|
||||
rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname);
|
||||
write_varint(f_out, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
write_varint(f_out, len); /* length might have changed! */
|
||||
write_buf(f_out, ptr, len);
|
||||
@@ -495,37 +512,16 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
write_byte(f_out, 0); /* end the list */
|
||||
}
|
||||
|
||||
/* Any items set locally by the generator that the receiver doesn't
|
||||
* get told about get changed back to XSTATE_ABBREV. */
|
||||
void xattr_clear_locals(struct file_struct *file)
|
||||
{
|
||||
item_list *lst = rsync_xal_l.items;
|
||||
rsync_xa *rxa;
|
||||
int cnt;
|
||||
|
||||
if (F_XATTR(file) < 0)
|
||||
return;
|
||||
|
||||
lst += F_XATTR(file);
|
||||
cnt = lst->count;
|
||||
for (rxa = lst->items; cnt--; rxa++) {
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM)
|
||||
continue;
|
||||
if (rxa->datum[0] == XSTATE_LOCAL)
|
||||
rxa->datum[0] = XSTATE_ABBREV;
|
||||
}
|
||||
}
|
||||
|
||||
/* When called by the sender, read the request from the generator and mark
|
||||
* any needed xattrs with a flag that lets us know they need to be sent to
|
||||
* the receiver. When called by the receiver, reads the sent data and
|
||||
* stores it in place of its checksum. */
|
||||
void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
int recv_xattr_request(struct file_struct *file, int f_in)
|
||||
{
|
||||
item_list *lst = rsync_xal_l.items;
|
||||
char *old_datum, *name;
|
||||
rsync_xa *rxa;
|
||||
int rel_pos, cnt;
|
||||
int rel_pos, cnt, num, got_xattr_data = 0;
|
||||
|
||||
if (F_XATTR(file) < 0) {
|
||||
rprintf(FERROR, "recv_xattr_request: internal data error!\n");
|
||||
@@ -535,13 +531,20 @@ void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
|
||||
cnt = lst->count;
|
||||
rxa = lst->items;
|
||||
rxa -= 1;
|
||||
num = 0;
|
||||
while ((rel_pos = read_varint(f_in)) != 0) {
|
||||
rxa += rel_pos;
|
||||
cnt -= rel_pos;
|
||||
if (cnt < 0 || rxa->datum_len <= MAX_FULL_DATUM
|
||||
|| rxa->datum[0] != XSTATE_ABBREV) {
|
||||
rprintf(FERROR, "recv_xattr_request: internal abbrev error!\n");
|
||||
num += rel_pos;
|
||||
while (cnt && rxa->num < num) {
|
||||
rxa++;
|
||||
cnt--;
|
||||
}
|
||||
if (!cnt || rxa->num != num) {
|
||||
rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",
|
||||
who_am_i(), num, f_name(file, NULL));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) {
|
||||
rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i());
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
@@ -563,7 +566,10 @@ void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
rxa->name = name;
|
||||
free(old_datum);
|
||||
read_buf(f_in, rxa->datum, rxa->datum_len);
|
||||
got_xattr_data = 1;
|
||||
}
|
||||
|
||||
return got_xattr_data;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -572,7 +578,12 @@ void recv_xattr_request(struct file_struct *file, int f_in)
|
||||
void receive_xattr(struct file_struct *file, int f)
|
||||
{
|
||||
static item_list temp_xattr = EMPTY_ITEM_LIST;
|
||||
int count;
|
||||
int count, num;
|
||||
#ifdef HAVE_LINUX_XATTRS
|
||||
int need_sort = 0;
|
||||
#else
|
||||
int need_sort = 1;
|
||||
#endif
|
||||
int ndx = read_varint(f);
|
||||
|
||||
if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
|
||||
@@ -591,7 +602,7 @@ void receive_xattr(struct file_struct *file, int f)
|
||||
temp_xattr.count = 0;
|
||||
}
|
||||
|
||||
while (count--) {
|
||||
for (num = 1; num <= count; num++) {
|
||||
char *ptr, *name;
|
||||
rsync_xa *rxa;
|
||||
size_t name_len = read_varint(f);
|
||||
@@ -615,14 +626,15 @@ void receive_xattr(struct file_struct *file, int f)
|
||||
}
|
||||
#ifdef HAVE_LINUX_XATTRS
|
||||
/* Non-root can only save the user namespace. */
|
||||
if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
|
||||
if (!am_root) {
|
||||
free(ptr);
|
||||
continue;
|
||||
}
|
||||
name -= RPRE_LEN;
|
||||
name_len += RPRE_LEN;
|
||||
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
|
||||
if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
|
||||
if (!am_root) {
|
||||
free(ptr);
|
||||
continue;
|
||||
}
|
||||
name -= RPRE_LEN;
|
||||
name_len += RPRE_LEN;
|
||||
memcpy(name, RSYNC_PREFIX, RPRE_LEN);
|
||||
need_sort = 1;
|
||||
}
|
||||
#else
|
||||
/* This OS only has a user namespace, so we either
|
||||
@@ -651,8 +663,12 @@ void receive_xattr(struct file_struct *file, int f)
|
||||
rxa->datum = ptr;
|
||||
rxa->name_len = name_len;
|
||||
rxa->datum_len = datum_len;
|
||||
rxa->num = num;
|
||||
}
|
||||
|
||||
if (need_sort && count > 1)
|
||||
qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
|
||||
|
||||
ndx = rsync_xal_l.count; /* pre-incremented count */
|
||||
rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
|
||||
|
||||
@@ -682,7 +698,8 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
ssize_t list_len;
|
||||
size_t i, len;
|
||||
char *name, *ptr, sum[MAX_DIGEST_LEN];
|
||||
int name_len, ret = 0;
|
||||
size_t name_len;
|
||||
int ret = 0;
|
||||
|
||||
/* This puts the current name list into the "namebuf" buffer. */
|
||||
if ((list_len = get_xattr_names(fname)) < 0)
|
||||
@@ -719,7 +736,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
if (fname == fnamecmp)
|
||||
; /* Value is already set when identical */
|
||||
else if (sys_lsetxattr(fname, name, ptr, len) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
ret = -1;
|
||||
@@ -727,8 +744,6 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
sxp->st.st_mtime = (time_t)-1;
|
||||
|
||||
if (am_generator) { /* generator items stay abbreviated */
|
||||
if (rxas[i].datum[0] == XSTATE_ABBREV)
|
||||
rxas[i].datum[0] = XSTATE_LOCAL;
|
||||
free(ptr);
|
||||
continue;
|
||||
}
|
||||
@@ -742,7 +757,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
}
|
||||
|
||||
if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
ret = -1;
|
||||
@@ -762,6 +777,9 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
: !HAS_PREFIX(name, USER_PREFIX))
|
||||
continue;
|
||||
#endif
|
||||
if (am_root < 0 && name_len > RPRE_LEN
|
||||
&& name[RPRE_LEN] == '%' && strcmp(name, XSTAT_ATTR) == 0)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < xalp->count; i++) {
|
||||
if (strcmp(name, rxas[i].name) == 0)
|
||||
@@ -769,7 +787,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
}
|
||||
if (i == xalp->count) {
|
||||
if (sys_lremovexattr(fname, name) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
ret = -1;
|
||||
@@ -804,6 +822,7 @@ int set_xattr(const char *fname, const struct file_struct *file,
|
||||
char *get_xattr_acl(const char *fname, int is_access_acl, size_t *len_p)
|
||||
{
|
||||
const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
|
||||
*len_p = 0; /* no extra data alloc needed from get_xattr_data() */
|
||||
return get_xattr_data(fname, name, len_p, 1);
|
||||
}
|
||||
|
||||
@@ -811,7 +830,7 @@ int set_xattr_acl(const char *fname, int is_access_acl, const char *buf, size_t
|
||||
{
|
||||
const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
|
||||
if (sys_lsetxattr(fname, name, buf, buf_len) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"set_xattr_acl: lsetxattr(\"%s\",\"%s\") failed",
|
||||
fname, name);
|
||||
return -1;
|
||||
@@ -856,7 +875,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst
|
||||
xst->st_gid = 0;
|
||||
return 0;
|
||||
}
|
||||
rsyserr(FERROR, errno, "failed to read xattr %s for %s",
|
||||
rsyserr(FERROR_XFER, errno, "failed to read xattr %s for %s",
|
||||
XSTAT_ATTR, full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
@@ -877,7 +896,7 @@ int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
|
||||
{
|
||||
STRUCT_STAT fst, xst;
|
||||
dev_t rdev;
|
||||
@@ -887,19 +906,19 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
return 0;
|
||||
|
||||
if (read_only || list_only) {
|
||||
rsyserr(FERROR, EROFS, "failed to write xattr %s for %s",
|
||||
rsyserr(FERROR_XFER, EROFS, "failed to write xattr %s for %s",
|
||||
XSTAT_ATTR, full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x_lstat(fname, &fst, &xst) < 0) {
|
||||
rsyserr(FERROR, errno, "failed to re-stat %s",
|
||||
rsyserr(FERROR_XFER, errno, "failed to re-stat %s",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fst.st_mode &= (_S_IFMT | CHMOD_BITS);
|
||||
fmode = file->mode & (_S_IFMT | CHMOD_BITS);
|
||||
fmode = new_mode & (_S_IFMT | CHMOD_BITS);
|
||||
|
||||
if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) {
|
||||
uint32 *devp = F_RDEV_P(file);
|
||||
@@ -919,7 +938,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
&& fst.st_uid == F_OWNER(file) && fst.st_gid == F_GROUP(file)) {
|
||||
/* xst.st_mode will be 0 if there's no current stat xattr */
|
||||
if (xst.st_mode && sys_lremovexattr(fname, XSTAT_ATTR) < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"delete of stat xattr failed for %s",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
@@ -937,7 +956,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file)
|
||||
if (sys_lsetxattr(fname, XSTAT_ATTR, buf, len) < 0) {
|
||||
if (errno == EPERM && S_ISLNK(fst.st_mode))
|
||||
return 0;
|
||||
rsyserr(FERROR, errno,
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"failed to write xattr %s for %s",
|
||||
XSTAT_ATTR, full_fname(fname));
|
||||
return -1;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
dummy
|
||||
Reference in New Issue
Block a user