mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 15:25:30 -04:00
Compare commits
261 Commits
v2.5.6
...
v2.6.0pre2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ac00eb16 | ||
|
|
45ddbf6204 | ||
|
|
276877cf77 | ||
|
|
6b45fcf160 | ||
|
|
49c24eccd4 | ||
|
|
0d7d3763f2 | ||
|
|
241dc65eee | ||
|
|
860bdd4571 | ||
|
|
55bf051bbc | ||
|
|
423dba8ea1 | ||
|
|
517c7b4dee | ||
|
|
18ced14631 | ||
|
|
ce67256218 | ||
|
|
9e83fa99fe | ||
|
|
256a9e376c | ||
|
|
ef5075e092 | ||
|
|
65653a6596 | ||
|
|
d5a0b48379 | ||
|
|
314a74d731 | ||
|
|
90e22f4b51 | ||
|
|
ab304c268c | ||
|
|
16a3fec02d | ||
|
|
abb0b532f8 | ||
|
|
43cd760fc1 | ||
|
|
9af87151ec | ||
|
|
8dd99390f5 | ||
|
|
e636af6b23 | ||
|
|
e3217f1448 | ||
|
|
66b711633f | ||
|
|
f40f2fc8ce | ||
|
|
e6f9e388cf | ||
|
|
3c1e2ad956 | ||
|
|
e6d2799170 | ||
|
|
2cfbf4bc0e | ||
|
|
f7731f1fc2 | ||
|
|
7d3f8ae2df | ||
|
|
a60fdd63f4 | ||
|
|
3a7dec59bc | ||
|
|
880ae34190 | ||
|
|
d00daf1f3f | ||
|
|
17fadf7d40 | ||
|
|
06c28400fa | ||
|
|
6e35c72fdb | ||
|
|
e2d22fee53 | ||
|
|
1bca1de6cc | ||
|
|
e0ed4e4087 | ||
|
|
4a7319be12 | ||
|
|
55d5937dd6 | ||
|
|
63596e1c4a | ||
|
|
603e6b05c7 | ||
|
|
dfad66a838 | ||
|
|
58cadc8608 | ||
|
|
b11b50bcd0 | ||
|
|
a73de5f3ba | ||
|
|
84c3645cea | ||
|
|
2a88a8cd30 | ||
|
|
8a97fc2e1b | ||
|
|
7a2fd68b96 | ||
|
|
6a7cc46cb2 | ||
|
|
aa6dc37ccb | ||
|
|
ea42541fe0 | ||
|
|
b7b2741f3a | ||
|
|
eb61be192d | ||
|
|
9b9114e8cd | ||
|
|
857e38bb45 | ||
|
|
4ea812445d | ||
|
|
e80a765412 | ||
|
|
15089022d4 | ||
|
|
f69204adad | ||
|
|
459a83c9cc | ||
|
|
6464bdbe13 | ||
|
|
4f3e9a0fba | ||
|
|
8a9709dee5 | ||
|
|
daa598df11 | ||
|
|
d04e9c51b4 | ||
|
|
d89a3a313a | ||
|
|
350e4e4dec | ||
|
|
c95dcb3935 | ||
|
|
1e4f48d6c4 | ||
|
|
fb55e28d83 | ||
|
|
067669dac7 | ||
|
|
24c906d3f7 | ||
|
|
14820f635d | ||
|
|
59192f5650 | ||
|
|
365346ca30 | ||
|
|
d01350a881 | ||
|
|
38b02c13d0 | ||
|
|
b017ec4e13 | ||
|
|
2c873122b3 | ||
|
|
6969ebcfcf | ||
|
|
1dbb94cadf | ||
|
|
8a78bb963d | ||
|
|
6931c13800 | ||
|
|
e6e3f12ffc | ||
|
|
e2559dbedc | ||
|
|
1f3d6cdd86 | ||
|
|
4a7ee79d4d | ||
|
|
0c2ef5f42d | ||
|
|
ca20c7fd62 | ||
|
|
191e40da17 | ||
|
|
80ddadb7e8 | ||
|
|
31f3b68a97 | ||
|
|
d594399c6a | ||
|
|
d74a2e3ed5 | ||
|
|
d175d7e13e | ||
|
|
daa8ce838b | ||
|
|
b19fd07c02 | ||
|
|
47d6a60c2f | ||
|
|
980821ebab | ||
|
|
592f4696dc | ||
|
|
8a7846f97e | ||
|
|
87f18b6289 | ||
|
|
28063ba5b2 | ||
|
|
fe332038c6 | ||
|
|
3c0b1ebf78 | ||
|
|
f2fe4903c9 | ||
|
|
3151cbae89 | ||
|
|
3c30b99059 | ||
|
|
a7735ba085 | ||
|
|
d811b68901 | ||
|
|
1c8162a921 | ||
|
|
16417f8b9d | ||
|
|
b49d381d05 | ||
|
|
7da9a16d10 | ||
|
|
32f60a6e7b | ||
|
|
b7db090661 | ||
|
|
136c5c5ec3 | ||
|
|
85b80fbc73 | ||
|
|
16859cdbdc | ||
|
|
fc96552d26 | ||
|
|
15bb997d0a | ||
|
|
b6b42c892c | ||
|
|
5bb920003e | ||
|
|
37ff0e344d | ||
|
|
97d53f8c75 | ||
|
|
f2ac84c36d | ||
|
|
c21eeef5bc | ||
|
|
e11c425119 | ||
|
|
84229c7ac9 | ||
|
|
c9a59880f0 | ||
|
|
9a17dddbc5 | ||
|
|
277d99e8c9 | ||
|
|
2a1874cc82 | ||
|
|
d5c973ccb7 | ||
|
|
37f3ce61bb | ||
|
|
076f60eed0 | ||
|
|
20b2e9cef7 | ||
|
|
e37d8229f5 | ||
|
|
710faea9a4 | ||
|
|
70a6051cf1 | ||
|
|
7a1f46b6ac | ||
|
|
7ca9250db0 | ||
|
|
af7086c63f | ||
|
|
8808589277 | ||
|
|
6cd5096063 | ||
|
|
677cd34acd | ||
|
|
08c5385e65 | ||
|
|
d7bf70f196 | ||
|
|
6f3cff41dd | ||
|
|
5de45bcadc | ||
|
|
446ee5b110 | ||
|
|
d3e6fd3910 | ||
|
|
6813fa7eac | ||
|
|
0f5a04e3ff | ||
|
|
8801138b47 | ||
|
|
2473391971 | ||
|
|
7d6879328a | ||
|
|
900454132e | ||
|
|
92b8abfe80 | ||
|
|
52e628a861 | ||
|
|
4791825d49 | ||
|
|
d542c20c5f | ||
|
|
4762db4fc9 | ||
|
|
8645af1d8c | ||
|
|
429f98283f | ||
|
|
5be7fa93fc | ||
|
|
837cbad97f | ||
|
|
af1d91c562 | ||
|
|
908f5a9f9f | ||
|
|
9b74643315 | ||
|
|
986066873e | ||
|
|
9533e15a79 | ||
|
|
8dc74608a3 | ||
|
|
3e85237e5f | ||
|
|
9d0523ef4c | ||
|
|
4a7144ee7e | ||
|
|
c120ff37f5 | ||
|
|
83fd337d8e | ||
|
|
707c1a3085 | ||
|
|
8294b00c11 | ||
|
|
da2bcdd1c2 | ||
|
|
093acc5dad | ||
|
|
fd73b94d31 | ||
|
|
38499c1a49 | ||
|
|
170381c052 | ||
|
|
8113a033dd | ||
|
|
87cc45e136 | ||
|
|
f6b8d591f7 | ||
|
|
d31c09c872 | ||
|
|
337a1a86a7 | ||
|
|
b7dc46c0f6 | ||
|
|
ff57065957 | ||
|
|
0406a3a7a4 | ||
|
|
bc3b5b2558 | ||
|
|
d1cce1dd92 | ||
|
|
7bb7058e8d | ||
|
|
727fa3688f | ||
|
|
577ab12ce5 | ||
|
|
0f2ac85576 | ||
|
|
fab1f8898e | ||
|
|
f63d68be97 | ||
|
|
58665d23b4 | ||
|
|
195bd906a2 | ||
|
|
fc1ae6582f | ||
|
|
fc0257c9fd | ||
|
|
91c4da3fda | ||
|
|
990ff150ef | ||
|
|
e72b18a9bd | ||
|
|
bc63ae3f13 | ||
|
|
6e12886393 | ||
|
|
b5ca91ae4b | ||
|
|
89855e78ab | ||
|
|
e106de49c8 | ||
|
|
afbcc8f216 | ||
|
|
f177b7cca2 | ||
|
|
ea5164d181 | ||
|
|
ccdff3ebbf | ||
|
|
24d0fcde7f | ||
|
|
56014c8c0a | ||
|
|
7c2a9e766c | ||
|
|
bb24028f51 | ||
|
|
52d3e10613 | ||
|
|
67863f46e3 | ||
|
|
9c28e52628 | ||
|
|
1b2f167546 | ||
|
|
702d0c4529 | ||
|
|
51106bafc6 | ||
|
|
42d4edc067 | ||
|
|
fbc0bc4d53 | ||
|
|
1b2db7aecb | ||
|
|
1ce29566e7 | ||
|
|
3742bf3ac3 | ||
|
|
18d6b679af | ||
|
|
dbda5fbf06 | ||
|
|
2154309a54 | ||
|
|
afb6e9450d | ||
|
|
dfa3248380 | ||
|
|
2cda256088 | ||
|
|
d9c7edf63f | ||
|
|
a151343943 | ||
|
|
85ed0aa396 | ||
|
|
3019f95f37 | ||
|
|
5702bc12b3 | ||
|
|
b0d791bb35 | ||
|
|
3903928ca0 | ||
|
|
827c37f631 | ||
|
|
b45b059a3d | ||
|
|
f39281ae56 | ||
|
|
e2bea9eb8d | ||
|
|
931a979904 | ||
|
|
3fccfafd30 |
@@ -20,4 +20,5 @@ testtmp.*
|
||||
tls
|
||||
trimslash
|
||||
t_unsafe
|
||||
wildtest
|
||||
zlib/dummy
|
||||
|
||||
17
INSTALL
17
INSTALL
@@ -11,7 +11,7 @@ to ./configure. To see them, use:
|
||||
|
||||
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
|
||||
cut-down copy of release 1.5 is included in the rsync distribution,
|
||||
and will be used it there is no popt library on your build host, or if
|
||||
and will be used if there is no popt library on your build host, or if
|
||||
the --with-included-popt option is passed to ./configure.
|
||||
|
||||
If you configure using --enable-maintainer-mode, then rsync will try
|
||||
@@ -19,6 +19,13 @@ to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
|
||||
useful, but it should be turned off for production builds.
|
||||
|
||||
|
||||
RPM NOTES
|
||||
---------
|
||||
|
||||
Under packaging you will find .spec files for several distributions.
|
||||
The .spec file in packaging/lsb can be used for Linux systems that
|
||||
adhere to the Linux Standards Base (e.g., RedHat and others).
|
||||
|
||||
HP-UX NOTES
|
||||
-----------
|
||||
|
||||
@@ -41,5 +48,11 @@ completely implement the "New Sockets" API.
|
||||
<http://www.ipv6.org/impl/mac.html> says that Apple do not support
|
||||
IPv6 yet. If your build fails, try again with --disable-ipv6.
|
||||
|
||||
IBM AIX NOTES
|
||||
-------------
|
||||
|
||||
|
||||
IBM AIX has a largefile problem with mkstemp. See IBM PR-51921.
|
||||
The workaround is to append the below to config.h
|
||||
#ifdef _LARGE_FILES
|
||||
#undef HAVE_SECURE_MKSTEMP
|
||||
#endif
|
||||
|
||||
13
Makefile.in
13
Makefile.in
@@ -25,7 +25,8 @@ VERSION=@VERSION@
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
LIBOBJ=lib/fnmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
|
||||
lib/permstring.o @LIBOBJS@
|
||||
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
@@ -44,10 +45,10 @@ TLS_OBJ = tls.o syscall.o lib/permstring.o
|
||||
|
||||
# Programs we must have to run the test cases
|
||||
CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) \
|
||||
trimslash$(EXEEXT) t_unsafe$(EXEEXT)
|
||||
trimslash$(EXEEXT) t_unsafe$(EXEEXT) wildtest$(EXEEXT)
|
||||
|
||||
# Objects for CHECK_PROGS to clean
|
||||
CHECK_OBJS=getgroups.o t_stub.o t_unsafe.o trimslash.o
|
||||
CHECK_OBJS=getgroups.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:
|
||||
@@ -73,7 +74,7 @@ install-strip:
|
||||
rsync$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): config.h
|
||||
$(OBJS): $(HEADERS)
|
||||
|
||||
tls$(EXEEXT): $(TLS_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TLS_OBJ) $(LIBS)
|
||||
@@ -158,6 +159,10 @@ test: check
|
||||
check: all $(CHECK_PROGS)
|
||||
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin=`pwd`/rsync$(EXEEXT) srcdir="$(srcdir)" $(srcdir)/runtests.sh
|
||||
|
||||
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
|
||||
wildtest$(EXEEXT): wildtest.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o @BUILD_POPT@ $(LIBS)
|
||||
|
||||
# This does *not* depend on building or installing: you can use it to
|
||||
# check a version installed from a binary or some other source tree,
|
||||
# if you want.
|
||||
|
||||
171
NEWS
171
NEWS
@@ -1,91 +1,134 @@
|
||||
NEWS for rsync version 2.5.6, aka the dwd-between-jobs release
|
||||
Changes since version 2.5.5:
|
||||
NEWS for rsync 2.6.0 (1 Jan 2004)
|
||||
Protocol: 27 (changed)
|
||||
Changes since 2.5.7:
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* The --delete-after option now implies --delete. (Wayne Davison)
|
||||
* "ssh" is now the default remote shell for rsync. If you want to
|
||||
change this, configure like this: "./configure --with-rsh=rsh".
|
||||
|
||||
* The --suffix option can now be used with --backup-dir. (Michael
|
||||
Zimmerman)
|
||||
* Added --files-from, --no-relative, --no-implied-dirs, and --from0.
|
||||
Note that --from0 affects the line-ending character for all the
|
||||
files read by the --*-from options. (Wayne Davison)
|
||||
|
||||
* Combining "::" syntax with the -rsh/-e option now uses the
|
||||
specified remote-shell as a transport to talk to a (newly-spawned)
|
||||
server-daemon. This allows someone to use daemon features, such
|
||||
as modules, over a secure protocol, such as ssh. (JD Paul)
|
||||
* Length of csum2 is now per-file starting with protocol version
|
||||
27. (J.W. Schultz)
|
||||
|
||||
* The rsync:// syntax for daemon connections is now accepted in the
|
||||
destination field.
|
||||
* Per-file dynamic block size is now sqrt(file length). The
|
||||
per-file checksum size is determined according to an algorithm
|
||||
provided by Donovan Baarda which reduces the probability of rsync
|
||||
algorithm corrupting data and falling back using the whole md4
|
||||
checksums. (J.W. Schultz, Donovan Baarda)
|
||||
|
||||
* If the file name given to --include-from or --exclude-from is "-",
|
||||
rsync will read from standard input. (J.W. Schultz)
|
||||
* The --stats option no longer includes the (debug) malloc summary
|
||||
unless the verbose option was specified at least twice.
|
||||
|
||||
* New option --link-dest which is like --compare-dest except that
|
||||
unchanged files are hard-linked in to the destination directory.
|
||||
(J.W. Schultz)
|
||||
* Added a new error/warning code for when files vanish from the
|
||||
sending side. Made vanished source files not interfere with the
|
||||
file-deletion pass when --delete-after was specified.
|
||||
|
||||
* Don't report an error if an excluded file disappears during an
|
||||
rsync run. (Eugene Chupriyanov and Bo Kersey)
|
||||
|
||||
* Added .svn to --cvs-exclude list to support subversion. (Jon
|
||||
Middleton)
|
||||
|
||||
* Properly support IPv6 addresses in the rsyncd.conf "hosts allow"
|
||||
and "hosts deny" fields. (Hideaki Yoshifuji)
|
||||
|
||||
* Changed exclude file handling to permit DOS or MAC style line
|
||||
terminations. (J.W. Schultz)
|
||||
|
||||
* Ignore errors from chmod when -p/-a/--preserve-perms is not set.
|
||||
(Dave Dykstra)
|
||||
* Various trailing-info sections are now preceded by a newline.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix "forward name lookup failed" errors on AIX 4.3.3. (John
|
||||
L. Allen, Martin Pool)
|
||||
|
||||
* Generate each file's rolling-checksum data as we send it, not
|
||||
in a separate (memory-eating) pass before hand. This prevents
|
||||
timeout errors on really large files. (Stefan Nehlsen)
|
||||
* Fixed several exclude/include matching bugs when using wild-cards.
|
||||
This has a several user-visible effects, all of which make the
|
||||
matching more consistent and intuitive. This should hopefully not
|
||||
cause anyone problems since it makes the matching work more like
|
||||
what people are expecting. (Wayne Davison)
|
||||
|
||||
* Fix compilation on Tru64. (Albert Chin, Zoong Pham)
|
||||
- A pattern with a "**" no longer causes a "*" to match slashes.
|
||||
For example, with "/*/foo/**", "foo" must be 2 levels deep.
|
||||
|
||||
* Better handling of some client-server errors. (Martin Pool)
|
||||
- "**/foo" now matches at the base of the transfer (i.e. /foo).
|
||||
|
||||
* Fixed a crash that would occur when sending a list of files that
|
||||
contains a duplicate name (if it sorts to the end of the file
|
||||
list) and using --delete. (Wayne Davison)
|
||||
- An non-anchored wildcard term floats to match beyond the base of
|
||||
the transfer. E.g. "CVS/R*" matches at the end of the path,
|
||||
just like the non-wildcard term "CVS/Root" does.
|
||||
|
||||
* Fixed the file-name duplicate-removal code when dealing with multiple
|
||||
dups in a row. (Wayne Davison)
|
||||
- Including a "**" in the match term causes it to be matched
|
||||
against the entire path, not just the name portion, even if
|
||||
there aren't any interior slashes in the term. E.g. "foo**bar"
|
||||
would exclude "/path/foo-bar" (just like before) as well as
|
||||
"/foo-path/baz-bar" (unlike before).
|
||||
|
||||
* Fixed a bug that caused rsync to lose the exit status of its child
|
||||
processes and sometimes return an exit code of 0 instead of showing
|
||||
an error. (David R. Staples, Dave Dykstra)
|
||||
* The exclude list specified in the daemon's config file is now
|
||||
properly applied to the pulled items no matter how deep the
|
||||
user's file-args are in the source tree. (Wayne Davison)
|
||||
|
||||
* Fixed bug in --copy-unsafe-links that caused it to be completely
|
||||
broken. (Dave Dykstra)
|
||||
* For protocol version >= 27, mdfour_tail() is called when the
|
||||
block size (including checksum_seed) is a multiple of 64.
|
||||
Previously it was not called, giving the wrong MD4 checksum.
|
||||
(Craig Barratt)
|
||||
|
||||
* Prevent infinite recursion in cleanup code under certain circumstances.
|
||||
(Sviatoslav Sviridov and Marc Espie)
|
||||
* For protocol version >= 27, a 64 bit bit counter is used in
|
||||
mdfour.c as required by the RFC. Previously only a 32 bit bit
|
||||
counter was used, causing incorrect MD4 file checksums for
|
||||
file sizes >= 512MB - 4. (Craig Barratt)
|
||||
|
||||
* Fixed a bug that prevented rsync from creating intervening directories
|
||||
when --relative-paths/-R is set. (Craig Barratt)
|
||||
* Fixed a crash bug when interacting with older rsync versions and
|
||||
multiple files of the same name are destined for the same dir.
|
||||
(Wayne Davison)
|
||||
|
||||
* Prevent "Connection reset by peer" messages from Cygwin. (Randy O'Meara)
|
||||
* Keep tmp names from overflowing MAXPATHLEN.
|
||||
|
||||
* Make --link-dest honor the absence of -p, -o, and -g.
|
||||
|
||||
* Made rsync treat a trailing slash in the destination in a more
|
||||
consistent manner.
|
||||
|
||||
* Fixed file I/O error detection. (John Van Essen)
|
||||
|
||||
* Fixed bogus "malformed address {hostname}" message in rsyncd log
|
||||
when checking IP address against hostnames from "hosts allow"
|
||||
and "hosts deny" parameters in config file.
|
||||
|
||||
* Print heap statistics when verbose >= 2 instead of when >= 1.
|
||||
|
||||
* Fixed a compression (-z) bug when syncing a mostly-matching file
|
||||
that contains already-compressed data. (Yasuoka Masahiko and
|
||||
Wayne Davison)
|
||||
|
||||
* Fixed a bug in the --backup code that could cause deleted files
|
||||
to not get backed up.
|
||||
|
||||
* When the backup code makes new directories, create them with mode
|
||||
0700 instead of 0755 (since the directory permissions in the
|
||||
backup tree are not yet copied from the main tree).
|
||||
|
||||
* Call setgroups() in a more portable manner.
|
||||
|
||||
* Improved file-related error messages to better indicate exactly
|
||||
what pathname failed. (Wayne Davison)
|
||||
|
||||
* Fixed some bugs in the handling of --delete and --exclude when
|
||||
using the --relative (-R) option. (Wayne Davison)
|
||||
|
||||
* Fixed bug that prevented regular files from replacing
|
||||
special files and caused a directory in --link-dest or
|
||||
--compare-dest to block the creation of a file with the
|
||||
same path. A directory still cannot be replaced by a
|
||||
regular file unless --delete specified. (J.W. Schultz)
|
||||
|
||||
* Detect and report when open or opendir succeed but read and
|
||||
readdir fail caused by network filesystems issues and truncated
|
||||
files. (David Norwood, Michael Brown, J.W. Schultz)
|
||||
|
||||
* Added a fix that should give ssh time to restore the tty settings
|
||||
if the user presses Ctrl-C at an ssh password prompt.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
* Many code cleanups and improved internal documentation. (Martin
|
||||
Pool, Nelson Beebe)
|
||||
* Eliminated vestigial support for old versions that we stopped
|
||||
supporting. (J.W. Schultz)
|
||||
|
||||
* Portability fixes. (Dave Dykstra and Wayne Davison)
|
||||
* Simplified some of the option-parsing code. (Wayne Davison)
|
||||
|
||||
* More test cases. (Martin Pool)
|
||||
* Some cleanup made to the exclude code, as well as some new
|
||||
defines added to enhance readability. (Wayne Davison)
|
||||
|
||||
* Some test-case fixes. (Brian Poole, Wayne Davison)
|
||||
|
||||
* Updated included popt to the latest vendor drop, version 1.6.4.
|
||||
(Jos Backus)
|
||||
|
||||
* Updated config.guess and config.sub to latest versions; this
|
||||
means rsync should build on more platforms. (Paul Green)
|
||||
* Changed the protocol-version code so that it can interact at a
|
||||
lower protocol level than the maximum supported by both sides.
|
||||
Added an undocumented option, --protocol=N, to force the value
|
||||
we advertise to the other side (primarily for testing purposes).
|
||||
(Wayne Davison)
|
||||
|
||||
207
OLDNEWS
207
OLDNEWS
@@ -1,4 +1,110 @@
|
||||
rsync 2.5.5 "Snowy River" (2 April 2002)
|
||||
NEWS for rsync 2.5.7 (4 Dec 2003)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.6:
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
* Fix buffer handling bugs. (Andrew Tridgell, Martin Pool, Paul
|
||||
Russell, Andrea Barisani)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.6, aka "the dwd-between-jobs release" (26 Jan 2003)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.5:
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* The --delete-after option now implies --delete. (Wayne Davison)
|
||||
|
||||
* The --suffix option can now be used with --backup-dir. (Michael
|
||||
Zimmerman)
|
||||
|
||||
* Combining "::" syntax with the -rsh/-e option now uses the
|
||||
specified remote-shell as a transport to talk to a (newly-spawned)
|
||||
server-daemon. This allows someone to use daemon features, such
|
||||
as modules, over a secure protocol, such as ssh. (JD Paul)
|
||||
|
||||
* The rsync:// syntax for daemon connections is now accepted in the
|
||||
destination field.
|
||||
|
||||
* If the file name given to --include-from or --exclude-from is "-",
|
||||
rsync will read from standard input. (J.W. Schultz)
|
||||
|
||||
* New option --link-dest which is like --compare-dest except that
|
||||
unchanged files are hard-linked in to the destination directory.
|
||||
(J.W. Schultz)
|
||||
|
||||
* Don't report an error if an excluded file disappears during an
|
||||
rsync run. (Eugene Chupriyanov and Bo Kersey)
|
||||
|
||||
* Added .svn to --cvs-exclude list to support subversion. (Jon
|
||||
Middleton)
|
||||
|
||||
* Properly support IPv6 addresses in the rsyncd.conf "hosts allow"
|
||||
and "hosts deny" fields. (Hideaki Yoshifuji)
|
||||
|
||||
* Changed exclude file handling to permit DOS or MAC style line
|
||||
terminations. (J.W. Schultz)
|
||||
|
||||
* Ignore errors from chmod when -p/-a/--preserve-perms is not set.
|
||||
(Dave Dykstra)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix "forward name lookup failed" errors on AIX 4.3.3. (John
|
||||
L. Allen, Martin Pool)
|
||||
|
||||
* Generate each file's rolling-checksum data as we send it, not
|
||||
in a separate (memory-eating) pass before hand. This prevents
|
||||
timeout errors on really large files. (Stefan Nehlsen)
|
||||
|
||||
* Fix compilation on Tru64. (Albert Chin, Zoong Pham)
|
||||
|
||||
* Better handling of some client-server errors. (Martin Pool)
|
||||
|
||||
* Fixed a crash that would occur when sending a list of files that
|
||||
contains a duplicate name (if it sorts to the end of the file
|
||||
list) and using --delete. (Wayne Davison)
|
||||
|
||||
* Fixed the file-name duplicate-removal code when dealing with multiple
|
||||
dups in a row. (Wayne Davison)
|
||||
|
||||
* Fixed a bug that caused rsync to lose the exit status of its child
|
||||
processes and sometimes return an exit code of 0 instead of showing
|
||||
an error. (David R. Staples, Dave Dykstra)
|
||||
|
||||
* Fixed bug in --copy-unsafe-links that caused it to be completely
|
||||
broken. (Dave Dykstra)
|
||||
|
||||
* Prevent infinite recursion in cleanup code under certain circumstances.
|
||||
(Sviatoslav Sviridov and Marc Espie)
|
||||
|
||||
* Fixed a bug that prevented rsync from creating intervening directories
|
||||
when --relative-paths/-R is set. (Craig Barratt)
|
||||
|
||||
* Prevent "Connection reset by peer" messages from Cygwin. (Randy O'Meara)
|
||||
|
||||
INTERNAL:
|
||||
|
||||
* Many code cleanups and improved internal documentation. (Martin
|
||||
Pool, Nelson Beebe)
|
||||
|
||||
* Portability fixes. (Dave Dykstra and Wayne Davison)
|
||||
|
||||
* More test cases. (Martin Pool)
|
||||
|
||||
* Some test-case fixes. (Brian Poole, Wayne Davison)
|
||||
|
||||
* Updated included popt to the latest vendor drop, version 1.6.4.
|
||||
(Jos Backus)
|
||||
|
||||
* Updated config.guess and config.sub to latest versions; this
|
||||
means rsync should build on more platforms. (Paul Green)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.5, aka Snowy River (2 Apr 2002)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.4:
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
@@ -37,15 +143,15 @@ rsync 2.5.5 "Snowy River" (2 April 2002)
|
||||
* Improved network error handling. (Greg A. Woods)
|
||||
|
||||
|
||||
rsync 2.5.4 (13 March 2002)
|
||||
|
||||
"Imitation lizard skin"
|
||||
NEWS for rsync 2.5.4, aka "Imitation lizard skin" (13 Mar 2002)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.3:
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Additional fix for zlib double-free bug. (Martin Pool, Andrew
|
||||
Tridgell) (CVE CAN-2002-0059)
|
||||
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* Merge in changes from zlib 1.1.3 to zlib 1.1.4. (Jos Backus)
|
||||
@@ -55,9 +161,9 @@ rsync 2.5.4 (13 March 2002)
|
||||
* Additional test cases for --compress. (Martin Pool)
|
||||
|
||||
|
||||
rsync 2.5.3 (11 March 2002)
|
||||
|
||||
"Happy 26"
|
||||
NEWS for rsync 2.5.3, aka "Happy 26" (11 Mar 2002)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.2:
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
@@ -70,7 +176,7 @@ rsync 2.5.3 (11 March 2002)
|
||||
* Fix zlib double-free bug. (Owen Taylor, Mark J Cox) (CVE
|
||||
CAN-2002-0059)
|
||||
|
||||
* Fixed problem that in many cases caused the error message
|
||||
* Fixed problem that in many cases caused the error message
|
||||
unexpected read size of 0 in map_ptr
|
||||
and resulted in the wrong data being copied.
|
||||
|
||||
@@ -91,7 +197,7 @@ rsync 2.5.3 (11 March 2002)
|
||||
* Merge in changes from zlib 1.1.2 to zlib 1.1.3. (Note that
|
||||
rsync still uses a custom version of zlib; you can not just link
|
||||
against a system library. See zlib/README.rsync)
|
||||
|
||||
|
||||
* Command to initiate connections is only shown with -vv, rather
|
||||
than -v as in 2.5.2. Output from plain -v is more similar to
|
||||
what was historically used so as not to break scripts that try
|
||||
@@ -105,7 +211,10 @@ rsync 2.5.3 (11 March 2002)
|
||||
* If the daemon is unable to fork a child to accept a connection,
|
||||
print an error message. (Colin Walters)
|
||||
|
||||
rsync 2.5.2 (26 Jan 2002)
|
||||
|
||||
NEWS for rsync 2.5.2 (26 Jan 2002)
|
||||
Protocol: 26 (changed)
|
||||
Changes since 2.5.1:
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
@@ -132,7 +241,7 @@ rsync 2.5.2 (26 Jan 2002)
|
||||
connection.
|
||||
|
||||
* --statistics now shows memory heap usage on platforms that
|
||||
support mallinfo().
|
||||
support mallinfo().
|
||||
|
||||
* "The Ted T'so school of program optimization": make progress
|
||||
visible and people will think it's faster. (With --progress,
|
||||
@@ -141,14 +250,17 @@ rsync 2.5.2 (26 Jan 2002)
|
||||
|
||||
* Improvements to batch mode support. This is still experimental
|
||||
but testing would be welcome. (Jos Backus)
|
||||
|
||||
|
||||
* New --ignore-existing option, patch previously distributed with
|
||||
Vipul's Razor. (Debian #124286)
|
||||
|
||||
rsync 2.5.1 (2002-01-03)
|
||||
|
||||
NEWS for rsync 2.5.1 (3 Jan 2002)
|
||||
Protocol: 25 (unchanged)
|
||||
Changes since 2.5.0:
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix for segfault in --daemon mode configuration parser. (Paul
|
||||
Mackerras)
|
||||
|
||||
@@ -170,17 +282,19 @@ rsync 2.5.1 (2002-01-03)
|
||||
ENHANCEMENTS:
|
||||
|
||||
* --progress and -P now show estimated data transfer rate (in a
|
||||
multiple of bytes/s) and estimated time to completion. (Rik
|
||||
Faith)
|
||||
|
||||
multiple of bytes/s) and estimated time to completion. (Rik
|
||||
Faith)
|
||||
|
||||
* --no-detach option, required to run as a W32 service and also
|
||||
useful when running on Unix under daemontools, AIX's SRC, or a
|
||||
debugger. (Max Bowsher, Jos Backus)
|
||||
useful when running on Unix under daemontools, AIX's SRC, or a
|
||||
debugger. (Max Bowsher, Jos Backus)
|
||||
|
||||
* Clearer error messages for some conditions.
|
||||
|
||||
|
||||
rsync 2.5.0 (2001-11-30)
|
||||
NEWS for rsync 2.5.0 (30 Nov 2001)
|
||||
Protocol: 25 (changed)
|
||||
Changes since 2.4.6:
|
||||
|
||||
ANNOUNCEMENTS
|
||||
|
||||
@@ -242,7 +356,7 @@ rsync 2.5.0 (2001-11-30)
|
||||
* Attempt to fix error handling lockup bug.
|
||||
|
||||
* Give a non-0 exit code if *any* of the files we have been asked
|
||||
to transfer fail to transfer
|
||||
to transfer fail to transfer.
|
||||
|
||||
* For log messages containing ridiculously long strings that might
|
||||
overflow a buffer rsync no longer aborts, but rather prints an
|
||||
@@ -253,7 +367,7 @@ rsync 2.5.0 (2001-11-30)
|
||||
* Improved support for UNICOS (tested on Cray T3E and Cray SV1)
|
||||
|
||||
* autoconf2.52 (or later) is now required to rebuild the autoconf
|
||||
scripts. It is not required to simply build rsync.
|
||||
scripts. It is not required to simply build rsync.
|
||||
|
||||
* Platforms thought to work in this release:
|
||||
|
||||
@@ -294,3 +408,48 @@ rsync 2.5.0 (2001-11-30)
|
||||
* The existing test.sh script by Phil Hands has been merged into a
|
||||
test framework that works from both "make check" and the Samba
|
||||
build farm.
|
||||
|
||||
Partial Protocol History
|
||||
RELEASE DATE VER. DATE OF COMMIT PROTOCOL
|
||||
01 Jan 2004 2.6.0 10 Apr 2003 27 (MAX=40)
|
||||
04 Dec 2003 2.5.7 26
|
||||
26 Jan 2003 2.5.6 26
|
||||
02 Apr 2002 2.5.5 26
|
||||
13 Mar 2002 2.5.4 26
|
||||
11 Mar 2002 2.5.3 26
|
||||
26 Jan 2002 2.5.2 11 Jan 2002 26
|
||||
03 Jan 2002 2.5.1 25
|
||||
30 Nov 2001 2.5.0 23 Aug 2001 25
|
||||
06 Sep 2000 2.4.6 24
|
||||
19 Aug 2000 2.4.5 24
|
||||
29 Jul 2000 2.4.4 24
|
||||
09 Apr 2000 2.4.3 24
|
||||
30 Mar 2000 2.4.2 24
|
||||
30 Jan 2000 2.4.1 29 Jan 2000 24
|
||||
29 Jan 2000 2.4.0 28 Jan 2000 23
|
||||
25 Jan 2000 2.3.3 23 Jan 2000 22
|
||||
08 Nov 1999 2.3.2 26 Jun 1999 21
|
||||
06 Apr 1999 2.3.1 20
|
||||
15 Mar 1999 2.3.0 15 Mar 1999 20
|
||||
25 Nov 1998 2.2.1 19
|
||||
03 Nov 1998 2.2.0 19
|
||||
09 Sep 1998 2.1.1 19
|
||||
20 Jul 1998 2.1.0 19
|
||||
17 Jul 1998 2.0.19 19
|
||||
18 Jun 1998 2.0.17 19
|
||||
01 Jun 1998 2.0.16 19
|
||||
27 May 1998 2.0.13 27 May 1998 19
|
||||
26 May 1998 2.0.12 18
|
||||
22 May 1998 2.0.11 18
|
||||
18 May 1998 2.0.9 18 May 1998 18
|
||||
17 May 1998 2.0.8 17
|
||||
15 May 1998 2.0.1 17
|
||||
14 May 1998 2.0.0 17
|
||||
17 Apr 1998 1.7.4 17
|
||||
13 Apr 1998 1.7.3 17
|
||||
05 Apr 1998 1.7.2 17
|
||||
26 Mar 1998 1.7.1 17
|
||||
26 Mar 1998 1.7.0 26 Mar 1998 17 (MAX=30)
|
||||
13 Jan 1998 1.6.9 13 Jan 1998 15 (MAX=20)
|
||||
|
||||
* DATE OF COMMIT is the date the protocol change was committed to CVS.
|
||||
|
||||
22
access.c
22
access.c
@@ -27,7 +27,7 @@
|
||||
static int match_hostname(char *host, char *tok)
|
||||
{
|
||||
if (!host || !*host) return 0;
|
||||
return (fnmatch(tok, host, 0) == 0);
|
||||
return wildmatch(tok, host);
|
||||
}
|
||||
|
||||
static int match_binary(char *b1, char *b2, char *mask, int addrlen)
|
||||
@@ -73,11 +73,24 @@ static int match_address(char *addr, char *tok)
|
||||
#endif
|
||||
char mask[16];
|
||||
char *a = NULL, *t = NULL;
|
||||
unsigned int len;
|
||||
|
||||
if (!addr || !*addr) return 0;
|
||||
|
||||
p = strchr(tok,'/');
|
||||
if (p) *p = 0;
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
len = p - tok;
|
||||
}
|
||||
else
|
||||
len = strlen(tok);
|
||||
|
||||
/* Fail quietly if tok is a hostname (not an address) */
|
||||
if (strspn(tok, ".0123456789") != len
|
||||
#ifdef INET6
|
||||
&& !strchr(tok, ':')
|
||||
#endif
|
||||
) return 0;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
@@ -93,7 +106,10 @@ static int match_address(char *addr, char *tok)
|
||||
if (p)
|
||||
*p++ = '/';
|
||||
if (gai) {
|
||||
rprintf(FERROR,"malformed address %s\n", tok);
|
||||
rprintf(FERROR,
|
||||
"error matching address %s: %s\n",
|
||||
tok,
|
||||
gai_strerror(gai));
|
||||
freeaddrinfo(resa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
|
||||
if (!users) return NULL;
|
||||
|
||||
for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
|
||||
if (fnmatch(tok, user, 0) == 0) break;
|
||||
if (wildmatch(tok, user)) break;
|
||||
}
|
||||
free(users);
|
||||
|
||||
@@ -273,8 +273,14 @@ void auth_client(int fd, char *user, char *challenge)
|
||||
|
||||
if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
|
||||
/* XXX: cyeoh says that getpass is deprecated, because
|
||||
it may return a truncated password on some systems,
|
||||
and it is not in the LSB. */
|
||||
* it may return a truncated password on some systems,
|
||||
* and it is not in the LSB.
|
||||
*
|
||||
* Andrew Klein says that getpassphrase() is present
|
||||
* on Solaris and reads up to 256 characters.
|
||||
*
|
||||
* OpenBSD has a readpassphrase() that might be more suitable.
|
||||
*/
|
||||
pass = getpass("Password: ");
|
||||
}
|
||||
|
||||
|
||||
228
backup.c
228
backup.c
@@ -21,11 +21,11 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int suffix_specified;
|
||||
extern int backup_suffix_len;
|
||||
extern int backup_dir_len;
|
||||
extern char *backup_suffix;
|
||||
extern char *backup_dir;
|
||||
|
||||
|
||||
extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_links;
|
||||
@@ -35,20 +35,20 @@ extern int preserve_hard_links;
|
||||
static int make_simple_backup(char *fname)
|
||||
{
|
||||
char fnamebak[MAXPATHLEN];
|
||||
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
|
||||
rprintf(FERROR,"backup filename too long\n");
|
||||
if (strlen(fname) + backup_suffix_len > MAXPATHLEN-1) {
|
||||
rprintf(FERROR, "backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix);
|
||||
if (do_rename(fname,fnamebak) != 0) {
|
||||
snprintf(fnamebak, sizeof(fnamebak), "%s%s", fname, backup_suffix);
|
||||
if (do_rename(fname, fnamebak) != 0) {
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno != ENOENT && errno != EINVAL) {
|
||||
rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
|
||||
return 0;
|
||||
}
|
||||
} else if (verbose > 1) {
|
||||
rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
|
||||
rprintf(FINFO, "backed up %s to %s\n", fname, fnamebak);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -81,50 +81,53 @@ static int make_dir(char *name, int mask)
|
||||
Create a directory given an absolute path, perms based upon another directory
|
||||
path
|
||||
****************************************************************************/
|
||||
static int make_bak_dir(char *fname,char *bak_path)
|
||||
static int make_bak_dir(char *fname, char *bak_path)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
STRUCT_STAT *st2;
|
||||
char fullpath[MAXPATHLEN];
|
||||
extern int orig_umask;
|
||||
char *p;
|
||||
char *q;
|
||||
STRUCT_STAT st;
|
||||
STRUCT_STAT *st2;
|
||||
char fullpath[MAXPATHLEN];
|
||||
extern int orig_umask;
|
||||
char *p;
|
||||
char *q;
|
||||
|
||||
while(strncmp(bak_path,"./",2)==0) bak_path += 2;
|
||||
while(strncmp(bak_path, "./", 2) == 0) bak_path += 2;
|
||||
|
||||
if(bak_path[strlen(bak_path)-1]!='/') {
|
||||
snprintf(fullpath,sizeof(fullpath),"%s/",bak_path);
|
||||
} else {
|
||||
snprintf(fullpath,sizeof(fullpath),"%s",bak_path);
|
||||
}
|
||||
p=fullpath;
|
||||
q=&fullpath[strlen(fullpath)]; /* End of bak_path string */
|
||||
strcat(fullpath,fname);
|
||||
if(bak_path[strlen(bak_path)-1] != '/') {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/", bak_path);
|
||||
} else {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s", bak_path);
|
||||
}
|
||||
p = fullpath;
|
||||
q = &fullpath[strlen(fullpath)]; /* End of bak_path string */
|
||||
strcat(fullpath, fname);
|
||||
|
||||
/* Make the directories */
|
||||
while ((p=strchr(p,'/'))) {
|
||||
*p = 0;
|
||||
if(do_lstat(fullpath,&st)!=0) {
|
||||
do_mkdir(fullpath,0777 & ~orig_umask);
|
||||
if(p>q) {
|
||||
if(do_lstat(q,&st)!=0) {
|
||||
rprintf(FERROR,"make_bak_dir stat %s : %s\n",fullpath,strerror(errno));
|
||||
} else {
|
||||
st2=&st;
|
||||
set_modtime(fullpath,st2->st_mtime);
|
||||
if(do_lchown(fullpath,st2->st_uid,st2->st_gid)!=0) {
|
||||
rprintf(FERROR,"make_bak_dir chown %s : %s\n",fullpath,strerror(errno));
|
||||
};
|
||||
if(do_chmod(fullpath,st2->st_mode)!=0) {
|
||||
rprintf(FERROR,"make_bak_dir failed to set permissions on %s : %s\n",fullpath,strerror(errno));
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
*p = '/';
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
/* Make the directories */
|
||||
while ((p = strchr(p, '/'))) {
|
||||
*p = 0;
|
||||
if(do_lstat(fullpath, &st) != 0) {
|
||||
do_mkdir(fullpath, 0777 & ~orig_umask);
|
||||
if(p>q) {
|
||||
if(do_lstat(q, &st) != 0) {
|
||||
rprintf(FERROR, "make_bak_dir stat %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
} else {
|
||||
st2 = &st;
|
||||
set_modtime(fullpath, st2->st_mtime);
|
||||
if(do_lchown(fullpath, st2->st_uid, st2->st_gid) != 0) {
|
||||
rprintf(FERROR, "make_bak_dir chown %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
}
|
||||
if(do_chmod(fullpath, st2->st_mode) != 0) {
|
||||
rprintf(FERROR, "make_bak_dir failed to set permissions on %s: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '/';
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* robustly move a file, creating new directory structures if necessary */
|
||||
@@ -147,7 +150,7 @@ static int robust_move(char *src, char *dst)
|
||||
if (failed) {
|
||||
if (verbose > 2)
|
||||
rprintf (FERROR, "robust_move failed: %s(%d)\n",
|
||||
strerror (errno), errno);
|
||||
strerror (errno), errno);
|
||||
switch (errno) {
|
||||
/* external filesystem */
|
||||
case EXDEV:
|
||||
@@ -156,7 +159,7 @@ static int robust_move(char *src, char *dst)
|
||||
break;
|
||||
/* no directory to write to */
|
||||
case ENOENT:
|
||||
make_dir (dst, 0755);
|
||||
make_dir(dst, 0700);
|
||||
keep_trying--;
|
||||
break;
|
||||
default:
|
||||
@@ -180,12 +183,12 @@ static int keep_backup(char *fname)
|
||||
STRUCT_STAT st;
|
||||
struct file_struct *file;
|
||||
|
||||
int kept=0;
|
||||
int kept = 0;
|
||||
int ret_code;
|
||||
|
||||
if (!initialised) {
|
||||
if (backup_dir[strlen(backup_dir) - 1] == '/')
|
||||
backup_dir[strlen(backup_dir) - 1] = 0;
|
||||
if (backup_dir_len && backup_dir[backup_dir_len - 1] == '/')
|
||||
backup_dir[--backup_dir_len] = '\0';
|
||||
if (verbose > 0)
|
||||
rprintf (FINFO, "backup_dir is %s\n", backup_dir);
|
||||
initialised = 1;
|
||||
@@ -198,84 +201,86 @@ static int keep_backup(char *fname)
|
||||
if (do_stat (fname, &st)) return 1;
|
||||
#endif
|
||||
|
||||
file = make_file(-1, fname, NULL, 1);
|
||||
file = make_file(fname, NULL, NO_EXCLUDES);
|
||||
|
||||
/* the file could have disappeared */
|
||||
if (!file) return 1;
|
||||
|
||||
/* make a complete pathname for backup file */
|
||||
if (strlen(backup_dir) + strlen(fname) +
|
||||
(suffix_specified ? strlen(backup_suffix) : 0) > (MAXPATHLEN - 1)) {
|
||||
rprintf (FERROR, "keep_backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (suffix_specified) {
|
||||
snprintf(keep_name, sizeof (keep_name), "%s/%s%s", backup_dir, fname, backup_suffix);
|
||||
} else {
|
||||
snprintf(keep_name, sizeof (keep_name), "%s/%s", backup_dir, fname);
|
||||
}
|
||||
/* make a complete pathname for backup file */
|
||||
if (backup_dir_len+strlen(fname)+backup_suffix_len > MAXPATHLEN-1) {
|
||||
rprintf (FERROR, "keep_backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(keep_name, sizeof (keep_name), "%s/%s%s",
|
||||
backup_dir, fname, backup_suffix);
|
||||
|
||||
#ifdef HAVE_MKNOD
|
||||
/* Check to see if this is a device file, or link */
|
||||
if(IS_DEVICE(file->mode)) {
|
||||
if(am_root && preserve_devices) {
|
||||
make_bak_dir(fname,backup_dir);
|
||||
if(do_mknod(keep_name,file->mode,file->rdev)!=0) {
|
||||
rprintf(FERROR,"mknod %s : %s\n",keep_name,strerror(errno));
|
||||
} else {
|
||||
if(verbose>2)
|
||||
rprintf(FINFO,"make_backup : DEVICE %s successful.\n",fname);
|
||||
};
|
||||
};
|
||||
kept=1;
|
||||
do_unlink(fname);
|
||||
};
|
||||
if(IS_DEVICE(file->mode)) {
|
||||
if(am_root && preserve_devices) {
|
||||
make_bak_dir(fname, backup_dir);
|
||||
if(do_mknod(keep_name, file->mode, file->rdev) != 0) {
|
||||
rprintf(FERROR, "mknod %s failed: %s\n",
|
||||
full_fname(keep_name), strerror(errno));
|
||||
} else if(verbose>2) {
|
||||
rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
|
||||
}
|
||||
}
|
||||
kept = 1;
|
||||
do_unlink(fname);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!kept && S_ISDIR(file->mode)) {
|
||||
/* make an empty directory */
|
||||
make_bak_dir(fname,backup_dir);
|
||||
do_mkdir(keep_name,file->mode);
|
||||
ret_code=do_rmdir(fname);
|
||||
if(verbose>2)
|
||||
rprintf(FINFO,"make_backup : RMDIR %s returns %i\n",fname,ret_code);
|
||||
kept=1;
|
||||
};
|
||||
make_bak_dir(fname, backup_dir);
|
||||
do_mkdir(keep_name, file->mode);
|
||||
ret_code = do_rmdir(fname);
|
||||
|
||||
if(verbose>2) {
|
||||
rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
|
||||
full_fname(fname), ret_code);
|
||||
}
|
||||
kept = 1;
|
||||
}
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
if(!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
extern int safe_symlinks;
|
||||
if (safe_symlinks && unsafe_symlink(file->link, keep_name)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
|
||||
keep_name,file->link);
|
||||
}
|
||||
kept=1;
|
||||
}
|
||||
make_bak_dir(fname,backup_dir);
|
||||
if(do_symlink(file->link,keep_name) != 0) {
|
||||
rprintf(FERROR,"link %s -> %s : %s\n",keep_name,file->link,strerror(errno));
|
||||
};
|
||||
do_unlink(fname);
|
||||
kept=1;
|
||||
};
|
||||
if(!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
extern int safe_symlinks;
|
||||
if (safe_symlinks && unsafe_symlink(file->link, keep_name)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
|
||||
full_fname(keep_name), file->link);
|
||||
}
|
||||
kept = 1;
|
||||
}
|
||||
make_bak_dir(fname, backup_dir);
|
||||
if(do_symlink(file->link, keep_name) != 0) {
|
||||
rprintf(FERROR, "link %s -> %s : %s\n",
|
||||
full_fname(keep_name), file->link, strerror(errno));
|
||||
}
|
||||
do_unlink(fname);
|
||||
kept = 1;
|
||||
}
|
||||
#endif
|
||||
if(!kept && preserve_hard_links && check_hard_link(file)) {
|
||||
if(verbose > 1) rprintf(FINFO,"%s is a hard link\n",f_name(file));
|
||||
};
|
||||
if(!kept && preserve_hard_links && check_hard_link(file)) {
|
||||
if(verbose > 1)
|
||||
rprintf(FINFO, "%s is a hard link\n", f_name(file));
|
||||
}
|
||||
|
||||
if(!kept && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO,"make_bak: skipping non-regular file %s\n",fname);
|
||||
}
|
||||
if(!kept && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
|
||||
fname);
|
||||
}
|
||||
|
||||
/* move to keep tree if a file */
|
||||
if(!kept) {
|
||||
if (!robust_move (fname, keep_name))
|
||||
rprintf(FERROR, "keep_backup failed %s -> %s : %s\n",
|
||||
fname, keep_name, strerror(errno));
|
||||
};
|
||||
if (!robust_move (fname, keep_name)) {
|
||||
rprintf(FERROR, "keep_backup failed: %s -> \"%s\": %s\n",
|
||||
full_fname(fname), keep_name, strerror(errno));
|
||||
}
|
||||
}
|
||||
set_perms (keep_name, file, NULL, 0);
|
||||
free_file (file);
|
||||
free (file);
|
||||
@@ -294,4 +299,3 @@ int make_backup(char *fname)
|
||||
else
|
||||
return (make_simple_backup(fname));
|
||||
}
|
||||
|
||||
|
||||
21
batch.c
21
batch.c
@@ -185,15 +185,14 @@ struct file_list *create_flist_from_batch(void)
|
||||
fdb_open = 1;
|
||||
fdb_close = 0;
|
||||
|
||||
batch_flist = (struct file_list *) malloc(sizeof(batch_flist[0]));
|
||||
batch_flist = new(struct file_list);
|
||||
if (!batch_flist) {
|
||||
out_of_memory("create_flist_from_batch");
|
||||
}
|
||||
batch_flist->count = 0;
|
||||
batch_flist->malloced = 1000;
|
||||
batch_flist->files =
|
||||
(struct file_struct **) malloc(sizeof(batch_flist->files[0]) *
|
||||
batch_flist->malloced);
|
||||
batch_flist->files = new_array(struct file_struct *,
|
||||
batch_flist->malloced);
|
||||
if (!batch_flist->files) {
|
||||
out_of_memory("create_flist_from_batch");
|
||||
}
|
||||
@@ -207,14 +206,10 @@ struct file_list *create_flist_from_batch(void)
|
||||
batch_flist->malloced += 1000;
|
||||
else
|
||||
batch_flist->malloced *= 2;
|
||||
batch_flist->files =
|
||||
(struct file_struct **) realloc(batch_flist->
|
||||
files,
|
||||
sizeof
|
||||
(batch_flist->
|
||||
files[0]) *
|
||||
batch_flist->
|
||||
malloced);
|
||||
batch_flist->files
|
||||
= realloc_array(batch_flist->files,
|
||||
struct file_struct *,
|
||||
batch_flist->malloced);
|
||||
if (!batch_flist->files)
|
||||
out_of_memory("create_flist_from_batch");
|
||||
}
|
||||
@@ -282,7 +277,7 @@ void read_batch_flist_info(struct file_struct **fptr)
|
||||
char buff[256];
|
||||
struct file_struct *file;
|
||||
|
||||
file = (struct file_struct *) malloc(sizeof(*file));
|
||||
file = new(struct file_struct);
|
||||
if (!file)
|
||||
out_of_memory("read_batch_flist_info");
|
||||
memset((char *) file, 0, sizeof(*file));
|
||||
|
||||
32
checksum.c
32
checksum.c
@@ -24,7 +24,7 @@ int csum_length=2; /* initial value */
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
int checksum_seed = 0;
|
||||
extern int remote_version;
|
||||
extern int protocol_version;
|
||||
|
||||
/*
|
||||
a simple 32 bit checksum that can be upadted from either end
|
||||
@@ -58,7 +58,7 @@ void get_checksum2(char *buf,int len,char *sum)
|
||||
|
||||
if (len > len1) {
|
||||
if (buf1) free(buf1);
|
||||
buf1 = (char *)malloc(len+4);
|
||||
buf1 = new_array(char, len+4);
|
||||
len1 = len;
|
||||
if (!buf1) out_of_memory("get_checksum2");
|
||||
}
|
||||
@@ -74,7 +74,13 @@ void get_checksum2(char *buf,int len,char *sum)
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
|
||||
}
|
||||
if (len - i > 0) {
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0 || protocol_version >= 27) {
|
||||
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
|
||||
}
|
||||
|
||||
@@ -105,8 +111,16 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0) {
|
||||
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
|
||||
}
|
||||
if (len - i > 0 || protocol_version >= 27) {
|
||||
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
|
||||
}
|
||||
|
||||
@@ -117,16 +131,6 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
}
|
||||
|
||||
|
||||
void checksum_init(void)
|
||||
{
|
||||
if (remote_version >= 14)
|
||||
csum_length = 2; /* adaptive */
|
||||
else
|
||||
csum_length = SUM_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sumresidue;
|
||||
static char sumrbuf[CSUM_CHUNK];
|
||||
static struct mdfour md;
|
||||
@@ -180,7 +184,7 @@ void sum_update(char *p, int len)
|
||||
|
||||
void sum_end(char *sum)
|
||||
{
|
||||
if (sumresidue) {
|
||||
if (sumresidue || protocol_version >= 27) {
|
||||
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* shutdown() of socket connections. This eliminates the abortive
|
||||
* TCP RST sent by a Winsock-based system when the close() occurs.
|
||||
**/
|
||||
void close_all()
|
||||
void close_all(void)
|
||||
{
|
||||
#ifdef SHUTDOWN_ALL_SOCKETS
|
||||
int max_fd;
|
||||
@@ -131,8 +131,11 @@ void _exit_cleanup(int code, const char *file, int line)
|
||||
}
|
||||
}
|
||||
|
||||
if (code == 0 && (io_error || log_got_error)) {
|
||||
code = RERR_PARTIAL;
|
||||
if (code == 0) {
|
||||
if ((io_error & ~IOERR_VANISHED) || log_got_error)
|
||||
code = RERR_PARTIAL;
|
||||
else if (io_error)
|
||||
code = RERR_VANISHED;
|
||||
}
|
||||
|
||||
if (code) log_exit(code, file, line);
|
||||
|
||||
168
clientserver.c
168
clientserver.c
@@ -1,18 +1,18 @@
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
*
|
||||
*
|
||||
* Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2001-2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -33,6 +33,11 @@ extern int verbose;
|
||||
extern int rsync_port;
|
||||
char *auth_user;
|
||||
extern int sanitize_paths;
|
||||
extern int filesfrom_fd;
|
||||
extern int remote_protocol;
|
||||
extern int protocol_version;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
extern char *exclude_path_prefix;
|
||||
|
||||
/**
|
||||
* Run a client connected to an rsyncd. The alternative to this
|
||||
@@ -54,10 +59,10 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
char *p, *user=NULL;
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
|
||||
|
||||
/* this is redundant with code in start_inband_exchange(), but
|
||||
this short-circuits a problem before we open a socket, and
|
||||
the extra check won't hurt */
|
||||
* this short-circuits a problem before we open a socket, and
|
||||
* the extra check won't hurt */
|
||||
if (*path == '/') {
|
||||
rprintf(FERROR,"ERROR: The remote path must start with a module name not a /\n");
|
||||
return -1;
|
||||
@@ -77,8 +82,8 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
rprintf(FINFO, "opening tcp connection to %s port %d\n",
|
||||
host, rsync_port);
|
||||
}
|
||||
fd = open_socket_out_wrapped (host, rsync_port, bind_address,
|
||||
default_af_hint);
|
||||
fd = open_socket_out_wrapped(host, rsync_port, bind_address,
|
||||
default_af_hint);
|
||||
if (fd == -1) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
@@ -95,7 +100,6 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
int sargc = 0;
|
||||
char line[MAXPATHLEN];
|
||||
char *p;
|
||||
extern int remote_version;
|
||||
extern int kludge_around_eof;
|
||||
extern int am_sender;
|
||||
extern int daemon_over_rsh;
|
||||
@@ -112,15 +116,15 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
if (!user) user = getenv("USER");
|
||||
if (!user) user = getenv("LOGNAME");
|
||||
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
daemon_over_rsh = 0;
|
||||
server_options(sargs, &sargc);
|
||||
|
||||
sargs[sargc++] = ".";
|
||||
|
||||
if (path && *path)
|
||||
if (path && *path)
|
||||
sargs[sargc++] = path;
|
||||
|
||||
sargs[sargc] = NULL;
|
||||
@@ -132,12 +136,14 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf(line,"@RSYNCD: %d", &remote_version) != 1) {
|
||||
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
|
||||
/* note that read_line strips of \n or \r */
|
||||
rprintf(FERROR, "rsync: server sent \"%s\" rather than greeting\n",
|
||||
line);
|
||||
return -1;
|
||||
}
|
||||
if (protocol_version > remote_protocol)
|
||||
protocol_version = remote_protocol;
|
||||
|
||||
p = strchr(path,'/');
|
||||
if (p) *p = 0;
|
||||
@@ -146,7 +152,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
|
||||
/* Old servers may just drop the connection here,
|
||||
rather than sending a proper EXIT command. Yuck. */
|
||||
kludge_around_eof = list_only && (remote_version < 25);
|
||||
kludge_around_eof = list_only && (protocol_version < 25);
|
||||
|
||||
while (1) {
|
||||
if (!read_line(f_in, line, sizeof(line)-1)) {
|
||||
@@ -185,8 +191,8 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
}
|
||||
io_printf(f_out, "\n");
|
||||
|
||||
if (remote_version < 23) {
|
||||
if (remote_version == 22 || (remote_version > 17 && !am_sender))
|
||||
if (protocol_version < 23) {
|
||||
if (protocol_version == 22 || (protocol_version > 17 && !am_sender))
|
||||
io_start_multiplex_in(f_in);
|
||||
}
|
||||
|
||||
@@ -214,7 +220,6 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int remote_version;
|
||||
extern int am_root;
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
@@ -239,19 +244,20 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
} else {
|
||||
rprintf(FERROR,"max connections (%d) reached\n",
|
||||
lp_max_connections(i));
|
||||
io_printf(f_out, "@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i));
|
||||
io_printf(f_out, "@ERROR: max connections (%d) reached - try again later\n",
|
||||
lp_max_connections(i));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
auth_user = auth_server(f_in, f_out, i, addr, "@RSYNCD: AUTHREQD ");
|
||||
|
||||
if (!auth_user) {
|
||||
rprintf(FERROR,"auth failed on module %s from %s (%s)\n",
|
||||
name, host, addr);
|
||||
io_printf(f_out, "@ERROR: auth failed on module %s\n", name);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
module_id = i;
|
||||
@@ -265,7 +271,7 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
rprintf(FERROR,"Invalid uid %s\n", p);
|
||||
io_printf(f_out, "@ERROR: invalid uid %s\n", p);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
uid = atoi(p);
|
||||
}
|
||||
|
||||
@@ -275,29 +281,35 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
rprintf(FERROR,"Invalid gid %s\n", p);
|
||||
io_printf(f_out, "@ERROR: invalid gid %s\n", p);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
gid = atoi(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: If we're not root, but the configuration requests
|
||||
* that we change to some uid other than the current one, then
|
||||
* log a warning. */
|
||||
|
||||
/* TODO: Perhaps take a list of gids, and make them into the
|
||||
* supplementary groups. */
|
||||
/* TODO: If we're not root, but the configuration requests
|
||||
* that we change to some uid other than the current one, then
|
||||
* log a warning. */
|
||||
|
||||
/* TODO: Perhaps take a list of gids, and make them into the
|
||||
* supplementary groups. */
|
||||
|
||||
exclude_path_prefix = use_chroot? "" : lp_path(i);
|
||||
if (*exclude_path_prefix == '/' && !exclude_path_prefix[1])
|
||||
exclude_path_prefix = "";
|
||||
|
||||
p = lp_include_from(i);
|
||||
add_exclude_file(p, 1, 1);
|
||||
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_INCLUDE);
|
||||
|
||||
p = lp_include(i);
|
||||
add_include_line(p);
|
||||
add_exclude_line(&server_exclude_list, p, ADD_INCLUDE);
|
||||
|
||||
p = lp_exclude_from(i);
|
||||
add_exclude_file(p, 1, 0);
|
||||
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_EXCLUDE);
|
||||
|
||||
p = lp_exclude(i);
|
||||
add_exclude_line(p);
|
||||
add_exclude_line(&server_exclude_list, p, ADD_EXCLUDE);
|
||||
|
||||
exclude_path_prefix = NULL;
|
||||
|
||||
log_init();
|
||||
|
||||
@@ -321,7 +333,7 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
}
|
||||
|
||||
if (!push_dir("/", 0)) {
|
||||
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
|
||||
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
|
||||
io_printf(f_out, "@ERROR: chdir failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -336,16 +348,6 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
}
|
||||
|
||||
if (am_root) {
|
||||
#ifdef HAVE_SETGROUPS
|
||||
/* Get rid of any supplementary groups this process
|
||||
* might have inheristed. */
|
||||
if (setgroups(0, NULL)) {
|
||||
rsyserr(FERROR, errno, "setgroups failed");
|
||||
io_printf(f_out, "@ERROR: setgroups failed\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXXX: You could argue that if the daemon is started
|
||||
* by a non-root user and they explicitly specify a
|
||||
* gid, then we should try to change to that gid --
|
||||
@@ -361,6 +363,15 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
io_printf(f_out, "@ERROR: setgid failed\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_SETGROUPS
|
||||
/* Get rid of any supplementary groups this process
|
||||
* might have inheristed. */
|
||||
if (setgroups(1, &gid)) {
|
||||
rsyserr(FERROR, errno, "setgroups failed");
|
||||
io_printf(f_out, "@ERROR: setgroups failed\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (setuid(uid)) {
|
||||
rsyserr(FERROR, errno, "setuid %d failed", (int) uid);
|
||||
@@ -421,9 +432,12 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
}
|
||||
}
|
||||
|
||||
argp = argv;
|
||||
argp = argv;
|
||||
ret = parse_arguments(&argc, (const char ***) &argp, 0);
|
||||
|
||||
if (filesfrom_fd == 0)
|
||||
filesfrom_fd = f_in;
|
||||
|
||||
if (request) {
|
||||
if (*auth_user) {
|
||||
rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n",
|
||||
@@ -442,22 +456,22 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
if (verbose > 1) verbose = 1;
|
||||
#endif
|
||||
|
||||
if (remote_version < 23) {
|
||||
if (remote_version == 22 || (remote_version > 17 && am_sender))
|
||||
if (protocol_version < 23) {
|
||||
if (protocol_version == 22 || (protocol_version > 17 && am_sender))
|
||||
io_start_multiplex_out(f_out);
|
||||
}
|
||||
|
||||
/* For later protocol versions, we don't start multiplexing
|
||||
* until we've configured nonblocking in start_server. That
|
||||
* means we're in a sticky situation now: there's no way to
|
||||
* convey errors to the client. */
|
||||
|
||||
/* FIXME: Hold off on reporting option processing errors until
|
||||
* we've set up nonblocking and multiplexed IO and can get the
|
||||
* message back to them. */
|
||||
/* For later protocol versions, we don't start multiplexing
|
||||
* until we've configured nonblocking in start_server. That
|
||||
* means we're in a sticky situation now: there's no way to
|
||||
* convey errors to the client. */
|
||||
|
||||
/* FIXME: Hold off on reporting option processing errors until
|
||||
* we've set up nonblocking and multiplexed IO and can get the
|
||||
* message back to them. */
|
||||
if (!ret) {
|
||||
option_error();
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
option_error();
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (lp_timeout(i)) {
|
||||
@@ -476,13 +490,12 @@ static void send_listing(int fd)
|
||||
{
|
||||
int n = lp_numservices();
|
||||
int i;
|
||||
extern int remote_version;
|
||||
|
||||
for (i=0;i<n;i++)
|
||||
if (lp_list(i))
|
||||
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
|
||||
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
|
||||
|
||||
if (remote_version >= 25)
|
||||
if (protocol_version >= 25)
|
||||
io_printf(fd,"@RSYNCD: EXIT\n");
|
||||
}
|
||||
|
||||
@@ -495,7 +508,6 @@ int start_daemon(int f_in, int f_out)
|
||||
char *motd;
|
||||
int i = -1;
|
||||
extern char *config_file;
|
||||
extern int remote_version;
|
||||
extern int am_server;
|
||||
|
||||
if (!lp_load(config_file, 0)) {
|
||||
@@ -530,10 +542,12 @@ int start_daemon(int f_in, int f_out)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf(line,"@RSYNCD: %d", &remote_version) != 1) {
|
||||
if (sscanf(line,"@RSYNCD: %d", &remote_protocol) != 1) {
|
||||
io_printf(f_out, "@ERROR: protocol startup error\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (protocol_version > remote_protocol)
|
||||
protocol_version = remote_protocol;
|
||||
|
||||
while (i == -1) {
|
||||
line[0] = 0;
|
||||
@@ -544,7 +558,7 @@ int start_daemon(int f_in, int f_out)
|
||||
if (!*line || strcmp(line,"#list")==0) {
|
||||
send_listing(f_out);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*line == '#') {
|
||||
/* it's some sort of command that I don't understand */
|
||||
@@ -574,10 +588,10 @@ int daemon_main(void)
|
||||
int i;
|
||||
|
||||
/* we are running via inetd - close off stdout and
|
||||
stderr so that library functions (and getopt) don't
|
||||
try to use them. Redirect them to /dev/null */
|
||||
* stderr so that library functions (and getopt) don't
|
||||
* try to use them. Redirect them to /dev/null */
|
||||
for (i=1;i<3;i++) {
|
||||
close(i);
|
||||
close(i);
|
||||
open("/dev/null", O_RDWR);
|
||||
}
|
||||
|
||||
@@ -585,7 +599,7 @@ int daemon_main(void)
|
||||
}
|
||||
|
||||
if (!no_detach)
|
||||
become_daemon();
|
||||
become_daemon();
|
||||
|
||||
if (!lp_load(config_file, 1)) {
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -594,11 +608,10 @@ int daemon_main(void)
|
||||
log_init();
|
||||
|
||||
rprintf(FINFO, "rsyncd version %s starting, listening on port %d\n",
|
||||
RSYNC_VERSION,
|
||||
rsync_port);
|
||||
/* TODO: If listening on a particular address, then show that
|
||||
* address too. In fact, why not just do inet_ntop on the
|
||||
* local address??? */
|
||||
RSYNC_VERSION, rsync_port);
|
||||
/* TODO: If listening on a particular address, then show that
|
||||
* address too. In fact, why not just do inet_ntop on the
|
||||
* local address??? */
|
||||
|
||||
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
|
||||
char pidbuf[16];
|
||||
@@ -607,9 +620,9 @@ int daemon_main(void)
|
||||
cleanup_set_pid(pid);
|
||||
if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
|
||||
0666 & ~orig_umask)) == -1) {
|
||||
cleanup_set_pid(0);
|
||||
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
cleanup_set_pid(0);
|
||||
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
snprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
|
||||
write(fd, pidbuf, strlen(pidbuf));
|
||||
@@ -619,4 +632,3 @@ int daemon_main(void)
|
||||
start_accept_loop(rsync_port, start_daemon);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
67
compat.c
67
compat.c
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
int remote_protocol = 0;
|
||||
|
||||
extern int am_server;
|
||||
|
||||
extern int preserve_links;
|
||||
@@ -37,43 +39,58 @@ extern int always_checksum;
|
||||
extern int checksum_seed;
|
||||
|
||||
|
||||
extern int remote_version;
|
||||
extern int protocol_version;
|
||||
extern int verbose;
|
||||
|
||||
extern int read_batch; /* dw */
|
||||
extern int write_batch; /* dw */
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
|
||||
void setup_protocol(int f_out,int f_in)
|
||||
{
|
||||
if (remote_version == 0) {
|
||||
if (remote_protocol == 0) {
|
||||
if (am_server) {
|
||||
remote_version = read_int(f_in);
|
||||
write_int(f_out,PROTOCOL_VERSION);
|
||||
remote_protocol = read_int(f_in);
|
||||
write_int(f_out, protocol_version);
|
||||
} else {
|
||||
write_int(f_out,PROTOCOL_VERSION);
|
||||
remote_version = read_int(f_in);
|
||||
write_int(f_out, protocol_version);
|
||||
remote_protocol = read_int(f_in);
|
||||
}
|
||||
if (protocol_version > remote_protocol)
|
||||
protocol_version = remote_protocol;
|
||||
}
|
||||
|
||||
if (remote_version < MIN_PROTOCOL_VERSION ||
|
||||
remote_version > MAX_PROTOCOL_VERSION) {
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n",
|
||||
am_server? "Server" : "Client", remote_protocol, protocol_version);
|
||||
}
|
||||
if (remote_protocol < MIN_PROTOCOL_VERSION
|
||||
|| remote_protocol > MAX_PROTOCOL_VERSION) {
|
||||
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
|
||||
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (remote_version >= 12) {
|
||||
if (am_server) {
|
||||
if (read_batch || write_batch) /* dw */
|
||||
checksum_seed = 32761;
|
||||
else
|
||||
checksum_seed = time(NULL);
|
||||
write_int(f_out,checksum_seed);
|
||||
} else {
|
||||
checksum_seed = read_int(f_in);
|
||||
}
|
||||
}
|
||||
|
||||
checksum_init();
|
||||
}
|
||||
if (remote_protocol < OLD_PROTOCOL_VERSION) {
|
||||
rprintf(FINFO,"%s is very old version of rsync, upgrade recommended.\n",
|
||||
am_server? "Client" : "Server");
|
||||
}
|
||||
if (protocol_version < MIN_PROTOCOL_VERSION) {
|
||||
rprintf(FERROR, "--protocol must be at least %d on the %s.\n",
|
||||
MIN_PROTOCOL_VERSION, am_server? "Server" : "Client");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (protocol_version > PROTOCOL_VERSION) {
|
||||
rprintf(FERROR, "--protocol must be no more than %d on the %s.\n",
|
||||
PROTOCOL_VERSION, am_server? "Server" : "Client");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (am_server) {
|
||||
if (read_batch || write_batch)
|
||||
checksum_seed = 32761;
|
||||
else
|
||||
checksum_seed = time(NULL);
|
||||
write_int(f_out,checksum_seed);
|
||||
} else {
|
||||
checksum_seed = read_int(f_in);
|
||||
}
|
||||
}
|
||||
|
||||
35
configure.in
35
configure.in
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
RSYNC_VERSION=2.5.6
|
||||
RSYNC_VERSION=2.6.0pre2
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -90,14 +90,14 @@ AC_ARG_WITH(included-popt,
|
||||
[ --with-included-popt use bundled popt library, not from system])
|
||||
|
||||
AC_ARG_WITH(rsync-path,
|
||||
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: \"rsync\")],
|
||||
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: rsync)],
|
||||
[ RSYNC_PATH="$with_rsync_path" ],
|
||||
[ RSYNC_PATH="rsync" ])
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
|
||||
|
||||
AC_ARG_WITH(rsh,
|
||||
AC_HELP_STRING([--with-rsh=CMD], [set rsh command to CMD (default: \"remsh\" or \"rsh\")]))
|
||||
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
|
||||
|
||||
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
|
||||
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
|
||||
@@ -105,11 +105,8 @@ AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
|
||||
if test x"$with_rsh" != x
|
||||
then
|
||||
RSYNC_RSH="$with_rsh"
|
||||
elif test x"$HAVE_REMSH" = x1
|
||||
then
|
||||
RSYNC_RSH="remsh"
|
||||
else
|
||||
RSYNC_RSH="rsh"
|
||||
RSYNC_RSH="ssh"
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
@@ -429,15 +426,6 @@ if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SOCKETPAIR, 1, [ ])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for working fnmatch],rsync_cv_HAVE_FNMATCH,[
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
main() { exit((fnmatch("*.o", "x.o", FNM_PATHNAME) == 0 &&
|
||||
fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME) != 0) ? 0: 1); }],
|
||||
rsync_cv_HAVE_FNMATCH=yes,rsync_cv_HAVE_FNMATCH=no,rsync_cv_HAVE_FNMATCH=cross)])
|
||||
if test x"$rsync_cv_HAVE_FNMATCH" = x"yes"; then
|
||||
AC_DEFINE(HAVE_FNMATCH, 1, [ ])
|
||||
fi
|
||||
|
||||
if test x"$with_included_popt" != x"yes"
|
||||
then
|
||||
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
|
||||
@@ -636,6 +624,21 @@ AC_SUBST(BUILD_POPT)
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
if test x"$with_rsh" = x; then
|
||||
if test x"$HAVE_REMSH" = x1; then
|
||||
rmsh1='remsh:'
|
||||
rmsh2='=remsh'
|
||||
else
|
||||
rmsh1='rsh: '
|
||||
rmsh2='=rsh '
|
||||
fi
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ **********************************************************************])
|
||||
AC_MSG_RESULT([ * As of v2.6.0, the default remote shell is ssh instead of rsh!! *])
|
||||
AC_MSG_RESULT([ * To use previous default of $rmsh1 ./configure --with-rsh$rmsh2 *])
|
||||
AC_MSG_RESULT([ **********************************************************************])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
/*
|
||||
* error codes returned by rsync. If you change these, please also update the
|
||||
* string mappings in log.c
|
||||
* string mappings in log.c and the EXIT VALUES in rsync.yo
|
||||
*/
|
||||
|
||||
#define RERR_OK 0
|
||||
#define RERR_SYNTAX 1 /* syntax or usage error */
|
||||
#define RERR_PROTOCOL 2 /* protocol incompatibility */
|
||||
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_STARTCLIENT 5 /* error starting client-server protocol */
|
||||
|
||||
#define RERR_SOCKETIO 10 /* error in socket IO */
|
||||
@@ -39,6 +39,7 @@
|
||||
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
|
||||
#define RERR_MALLOC 22 /* error allocating core memory buffers */
|
||||
#define RERR_PARTIAL 23 /* partial transfer */
|
||||
#define RERR_VANISHED 24 /* file(s) vanished on sender side */
|
||||
|
||||
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
|
||||
|
||||
|
||||
393
exclude.c
393
exclude.c
@@ -1,19 +1,19 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
*
|
||||
* Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 by Paul Mackerras
|
||||
* Copyright (C) 2002 by Martin Pool
|
||||
*
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -27,16 +27,20 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int delete_mode;
|
||||
|
||||
static struct exclude_struct **exclude_list;
|
||||
struct exclude_struct **exclude_list;
|
||||
struct exclude_struct **local_exclude_list;
|
||||
struct exclude_struct **server_exclude_list;
|
||||
char *exclude_path_prefix = NULL;
|
||||
|
||||
/** Build an exclude structure given a exclude pattern */
|
||||
static struct exclude_struct *make_exclude(const char *pattern, int include)
|
||||
{
|
||||
struct exclude_struct *ret;
|
||||
char *cp;
|
||||
int pat_len;
|
||||
|
||||
ret = (struct exclude_struct *)malloc(sizeof(*ret));
|
||||
ret = new(struct exclude_struct);
|
||||
if (!ret) out_of_memory("make_exclude");
|
||||
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
@@ -50,33 +54,37 @@ static struct exclude_struct *make_exclude(const char *pattern, int include)
|
||||
ret->include = include;
|
||||
}
|
||||
|
||||
ret->pattern = strdup(pattern);
|
||||
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
|
||||
if (strpbrk(pattern, "*[?")) {
|
||||
ret->regular_exp = 1;
|
||||
ret->fnmatch_flags = FNM_PATHNAME;
|
||||
if (strstr(pattern, "**")) {
|
||||
static int tested;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME)==0) {
|
||||
rprintf(FERROR,"WARNING: fnmatch FNM_PATHNAME is broken on your system\n");
|
||||
}
|
||||
}
|
||||
ret->fnmatch_flags = 0;
|
||||
}
|
||||
if (exclude_path_prefix)
|
||||
ret->match_flags |= MATCHFLG_ABS_PATH;
|
||||
if (exclude_path_prefix && *pattern == '/') {
|
||||
ret->pattern = new_array(char,
|
||||
strlen(exclude_path_prefix) + strlen(pattern) + 1);
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
sprintf(ret->pattern, "%s%s", exclude_path_prefix, pattern);
|
||||
}
|
||||
else {
|
||||
ret->pattern = strdup(pattern);
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
}
|
||||
|
||||
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
|
||||
ret->pattern[strlen(pattern)-1] = 0;
|
||||
if (strpbrk(pattern, "*[?")) {
|
||||
ret->match_flags |= MATCHFLG_WILD;
|
||||
if (strstr(pattern, "**")) {
|
||||
ret->match_flags |= MATCHFLG_WILD2;
|
||||
/* If the pattern starts with **, note that. */
|
||||
if (*pattern == '*' && pattern[1] == '*')
|
||||
ret->match_flags |= MATCHFLG_WILD2_PREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
pat_len = strlen(ret->pattern);
|
||||
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
|
||||
ret->pattern[pat_len-1] = 0;
|
||||
ret->directory = 1;
|
||||
}
|
||||
|
||||
if (!strchr(ret->pattern,'/')) {
|
||||
ret->local = 1;
|
||||
}
|
||||
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
|
||||
ret->slash_cnt++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -88,35 +96,98 @@ static void free_exclude(struct exclude_struct *ex)
|
||||
free(ex);
|
||||
}
|
||||
|
||||
|
||||
void free_exclude_list(struct exclude_struct ***listp)
|
||||
{
|
||||
struct exclude_struct **list = *listp;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"clearing exclude list\n");
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
while (*list)
|
||||
free_exclude(*list++);
|
||||
|
||||
free(*listp);
|
||||
*listp = NULL;
|
||||
}
|
||||
|
||||
static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
STRUCT_STAT *st)
|
||||
int name_is_dir)
|
||||
{
|
||||
char *p;
|
||||
int match_start=0;
|
||||
int match_start = 0;
|
||||
char *pattern = ex->pattern;
|
||||
|
||||
if (ex->local && (p=strrchr(name,'/')))
|
||||
name = p+1;
|
||||
/* If the pattern does not have any slashes AND it does not have
|
||||
* a "**" (which could match a slash), then we just match the
|
||||
* name portion of the path. */
|
||||
if (!ex->slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {
|
||||
if ((p = strrchr(name,'/')) != NULL)
|
||||
name = p+1;
|
||||
}
|
||||
else if ((ex->match_flags & MATCHFLG_ABS_PATH) && *name != '/') {
|
||||
static char full_name[MAXPATHLEN];
|
||||
extern char curr_dir[];
|
||||
int plus = curr_dir[1] == '\0'? 1 : 0;
|
||||
snprintf(full_name, sizeof full_name,
|
||||
"%s/%s", curr_dir+plus, name);
|
||||
name = full_name;
|
||||
}
|
||||
|
||||
if (!name[0]) return 0;
|
||||
|
||||
if (ex->directory && !S_ISDIR(st->st_mode)) return 0;
|
||||
if (ex->directory && !name_is_dir) return 0;
|
||||
|
||||
if (*pattern == '/' && *name != '/') {
|
||||
if (*pattern == '/') {
|
||||
match_start = 1;
|
||||
pattern++;
|
||||
if (*name == '/')
|
||||
name++;
|
||||
}
|
||||
|
||||
if (ex->regular_exp) {
|
||||
if (fnmatch(pattern, name, ex->fnmatch_flags) == 0) {
|
||||
return 1;
|
||||
if (ex->match_flags & MATCHFLG_WILD) {
|
||||
/* A non-anchored match with an infix slash and no "**"
|
||||
* needs to match the last slash_cnt+1 name elements. */
|
||||
if (!match_start && ex->slash_cnt &&
|
||||
!(ex->match_flags & MATCHFLG_WILD2)) {
|
||||
int cnt = ex->slash_cnt + 1;
|
||||
for (p = name + strlen(name) - 1; p >= name; p--) {
|
||||
if (*p == '/' && !--cnt)
|
||||
break;
|
||||
}
|
||||
name = p+1;
|
||||
}
|
||||
if (wildmatch(pattern, name))
|
||||
return 1;
|
||||
if (ex->match_flags & MATCHFLG_WILD2_PREFIX) {
|
||||
/* If the **-prefixed pattern has a '/' as the next
|
||||
* character, then try to match the rest of the
|
||||
* pattern at the root. */
|
||||
if (pattern[2] == '/' && wildmatch(pattern+3, name))
|
||||
return 1;
|
||||
}
|
||||
else if (!match_start && ex->match_flags & MATCHFLG_WILD2) {
|
||||
/* A non-anchored match with an infix or trailing "**"
|
||||
* (but not a prefixed "**") needs to try matching
|
||||
* after every slash. */
|
||||
while ((name = strchr(name, '/')) != NULL) {
|
||||
name++;
|
||||
if (wildmatch(pattern, name))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (match_start) {
|
||||
if (strcmp(name,pattern) == 0)
|
||||
return 1;
|
||||
} else {
|
||||
int l1 = strlen(name);
|
||||
int l2 = strlen(pattern);
|
||||
if (l2 <= l1 &&
|
||||
if (l2 <= l1 &&
|
||||
strcmp(name+(l1-l2),pattern) == 0 &&
|
||||
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/'))) {
|
||||
(l1==l2 || name[l1-(l2+1)] == '/')) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -127,18 +198,18 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
|
||||
static void report_exclude_result(char const *name,
|
||||
struct exclude_struct const *ent,
|
||||
STRUCT_STAT const *st)
|
||||
int name_is_dir)
|
||||
{
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by make_exclude. So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (verbose >= 2)
|
||||
rprintf(FINFO, "%s %s %s because of pattern %s%s\n",
|
||||
ent->include ? "including" : "excluding",
|
||||
S_ISDIR(st->st_mode) ? "directory" : "file",
|
||||
name, ent->pattern,
|
||||
ent->directory ? "/" : "");
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by make_exclude. So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (verbose >= 2)
|
||||
rprintf(FINFO, "%s %s %s because of pattern %s%s\n",
|
||||
ent->include ? "including" : "excluding",
|
||||
name_is_dir ? "directory" : "file",
|
||||
name, ent->pattern,
|
||||
ent->directory ? "/" : "");
|
||||
}
|
||||
|
||||
|
||||
@@ -146,136 +217,114 @@ static void report_exclude_result(char const *name,
|
||||
* Return true if file NAME is defined to be excluded by either
|
||||
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
|
||||
*/
|
||||
int check_exclude(char *name, struct exclude_struct **local_exclude_list,
|
||||
STRUCT_STAT *st)
|
||||
int check_exclude(struct exclude_struct **list, char *name, int name_is_dir)
|
||||
{
|
||||
int n;
|
||||
struct exclude_struct *ent;
|
||||
struct exclude_struct *ent;
|
||||
|
||||
if (name && (name[0] == '.') && !name[1])
|
||||
/* never exclude '.', even if somebody does --exclude '*' */
|
||||
return 0;
|
||||
|
||||
if (exclude_list) {
|
||||
for (n=0; exclude_list[n]; n++) {
|
||||
ent = exclude_list[n];
|
||||
if (check_one_exclude(name, ent, st)) {
|
||||
report_exclude_result(name, ent, st);
|
||||
return !ent->include;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (local_exclude_list) {
|
||||
for (n=0; local_exclude_list[n]; n++) {
|
||||
ent = local_exclude_list[n];
|
||||
if (check_one_exclude(name, ent, st)) {
|
||||
report_exclude_result(name, ent, st);
|
||||
return !ent->include;
|
||||
}
|
||||
}
|
||||
while ((ent = *list++) != NULL) {
|
||||
if (check_one_exclude(name, ent, name_is_dir)) {
|
||||
report_exclude_result(name, ent, name_is_dir);
|
||||
return !ent->include;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
|
||||
void add_exclude(struct exclude_struct ***listp, const char *pattern, int include)
|
||||
{
|
||||
int len=0;
|
||||
if (list && *list)
|
||||
for (; (*list)[len]; len++) ;
|
||||
struct exclude_struct **list = *listp;
|
||||
int len = 0;
|
||||
|
||||
if (strcmp(pattern,"!") == 0) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"clearing exclude list\n");
|
||||
while ((len)--) {
|
||||
free_exclude((*list)[len]);
|
||||
if (*pattern == '!' && !pattern[1]) {
|
||||
free_exclude_list(listp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (list)
|
||||
for (; list[len]; len++) {}
|
||||
|
||||
list = *listp = realloc_array(list, struct exclude_struct *, len+2);
|
||||
|
||||
if (!list || !(list[len] = make_exclude(pattern, include)))
|
||||
out_of_memory("add_exclude");
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"add_exclude(%s,%s)\n",pattern,
|
||||
include ? "include" : "exclude");
|
||||
}
|
||||
|
||||
list[len+1] = NULL;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(struct exclude_struct ***listp, const char *fname,
|
||||
int fatal, int include)
|
||||
{
|
||||
int fd;
|
||||
char line[MAXPATHLEN];
|
||||
char *eob = line + MAXPATHLEN - 1;
|
||||
extern int eol_nulls;
|
||||
|
||||
if (!fname || !*fname)
|
||||
return;
|
||||
|
||||
if (*fname != '-' || fname[1])
|
||||
fd = open(fname, O_RDONLY|O_BINARY);
|
||||
else
|
||||
fd = 0;
|
||||
if (fd < 0) {
|
||||
if (fatal) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to open %s file %s",
|
||||
include ? "include" : "exclude",
|
||||
fname);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
free((*list));
|
||||
*list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*list = (struct exclude_struct **)Realloc(*list,sizeof(struct exclude_struct *)*(len+2));
|
||||
|
||||
if (!*list || !((*list)[len] = make_exclude(pattern, include)))
|
||||
out_of_memory("add_exclude");
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"add_exclude(%s,%s)\n",pattern,
|
||||
include ? "include" : "exclude");
|
||||
}
|
||||
|
||||
(*list)[len+1] = NULL;
|
||||
}
|
||||
|
||||
void add_exclude(const char *pattern, int include)
|
||||
{
|
||||
add_exclude_list(pattern,&exclude_list, include);
|
||||
}
|
||||
|
||||
struct exclude_struct **make_exclude_list(const char *fname,
|
||||
struct exclude_struct **list1,
|
||||
int fatal, int include)
|
||||
{
|
||||
struct exclude_struct **list=list1;
|
||||
FILE *f;
|
||||
char line[MAXPATHLEN];
|
||||
|
||||
if (strcmp(fname, "-")) {
|
||||
f = fopen(fname,"r");
|
||||
} else {
|
||||
f = fdopen(0, "r");
|
||||
}
|
||||
if (!f) {
|
||||
if (fatal) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to open %s file %s",
|
||||
include ? "include" : "exclude",
|
||||
fname);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
while (1) {
|
||||
char ch, *s = line;
|
||||
int cnt;
|
||||
while (1) {
|
||||
if ((cnt = read(fd, &ch, 1)) <= 0) {
|
||||
if (cnt < 0 && errno == EINTR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
|
||||
break;
|
||||
if (s < eob)
|
||||
*s++ = ch;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
while (fgets(line,MAXPATHLEN,f)) {
|
||||
int l = strlen(line);
|
||||
while (l && (line[l-1] == '\n' || line[l-1] == '\r')) l--;
|
||||
line[l] = 0;
|
||||
if (line[0] && (line[0] != ';') && (line[0] != '#')) {
|
||||
*s = '\0';
|
||||
if (*line && *line != ';' && *line != '#') {
|
||||
/* Skip lines starting with semicolon or pound.
|
||||
It probably wouldn't cause any harm to not skip
|
||||
them but there's no need to save them. */
|
||||
add_exclude_list(line,&list,include);
|
||||
* It probably wouldn't cause any harm to not skip
|
||||
* them but there's no need to save them. */
|
||||
add_exclude(listp, line, include);
|
||||
}
|
||||
if (cnt <= 0)
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(const char *fname, int fatal, int include)
|
||||
{
|
||||
if (!fname || !*fname) return;
|
||||
|
||||
exclude_list = make_exclude_list(fname,exclude_list,fatal,include);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
void send_exclude_list(int f)
|
||||
{
|
||||
int i;
|
||||
extern int remote_version;
|
||||
extern int protocol_version;
|
||||
extern int list_only, recurse;
|
||||
|
||||
/* This is a complete hack - blame Rusty.
|
||||
*
|
||||
* FIXME: This pattern shows up in the output of
|
||||
* report_exclude_result(), which is not ideal. */
|
||||
if (list_only && !recurse) {
|
||||
add_exclude("/*/*", 0);
|
||||
}
|
||||
if (list_only && !recurse)
|
||||
add_exclude(&exclude_list, "/*/*", ADD_EXCLUDE);
|
||||
|
||||
if (!exclude_list) {
|
||||
write_int(f,0);
|
||||
@@ -286,13 +335,13 @@ void send_exclude_list(int f)
|
||||
int l;
|
||||
char pattern[MAXPATHLEN];
|
||||
|
||||
strlcpy(pattern,exclude_list[i]->pattern,sizeof(pattern));
|
||||
strlcpy(pattern,exclude_list[i]->pattern,sizeof(pattern));
|
||||
if (exclude_list[i]->directory) strlcat(pattern,"/", sizeof(pattern));
|
||||
|
||||
l = strlen(pattern);
|
||||
if (l == 0) continue;
|
||||
if (exclude_list[i]->include) {
|
||||
if (remote_version < 19) {
|
||||
if (protocol_version < 19) {
|
||||
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
@@ -302,7 +351,7 @@ void send_exclude_list(int f)
|
||||
write_int(f,l);
|
||||
}
|
||||
write_buf(f,pattern,l);
|
||||
}
|
||||
}
|
||||
|
||||
write_int(f,0);
|
||||
}
|
||||
@@ -316,7 +365,7 @@ void recv_exclude_list(int f)
|
||||
while ((l=read_int(f))) {
|
||||
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
|
||||
read_sbuf(f,line,l);
|
||||
add_exclude(line,0);
|
||||
add_exclude(&exclude_list, line, ADD_EXCLUDE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +401,7 @@ char *get_exclude_tok(char *p)
|
||||
/* Is this a '+' or '-' followed by a space (not whitespace)? */
|
||||
if ((*s=='+' || *s=='-') && *(s+1)==' ')
|
||||
s+=2;
|
||||
|
||||
|
||||
/* Skip to the next space or the end of the string */
|
||||
while (!isspace(* (unsigned char *) s) && *s != '\0')
|
||||
s++;
|
||||
@@ -368,26 +417,16 @@ char *get_exclude_tok(char *p)
|
||||
return(t);
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_line(char *p)
|
||||
{
|
||||
char *tok;
|
||||
if (!p || !*p) return;
|
||||
p = strdup(p);
|
||||
if (!p) out_of_memory("add_exclude_line");
|
||||
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
|
||||
add_exclude(tok, 0);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void add_include_line(char *p)
|
||||
void add_exclude_line(struct exclude_struct ***listp,
|
||||
const char *line, int include)
|
||||
{
|
||||
char *tok;
|
||||
if (!p || !*p) return;
|
||||
p = strdup(p);
|
||||
if (!p) out_of_memory("add_include_line");
|
||||
char *tok, *p;
|
||||
if (!line || !*line) return;
|
||||
p = strdup(line);
|
||||
if (!p) out_of_memory("add_exclude_line");
|
||||
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
|
||||
add_exclude(tok, 1);
|
||||
add_exclude(listp, tok, include);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@@ -405,14 +444,14 @@ void add_cvs_excludes(void)
|
||||
char fname[MAXPATHLEN];
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
|
||||
for (i=0; cvs_ignore_list[i]; i++)
|
||||
add_exclude(cvs_ignore_list[i], 0);
|
||||
add_exclude(&exclude_list, cvs_ignore_list[i], ADD_EXCLUDE);
|
||||
|
||||
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
|
||||
snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
|
||||
add_exclude_file(fname,0,0);
|
||||
add_exclude_file(&exclude_list,fname,MISSING_OK,ADD_EXCLUDE);
|
||||
}
|
||||
|
||||
add_exclude_line(getenv("CVSIGNORE"));
|
||||
add_exclude_line(&exclude_list, getenv("CVSIGNORE"), ADD_EXCLUDE);
|
||||
}
|
||||
|
||||
37
fileio.c
37
fileio.c
@@ -69,19 +69,22 @@ static int write_sparse(int f,char *buf,size_t len)
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* write_file does not allow incomplete writes. It loops internally
|
||||
* until len bytes are written or errno is set.
|
||||
*/
|
||||
int write_file(int f,char *buf,size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!sparse_files) {
|
||||
return write(f,buf,len);
|
||||
}
|
||||
|
||||
while (len>0) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
int r1 = write_sparse(f, buf, len1);
|
||||
int r1;
|
||||
if (sparse_files) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
r1 = write_sparse(f, buf, len1);
|
||||
} else {
|
||||
r1 = write(f, buf, len);
|
||||
}
|
||||
if (r1 <= 0) {
|
||||
if (ret > 0) return ret;
|
||||
return r1;
|
||||
@@ -102,7 +105,7 @@ int write_file(int f,char *buf,size_t len)
|
||||
struct map_struct *map_file(int fd,OFF_T len)
|
||||
{
|
||||
struct map_struct *map;
|
||||
map = (struct map_struct *)malloc(sizeof(*map));
|
||||
map = new(struct map_struct);
|
||||
if (!map) out_of_memory("map_file");
|
||||
|
||||
map->fd = fd;
|
||||
@@ -112,6 +115,7 @@ struct map_struct *map_file(int fd,OFF_T len)
|
||||
map->p_offset = 0;
|
||||
map->p_fd_offset = 0;
|
||||
map->p_len = 0;
|
||||
map->status = 0;
|
||||
|
||||
return map;
|
||||
}
|
||||
@@ -156,7 +160,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
|
||||
/* make sure we have allocated enough memory for the window */
|
||||
if (window_size > map->p_size) {
|
||||
map->p = (char *)Realloc(map->p, window_size);
|
||||
map->p = realloc_array(map->p, char, window_size);
|
||||
if (!map->p) out_of_memory("map_ptr");
|
||||
map->p_size = window_size;
|
||||
}
|
||||
@@ -188,7 +192,11 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
}
|
||||
|
||||
if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
|
||||
if (nread < 0) nread = 0;
|
||||
if (nread < 0) {
|
||||
nread = 0;
|
||||
if (!map->status)
|
||||
map->status = errno;
|
||||
}
|
||||
/* the best we can do is zero the buffer - the file
|
||||
has changed mid transfer! */
|
||||
memset(map->p+read_offset+nread, 0, read_size - nread);
|
||||
@@ -203,13 +211,18 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
}
|
||||
|
||||
|
||||
void unmap_file(struct map_struct *map)
|
||||
int unmap_file(struct map_struct *map)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (map->p) {
|
||||
free(map->p);
|
||||
map->p = NULL;
|
||||
}
|
||||
ret = map->status;
|
||||
memset(map, 0, sizeof(*map));
|
||||
free(map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
331
flist.c
331
flist.c
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -41,6 +41,8 @@ extern int always_checksum;
|
||||
extern int cvs_exclude;
|
||||
|
||||
extern int recurse;
|
||||
extern char *files_from;
|
||||
extern int filesfrom_fd;
|
||||
|
||||
extern int one_file_system;
|
||||
extern int make_backups;
|
||||
@@ -52,25 +54,29 @@ extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_times;
|
||||
extern int relative_paths;
|
||||
extern int implied_dirs;
|
||||
extern int copy_links;
|
||||
extern int copy_unsafe_links;
|
||||
extern int remote_version;
|
||||
extern int io_error;
|
||||
extern int protocol_version;
|
||||
extern int sanitize_paths;
|
||||
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
|
||||
static struct exclude_struct **local_exclude_list;
|
||||
extern struct exclude_struct **exclude_list;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
extern struct exclude_struct **local_exclude_list;
|
||||
|
||||
int io_error;
|
||||
|
||||
static struct file_struct null_file;
|
||||
|
||||
static void clean_flist(struct file_list *flist, int strip_root);
|
||||
static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
|
||||
|
||||
|
||||
static int show_filelist_p(void)
|
||||
{
|
||||
return verbose && recurse && !am_server;
|
||||
return verbose && (recurse || files_from) && !am_server;
|
||||
}
|
||||
|
||||
static void start_filelist_progress(char *kind)
|
||||
@@ -118,10 +124,10 @@ static struct string_area *string_area_new(int size)
|
||||
|
||||
if (size <= 0)
|
||||
size = ARENA_SIZE;
|
||||
a = malloc(sizeof(*a));
|
||||
a = new(struct string_area);
|
||||
if (!a)
|
||||
out_of_memory("string_area_new");
|
||||
a->current = a->base = malloc(size);
|
||||
a->current = a->base = new_array(char, size);
|
||||
if (!a->current)
|
||||
out_of_memory("string_area_new buffer");
|
||||
a->end = a->base + size;
|
||||
@@ -216,12 +222,12 @@ int readlink_stat(const char *path, STRUCT_STAT * buffer, char *linkbuf)
|
||||
if (S_ISLNK(buffer->st_mode)) {
|
||||
int l;
|
||||
l = readlink((char *) path, linkbuf, MAXPATHLEN - 1);
|
||||
if (l == -1)
|
||||
if (l == -1)
|
||||
return -1;
|
||||
linkbuf[l] = 0;
|
||||
if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) {
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
|
||||
rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
|
||||
path, linkbuf);
|
||||
}
|
||||
return do_stat(path, buffer);
|
||||
@@ -247,20 +253,37 @@ int link_stat(const char *path, STRUCT_STAT * buffer)
|
||||
}
|
||||
|
||||
/*
|
||||
This function is used to check if a file should be included/excluded
|
||||
from the list of files based on its name and type etc
|
||||
* This function is used to check if a file should be included/excluded
|
||||
* from the list of files based on its name and type etc. The value of
|
||||
* exclude_level is set to either SERVER_EXCLUDES or ALL_EXCLUDES.
|
||||
*/
|
||||
static int check_exclude_file(int f, char *fname, STRUCT_STAT * st)
|
||||
static int check_exclude_file(char *fname, int is_dir, int exclude_level)
|
||||
{
|
||||
extern int delete_excluded;
|
||||
|
||||
/* f is set to -1 when calculating deletion file list */
|
||||
if ((f == -1) && delete_excluded) {
|
||||
#if 0 /* This currently never happens, so avoid a useless compare. */
|
||||
if (exclude_level == NO_EXCLUDES)
|
||||
return 0;
|
||||
#endif
|
||||
if (fname) {
|
||||
/* never exclude '.', even if somebody does --exclude '*' */
|
||||
if (fname[0] == '.' && !fname[1])
|
||||
return 0;
|
||||
/* Handle the -R version of the '.' dir. */
|
||||
if (fname[0] == '/') {
|
||||
int len = strlen(fname);
|
||||
if (fname[len-1] == '.' && fname[len-2] == '/')
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (check_exclude(fname, local_exclude_list, st)) {
|
||||
if (server_exclude_list
|
||||
&& check_exclude(server_exclude_list, fname, is_dir))
|
||||
return 1;
|
||||
if (exclude_level != ALL_EXCLUDES)
|
||||
return 0;
|
||||
if (exclude_list && check_exclude(exclude_list, fname, is_dir))
|
||||
return 1;
|
||||
if (local_exclude_list
|
||||
&& check_exclude(local_exclude_list, fname, is_dir))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -305,27 +328,29 @@ static char *flist_dir;
|
||||
static void flist_expand(struct file_list *flist)
|
||||
{
|
||||
if (flist->count >= flist->malloced) {
|
||||
size_t new_bytes;
|
||||
void *new_ptr;
|
||||
|
||||
|
||||
if (flist->malloced < 1000)
|
||||
flist->malloced += 1000;
|
||||
else
|
||||
flist->malloced *= 2;
|
||||
|
||||
new_bytes = sizeof(flist->files[0]) * flist->malloced;
|
||||
|
||||
if (flist->files)
|
||||
new_ptr = realloc(flist->files, new_bytes);
|
||||
else
|
||||
new_ptr = malloc(new_bytes);
|
||||
if (flist->files) {
|
||||
new_ptr = realloc_array(flist->files,
|
||||
struct file_struct *,
|
||||
flist->malloced);
|
||||
} else {
|
||||
new_ptr = new_array(struct file_struct *,
|
||||
flist->malloced);
|
||||
}
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "expand file_list to %.0f bytes, did%s move\n",
|
||||
(double) new_bytes,
|
||||
(double)sizeof(flist->files[0])
|
||||
* flist->malloced,
|
||||
(new_ptr == flist->files) ? " not" : "");
|
||||
}
|
||||
|
||||
|
||||
flist->files = (struct file_struct **) new_ptr;
|
||||
|
||||
if (!flist->files)
|
||||
@@ -374,7 +399,7 @@ static void send_file_entry(struct file_struct *file, int f,
|
||||
|
||||
for (l1 = 0;
|
||||
lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);
|
||||
l1++);
|
||||
l1++) {}
|
||||
l2 = strlen(fname) - l1;
|
||||
|
||||
if (l1 > 0)
|
||||
@@ -424,7 +449,7 @@ static void send_file_entry(struct file_struct *file, int f,
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links && S_ISREG(file->mode)) {
|
||||
if (remote_version < 26) {
|
||||
if (protocol_version < 26) {
|
||||
/* 32-bit dev_t and ino_t */
|
||||
write_int(f, (int) file->dev);
|
||||
write_int(f, (int) file->inode);
|
||||
@@ -437,7 +462,7 @@ static void send_file_entry(struct file_struct *file, int f,
|
||||
#endif
|
||||
|
||||
if (always_checksum) {
|
||||
if (remote_version < 21) {
|
||||
if (protocol_version < 21) {
|
||||
write_buf(f, file->sum, 2);
|
||||
} else {
|
||||
write_buf(f, file->sum, MD4_SUM_LENGTH);
|
||||
@@ -480,7 +505,7 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
else
|
||||
l2 = read_byte(f);
|
||||
|
||||
file = (struct file_struct *) malloc(sizeof(*file));
|
||||
file = new(struct file_struct);
|
||||
if (!file)
|
||||
out_of_memory("receive_file_entry");
|
||||
memset((char *) file, 0, sizeof(*file));
|
||||
@@ -547,7 +572,7 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
rprintf(FERROR, "overflow: l=%d\n", l);
|
||||
overflow("receive_file_entry");
|
||||
}
|
||||
file->link = (char *) malloc(l + 1);
|
||||
file->link = new_array(char, l + 1);
|
||||
if (!file->link)
|
||||
out_of_memory("receive_file_entry 2");
|
||||
read_sbuf(f, file->link, l);
|
||||
@@ -557,7 +582,7 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
}
|
||||
#if SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links && S_ISREG(file->mode)) {
|
||||
if (remote_version < 26) {
|
||||
if (protocol_version < 26) {
|
||||
file->dev = read_int(f);
|
||||
file->inode = read_int(f);
|
||||
} else {
|
||||
@@ -568,10 +593,10 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
#endif
|
||||
|
||||
if (always_checksum) {
|
||||
file->sum = (char *) malloc(MD4_SUM_LENGTH);
|
||||
file->sum = new_array(char, MD4_SUM_LENGTH);
|
||||
if (!file->sum)
|
||||
out_of_memory("md4 sum");
|
||||
if (remote_version < 21) {
|
||||
if (protocol_version < 21) {
|
||||
read_buf(f, file->sum, 2);
|
||||
} else {
|
||||
read_buf(f, file->sum, MD4_SUM_LENGTH);
|
||||
@@ -638,8 +663,8 @@ static int skip_filesystem(char *fname, STRUCT_STAT * st)
|
||||
* statting directories if we're not recursing, but this is not a very
|
||||
* important case. Some systems may not have d_type.
|
||||
**/
|
||||
struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
int noexcludes)
|
||||
struct file_struct *make_file(char *fname, struct string_area **ap,
|
||||
int exclude_level)
|
||||
{
|
||||
struct file_struct *file;
|
||||
STRUCT_STAT st;
|
||||
@@ -661,27 +686,26 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
|
||||
if (readlink_stat(fname, &st, linkbuf) != 0) {
|
||||
int save_errno = errno;
|
||||
if ((errno == ENOENT) && !noexcludes) {
|
||||
/* either symlink pointing nowhere or file that
|
||||
if (errno == ENOENT && exclude_level != NO_EXCLUDES) {
|
||||
/* either symlink pointing nowhere or file that
|
||||
* was removed during rsync run; see if excluded
|
||||
* before reporting an error */
|
||||
memset((char *) &st, 0, sizeof(st));
|
||||
if (check_exclude_file(f, fname, &st)) {
|
||||
if (check_exclude_file(fname, 0, exclude_level)) {
|
||||
/* file is excluded anyway, ignore silently */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "readlink %s: %s\n",
|
||||
fname, strerror(save_errno));
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "readlink %s failed: %s\n",
|
||||
full_fname(fname), strerror(save_errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* we use noexcludes from backup.c */
|
||||
if (noexcludes)
|
||||
/* backup.c calls us with exclude_level set to NO_EXCLUDES. */
|
||||
if (exclude_level == NO_EXCLUDES)
|
||||
goto skip_excludes;
|
||||
|
||||
if (S_ISDIR(st.st_mode) && !recurse) {
|
||||
if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
|
||||
rprintf(FINFO, "skipping directory %s\n", fname);
|
||||
return NULL;
|
||||
}
|
||||
@@ -691,19 +715,18 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (check_exclude_file(f, fname, &st))
|
||||
if (check_exclude_file(fname, S_ISDIR(st.st_mode) != 0, exclude_level))
|
||||
return NULL;
|
||||
|
||||
|
||||
if (lp_ignore_nonreadable(module_id) && access(fname, R_OK) != 0)
|
||||
return NULL;
|
||||
|
||||
skip_excludes:
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "make_file(%d,%s)\n", f, fname);
|
||||
rprintf(FINFO, "make_file(%s,*,%d)\n", fname, exclude_level);
|
||||
|
||||
file = (struct file_struct *) malloc(sizeof(*file));
|
||||
file = new(struct file_struct);
|
||||
if (!file)
|
||||
out_of_memory("make_file");
|
||||
memset((char *) file, 0, sizeof(*file));
|
||||
@@ -779,8 +802,12 @@ void send_file_name(int f, struct file_list *flist, char *fname,
|
||||
int recursive, unsigned base_flags)
|
||||
{
|
||||
struct file_struct *file;
|
||||
extern int delete_excluded;
|
||||
|
||||
file = make_file(f, fname, &flist->string_area, 0);
|
||||
/* f is set to -1 when calculating deletion file list */
|
||||
file = make_file(fname, &flist->string_area,
|
||||
f == -1 && delete_excluded? SERVER_EXCLUDES
|
||||
: ALL_EXCLUDES);
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
@@ -792,7 +819,7 @@ void send_file_name(int f, struct file_list *flist, char *fname,
|
||||
if (write_batch) /* dw */
|
||||
file->flags = FLAG_DELETE;
|
||||
|
||||
if (strcmp(file->basename, "")) {
|
||||
if (file->basename[0]) {
|
||||
flist->files[flist->count++] = file;
|
||||
send_file_entry(file, f, base_flags);
|
||||
}
|
||||
@@ -818,8 +845,9 @@ static void send_directory(int f, struct file_list *flist, char *dir)
|
||||
|
||||
d = opendir(dir);
|
||||
if (!d) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "opendir(%s): %s\n", dir, strerror(errno));
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "opendir %s failed: %s\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -827,10 +855,9 @@ static void send_directory(int f, struct file_list *flist, char *dir)
|
||||
l = strlen(fname);
|
||||
if (fname[l - 1] != '/') {
|
||||
if (l == MAXPATHLEN - 1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,
|
||||
"skipping long-named directory %s\n",
|
||||
fname);
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "skipping long-named directory: %s\n",
|
||||
full_fname(fname));
|
||||
closedir(d);
|
||||
return;
|
||||
}
|
||||
@@ -844,45 +871,51 @@ static void send_directory(int f, struct file_list *flist, char *dir)
|
||||
if (cvs_exclude) {
|
||||
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN - 1) {
|
||||
strcpy(p, ".cvsignore");
|
||||
local_exclude_list =
|
||||
make_exclude_list(fname, NULL, 0, 0);
|
||||
add_exclude_file(&exclude_list,fname,MISSING_OK,ADD_EXCLUDE);
|
||||
} else {
|
||||
io_error = 1;
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FINFO,
|
||||
"cannot cvs-exclude in long-named directory %s\n",
|
||||
fname);
|
||||
full_fname(fname));
|
||||
}
|
||||
}
|
||||
|
||||
for (di = readdir(d); di; di = readdir(d)) {
|
||||
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
|
||||
char *dname = d_name(di);
|
||||
if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0)
|
||||
if (dname[0] == '.' && (dname[1] == '\0'
|
||||
|| (dname[1] == '.' && dname[2] == '\0')))
|
||||
continue;
|
||||
strlcpy(p, dname, MAXPATHLEN - l);
|
||||
send_file_name(f, flist, fname, recurse, 0);
|
||||
}
|
||||
|
||||
if (local_exclude_list) {
|
||||
add_exclude_list("!", &local_exclude_list, 0);
|
||||
if (errno) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "readdir(%s): (%d) %s\n",
|
||||
dir, errno, strerror(errno));
|
||||
}
|
||||
|
||||
if (local_exclude_list)
|
||||
free_exclude_list(&local_exclude_list); /* Zeros pointer too */
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* I <b>think</b> f==-1 means that the list should just be built in
|
||||
* memory and not transmitted. But who can tell? -- mbp
|
||||
* The delete_files() function in receiver.c sets f to -1 so that we just
|
||||
* construct the file list in memory without sending it over the wire. It
|
||||
* also has the side-effect of ignoring user-excludes if delete_excluded
|
||||
* is set (so that the delete list includes user-excluded files).
|
||||
**/
|
||||
struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
{
|
||||
int i, l;
|
||||
int l;
|
||||
STRUCT_STAT st;
|
||||
char *p, *dir, *olddir;
|
||||
char lastpath[MAXPATHLEN] = "";
|
||||
struct file_list *flist;
|
||||
int64 start_write;
|
||||
int use_ff_fd = 0;
|
||||
|
||||
if (show_filelist_p() && f != -1)
|
||||
start_filelist_progress("building file list");
|
||||
@@ -893,23 +926,37 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
|
||||
if (f != -1) {
|
||||
io_start_buffering(f);
|
||||
if (filesfrom_fd >= 0) {
|
||||
if (argv[0] && !push_dir(argv[0], 0)) {
|
||||
rprintf(FERROR, "push_dir %s failed: %s\n",
|
||||
full_fname(argv[0]), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
use_ff_fd = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
while (1) {
|
||||
char fname2[MAXPATHLEN];
|
||||
char *fname = fname2;
|
||||
|
||||
strlcpy(fname, argv[i], MAXPATHLEN);
|
||||
if (use_ff_fd) {
|
||||
if (read_filesfrom_line(filesfrom_fd, fname) == 0)
|
||||
break;
|
||||
sanitize_path(fname, NULL);
|
||||
} else {
|
||||
if (argc-- == 0)
|
||||
break;
|
||||
strlcpy(fname, *argv++, MAXPATHLEN);
|
||||
if (sanitize_paths)
|
||||
sanitize_path(fname, NULL);
|
||||
}
|
||||
|
||||
l = strlen(fname);
|
||||
if (l != 1 && fname[l - 1] == '/') {
|
||||
if ((l == 2) && (fname[0] == '.')) {
|
||||
/* Turn ./ into just . rather than ./.
|
||||
This was put in to avoid a problem with
|
||||
rsync -aR --delete from ./
|
||||
The send_file_name() below of ./ was
|
||||
mysteriously preventing deletes */
|
||||
fname[1] = 0;
|
||||
if (fname[l - 1] == '/') {
|
||||
if (l == 2 && fname[0] == '.') {
|
||||
/* Turn "./" into just "." rather than "./." */
|
||||
fname[1] = '\0';
|
||||
} else {
|
||||
strlcat(fname, ".", MAXPATHLEN);
|
||||
}
|
||||
@@ -917,14 +964,14 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
|
||||
if (link_stat(fname, &st) != 0) {
|
||||
if (f != -1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "link_stat %s : %s\n",
|
||||
fname, strerror(errno));
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "link_stat %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode) && !recurse) {
|
||||
if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
|
||||
rprintf(FINFO, "skipping directory %s\n", fname);
|
||||
continue;
|
||||
}
|
||||
@@ -942,31 +989,37 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
dir = fname;
|
||||
fname = p + 1;
|
||||
}
|
||||
} else if (f != -1 && (p = strrchr(fname, '/'))) {
|
||||
} else if (f != -1 && implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
|
||||
/* this ensures we send the intermediate directories,
|
||||
thus getting their permissions right */
|
||||
char *lp = lastpath, *fn = fname, *slash = fname;
|
||||
*p = 0;
|
||||
if (strcmp(lastpath, fname)) {
|
||||
strlcpy(lastpath, fname, sizeof(lastpath));
|
||||
*p = '/';
|
||||
for (p = fname + 1; (p = strchr(p, '/'));
|
||||
p++) {
|
||||
int copy_links_saved = copy_links;
|
||||
int recurse_saved = recurse;
|
||||
*p = 0;
|
||||
copy_links = copy_unsafe_links;
|
||||
/* set recurse to 1 to prevent make_file
|
||||
from ignoring directory, but still
|
||||
turn off the recursive parameter to
|
||||
send_file_name */
|
||||
recurse = 1;
|
||||
send_file_name(f, flist, fname, 0,
|
||||
0);
|
||||
copy_links = copy_links_saved;
|
||||
recurse = recurse_saved;
|
||||
*p = '/';
|
||||
/* Skip any initial directories in our path that we
|
||||
* have in common with lastpath. */
|
||||
while (*fn && *lp == *fn) {
|
||||
if (*fn == '/')
|
||||
slash = fn;
|
||||
lp++, fn++;
|
||||
}
|
||||
*p = '/';
|
||||
if (fn != p || (*lp && *lp != '/')) {
|
||||
int copy_links_saved = copy_links;
|
||||
int recurse_saved = recurse;
|
||||
copy_links = copy_unsafe_links;
|
||||
/* set recurse to 1 to prevent make_file
|
||||
* from ignoring directory, but still
|
||||
* turn off the recursive parameter to
|
||||
* send_file_name */
|
||||
recurse = 1;
|
||||
while ((slash = strchr(slash+1, '/')) != 0) {
|
||||
*slash = 0;
|
||||
send_file_name(f, flist, fname, 0, 0);
|
||||
*slash = '/';
|
||||
}
|
||||
} else {
|
||||
copy_links = copy_links_saved;
|
||||
recurse = recurse_saved;
|
||||
*p = 0;
|
||||
strlcpy(lastpath, fname, sizeof lastpath);
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
@@ -978,9 +1031,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
olddir = push_dir(dir, 1);
|
||||
|
||||
if (!olddir) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "push_dir %s : %s\n",
|
||||
dir, strerror(errno));
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "push_dir %s failed: %s\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -995,8 +1048,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
if (olddir != NULL) {
|
||||
flist_dir = NULL;
|
||||
if (pop_dir(olddir) != 0) {
|
||||
rprintf(FERROR, "pop_dir %s : %s\n",
|
||||
dir, strerror(errno));
|
||||
rprintf(FERROR, "pop_dir %s failed: %s\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
}
|
||||
@@ -1010,16 +1063,16 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
finish_filelist_progress(flist);
|
||||
}
|
||||
|
||||
clean_flist(flist, 0);
|
||||
clean_flist(flist, 0, 0);
|
||||
|
||||
/* now send the uid/gid list. This was introduced in protocol
|
||||
version 15 */
|
||||
if (f != -1 && remote_version >= 15) {
|
||||
if (f != -1) {
|
||||
send_uid_list(f);
|
||||
}
|
||||
|
||||
/* if protocol version is >= 17 then send the io_error flag */
|
||||
if (f != -1 && remote_version >= 17) {
|
||||
/* send the io_error flag */
|
||||
if (f != -1) {
|
||||
extern int module_id;
|
||||
write_int(f, lp_ignore_errors(module_id) ? 0 : io_error);
|
||||
}
|
||||
@@ -1051,22 +1104,20 @@ struct file_list *recv_file_list(int f)
|
||||
|
||||
start_read = stats.total_read;
|
||||
|
||||
flist = (struct file_list *) malloc(sizeof(flist[0]));
|
||||
flist = new(struct file_list);
|
||||
if (!flist)
|
||||
goto oom;
|
||||
|
||||
flist->count = 0;
|
||||
flist->malloced = 1000;
|
||||
flist->files =
|
||||
(struct file_struct **) malloc(sizeof(flist->files[0]) *
|
||||
flist->malloced);
|
||||
flist->files = new_array(struct file_struct *, flist->malloced);
|
||||
if (!flist->files)
|
||||
goto oom;
|
||||
|
||||
|
||||
for (flags = read_byte(f); flags; flags = read_byte(f)) {
|
||||
int i = flist->count;
|
||||
|
||||
|
||||
flist_expand(flist);
|
||||
|
||||
receive_file_entry(&flist->files[i], flags, f);
|
||||
@@ -1087,19 +1138,19 @@ struct file_list *recv_file_list(int f)
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "received %d names\n", flist->count);
|
||||
|
||||
clean_flist(flist, relative_paths);
|
||||
clean_flist(flist, relative_paths, 1);
|
||||
|
||||
if (show_filelist_p()) {
|
||||
finish_filelist_progress(flist);
|
||||
}
|
||||
|
||||
/* now recv the uid/gid list. This was introduced in protocol version 15 */
|
||||
if (f != -1 && remote_version >= 15) {
|
||||
if (f != -1) {
|
||||
recv_uid_list(f, flist);
|
||||
}
|
||||
|
||||
/* if protocol version is >= 17 then recv the io_error flag */
|
||||
if (f != -1 && remote_version >= 17 && !read_batch) { /* dw-added readbatch */
|
||||
/* recv the io_error flag */
|
||||
if (f != -1 && !read_batch) { /* dw-added readbatch */
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
if (lp_ignore_errors(module_id) || ignore_errors) {
|
||||
@@ -1201,7 +1252,7 @@ struct file_list *flist_new(void)
|
||||
{
|
||||
struct file_list *flist;
|
||||
|
||||
flist = (struct file_list *) malloc(sizeof(flist[0]));
|
||||
flist = new(struct file_list);
|
||||
if (!flist)
|
||||
out_of_memory("send_file_list");
|
||||
|
||||
@@ -1244,11 +1295,11 @@ void flist_free(struct file_list *flist)
|
||||
|
||||
/*
|
||||
* This routine ensures we don't have any duplicate names in our file list.
|
||||
* duplicate names can cause corruption because of the pipelining
|
||||
* duplicate names can cause corruption because of the pipelining
|
||||
*/
|
||||
static void clean_flist(struct file_list *flist, int strip_root)
|
||||
static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
|
||||
{
|
||||
int i;
|
||||
int i, prev_i = 0;
|
||||
char *name, *prev_name = NULL;
|
||||
|
||||
if (!flist || flist->count == 0)
|
||||
@@ -1257,8 +1308,9 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
qsort(flist->files, flist->count,
|
||||
sizeof(flist->files[0]), (int (*)()) file_compare);
|
||||
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
for (i = no_dups? 0 : flist->count; i < flist->count; i++) {
|
||||
if (flist->files[i]->basename) {
|
||||
prev_i = i;
|
||||
prev_name = f_name(flist->files[i]);
|
||||
break;
|
||||
}
|
||||
@@ -1273,6 +1325,11 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
"removing duplicate name %s from file list %d\n",
|
||||
name, i);
|
||||
}
|
||||
/* Make sure that if we unduplicate '.', that we don't
|
||||
* lose track of a user-specified starting point (or
|
||||
* else deletions will mysteriously fail with -R). */
|
||||
if (flist->files[i]->flags & FLAG_DELETE)
|
||||
flist->files[prev_i]->flags |= FLAG_DELETE;
|
||||
/* it's not great that the flist knows the semantics of
|
||||
* the file memory usage, but i'd rather not add a flag
|
||||
* byte to that struct.
|
||||
@@ -1282,6 +1339,10 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
else
|
||||
free_file(flist->files[i]);
|
||||
}
|
||||
else
|
||||
prev_i = i;
|
||||
/* We set prev_name every iteration to avoid it becoming
|
||||
* invalid when names[][] in f_name() wraps around. */
|
||||
prev_name = name;
|
||||
}
|
||||
|
||||
|
||||
318
generator.c
318
generator.c
@@ -1,21 +1,21 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -32,12 +32,11 @@ extern int preserve_devices;
|
||||
extern int preserve_hard_links;
|
||||
extern int update_only;
|
||||
extern int opt_ignore_existing;
|
||||
extern int block_size;
|
||||
extern int csum_length;
|
||||
extern int ignore_times;
|
||||
extern int size_only;
|
||||
extern int io_timeout;
|
||||
extern int remote_version;
|
||||
extern int protocol_version;
|
||||
extern int always_checksum;
|
||||
extern int modify_window;
|
||||
extern char *compare_dest;
|
||||
@@ -52,16 +51,22 @@ static int skip_file(char *fname,
|
||||
return 0;
|
||||
}
|
||||
if (link_dest) {
|
||||
if((st->st_mode & ~_S_IFMT) != (file->mode & ~_S_IFMT)) {
|
||||
extern int preserve_perms;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
|
||||
if(preserve_perms
|
||||
&& (st->st_mode & ~_S_IFMT) != (file->mode & ~_S_IFMT))
|
||||
return 0;
|
||||
}
|
||||
if (st->st_uid != file->uid || st->st_gid != file->gid) {
|
||||
|
||||
if (preserve_uid && st->st_uid != file->uid)
|
||||
return 0;
|
||||
|
||||
if (preserve_gid && st->st_gid != file->gid)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* if always checksum is set then we use the checksum instead
|
||||
/* if always checksum is set then we use the checksum instead
|
||||
of the file time to determine whether to sync */
|
||||
if (always_checksum && S_ISREG(st->st_mode)) {
|
||||
char sum[MD4_SUM_LENGTH];
|
||||
@@ -70,12 +75,12 @@ static int skip_file(char *fname,
|
||||
if (compare_dest != NULL) {
|
||||
if (access(fname, 0) != 0) {
|
||||
snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
|
||||
compare_dest,fname);
|
||||
compare_dest,fname);
|
||||
fname = fnamecmpdest;
|
||||
}
|
||||
}
|
||||
file_checksum(fname,sum,st->st_size);
|
||||
if (remote_version < 21) {
|
||||
if (protocol_version < 21) {
|
||||
return (memcmp(sum,file->sum,2) == 0);
|
||||
} else {
|
||||
return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
|
||||
@@ -94,32 +99,105 @@ static int skip_file(char *fname,
|
||||
}
|
||||
|
||||
|
||||
/* use a larger block size for really big files */
|
||||
static int adapt_block_size(struct file_struct *file, int bsize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bsize != BLOCK_SIZE) return bsize;
|
||||
|
||||
ret = file->length / (10000); /* rough heuristic */
|
||||
ret = ret & ~15; /* multiple of 16 */
|
||||
if (ret < bsize) ret = bsize;
|
||||
if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
send a header that says "we have no checksums" down the f_out fd
|
||||
*/
|
||||
static void send_null_sums(int f_out)
|
||||
* NULL sum_struct means we have no checksums
|
||||
*/
|
||||
|
||||
void write_sum_head(int f, struct sum_struct *sum)
|
||||
{
|
||||
write_int(f_out, 0);
|
||||
write_int(f_out, block_size);
|
||||
write_int(f_out, 0);
|
||||
static struct sum_struct null_sum;
|
||||
|
||||
if (sum == (struct sum_struct *)NULL)
|
||||
sum = &null_sum;
|
||||
|
||||
write_int(f, sum->count);
|
||||
write_int(f, sum->blength);
|
||||
if (protocol_version >= 27)
|
||||
write_int(f, sum->s2length);
|
||||
write_int(f, sum->remainder);
|
||||
}
|
||||
|
||||
/*
|
||||
* set (initialize) the size entries in the per-file sum_struct
|
||||
* calulating dynamic block ans checksum sizes.
|
||||
*
|
||||
* This is only called from generate_and_send_sums() but is a seperate
|
||||
* function to encapsulate the logic.
|
||||
*
|
||||
* The block size is a rounded square root of file length.
|
||||
*
|
||||
* The checksum size is determined according to:
|
||||
* blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
|
||||
* provided by Donovan Baarda which gives a probability of rsync
|
||||
* algorithm corrupting data and falling back using the whole md4
|
||||
* checksums.
|
||||
*
|
||||
* This might be made one of several selectable heuristics.
|
||||
*/
|
||||
|
||||
static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
|
||||
{
|
||||
extern int block_size;
|
||||
int blength, s2length, b;
|
||||
uint32 c;
|
||||
uint64 l;
|
||||
|
||||
if (block_size) {
|
||||
blength = block_size;
|
||||
} else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
|
||||
blength = BLOCK_SIZE;
|
||||
} else {
|
||||
l = len;
|
||||
c = 1;
|
||||
while (l >>= 2) {
|
||||
c <<= 1;
|
||||
}
|
||||
blength = 0;
|
||||
do {
|
||||
blength |= c;
|
||||
if (len < (uint64)blength * blength)
|
||||
blength &= ~c;
|
||||
c >>= 1;
|
||||
} while (c >= 8); /* round to multiple of 8 */
|
||||
blength = MAX(blength, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if (protocol_version < 27) {
|
||||
s2length = csum_length;
|
||||
} else if (csum_length == SUM_LENGTH) {
|
||||
s2length = SUM_LENGTH;
|
||||
} else {
|
||||
b = BLOCKSUM_BIAS;
|
||||
l = len;
|
||||
while (l >>= 1) {
|
||||
b += 2;
|
||||
}
|
||||
c = blength;
|
||||
while (c >>= 1 && b) {
|
||||
b--;
|
||||
}
|
||||
s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
|
||||
* subtract rollsum,
|
||||
* round up
|
||||
* --optimize in compiler--
|
||||
*/
|
||||
s2length = MAX(s2length, csum_length);
|
||||
s2length = MIN(s2length, SUM_LENGTH);
|
||||
}
|
||||
|
||||
sum->flength = len;
|
||||
sum->blength = blength;
|
||||
sum->s2length = s2length;
|
||||
sum->count = (len + (blength - 1)) / blength;
|
||||
sum->remainder = (len % blength);
|
||||
|
||||
if (sum->count && verbose > 2) {
|
||||
rprintf(FINFO, "count=%ld rem=%ld blength=%ld s2length=%ld flength=%.0f\n",
|
||||
(long) sum->count, (long) sum->remainder,
|
||||
(long) sum->blength, (long) sum->s2length,
|
||||
(double) sum->flength);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perhaps we want to just send an empty checksum set for this file,
|
||||
@@ -132,22 +210,15 @@ static void send_null_sums(int f_out)
|
||||
* Whew. */
|
||||
static BOOL disable_deltas_p(void)
|
||||
{
|
||||
extern int whole_file, no_whole_file;
|
||||
extern int whole_file;
|
||||
extern int local_server;
|
||||
extern int write_batch;
|
||||
|
||||
assert(whole_file == 0 || whole_file == 1);
|
||||
|
||||
/* whole_file and no_whole_file are never both on at the same time */
|
||||
|
||||
if (whole_file)
|
||||
if (whole_file > 0)
|
||||
return True;
|
||||
else if (no_whole_file)
|
||||
if (whole_file == 0 || write_batch)
|
||||
return False;
|
||||
else if (write_batch)
|
||||
return False;
|
||||
else
|
||||
return local_server;
|
||||
return local_server;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,31 +227,18 @@ static BOOL disable_deltas_p(void)
|
||||
*
|
||||
* Generate approximately one checksum every block_len bytes.
|
||||
*/
|
||||
static void generate_and_send_sums(struct map_struct *buf, OFF_T len,
|
||||
int block_len, int f_out)
|
||||
static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
|
||||
{
|
||||
size_t i;
|
||||
struct sum_struct sum;
|
||||
OFF_T offset = 0;
|
||||
|
||||
sum.count = (len + (block_len - 1)) / block_len;
|
||||
sum.remainder = (len % block_len);
|
||||
sum.n = block_len;
|
||||
sum.flength = len;
|
||||
/* not needed here sum.sums = NULL; */
|
||||
sum_sizes_sqroot(&sum, len);
|
||||
|
||||
if (sum.count && verbose > 3) {
|
||||
rprintf(FINFO, "count=%ld rem=%ld n=%ld flength=%.0f\n",
|
||||
(long) sum.count, (long) sum.remainder,
|
||||
(long) sum.n, (double) sum.flength);
|
||||
}
|
||||
|
||||
write_int(f_out, sum.count);
|
||||
write_int(f_out, sum.n);
|
||||
write_int(f_out, sum.remainder);
|
||||
write_sum_head(f_out, &sum);
|
||||
|
||||
for (i = 0; i < sum.count; i++) {
|
||||
int n1 = MIN(len, block_len);
|
||||
int n1 = MIN(len, sum.blength);
|
||||
char *map = map_ptr(buf, offset, n1);
|
||||
uint32 sum1 = get_checksum1(map, n1);
|
||||
char sum2[SUM_LENGTH];
|
||||
@@ -189,11 +247,11 @@ static void generate_and_send_sums(struct map_struct *buf, OFF_T len,
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"chunk[%d] offset=%.0f len=%d sum1=%08lx\n",
|
||||
i, (double) offset, n1, (unsigned long) sum1);
|
||||
"chunk[%ld] offset=%.0f len=%d sum1=%08lx\n",
|
||||
(long)i,(double)offset,n1,(unsigned long)sum1);
|
||||
}
|
||||
write_int(f_out, sum1);
|
||||
write_buf(f_out, sum2, csum_length);
|
||||
write_buf(f_out, sum2, sum.s2length);
|
||||
len -= n1;
|
||||
offset += n1;
|
||||
}
|
||||
@@ -208,9 +266,9 @@ static void generate_and_send_sums(struct map_struct *buf, OFF_T len,
|
||||
*
|
||||
* @note This comment was added later by mbp who was trying to work it
|
||||
* out. It might be wrong.
|
||||
**/
|
||||
**/
|
||||
void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
{
|
||||
{
|
||||
int fd;
|
||||
STRUCT_STAT st;
|
||||
struct map_struct *buf;
|
||||
@@ -237,43 +295,43 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
return;
|
||||
}
|
||||
|
||||
if (statret == 0 &&
|
||||
!preserve_perms &&
|
||||
if (statret == 0 &&
|
||||
!preserve_perms &&
|
||||
(S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
|
||||
/* if the file exists already and we aren't perserving
|
||||
presmissions then act as though the remote end sent
|
||||
us the file permissions we already have */
|
||||
* permissions then act as though the remote end sent
|
||||
* us the file permissions we already have */
|
||||
file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
|
||||
}
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
/* The file to be received is a directory, so we need
|
||||
* to prepare appropriately. If there is already a
|
||||
* file of that name and it is *not* a directory, then
|
||||
* we need to delete it. If it doesn't exist, then
|
||||
* recursively create it. */
|
||||
|
||||
/* The file to be received is a directory, so we need
|
||||
* to prepare appropriately. If there is already a
|
||||
* file of that name and it is *not* a directory, then
|
||||
* we need to delete it. If it doesn't exist, then
|
||||
* recursively create it. */
|
||||
|
||||
if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
|
||||
if (statret == 0 && !S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": recv_generator: unlink \"%s\" to make room for directory: %s\n",
|
||||
fname,strerror(errno));
|
||||
rprintf(FERROR,
|
||||
"recv_generator: unlink %s to make room for directory: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return;
|
||||
}
|
||||
statret = -1;
|
||||
}
|
||||
if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
|
||||
if (!(relative_paths && errno==ENOENT &&
|
||||
create_directory_path(fname, orig_umask)==0 &&
|
||||
if (!(relative_paths && errno==ENOENT &&
|
||||
create_directory_path(fname, orig_umask)==0 &&
|
||||
do_mkdir(fname,file->mode)==0)) {
|
||||
rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
|
||||
fname,strerror(errno));
|
||||
rprintf(FERROR, "recv_generator: mkdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
}
|
||||
}
|
||||
/* f_out is set to -1 when doing final directory
|
||||
/* f_out is set to -1 when doing final directory
|
||||
permission and modification time repair */
|
||||
if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
|
||||
if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
|
||||
rprintf(FINFO,"%s/\n",fname);
|
||||
return;
|
||||
}
|
||||
@@ -286,8 +344,8 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
|
||||
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
|
||||
fname,file->link);
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
|
||||
full_fname(fname), file->link);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -302,15 +360,15 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Not a symlink, so delete whatever's
|
||||
* already there and put a new symlink
|
||||
* in place. */
|
||||
* in place. */
|
||||
delete_file(fname);
|
||||
}
|
||||
if (do_symlink(file->link,fname) != 0) {
|
||||
rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
|
||||
fname,file->link,strerror(errno));
|
||||
rprintf(FERROR, "symlink %s -> \"%s\" failed: %s\n",
|
||||
full_fname(fname), file->link, strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
if (verbose) {
|
||||
@@ -323,15 +381,16 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
|
||||
#ifdef HAVE_MKNOD
|
||||
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
|
||||
if (statret != 0 ||
|
||||
if (statret != 0 ||
|
||||
st.st_mode != file->mode ||
|
||||
st.st_rdev != file->rdev) {
|
||||
(DEV64_T)st.st_rdev != file->rdev) {
|
||||
delete_file(fname);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
|
||||
fname,(int)file->mode,(int)file->rdev);
|
||||
if (do_mknod(fname,file->mode,file->rdev) != 0) {
|
||||
rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
|
||||
rprintf(FERROR, "mknod %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
if (verbose)
|
||||
@@ -385,12 +444,11 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
if (statret == -1) {
|
||||
if (errno == ENOENT) {
|
||||
write_int(f_out,i);
|
||||
if (!dry_run) send_null_sums(f_out);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": recv_generator failed to open \"%s\": %s\n",
|
||||
fname, strerror(errno));
|
||||
if (!dry_run) write_sum_head(f_out, NULL);
|
||||
} else if (verbose > 1) {
|
||||
rprintf(FERROR,
|
||||
"recv_generator: failed to open %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -402,15 +460,15 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
|
||||
/* now pretend the file didn't exist */
|
||||
write_int(f_out,i);
|
||||
if (!dry_run) send_null_sums(f_out);
|
||||
if (!dry_run) write_sum_head(f_out, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_ignore_existing && fnamecmp == fname) {
|
||||
if (opt_ignore_existing && fnamecmp == fname) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"%s exists\n",fname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
|
||||
if (verbose > 1)
|
||||
@@ -431,18 +489,19 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
|
||||
if (disable_deltas_p()) {
|
||||
write_int(f_out,i);
|
||||
send_null_sums(f_out);
|
||||
write_sum_head(f_out, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
/* open the file */
|
||||
fd = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if (fd == -1) {
|
||||
rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
|
||||
rprintf(FERROR, "failed to open %s, continuing: %s\n",
|
||||
full_fname(fnamecmp), strerror(errno));
|
||||
/* pretend the file didn't exist */
|
||||
write_int(f_out,i);
|
||||
send_null_sums(f_out);
|
||||
write_sum_head(f_out, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -459,8 +518,7 @@ void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
rprintf(FINFO, "generating and sending sums for %d\n", i);
|
||||
|
||||
write_int(f_out,i);
|
||||
generate_and_send_sums(buf, st.st_size,
|
||||
adapt_block_size(file, block_size), f_out);
|
||||
generate_and_send_sums(buf, st.st_size, f_out);
|
||||
|
||||
close(fd);
|
||||
if (buf) unmap_file(buf);
|
||||
@@ -479,11 +537,11 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO,
|
||||
disable_deltas_p()
|
||||
disable_deltas_p()
|
||||
? "delta-transmission disabled for local transfer or --whole-file\n"
|
||||
: "delta transmission enabled\n");
|
||||
}
|
||||
|
||||
|
||||
/* we expect to just sit around now, so don't exit on a
|
||||
timeout. If we really get a timeout then the other process should
|
||||
exit */
|
||||
@@ -499,12 +557,11 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
them. This is then fixed after the files are transferred */
|
||||
if (!am_root && S_ISDIR(file->mode)) {
|
||||
file->mode |= S_IWUSR; /* user write */
|
||||
/* XXX: Could this be causing a problem on SCO? Perhaps their
|
||||
* handling of permissions is strange? */
|
||||
/* XXX: Could this be causing a problem on SCO? Perhaps their
|
||||
* handling of permissions is strange? */
|
||||
}
|
||||
|
||||
recv_generator(local_name?local_name:f_name(file),
|
||||
flist,i,f);
|
||||
recv_generator(local_name?local_name:f_name(file), flist,i,f);
|
||||
|
||||
file->mode = saved_mode;
|
||||
}
|
||||
@@ -518,19 +575,16 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
|
||||
write_int(f,-1);
|
||||
|
||||
if (remote_version >= 13) {
|
||||
/* in newer versions of the protocol the files can cycle through
|
||||
the system more than once to catch initial checksum errors */
|
||||
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
recv_generator(local_name?local_name:f_name(file),
|
||||
flist,i,f);
|
||||
}
|
||||
|
||||
phase++;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
/* files can cycle through the system more than once
|
||||
* to catch initial checksum errors */
|
||||
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
recv_generator(local_name?local_name:f_name(file), flist,i,f);
|
||||
}
|
||||
|
||||
phase++;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
# define NGROUPS 32
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
int
|
||||
main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
int n, i;
|
||||
gid_t list[NGROUPS];
|
||||
|
||||
4
hlink.c
4
hlink.c
@@ -57,9 +57,7 @@ void init_hard_links(struct file_list *flist)
|
||||
if (hlink_list)
|
||||
free(hlink_list);
|
||||
|
||||
if (!(hlink_list =
|
||||
(struct file_struct *) malloc(sizeof(hlink_list[0]) *
|
||||
flist->count)))
|
||||
if (!(hlink_list = new_array(struct file_struct, flist->count)))
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
for (i = 0; i < flist->count; i++)
|
||||
|
||||
259
io.c
259
io.c
@@ -76,6 +76,12 @@ int kludge_around_eof = False;
|
||||
|
||||
|
||||
static int io_error_fd = -1;
|
||||
static int io_filesfrom_f_in = -1;
|
||||
static int io_filesfrom_f_out = -1;
|
||||
static char io_filesfrom_buf[2048];
|
||||
static char *io_filesfrom_bp;
|
||||
static char io_filesfrom_lastchar;
|
||||
static int io_filesfrom_buflen;
|
||||
|
||||
static void read_loop(int fd, char *buf, size_t len);
|
||||
|
||||
@@ -85,7 +91,7 @@ static void check_timeout(void)
|
||||
time_t t;
|
||||
|
||||
err_list_push();
|
||||
|
||||
|
||||
if (!io_timeout) return;
|
||||
|
||||
if (!last_io) {
|
||||
@@ -118,8 +124,8 @@ static void read_error_fd(void)
|
||||
int fd = io_error_fd;
|
||||
int tag, len;
|
||||
|
||||
/* io_error_fd is temporarily disabled -- is this meant to
|
||||
* prevent indefinite recursion? */
|
||||
/* io_error_fd is temporarily disabled -- is this meant to
|
||||
* prevent indefinite recursion? */
|
||||
io_error_fd = -1;
|
||||
|
||||
read_loop(fd, buf, 4);
|
||||
@@ -131,8 +137,8 @@ static void read_error_fd(void)
|
||||
|
||||
while (len) {
|
||||
n = len;
|
||||
if (n > (sizeof(buf)-1))
|
||||
n = sizeof(buf)-1;
|
||||
if (n > (sizeof buf - 1))
|
||||
n = sizeof buf - 1;
|
||||
read_loop(fd, buf, n);
|
||||
rwrite((enum logcode)tag, buf, n);
|
||||
len -= n;
|
||||
@@ -141,6 +147,24 @@ static void read_error_fd(void)
|
||||
io_error_fd = fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* When we're the receiver and we have a local --files-from list of names
|
||||
* that needs to be sent over the socket to the sender, we have to do two
|
||||
* things at the same time: send the sender a list of what files we're
|
||||
* processing and read the incoming file+info list from the sender. We do
|
||||
* this by augmenting the read_timeout() function to copy this data. It
|
||||
* uses the io_filesfrom_buf to read a block of data from f_in (when it is
|
||||
* ready, since it might be a pipe) and then blast it out f_out (when it
|
||||
* is ready to receive more data).
|
||||
*/
|
||||
void io_set_filesfrom_fds(int f_in, int f_out)
|
||||
{
|
||||
io_filesfrom_f_in = f_in;
|
||||
io_filesfrom_f_out = f_out;
|
||||
io_filesfrom_bp = io_filesfrom_buf;
|
||||
io_filesfrom_lastchar = '\0';
|
||||
io_filesfrom_buflen = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's almost always an error to get an EOF when we're trying to read
|
||||
@@ -152,28 +176,28 @@ static void read_error_fd(void)
|
||||
* program where that is a problem (start_socket_client),
|
||||
* kludge_around_eof is True and we just exit.
|
||||
*/
|
||||
static void whine_about_eof (void)
|
||||
static void whine_about_eof(void)
|
||||
{
|
||||
if (kludge_around_eof)
|
||||
exit_cleanup (0);
|
||||
exit_cleanup(0);
|
||||
else {
|
||||
rprintf (FERROR,
|
||||
"%s: connection unexpectedly closed "
|
||||
"(%.0f bytes read so far)\n",
|
||||
RSYNC_NAME, (double)stats.total_read);
|
||||
|
||||
exit_cleanup (RERR_STREAMIO);
|
||||
rprintf(FERROR,
|
||||
"%s: connection unexpectedly closed "
|
||||
"(%.0f bytes read so far)\n",
|
||||
RSYNC_NAME, (double)stats.total_read);
|
||||
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void die_from_readerr (int err)
|
||||
static void die_from_readerr(int err)
|
||||
{
|
||||
/* this prevents us trying to write errors on a dead socket */
|
||||
io_multiplexing_close();
|
||||
|
||||
|
||||
rprintf(FERROR, "%s: read error: %s\n",
|
||||
RSYNC_NAME, strerror (err));
|
||||
RSYNC_NAME, strerror(err));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
@@ -189,7 +213,7 @@ static void die_from_readerr (int err)
|
||||
* give a better explanation. We can tell whether the connection has
|
||||
* started by looking e.g. at whether the remote version is known yet.
|
||||
*/
|
||||
static int read_timeout (int fd, char *buf, size_t len)
|
||||
static int read_timeout(int fd, char *buf, size_t len)
|
||||
{
|
||||
int n, ret=0;
|
||||
|
||||
@@ -197,16 +221,33 @@ static int read_timeout (int fd, char *buf, size_t len)
|
||||
|
||||
while (ret == 0) {
|
||||
/* until we manage to read *something* */
|
||||
fd_set fds;
|
||||
fd_set r_fds, w_fds;
|
||||
struct timeval tv;
|
||||
int fd_count = fd+1;
|
||||
int count;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd, &r_fds);
|
||||
if (io_error_fd != -1) {
|
||||
FD_SET(io_error_fd, &fds);
|
||||
if (io_error_fd > fd) fd_count = io_error_fd+1;
|
||||
FD_SET(io_error_fd, &r_fds);
|
||||
if (io_error_fd >= fd_count) fd_count = io_error_fd+1;
|
||||
}
|
||||
if (io_filesfrom_f_out != -1) {
|
||||
int new_fd;
|
||||
if (io_filesfrom_buflen == 0) {
|
||||
if (io_filesfrom_f_in != -1) {
|
||||
FD_SET(io_filesfrom_f_in, &r_fds);
|
||||
new_fd = io_filesfrom_f_in;
|
||||
} else {
|
||||
io_filesfrom_f_out = -1;
|
||||
new_fd = -1;
|
||||
}
|
||||
} else {
|
||||
FD_ZERO(&w_fds);
|
||||
FD_SET(io_filesfrom_f_out, &w_fds);
|
||||
new_fd = io_filesfrom_f_out;
|
||||
}
|
||||
if (new_fd >= fd_count) fd_count = new_fd+1;
|
||||
}
|
||||
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
@@ -214,7 +255,9 @@ static int read_timeout (int fd, char *buf, size_t len)
|
||||
|
||||
errno = 0;
|
||||
|
||||
count = select(fd_count, &fds, NULL, NULL, &tv);
|
||||
count = select(fd_count, &r_fds,
|
||||
io_filesfrom_buflen? &w_fds : NULL,
|
||||
NULL, &tv);
|
||||
|
||||
if (count == 0) {
|
||||
check_timeout();
|
||||
@@ -227,11 +270,75 @@ static int read_timeout (int fd, char *buf, size_t len)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
|
||||
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
|
||||
read_error_fd();
|
||||
}
|
||||
|
||||
if (!FD_ISSET(fd, &fds)) continue;
|
||||
if (io_filesfrom_f_out != -1) {
|
||||
if (io_filesfrom_buflen) {
|
||||
if (FD_ISSET(io_filesfrom_f_out, &w_fds)) {
|
||||
int l = write(io_filesfrom_f_out,
|
||||
io_filesfrom_bp,
|
||||
io_filesfrom_buflen);
|
||||
if (l > 0) {
|
||||
if (!(io_filesfrom_buflen -= l))
|
||||
io_filesfrom_bp = io_filesfrom_buf;
|
||||
else
|
||||
io_filesfrom_bp += l;
|
||||
} else {
|
||||
/* XXX should we complain? */
|
||||
io_filesfrom_f_out = -1;
|
||||
}
|
||||
}
|
||||
} else if (io_filesfrom_f_in != -1) {
|
||||
if (FD_ISSET(io_filesfrom_f_in, &r_fds)) {
|
||||
int l = read(io_filesfrom_f_in,
|
||||
io_filesfrom_buf,
|
||||
sizeof io_filesfrom_buf);
|
||||
if (l <= 0) {
|
||||
/* Send end-of-file marker */
|
||||
io_filesfrom_buf[0] = '\0';
|
||||
io_filesfrom_buf[1] = '\0';
|
||||
io_filesfrom_buflen = io_filesfrom_lastchar? 2 : 1;
|
||||
io_filesfrom_f_in = -1;
|
||||
} else {
|
||||
extern int eol_nulls;
|
||||
if (!eol_nulls) {
|
||||
char *s = io_filesfrom_buf + l;
|
||||
/* Transform CR and/or LF into '\0' */
|
||||
while (s-- > io_filesfrom_buf) {
|
||||
if (*s == '\n' || *s == '\r')
|
||||
*s = '\0';
|
||||
}
|
||||
}
|
||||
if (!io_filesfrom_lastchar) {
|
||||
/* Last buf ended with a '\0', so don't
|
||||
* let this buf start with one. */
|
||||
while (l && !*io_filesfrom_bp)
|
||||
io_filesfrom_bp++, l--;
|
||||
}
|
||||
if (!l)
|
||||
io_filesfrom_bp = io_filesfrom_buf;
|
||||
else {
|
||||
char *f = io_filesfrom_bp;
|
||||
char *t = f;
|
||||
char *eob = f + l;
|
||||
/* Eliminate any multi-'\0' runs. */
|
||||
while (f != eob) {
|
||||
if (!(*t++ = *f++)) {
|
||||
while (f != eob && !*f)
|
||||
f++, l--;
|
||||
}
|
||||
}
|
||||
io_filesfrom_lastchar = f[-1];
|
||||
}
|
||||
io_filesfrom_buflen = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!FD_ISSET(fd, &r_fds)) continue;
|
||||
|
||||
n = read(fd, buf, len);
|
||||
|
||||
@@ -243,28 +350,75 @@ static int read_timeout (int fd, char *buf, size_t len)
|
||||
last_io = time(NULL);
|
||||
continue;
|
||||
} else if (n == 0) {
|
||||
whine_about_eof ();
|
||||
whine_about_eof();
|
||||
return -1; /* doesn't return */
|
||||
} else if (n == -1) {
|
||||
if (errno == EINTR || errno == EWOULDBLOCK ||
|
||||
errno == EAGAIN)
|
||||
continue;
|
||||
else
|
||||
die_from_readerr (errno);
|
||||
die_from_readerr(errno);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line into the "fname" buffer (which must be at least MAXPATHLEN
|
||||
* characters long).
|
||||
*/
|
||||
int read_filesfrom_line(int fd, char *fname)
|
||||
{
|
||||
char ch, *s, *eob = fname + MAXPATHLEN - 1;
|
||||
int cnt;
|
||||
extern int io_timeout;
|
||||
extern int eol_nulls;
|
||||
extern char *remote_filesfrom_file;
|
||||
int reading_remotely = remote_filesfrom_file != NULL;
|
||||
int nulls = eol_nulls || reading_remotely;
|
||||
|
||||
start:
|
||||
s = fname;
|
||||
while (1) {
|
||||
cnt = read(fd, &ch, 1);
|
||||
if (cnt < 0 && (errno == EWOULDBLOCK
|
||||
|| errno == EINTR || errno == EAGAIN)) {
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = io_timeout? io_timeout : SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(fd+1, &fds, NULL, NULL, &tv))
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
if (cnt != 1)
|
||||
break;
|
||||
if (nulls? !ch : (ch == '\r' || ch == '\n')) {
|
||||
/* Skip empty lines if reading locally. */
|
||||
if (!reading_remotely && s == fname)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (s < eob)
|
||||
*s++ = ch;
|
||||
}
|
||||
*s = '\0';
|
||||
|
||||
/* Dump comments. */
|
||||
if (*fname == '#' || *fname == ';')
|
||||
goto start;
|
||||
|
||||
return s - fname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Continue trying to read len bytes - don't return until len has been
|
||||
* read.
|
||||
**/
|
||||
static void read_loop (int fd, char *buf, size_t len)
|
||||
static void read_loop(int fd, char *buf, size_t len)
|
||||
{
|
||||
while (len) {
|
||||
int n = read_timeout(fd, buf, len);
|
||||
@@ -315,9 +469,9 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
if (remaining > sizeof(line) - 1) {
|
||||
rprintf(FERROR, "multiplexing overflow %d\n\n",
|
||||
remaining);
|
||||
if (remaining > sizeof line - 1) {
|
||||
rprintf(FERROR, "multiplexing overflow %ld\n\n",
|
||||
(long)remaining);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
@@ -338,15 +492,15 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
* have been read. If all @p n can't be read then exit with an
|
||||
* error.
|
||||
**/
|
||||
static void readfd (int fd, char *buffer, size_t N)
|
||||
static void readfd(int fd, char *buffer, size_t N)
|
||||
{
|
||||
int ret;
|
||||
size_t total=0;
|
||||
|
||||
|
||||
while (total < N) {
|
||||
io_flush();
|
||||
|
||||
ret = read_unbuffered (fd, buffer + total, N-total);
|
||||
ret = read_unbuffered(fd, buffer + total, N-total);
|
||||
total += ret;
|
||||
}
|
||||
|
||||
@@ -367,7 +521,6 @@ int32 read_int(int f)
|
||||
|
||||
int64 read_longint(int f)
|
||||
{
|
||||
extern int remote_version;
|
||||
int64 ret;
|
||||
char b[8];
|
||||
ret = read_int(f);
|
||||
@@ -380,10 +533,8 @@ int64 read_longint(int f)
|
||||
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
#else
|
||||
if (remote_version >= 16) {
|
||||
readfd(f,b,8);
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
}
|
||||
readfd(f,b,8);
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
@@ -396,14 +547,14 @@ void read_buf(int f,char *buf,size_t len)
|
||||
|
||||
void read_sbuf(int f,char *buf,size_t len)
|
||||
{
|
||||
read_buf (f,buf,len);
|
||||
read_buf(f,buf,len);
|
||||
buf[len] = 0;
|
||||
}
|
||||
|
||||
unsigned char read_byte(int f)
|
||||
{
|
||||
unsigned char c;
|
||||
read_buf (f, (char *)&c, 1);
|
||||
read_buf(f, (char *)&c, 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -426,7 +577,7 @@ static void sleep_for_bwlimit(int bytes_written)
|
||||
|
||||
assert(bytes_written > 0);
|
||||
assert(bwlimit > 0);
|
||||
|
||||
|
||||
tv.tv_usec = bytes_written * 1000 / bwlimit;
|
||||
tv.tv_sec = tv.tv_usec / 1000000;
|
||||
tv.tv_usec = tv.tv_usec % 1000000;
|
||||
@@ -454,11 +605,11 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
|
||||
while (total < len) {
|
||||
FD_ZERO(&w_fds);
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd,&w_fds);
|
||||
fd_count = fd;
|
||||
|
||||
if (io_error_fd != -1) {
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(io_error_fd,&r_fds);
|
||||
if (io_error_fd > fd_count)
|
||||
fd_count = io_error_fd;
|
||||
@@ -535,7 +686,7 @@ void io_start_buffering(int fd)
|
||||
{
|
||||
if (io_buffer) return;
|
||||
multiplex_out_fd = fd;
|
||||
io_buffer = (char *)malloc(IO_BUFFER_SIZE);
|
||||
io_buffer = new_array(char, IO_BUFFER_SIZE);
|
||||
if (!io_buffer) out_of_memory("writefd");
|
||||
io_buffer_count = 0;
|
||||
}
|
||||
@@ -551,8 +702,8 @@ static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
if (n > (sizeof(buffer)-4)) {
|
||||
n = sizeof(buffer)-4;
|
||||
if (n > (sizeof buffer - 4)) {
|
||||
n = sizeof buffer - 4;
|
||||
}
|
||||
|
||||
memcpy(&buffer[4], buf, n);
|
||||
@@ -612,7 +763,7 @@ static void writefd(int fd,char *buf,size_t len)
|
||||
len -= n;
|
||||
io_buffer_count += n;
|
||||
}
|
||||
|
||||
|
||||
if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
|
||||
}
|
||||
}
|
||||
@@ -640,19 +791,23 @@ void write_int_named(int f, int32 x, const char *phase)
|
||||
*/
|
||||
void write_longint(int f, int64 x)
|
||||
{
|
||||
extern int remote_version;
|
||||
char b[8];
|
||||
|
||||
if (remote_version < 16 || x <= 0x7FFFFFFF) {
|
||||
if (x <= 0x7FFFFFFF) {
|
||||
write_int(f, (int)x);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NO_INT64
|
||||
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
#else
|
||||
write_int(f, (int32)0xFFFFFFFF);
|
||||
SIVAL(b,0,(x&0xFFFFFFFF));
|
||||
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
|
||||
|
||||
writefd(f,b,8);
|
||||
#endif
|
||||
}
|
||||
|
||||
void write_buf(int f,char *buf,size_t len)
|
||||
@@ -710,9 +865,9 @@ void io_printf(int fd, const char *format, ...)
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
len = vsnprintf(buf, sizeof buf, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) exit_cleanup(RERR_STREAMIO);
|
||||
|
||||
482
lib/fnmatch.c
482
lib/fnmatch.c
@@ -1,482 +0,0 @@
|
||||
#include "../rsync.h"
|
||||
#ifndef HAVE_FNMATCH
|
||||
|
||||
/* ----- THE FOLLOWING UP TO 'END' is glibc-2.1.2 posix/fnmatch.c
|
||||
except for the parts with '#if 0' */
|
||||
|
||||
/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if 0 /* header files included better by ../rsync.h */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* Enable GNU extensions in fnmatch.h. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_STRING_H || defined _LIBC
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#if defined STDC_HEADERS || defined _LIBC
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#endif /* 0 */
|
||||
/* For platform which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
#endif
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if 1
|
||||
|
||||
# if defined STDC_HEADERS || !defined isascii
|
||||
# define ISASCII(c) 1
|
||||
# else
|
||||
# define ISASCII(c) isascii(c)
|
||||
# endif
|
||||
|
||||
#ifdef isblank
|
||||
# define ISBLANK(c) (ISASCII (c) && isblank (c))
|
||||
#else
|
||||
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
|
||||
#endif
|
||||
#ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
|
||||
#else
|
||||
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
|
||||
#endif
|
||||
|
||||
#define ISPRINT(c) (ISASCII (c) && isprint (c))
|
||||
#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
|
||||
#define ISALNUM(c) (ISASCII (c) && isalnum (c))
|
||||
#define ISALPHA(c) (ISASCII (c) && isalpha (c))
|
||||
#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
|
||||
#define ISLOWER(c) (ISASCII (c) && islower (c))
|
||||
#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
|
||||
#define ISSPACE(c) (ISASCII (c) && isspace (c))
|
||||
#define ISUPPER(c) (ISASCII (c) && isupper (c))
|
||||
#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
|
||||
|
||||
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
|
||||
|
||||
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
/* The GNU C library provides support for user-defined character classes
|
||||
and the functions from ISO C amendement 1. */
|
||||
# ifdef CHARCLASS_NAME_MAX
|
||||
# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
|
||||
# else
|
||||
/* This shouldn't happen but some implementation might still have this
|
||||
problem. Use a reasonable default value. */
|
||||
# define CHAR_CLASS_MAX_LENGTH 256
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define IS_CHAR_CLASS(string) __wctype (string)
|
||||
# else
|
||||
# define IS_CHAR_CLASS(string) wctype (string)
|
||||
# endif
|
||||
# else
|
||||
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
|
||||
|
||||
# define IS_CHAR_CLASS(string) \
|
||||
(STREQ (string, "alpha") || STREQ (string, "upper") \
|
||||
|| STREQ (string, "lower") || STREQ (string, "digit") \
|
||||
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|
||||
|| STREQ (string, "space") || STREQ (string, "print") \
|
||||
|| STREQ (string, "punct") || STREQ (string, "graph") \
|
||||
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
|
||||
# endif
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
# if !defined _LIBC && !defined getenv
|
||||
extern char *getenv ();
|
||||
# endif
|
||||
|
||||
# ifndef errno
|
||||
extern int errno;
|
||||
# endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, nonzero if not. */
|
||||
static int
|
||||
#ifdef _LIBC
|
||||
internal_function
|
||||
#endif
|
||||
internal_fnmatch (const char *pattern, const char *string,
|
||||
int no_leading_period, int flags)
|
||||
{
|
||||
register const char *p = pattern, *n = string;
|
||||
register unsigned char c;
|
||||
|
||||
/* Note that this evaluates C many times. */
|
||||
# ifdef _LIBC
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
|
||||
# else
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
# endif
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
c = FOLD (c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
return FNM_NOMATCH;
|
||||
else if (*n == '.' && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/' && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
{
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
/* Trailing \ loses. */
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD ((unsigned char) *n) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if (*n == '.' && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/' && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++)
|
||||
{
|
||||
if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
/* A slash does not match a wildcard under FNM_FILE_NAME. */
|
||||
return FNM_NOMATCH;
|
||||
else if (c == '?')
|
||||
{
|
||||
/* A ? needs to match one character. */
|
||||
if (*n == '\0')
|
||||
/* There isn't another character; no match. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
less than three characters. */
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '\0')
|
||||
/* The wildcard(s) is/are the last element of the pattern.
|
||||
If the name is a file name and contains another slash
|
||||
this does mean it cannot match. */
|
||||
return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
|
||||
? FNM_NOMATCH : 0);
|
||||
else
|
||||
{
|
||||
const char *endp;
|
||||
|
||||
#if 0
|
||||
endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
|
||||
#else
|
||||
/* replace call to internal glibc function with equivalent */
|
||||
if (!(flags & FNM_FILE_NAME) || ((endp = strchr(n, '/')) == NULL))
|
||||
endp = n + strlen(n);
|
||||
#endif
|
||||
|
||||
if (c == '[')
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
|
||||
for (--p; n < endp; ++n)
|
||||
if (internal_fnmatch (p, n,
|
||||
(no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/'
|
||||
&& (flags
|
||||
& FNM_FILE_NAME)))),
|
||||
flags2)
|
||||
== 0)
|
||||
return 0;
|
||||
}
|
||||
else if (c == '/' && (flags & FNM_FILE_NAME))
|
||||
{
|
||||
while (*n != '\0' && *n != '/')
|
||||
++n;
|
||||
if (*n == '/'
|
||||
&& (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
|
||||
flags) == 0))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
|
||||
if (c == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c = *p;
|
||||
c = FOLD (c);
|
||||
for (--p; n < endp; ++n)
|
||||
if (FOLD ((unsigned char) *n) == c
|
||||
&& (internal_fnmatch (p, n,
|
||||
(no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/'
|
||||
&& (flags
|
||||
& FNM_FILE_NAME)))),
|
||||
flags2) == 0))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we come here no match is possible with the wildcard. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
case '[':
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
static int posixly_correct;
|
||||
register int not;
|
||||
char cold;
|
||||
|
||||
if (posixly_correct == 0)
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
|
||||
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*n == '.' && no_leading_period && (n == string
|
||||
|| (n[-1] == '/'
|
||||
&& (flags
|
||||
& FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
/* `/' cannot be matched. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
unsigned char fn = FOLD ((unsigned char) *n);
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD ((unsigned char) *p);
|
||||
++p;
|
||||
|
||||
if (c == fn)
|
||||
goto matched;
|
||||
}
|
||||
else if (c == '[' && *p == ':')
|
||||
{
|
||||
/* Leave room for the null. */
|
||||
char str[CHAR_CLASS_MAX_LENGTH + 1];
|
||||
size_t c1 = 0;
|
||||
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
wctype_t wt;
|
||||
# endif
|
||||
const char *startp = p;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (c1 == CHAR_CLASS_MAX_LENGTH)
|
||||
/* The name is too long and therefore the pattern
|
||||
is ill-formed. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *++p;
|
||||
if (c == ':' && p[1] == ']')
|
||||
{
|
||||
p += 2;
|
||||
break;
|
||||
}
|
||||
if (c < 'a' || c >= 'z')
|
||||
{
|
||||
/* This cannot possibly be a character class name.
|
||||
Match it as a normal range. */
|
||||
p = startp;
|
||||
c = '[';
|
||||
goto normal_bracket;
|
||||
}
|
||||
str[c1++] = c;
|
||||
}
|
||||
str[c1] = '\0';
|
||||
|
||||
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
wt = IS_CHAR_CLASS (str);
|
||||
if (wt == 0)
|
||||
/* Invalid character class name. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (__iswctype (__btowc ((unsigned char) *n), wt))
|
||||
goto matched;
|
||||
# else
|
||||
if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
|
||||
|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
|
||||
|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
|
||||
|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
|
||||
|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
|
||||
|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
|
||||
|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
|
||||
|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
|
||||
|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
|
||||
|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
|
||||
|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
|
||||
|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
|
||||
goto matched;
|
||||
# endif
|
||||
}
|
||||
else if (c == '\0')
|
||||
/* [ (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
{
|
||||
normal_bracket:
|
||||
if (FOLD (c) == fn)
|
||||
goto matched;
|
||||
|
||||
cold = c;
|
||||
c = *p++;
|
||||
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
/* It is a range. */
|
||||
unsigned char cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (cold <= fn && fn <= FOLD (cend))
|
||||
goto matched;
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
|
||||
if (!not)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != ']')
|
||||
{
|
||||
if (c == '\0')
|
||||
/* [... (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
else if (c == '[' && *p == ':')
|
||||
{
|
||||
do
|
||||
if (*++p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
while (*p != ':' || p[1] == ']');
|
||||
p += 2;
|
||||
c = *p;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c != FOLD ((unsigned char) *n))
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
if (*n == '\0')
|
||||
return 0;
|
||||
|
||||
if ((flags & FNM_LEADING_DIR) && *n == '/')
|
||||
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
|
||||
return 0;
|
||||
|
||||
return FNM_NOMATCH;
|
||||
|
||||
# undef FOLD
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
const char *pattern;
|
||||
const char *string;
|
||||
int flags;
|
||||
{
|
||||
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
/* ----- END glibc-2.1.2 posix/fnmatch.c */
|
||||
|
||||
#else /* HAVE_FNMATCH */
|
||||
void fnmatch_dummy(void) {}
|
||||
#endif
|
||||
@@ -1,88 +0,0 @@
|
||||
/* Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
|
||||
# if !defined __GLIBC__ || !defined __P
|
||||
# undef __P
|
||||
# define __P(protos) protos
|
||||
# endif
|
||||
#else /* Not C++ or ANSI C. */
|
||||
# undef __P
|
||||
# define __P(protos) ()
|
||||
/* We can get away without defining `const' here only because in this file
|
||||
it is used only inside the prototype for `fnmatch', which is elided in
|
||||
non-ANSI C where `const' is problematical. */
|
||||
#endif /* C++ or ANSI C. */
|
||||
|
||||
#ifndef const
|
||||
# if (defined __STDC__ && __STDC__) || defined __cplusplus
|
||||
# define __const const
|
||||
# else
|
||||
# define __const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
#undef FNM_PATHNAME
|
||||
#undef FNM_NOESCAPE
|
||||
#undef FNM_PERIOD
|
||||
|
||||
/* Bits set in the FLAGS argument to `fnmatch'. */
|
||||
#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
|
||||
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
|
||||
|
||||
#ifndef FNM_FILE_NAME
|
||||
# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
#endif
|
||||
#ifndef FNM_LEADING_DIR
|
||||
# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
#endif
|
||||
#ifndef FNM_CASEFOLD
|
||||
# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* This value is returned if the implementation does not support
|
||||
`fnmatch'. Since this is not the case here it will never be
|
||||
returned but the conformance test suites still require the symbol
|
||||
to be defined. */
|
||||
#ifdef _XOPEN_SOURCE
|
||||
# define FNM_NOSYS (-1)
|
||||
#endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch __P ((__const char *__pattern, __const char *__string,
|
||||
int __flags));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* fnmatch.h */
|
||||
49
lib/mdfour.c
49
lib/mdfour.c
@@ -109,29 +109,53 @@ void mdfour_begin(struct mdfour *md)
|
||||
md->C = 0x98badcfe;
|
||||
md->D = 0x10325476;
|
||||
md->totalN = 0;
|
||||
md->totalN2 = 0;
|
||||
}
|
||||
|
||||
|
||||
static void mdfour_tail(unsigned char *in, int n)
|
||||
static void mdfour_tail(unsigned char *in, uint32 n)
|
||||
{
|
||||
unsigned char buf[128];
|
||||
uint32 M[16];
|
||||
uint32 b;
|
||||
extern int protocol_version;
|
||||
|
||||
m->totalN += n;
|
||||
|
||||
b = m->totalN * 8;
|
||||
/*
|
||||
* Count total number of bits, modulo 2^64
|
||||
*/
|
||||
m->totalN += n << 3;
|
||||
if (m->totalN < (n << 3)) {
|
||||
m->totalN2++;
|
||||
}
|
||||
m->totalN2 += n >> 29;
|
||||
|
||||
memset(buf, 0, 128);
|
||||
if (n) memcpy(buf, in, n);
|
||||
buf[n] = 0x80;
|
||||
|
||||
if (n <= 55) {
|
||||
copy4(buf+56, b);
|
||||
copy4(buf+56, m->totalN);
|
||||
/*
|
||||
* Prior to protocol version 27 only the number of bits
|
||||
* modulo 2^32 was included. MD4 requires the number
|
||||
* of bits modulo 2^64, which was fixed starting with
|
||||
* protocol version 27.
|
||||
*/
|
||||
if (protocol_version >= 27) {
|
||||
copy4(buf+60, m->totalN2);
|
||||
}
|
||||
copy64(M, buf);
|
||||
mdfour64(M);
|
||||
} else {
|
||||
copy4(buf+120, b);
|
||||
copy4(buf+120, m->totalN);
|
||||
/*
|
||||
* Prior to protocol version 27 only the number of bits
|
||||
* modulo 2^32 was included. MD4 requires the number
|
||||
* of bits modulo 2^64, which was fixed starting with
|
||||
* protocol version 27.
|
||||
*/
|
||||
if (protocol_version >= 27) {
|
||||
copy4(buf+124, m->totalN2);
|
||||
}
|
||||
copy64(M, buf);
|
||||
mdfour64(M);
|
||||
copy64(M, buf+64);
|
||||
@@ -139,20 +163,23 @@ static void mdfour_tail(unsigned char *in, int n)
|
||||
}
|
||||
}
|
||||
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, int n)
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n)
|
||||
{
|
||||
uint32 M[16];
|
||||
|
||||
if (n == 0) mdfour_tail(in, n);
|
||||
|
||||
m = md;
|
||||
|
||||
if (n == 0) mdfour_tail(in, n);
|
||||
|
||||
while (n >= 64) {
|
||||
copy64(M, in);
|
||||
mdfour64(M);
|
||||
in += 64;
|
||||
n -= 64;
|
||||
m->totalN += 64;
|
||||
m->totalN += 64 << 3;
|
||||
if (m->totalN < 64 << 3) {
|
||||
m->totalN2++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n) mdfour_tail(in, n);
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
|
||||
struct mdfour {
|
||||
uint32 A, B, C, D;
|
||||
uint32 totalN;
|
||||
uint32 totalN; /* bit count, lower 32 bits */
|
||||
uint32 totalN2; /* bit count, upper 32 bits */
|
||||
};
|
||||
|
||||
void mdfour_begin(struct mdfour *md);
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, int n);
|
||||
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n);
|
||||
void mdfour_result(struct mdfour *md, unsigned char *out);
|
||||
void mdfour(unsigned char *out, unsigned char *in, int n);
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@
|
||||
* got rid of fcvt code (twas buggy and made testing harder)
|
||||
* added C99 semantics
|
||||
*
|
||||
* Paul Green (paulg@samba.org) April 9, 2003
|
||||
* fixed handling of %f when converting fractions with leading zeros.
|
||||
* (e.g., 0.025).
|
||||
**************************************************************/
|
||||
|
||||
#ifndef NO_CONFIG_H /* for some tests */
|
||||
@@ -725,15 +728,15 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
if (max > 0) {
|
||||
dopr_outch (buffer, currlen, maxlen, '.');
|
||||
|
||||
while (zpadlen > 0) {
|
||||
dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
|
||||
while (fplace > 0)
|
||||
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||
}
|
||||
|
||||
while (zpadlen > 0) {
|
||||
dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
|
||||
while (padlen < 0) {
|
||||
dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++padlen;
|
||||
@@ -749,13 +752,15 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
}
|
||||
|
||||
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
|
||||
#define vsnprintf rsync_vsnprintf
|
||||
int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
|
||||
{
|
||||
return dopr(str, count, fmt, args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define snprintf rsync_snprintf
|
||||
int snprintf(char *str,size_t count,const char *fmt,...)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
229
lib/wildmatch.c
Normal file
229
lib/wildmatch.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
** Do shell-style pattern matching for ?, \, [], and * characters.
|
||||
** It is 8bit clean.
|
||||
**
|
||||
** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
|
||||
** Rich $alz is now <rsalz@bbn.com>.
|
||||
**
|
||||
** Modified by Wayne Davison to special-case '/' matching, to make '**'
|
||||
** work differently than '*', and to fix the character-class code.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* What character marks an inverted character class? */
|
||||
#define NEGATE_CLASS '!'
|
||||
#define NEGATE_CLASS2 '^'
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#define ABORT_ALL -1
|
||||
#define ABORT_TO_STARSTAR -2
|
||||
|
||||
#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \
|
||||
&& *(class) == *(litmatch) \
|
||||
&& strncmp((char*)class, litmatch, len) == 0)
|
||||
|
||||
#if defined STDC_HEADERS || !defined isascii
|
||||
# define ISASCII(c) 1
|
||||
#else
|
||||
# define ISASCII(c) isascii(c)
|
||||
#endif
|
||||
|
||||
#ifdef isblank
|
||||
# define ISBLANK(c) (ISASCII(c) && isblank(c))
|
||||
#else
|
||||
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
|
||||
#endif
|
||||
|
||||
#ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII(c) && isgraph(c))
|
||||
#else
|
||||
# define ISGRAPH(c) (ISASCII(c) && isprint(c) && !isspace(c))
|
||||
#endif
|
||||
|
||||
#define ISPRINT(c) (ISASCII(c) && isprint(c))
|
||||
#define ISDIGIT(c) (ISASCII(c) && isdigit(c))
|
||||
#define ISALNUM(c) (ISASCII(c) && isalnum(c))
|
||||
#define ISALPHA(c) (ISASCII(c) && isalpha(c))
|
||||
#define ISCNTRL(c) (ISASCII(c) && iscntrl(c))
|
||||
#define ISLOWER(c) (ISASCII(c) && islower(c))
|
||||
#define ISPUNCT(c) (ISASCII(c) && ispunct(c))
|
||||
#define ISSPACE(c) (ISASCII(c) && isspace(c))
|
||||
#define ISUPPER(c) (ISASCII(c) && isupper(c))
|
||||
#define ISXDIGIT(c) (ISASCII(c) && isxdigit(c))
|
||||
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
int wildmatch_iteration_count;
|
||||
#endif
|
||||
|
||||
static int domatch(const unsigned char *p, const unsigned char *text)
|
||||
{
|
||||
int matched, special;
|
||||
unsigned char ch, prev;
|
||||
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count++;
|
||||
#endif
|
||||
|
||||
for ( ; (ch = *p) != '\0'; text++, p++) {
|
||||
if (*text == '\0' && ch != '*')
|
||||
return FALSE;
|
||||
switch (ch) {
|
||||
case '\\':
|
||||
/* Literal match with following character. Note that the test
|
||||
* in "default" handles the p[1] == '\0' failure case. */
|
||||
ch = *++p;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (*text != ch)
|
||||
return FALSE;
|
||||
continue;
|
||||
case '?':
|
||||
/* Match anything but '/'. */
|
||||
if (*text == '/')
|
||||
return FALSE;
|
||||
continue;
|
||||
case '*':
|
||||
if (*++p == '*') {
|
||||
while (*++p == '*') {}
|
||||
special = TRUE;
|
||||
}
|
||||
else
|
||||
special = FALSE;
|
||||
if (*p == '\0') {
|
||||
/* Trailing "**" matches everything. Trailing "*" matches
|
||||
* only if there are no more slash characters. */
|
||||
return special? TRUE : strchr((char*)text, '/') == NULL;
|
||||
}
|
||||
for ( ; *text; text++) {
|
||||
if ((matched = domatch(p, text)) != FALSE) {
|
||||
if (!special || matched != ABORT_TO_STARSTAR)
|
||||
return matched;
|
||||
}
|
||||
else if (!special && *text == '/')
|
||||
return ABORT_TO_STARSTAR;
|
||||
}
|
||||
return ABORT_ALL;
|
||||
case '[':
|
||||
ch = *++p;
|
||||
#ifdef NEGATE_CLASS2
|
||||
if (ch == NEGATE_CLASS2)
|
||||
ch = NEGATE_CLASS;
|
||||
#endif
|
||||
/* Assign literal TRUE/FALSE because of "matched" comparison. */
|
||||
special = ch == NEGATE_CLASS? TRUE : FALSE;
|
||||
if (special) {
|
||||
/* Inverted character class. */
|
||||
ch = *++p;
|
||||
}
|
||||
prev = 0;
|
||||
matched = FALSE;
|
||||
do {
|
||||
if (!ch)
|
||||
return ABORT_ALL;
|
||||
if (ch == '\\') {
|
||||
ch = *++p;
|
||||
if (!ch)
|
||||
return ABORT_ALL;
|
||||
if (*text == ch)
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (ch == '-' && prev && p[1] && p[1] != ']') {
|
||||
ch = *++p;
|
||||
if (ch == '\\') {
|
||||
ch = *++p;
|
||||
if (!ch)
|
||||
return ABORT_ALL;
|
||||
}
|
||||
if (*text <= ch && *text >= prev)
|
||||
matched = TRUE;
|
||||
ch = 0; /* This makes "prev" get set to 0. */
|
||||
}
|
||||
else if (ch == '[' && p[1] == ':') {
|
||||
const unsigned char *s = p += 2;
|
||||
int i;
|
||||
while ((ch = *p) && ch != ']') p++;
|
||||
if (!ch)
|
||||
return ABORT_ALL;
|
||||
i = p - s - 1;
|
||||
if (i < 0 || p[-1] != ':') {
|
||||
/* Didn't find ":]", so treat like a normal set. */
|
||||
p = s - 2;
|
||||
ch = '[';
|
||||
if (*text == ch)
|
||||
matched = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (CC_EQ(s,i, "alnum")) {
|
||||
if (ISALNUM(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "alpha")) {
|
||||
if (ISALPHA(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "blank")) {
|
||||
if (ISBLANK(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "cntrl")) {
|
||||
if (ISCNTRL(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "digit")) {
|
||||
if (ISDIGIT(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "graph")) {
|
||||
if (ISGRAPH(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "lower")) {
|
||||
if (ISLOWER(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "print")) {
|
||||
if (ISPRINT(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "punct")) {
|
||||
if (ISPUNCT(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "space")) {
|
||||
if (ISSPACE(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "upper")) {
|
||||
if (ISUPPER(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else if (CC_EQ(s,i, "xdigit")) {
|
||||
if (ISXDIGIT(*text))
|
||||
matched = TRUE;
|
||||
}
|
||||
else /* malformed [:class:] string */
|
||||
return ABORT_ALL;
|
||||
ch = 0; /* This makes "prev" get set to 0. */
|
||||
}
|
||||
else if (*text == ch)
|
||||
matched = TRUE;
|
||||
} while (prev = ch, (ch = *++p) != ']');
|
||||
if (matched == special || *text == '/')
|
||||
return FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return *text == '\0';
|
||||
}
|
||||
|
||||
/* Find the pattern (p) in the text string (t). */
|
||||
int wildmatch(const char *p, const char *t)
|
||||
{
|
||||
#ifdef WILD_TEST_ITERATIONS
|
||||
wildmatch_iteration_count = 0;
|
||||
#endif
|
||||
return domatch((const unsigned char*)p, (const unsigned char*)t) == TRUE;
|
||||
}
|
||||
3
lib/wildmatch.h
Normal file
3
lib/wildmatch.h
Normal file
@@ -0,0 +1,3 @@
|
||||
/* wildmatch.h */
|
||||
|
||||
int wildmatch(const char *p, const char *text);
|
||||
86
loadparm.c
86
loadparm.c
@@ -6,17 +6,17 @@
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -36,7 +36,7 @@
|
||||
* 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
|
||||
* 4) If it's a global then initialise it in init_globals. If a local
|
||||
* (ie. service) parameter then initialise it in the sDefault structure
|
||||
*
|
||||
*
|
||||
*
|
||||
* Notes:
|
||||
* The configuration file is processed sequentially for speed. It is NOT
|
||||
@@ -61,7 +61,7 @@ typedef char pstring[1024];
|
||||
typedef enum
|
||||
{
|
||||
P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
|
||||
P_STRING,P_GSTRING,P_ENUM,P_SEP
|
||||
P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
|
||||
} parm_type;
|
||||
|
||||
typedef enum
|
||||
@@ -93,7 +93,7 @@ struct parm_struct
|
||||
#define iSERVICE(i) (*pSERVICE(i))
|
||||
#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
|
||||
|
||||
/*
|
||||
/*
|
||||
* This structure describes global (ie., server-wide) parameters.
|
||||
*/
|
||||
typedef struct
|
||||
@@ -109,8 +109,8 @@ static global Globals;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This structure describes a single service.
|
||||
/*
|
||||
* This structure describes a single service.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -144,7 +144,7 @@ typedef struct
|
||||
|
||||
|
||||
/* This is a default service used to prime a services structure */
|
||||
static service sDefault =
|
||||
static service sDefault =
|
||||
{
|
||||
NULL, /* name */
|
||||
NULL, /* path */
|
||||
@@ -156,7 +156,7 @@ static service sDefault =
|
||||
False, /* transfer logging */
|
||||
False, /* ignore errors */
|
||||
"nobody",/* uid */
|
||||
|
||||
|
||||
/* TODO: This causes problems on Debian, where it is called
|
||||
* "nogroup". Debian patch this in their version of the
|
||||
* package, but it would be nice to be consistent. Possibly
|
||||
@@ -165,7 +165,7 @@ static service sDefault =
|
||||
* What is the best behaviour? Perhaps always using (gid_t)
|
||||
* -2? */
|
||||
"nobody",/* gid */
|
||||
|
||||
|
||||
NULL, /* hosts allow */
|
||||
NULL, /* hosts deny */
|
||||
NULL, /* auth users */
|
||||
@@ -222,7 +222,7 @@ static struct enum_list enum_facilities[] = {
|
||||
{ LOG_NEWS, "news" },
|
||||
#endif
|
||||
#ifdef LOG_AUTH
|
||||
{ LOG_AUTH, "security" },
|
||||
{ LOG_AUTH, "security" },
|
||||
#endif
|
||||
#ifdef LOG_SYSLOG
|
||||
{ LOG_SYSLOG, "syslog" },
|
||||
@@ -274,7 +274,7 @@ static struct parm_struct parm_table[] =
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
|
||||
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
|
||||
{"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
|
||||
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
|
||||
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
|
||||
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
|
||||
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
|
||||
@@ -319,8 +319,8 @@ static void init_locals(void)
|
||||
|
||||
|
||||
/*
|
||||
In this section all the functions that are used to access the
|
||||
parameters from the rest of the program are defined
|
||||
In this section all the functions that are used to access the
|
||||
parameters from the rest of the program are defined
|
||||
*/
|
||||
|
||||
#define FN_GLOBAL_STRING(fn_name,ptr) \
|
||||
@@ -376,12 +376,11 @@ FN_LOCAL_INTEGER(lp_timeout, timeout)
|
||||
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
|
||||
|
||||
/* local prototypes */
|
||||
static int strwicmp( char *psz1, char *psz2 );
|
||||
static int map_parameter( char *parmname);
|
||||
static BOOL set_boolean( BOOL *pb, char *parmvalue );
|
||||
static int strwicmp(char *psz1, char *psz2);
|
||||
static int map_parameter(char *parmname);
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue);
|
||||
static int getservicebyname(char *name, service *pserviceDest);
|
||||
static void copy_service( service *pserviceDest,
|
||||
service *pserviceSource);
|
||||
static void copy_service(service *pserviceDest, service *pserviceSource);
|
||||
static BOOL do_parameter(char *parmname, char *parmvalue);
|
||||
static BOOL do_section(char *sectionname);
|
||||
|
||||
@@ -421,7 +420,7 @@ static void string_set(char **s, const char *v)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
add a new service to the services array initialising it with the given
|
||||
add a new service to the services array initialising it with the given
|
||||
service
|
||||
***************************************************************************/
|
||||
static int add_a_service(service *pservice, char *name)
|
||||
@@ -433,7 +432,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
tservice = *pservice;
|
||||
|
||||
/* it might already exist */
|
||||
if (name)
|
||||
if (name)
|
||||
{
|
||||
i = getservicebyname(name,NULL);
|
||||
if (i >= 0)
|
||||
@@ -442,10 +441,10 @@ static int add_a_service(service *pservice, char *name)
|
||||
|
||||
i = iNumServices;
|
||||
|
||||
ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
|
||||
ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
|
||||
|
||||
if (ServicePtrs)
|
||||
pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
|
||||
pSERVICE(iNumServices) = new(service);
|
||||
|
||||
if (!ServicePtrs || !pSERVICE(iNumServices))
|
||||
return(-1);
|
||||
@@ -455,7 +454,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
init_service(pSERVICE(i));
|
||||
copy_service(pSERVICE(i),&tservice);
|
||||
if (name)
|
||||
string_set(&iSERVICE(i).name,name);
|
||||
string_set(&iSERVICE(i).name,name);
|
||||
|
||||
return(i);
|
||||
}
|
||||
@@ -493,7 +492,7 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Map a parameter's string representation to something we can use.
|
||||
Map a parameter's string representation to something we can use.
|
||||
Returns False if the parameter string is not recognised, else TRUE.
|
||||
***************************************************************************/
|
||||
static int map_parameter(char *parmname)
|
||||
@@ -503,7 +502,7 @@ static int map_parameter(char *parmname)
|
||||
if (*parmname == '-')
|
||||
return(-1);
|
||||
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
|
||||
return(iIndex);
|
||||
|
||||
@@ -514,7 +513,7 @@ static int map_parameter(char *parmname)
|
||||
|
||||
/***************************************************************************
|
||||
Set a boolean variable from the text value stored in the passed string.
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
represent a boolean.
|
||||
***************************************************************************/
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
@@ -548,7 +547,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
int iService;
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--)
|
||||
if (strwicmp(iSERVICE(iService).name, name) == 0)
|
||||
if (strwicmp(iSERVICE(iService).name, name) == 0)
|
||||
{
|
||||
if (pserviceDest != NULL)
|
||||
copy_service(pserviceDest, pSERVICE(iService));
|
||||
@@ -564,7 +563,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
Copy a service structure to another
|
||||
|
||||
***************************************************************************/
|
||||
static void copy_service(service *pserviceDest,
|
||||
static void copy_service(service *pserviceDest,
|
||||
service *pserviceSource)
|
||||
{
|
||||
int i;
|
||||
@@ -572,9 +571,9 @@ static void copy_service(service *pserviceDest,
|
||||
for (i=0;parm_table[i].label;i++)
|
||||
if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
|
||||
void *def_ptr = parm_table[i].ptr;
|
||||
void *src_ptr =
|
||||
void *src_ptr =
|
||||
((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
|
||||
void *dest_ptr =
|
||||
void *dest_ptr =
|
||||
((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
|
||||
|
||||
switch (parm_table[i].type)
|
||||
@@ -594,6 +593,7 @@ static void copy_service(service *pserviceDest,
|
||||
*(char *)dest_ptr = *(char *)src_ptr;
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
case P_STRING:
|
||||
string_set(dest_ptr,*(char **)src_ptr);
|
||||
break;
|
||||
@@ -614,6 +614,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
int parmnum, i;
|
||||
void *parm_ptr=NULL; /* where we are going to store the result */
|
||||
void *def_ptr=NULL;
|
||||
char *cp;
|
||||
|
||||
parmnum = map_parameter(parmname);
|
||||
|
||||
@@ -660,6 +661,15 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
sscanf(parmvalue,"%o",(int *)parm_ptr);
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
string_set(parm_ptr,parmvalue);
|
||||
if ((cp = *(char**)parm_ptr) != NULL) {
|
||||
int len = strlen(cp);
|
||||
while (len > 1 && cp[len-1] == '/') len--;
|
||||
cp[len] = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
case P_STRING:
|
||||
string_set(parm_ptr,parmvalue);
|
||||
break;
|
||||
@@ -711,7 +721,7 @@ static BOOL do_section(char *sectionname)
|
||||
init_locals();
|
||||
|
||||
/* if we've just struck a global section, note the fact. */
|
||||
bInGlobalSection = isglobal;
|
||||
bInGlobalSection = isglobal;
|
||||
|
||||
/* check for multiple global sections */
|
||||
if (bInGlobalSection)
|
||||
@@ -743,7 +753,7 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Load the services array from the services file. Return True on success,
|
||||
Load the services array from the services file. Return True on success,
|
||||
False on failure.
|
||||
***************************************************************************/
|
||||
BOOL lp_load(char *pszFname, int globals_only)
|
||||
@@ -753,11 +763,11 @@ BOOL lp_load(char *pszFname, int globals_only)
|
||||
extern int am_root;
|
||||
pstring n2;
|
||||
BOOL bRetval;
|
||||
|
||||
|
||||
bRetval = False;
|
||||
|
||||
bInGlobalSection = True;
|
||||
|
||||
|
||||
init_globals();
|
||||
|
||||
if (pszFname)
|
||||
@@ -770,7 +780,7 @@ BOOL lp_load(char *pszFname, int globals_only)
|
||||
/* We get sections first, so have to start 'behind' to make up */
|
||||
iServiceIndex = -1;
|
||||
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
|
||||
|
||||
|
||||
return (bRetval);
|
||||
}
|
||||
|
||||
@@ -794,7 +804,7 @@ int lp_number(char *name)
|
||||
int iService;
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--)
|
||||
if (strequal(lp_name(iService), name))
|
||||
if (strequal(lp_name(iService), name))
|
||||
break;
|
||||
|
||||
return (iService);
|
||||
|
||||
196
log.c
196
log.c
@@ -1,18 +1,18 @@
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
|
||||
|
||||
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -39,26 +39,27 @@ struct {
|
||||
int code;
|
||||
char const *name;
|
||||
} const rerr_names[] = {
|
||||
{ RERR_SYNTAX , "syntax or usage error" },
|
||||
{ RERR_PROTOCOL , "protocol incompatibility" },
|
||||
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
|
||||
{ RERR_UNSUPPORTED, "requested action not supported" },
|
||||
{ RERR_STARTCLIENT, "error starting client-server protocol" },
|
||||
{ RERR_SOCKETIO , "error in socket IO" },
|
||||
{ RERR_FILEIO , "error in file IO" },
|
||||
{ RERR_STREAMIO , "error in rsync protocol data stream" },
|
||||
{ RERR_MESSAGEIO , "errors with program diagnostics" },
|
||||
{ RERR_IPC , "error in IPC code" },
|
||||
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
|
||||
{ RERR_WAITCHILD , "some error returned by waitpid()" },
|
||||
{ RERR_MALLOC , "error allocating core memory buffers" },
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_SYNTAX , "syntax or usage error" },
|
||||
{ RERR_PROTOCOL , "protocol incompatibility" },
|
||||
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
|
||||
{ RERR_UNSUPPORTED, "requested action not supported" },
|
||||
{ RERR_STARTCLIENT, "error starting client-server protocol" },
|
||||
{ RERR_SOCKETIO , "error in socket IO" },
|
||||
{ RERR_FILEIO , "error in file IO" },
|
||||
{ RERR_STREAMIO , "error in rsync protocol data stream" },
|
||||
{ RERR_MESSAGEIO , "errors with program diagnostics" },
|
||||
{ RERR_IPC , "error in IPC code" },
|
||||
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
|
||||
{ RERR_WAITCHILD , "some error returned by waitpid()" },
|
||||
{ RERR_MALLOC , "error allocating core memory buffers" },
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_VANISHED , "some files vanished before they could be transfered" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_CMD_FAILED , "remote shell failed" },
|
||||
{ RERR_CMD_KILLED , "remote shell killed" },
|
||||
{ RERR_CMD_RUN, "remote command could not be run" },
|
||||
{ RERR_CMD_NOTFOUND, "remote command not found" },
|
||||
{ 0, NULL }
|
||||
{ RERR_CMD_NOTFOUND, "remote command not found" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -68,12 +69,12 @@ struct {
|
||||
*/
|
||||
static char const *rerr_name(int code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; rerr_names[i].name; i++) {
|
||||
if (rerr_names[i].code == code)
|
||||
return rerr_names[i].name;
|
||||
}
|
||||
return NULL;
|
||||
int i;
|
||||
for (i = 0; rerr_names[i].name; i++) {
|
||||
if (rerr_names[i].code == code)
|
||||
return rerr_names[i].name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct err_list {
|
||||
@@ -90,10 +91,10 @@ static struct err_list *err_list_tail;
|
||||
static void err_list_add(int code, char *buf, int len)
|
||||
{
|
||||
struct err_list *el;
|
||||
el = (struct err_list *)malloc(sizeof(*el));
|
||||
el = new(struct err_list);
|
||||
if (!el) exit_cleanup(RERR_MALLOC);
|
||||
el->next = NULL;
|
||||
el->buf = malloc(len+4);
|
||||
el->buf = new_array(char, len+4);
|
||||
if (!el->buf) exit_cleanup(RERR_MALLOC);
|
||||
memcpy(el->buf+4, buf, len);
|
||||
SIVAL(el->buf, 0, ((code+MPLEX_BASE)<<24) | len);
|
||||
@@ -117,7 +118,7 @@ void err_list_push(void)
|
||||
struct err_list *el = err_list_head;
|
||||
int n = write(log_error_fd, el->buf+el->written, el->len - el->written);
|
||||
/* don't check for an error if the best way of handling the error is
|
||||
to ignore it */
|
||||
* to ignore it */
|
||||
if (n == -1) break;
|
||||
if (n > 0) {
|
||||
el->written += n;
|
||||
@@ -137,7 +138,7 @@ static void logit(int priority, char *buf)
|
||||
if (logfname) {
|
||||
if (!logfile)
|
||||
log_open();
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
timestring(time(NULL)), (int)getpid(), buf);
|
||||
fflush(logfile);
|
||||
} else {
|
||||
@@ -154,8 +155,8 @@ void log_init(void)
|
||||
log_initialised = 1;
|
||||
|
||||
/* this looks pointless, but it is needed in order for the
|
||||
C library on some systems to fetch the timezone info
|
||||
before the chroot */
|
||||
* C library on some systems to fetch the timezone info
|
||||
* before the chroot */
|
||||
t = time(NULL);
|
||||
localtime(&t);
|
||||
|
||||
@@ -203,7 +204,7 @@ void log_close(void)
|
||||
}
|
||||
|
||||
/* setup the error file descriptor - used when we are a server
|
||||
that is receiving files */
|
||||
* that is receiving files */
|
||||
void set_error_fd(int fd)
|
||||
{
|
||||
log_error_fd = fd;
|
||||
@@ -211,7 +212,7 @@ void set_error_fd(int fd)
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
it with FINFO, FERROR or FLOG */
|
||||
* it with FINFO, FERROR or FLOG */
|
||||
void rwrite(enum logcode code, char *buf, int len)
|
||||
{
|
||||
FILE *f=NULL;
|
||||
@@ -238,9 +239,9 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
return;
|
||||
}
|
||||
|
||||
/* next, if we are a server but not in daemon mode, and multiplexing
|
||||
* is enabled, pass it to the other side. */
|
||||
if (am_server && !am_daemon && io_multiplex_write(code, buf, len)) {
|
||||
/* next, if we are a server and multiplexing is enabled,
|
||||
* pass it to the other side. */
|
||||
if (am_server && io_multiplex_write(code, buf, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -250,7 +251,9 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
* side because we don't want the client to see most errors for
|
||||
* security reasons. We do want early messages when running daemon
|
||||
* mode over a remote shell to go to the remote side; those will
|
||||
* fall through to the next case. */
|
||||
* fall through to the next case.
|
||||
* Note that this is only for the time before multiplexing is enabled.
|
||||
*/
|
||||
if (am_daemon && (!am_server || log_initialised)) {
|
||||
static int depth;
|
||||
int priority = LOG_INFO;
|
||||
@@ -270,14 +273,14 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
if (code == FERROR) {
|
||||
log_got_error = 1;
|
||||
f = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == FINFO) {
|
||||
if (am_server)
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
@@ -291,7 +294,7 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
* FLOG. */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
@@ -340,11 +343,11 @@ void rprintf(enum logcode code, const char *format, ...)
|
||||
* message catalog we need to call it once before chroot-ing. */
|
||||
void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
size_t sys_len;
|
||||
char *sysmsg;
|
||||
char *sysmsg;
|
||||
|
||||
va_start(ap, format);
|
||||
/* Note: might return <0 */
|
||||
@@ -356,17 +359,17 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
if ((size_t) len > sizeof(buf)-1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
sysmsg = strerror(errcode);
|
||||
sys_len = strlen(sysmsg);
|
||||
if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
sysmsg = strerror(errcode);
|
||||
sys_len = strlen(sysmsg);
|
||||
if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
strcpy(buf + len, ": ");
|
||||
len += 2;
|
||||
strcpy(buf + len, sysmsg);
|
||||
len += sys_len;
|
||||
strcpy(buf + len, "\n");
|
||||
len++;
|
||||
strcpy(buf + len, ": ");
|
||||
len += 2;
|
||||
strcpy(buf + len, sysmsg);
|
||||
len += sys_len;
|
||||
strcpy(buf + len, "\n");
|
||||
len++;
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
@@ -384,19 +387,19 @@ void rflush(enum logcode code)
|
||||
|
||||
if (code == FLOG) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == FINFO) {
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(RERR_MESSAGEIO);
|
||||
fflush(f);
|
||||
@@ -405,7 +408,7 @@ void rflush(enum logcode code)
|
||||
|
||||
|
||||
/* a generic logging routine for send/recv, with parameter
|
||||
substitiution */
|
||||
* substitiution */
|
||||
static void log_formatted(enum logcode code,
|
||||
char *format, char *op, struct file_struct *file,
|
||||
struct stats *initial_stats)
|
||||
@@ -429,57 +432,56 @@ static void log_formatted(enum logcode code,
|
||||
memset(buf, 0, sizeof buf);
|
||||
strlcpy(buf, format, sizeof(buf));
|
||||
|
||||
for (s=&buf[0];
|
||||
s && (p=strchr(s,'%')); ) {
|
||||
for (s = &buf[0]; s && (p = strchr(s,'%')); ) {
|
||||
n = NULL;
|
||||
s = p + 1;
|
||||
|
||||
switch (p[1]) {
|
||||
case 'h': if (am_daemon) n = client_name(0); break;
|
||||
case 'a': if (am_daemon) n = client_addr(0); break;
|
||||
case 'l':
|
||||
snprintf(buf2,sizeof(buf2),"%.0f",
|
||||
(double)file->length);
|
||||
case 'l':
|
||||
snprintf(buf2,sizeof(buf2),"%.0f",
|
||||
(double)file->length);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'p':
|
||||
snprintf(buf2,sizeof(buf2),"%d",
|
||||
(int)getpid());
|
||||
case 'p':
|
||||
snprintf(buf2,sizeof(buf2),"%d",
|
||||
(int)getpid());
|
||||
n = buf2;
|
||||
break;
|
||||
case 'o': n = op; break;
|
||||
case 'f':
|
||||
snprintf(buf2, sizeof(buf2), "%s/%s",
|
||||
file->basedir?file->basedir:"",
|
||||
case 'f':
|
||||
snprintf(buf2, sizeof(buf2), "%s/%s",
|
||||
file->basedir?file->basedir:"",
|
||||
f_name(file));
|
||||
clean_fname(buf2);
|
||||
n = buf2;
|
||||
n = buf2;
|
||||
if (*n == '/') n++;
|
||||
break;
|
||||
case 'm': n = lp_name(module_id); break;
|
||||
case 't': n = timestring(time(NULL)); break;
|
||||
case 'P': n = lp_path(module_id); break;
|
||||
case 'u': n = auth_user; break;
|
||||
case 'b':
|
||||
case 'b':
|
||||
if (am_sender) {
|
||||
b = stats.total_written -
|
||||
b = stats.total_written -
|
||||
initial_stats->total_written;
|
||||
} else {
|
||||
b = stats.total_read -
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'c':
|
||||
case 'c':
|
||||
if (!am_sender) {
|
||||
b = stats.total_written -
|
||||
b = stats.total_written -
|
||||
initial_stats->total_written;
|
||||
} else {
|
||||
b = stats.total_read -
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
}
|
||||
@@ -560,27 +562,19 @@ void log_exit(int code, const char *file, int line)
|
||||
(double)stats.total_read,
|
||||
(double)stats.total_size);
|
||||
} else {
|
||||
const char *name;
|
||||
const char *name;
|
||||
|
||||
name = rerr_name(code);
|
||||
if (!name)
|
||||
name = "unexplained error";
|
||||
|
||||
rprintf(FERROR,"rsync error: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
name = rerr_name(code);
|
||||
if (!name)
|
||||
name = "unexplained error";
|
||||
|
||||
/* VANISHED is not an error, only a warning */
|
||||
if (code == RERR_VANISHED) {
|
||||
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
} else {
|
||||
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Log the incoming transfer of a file for interactive use,
|
||||
* this will be called at the end where the client was run.
|
||||
* Called when a file starts to be transferred.
|
||||
*/
|
||||
void log_transfer(struct file_struct *file, const char *fname)
|
||||
{
|
||||
extern int verbose;
|
||||
|
||||
if (!verbose) return;
|
||||
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
}
|
||||
|
||||
484
main.c
484
main.c
@@ -1,19 +1,19 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -24,7 +24,14 @@
|
||||
time_t starttime = 0;
|
||||
|
||||
extern struct stats stats;
|
||||
extern char *files_from;
|
||||
extern int filesfrom_fd;
|
||||
extern char *remote_filesfrom_file;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
extern int verbose;
|
||||
extern int protocol_version;
|
||||
|
||||
/* there's probably never more than at most 2 outstanding child processes,
|
||||
* but set it higher just in case.
|
||||
@@ -50,7 +57,7 @@ void wait_process(pid_t pid, int *status)
|
||||
msleep(20);
|
||||
io_flush();
|
||||
}
|
||||
|
||||
|
||||
if ((waited_pid == -1) && (errno == ECHILD)) {
|
||||
/* status of requested child no longer available.
|
||||
* check to see if it was processed by the sigchld_handler.
|
||||
@@ -64,25 +71,21 @@ void wait_process(pid_t pid, int *status)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: If the child exited on a signal, then log an
|
||||
* appropriate error message. Perhaps we should also accept a
|
||||
* message describing the purpose of the child. Also indicate
|
||||
* this to the caller so that thhey know something went
|
||||
* wrong. */
|
||||
/* TODO: If the child exited on a signal, then log an
|
||||
* appropriate error message. Perhaps we should also accept a
|
||||
* message describing the purpose of the child. Also indicate
|
||||
* this to the caller so that thhey know something went
|
||||
* wrong. */
|
||||
*status = WEXITSTATUS(*status);
|
||||
}
|
||||
|
||||
static void report(int f)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
extern int do_stats;
|
||||
extern int remote_version;
|
||||
int send_stats;
|
||||
|
||||
if (do_stats) {
|
||||
if (do_stats && verbose > 1) {
|
||||
/* These come out from every process */
|
||||
show_malloc_stats();
|
||||
show_flist_stats();
|
||||
@@ -93,12 +96,12 @@ static void report(int f)
|
||||
if (f == -1 || !am_sender) return;
|
||||
}
|
||||
|
||||
send_stats = verbose || (remote_version >= 20);
|
||||
send_stats = verbose || protocol_version >= 20;
|
||||
if (am_server) {
|
||||
if (am_sender && send_stats) {
|
||||
int64 w;
|
||||
/* store total_written in a temporary
|
||||
because write_longint changes it */
|
||||
* because write_longint changes it */
|
||||
w = stats.total_written;
|
||||
write_longint(f,stats.total_read);
|
||||
write_longint(f,w);
|
||||
@@ -108,7 +111,7 @@ static void report(int f)
|
||||
}
|
||||
|
||||
/* this is the client */
|
||||
|
||||
|
||||
if (!am_sender && send_stats) {
|
||||
int64 r;
|
||||
stats.total_written = read_longint(f);
|
||||
@@ -120,37 +123,37 @@ static void report(int f)
|
||||
|
||||
if (do_stats) {
|
||||
if (!am_sender && !send_stats) {
|
||||
/* missing the bytes written by the generator */
|
||||
rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
|
||||
rprintf(FINFO, "Use --stats -v to show stats\n");
|
||||
return;
|
||||
/* missing the bytes written by the generator */
|
||||
rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
|
||||
rprintf(FINFO, "Use --stats -v to show stats\n");
|
||||
return;
|
||||
}
|
||||
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
|
||||
rprintf(FINFO,"Number of files transferred: %d\n",
|
||||
stats.num_transferred_files);
|
||||
rprintf(FINFO,"Total file size: %.0f bytes\n",
|
||||
(double)stats.total_size);
|
||||
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
|
||||
(double)stats.total_transferred_size);
|
||||
rprintf(FINFO,"Literal data: %.0f bytes\n",
|
||||
(double)stats.literal_data);
|
||||
rprintf(FINFO,"Matched data: %.0f bytes\n",
|
||||
(double)stats.matched_data);
|
||||
rprintf(FINFO,"Number of files transferred: %d\n",
|
||||
stats.num_transferred_files);
|
||||
rprintf(FINFO,"Total file size: %.0f bytes\n",
|
||||
(double)stats.total_size);
|
||||
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
|
||||
(double)stats.total_transferred_size);
|
||||
rprintf(FINFO,"Literal data: %.0f bytes\n",
|
||||
(double)stats.literal_data);
|
||||
rprintf(FINFO,"Matched data: %.0f bytes\n",
|
||||
(double)stats.matched_data);
|
||||
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
|
||||
rprintf(FINFO,"Total bytes written: %.0f\n",
|
||||
(double)stats.total_written);
|
||||
rprintf(FINFO,"Total bytes read: %.0f\n\n",
|
||||
(double)stats.total_read);
|
||||
rprintf(FINFO,"Total bytes written: %.0f\n",
|
||||
(double)stats.total_written);
|
||||
rprintf(FINFO,"Total bytes read: %.0f\n",
|
||||
(double)stats.total_read);
|
||||
}
|
||||
|
||||
|
||||
if (verbose || do_stats) {
|
||||
rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
|
||||
(double)stats.total_written,
|
||||
(double)stats.total_read,
|
||||
(stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
|
||||
rprintf(FINFO,"\nwrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
|
||||
(double)stats.total_written,
|
||||
(double)stats.total_read,
|
||||
(stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
|
||||
rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
|
||||
(double)stats.total_size,
|
||||
(1.0*stats.total_size)/(stats.total_written+stats.total_read));
|
||||
(double)stats.total_size,
|
||||
(1.0*stats.total_size)/(stats.total_written+stats.total_read));
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
@@ -165,13 +168,10 @@ static void show_malloc_stats(void)
|
||||
{
|
||||
#ifdef HAVE_MALLINFO
|
||||
struct mallinfo mi;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
|
||||
mi = mallinfo();
|
||||
|
||||
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
|
||||
rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
|
||||
getpid(),
|
||||
am_server ? "server " : "",
|
||||
am_daemon ? "daemon " : "",
|
||||
@@ -205,20 +205,21 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
|
||||
extern int read_batch;
|
||||
|
||||
if (!read_batch && !local_server) {
|
||||
char *rsh_env = getenv(RSYNC_RSH_ENV);
|
||||
if (!cmd)
|
||||
cmd = getenv(RSYNC_RSH_ENV);
|
||||
cmd = rsh_env;
|
||||
if (!cmd)
|
||||
cmd = RSYNC_RSH;
|
||||
cmd = strdup(cmd);
|
||||
if (!cmd)
|
||||
if (!cmd)
|
||||
goto oom;
|
||||
|
||||
for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
|
||||
args[argc++] = tok;
|
||||
}
|
||||
|
||||
/* check to see if we've already been given '-l user' in
|
||||
the remote-shell command */
|
||||
/* check to see if we've already been given '-l user' in
|
||||
* the remote-shell command */
|
||||
for (i = 0; i < argc-1; i++) {
|
||||
if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
|
||||
dash_l_set = 1;
|
||||
@@ -241,16 +242,22 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
|
||||
|
||||
args[argc++] = rsync_path;
|
||||
|
||||
if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
|
||||
blocking_io = 1;
|
||||
if (blocking_io < 0) {
|
||||
char *cp;
|
||||
if ((cp = strrchr(cmd, '/')) != NULL)
|
||||
cp++;
|
||||
else
|
||||
cp = cmd;
|
||||
if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
|
||||
blocking_io = 1;
|
||||
}
|
||||
|
||||
server_options(args,&argc);
|
||||
|
||||
}
|
||||
|
||||
args[argc++] = ".";
|
||||
|
||||
if (!daemon_over_rsh && path && *path)
|
||||
if (!daemon_over_rsh && path && *path)
|
||||
args[argc++] = path;
|
||||
|
||||
args[argc] = NULL;
|
||||
@@ -264,7 +271,7 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
|
||||
|
||||
if (local_server) {
|
||||
if (read_batch)
|
||||
create_flist_from_batch(); /* sets batch_flist */
|
||||
create_flist_from_batch(); /* sets batch_flist */
|
||||
ret = local_child(argc, args, f_in, f_out, child_main);
|
||||
} else {
|
||||
ret = piped_child(args,f_in,f_out);
|
||||
@@ -285,20 +292,21 @@ oom:
|
||||
static char *get_local_name(struct file_list *flist,char *name)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
int e;
|
||||
extern int orig_umask;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"get_local_name count=%d %s\n",
|
||||
rprintf(FINFO,"get_local_name count=%d %s\n",
|
||||
flist->count, NS(name));
|
||||
|
||||
if (!name)
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (do_stat(name,&st) == 0) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (1)\n",
|
||||
name,strerror(errno));
|
||||
rprintf(FERROR, "push_dir %s failed: %s (1)\n",
|
||||
full_fname(name), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
return NULL;
|
||||
@@ -310,12 +318,12 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
return name;
|
||||
}
|
||||
|
||||
if (flist->count <= 1)
|
||||
if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
|
||||
return name;
|
||||
|
||||
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": mkdir %s: %s\n",
|
||||
name, strerror(errno));
|
||||
rprintf(FERROR, "mkdir %s failed: %s\n",
|
||||
full_fname(name), strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
} else {
|
||||
if (verbose > 0)
|
||||
@@ -323,8 +331,8 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
}
|
||||
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR, RSYNC_NAME ": push_dir %s: %s\n",
|
||||
name, strerror(errno));
|
||||
rprintf(FERROR, "push_dir %s failed: %s (2)\n",
|
||||
full_fname(name), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
@@ -341,21 +349,21 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
char *dir = argv[0];
|
||||
extern int relative_paths;
|
||||
extern int recurse;
|
||||
extern int remote_version;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
|
||||
|
||||
|
||||
if (!relative_paths && !push_dir(dir, 0)) {
|
||||
rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
|
||||
rprintf(FERROR, "push_dir %s failed: %s (3)\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
|
||||
if (strcmp(dir,".")) {
|
||||
int l = strlen(dir);
|
||||
if (strcmp(dir,"/") == 0)
|
||||
if (strcmp(dir,"/") == 0)
|
||||
l = 0;
|
||||
for (i=0;i<argc;i++)
|
||||
argv[i] += l+1;
|
||||
@@ -366,7 +374,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
argv--;
|
||||
argv[0] = ".";
|
||||
}
|
||||
|
||||
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (!flist || flist->count == 0) {
|
||||
exit_cleanup(0);
|
||||
@@ -375,8 +383,8 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
send_files(flist,f_out,f_in);
|
||||
io_flush();
|
||||
report(f_out);
|
||||
if (remote_version >= 24) {
|
||||
/* final goodbye message */
|
||||
if (protocol_version >= 24) {
|
||||
/* final goodbye message */
|
||||
read_int(f_in);
|
||||
}
|
||||
io_flush();
|
||||
@@ -394,7 +402,6 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
extern int delete_after;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
extern int remote_version;
|
||||
|
||||
if (preserve_hard_links)
|
||||
init_hard_links(flist);
|
||||
@@ -415,7 +422,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
rprintf(FERROR,"error pipe failed in do_recv\n");
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
|
||||
io_flush();
|
||||
|
||||
if ((pid=do_fork()) == 0) {
|
||||
@@ -437,8 +444,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
close(recv_pipe[1]);
|
||||
io_flush();
|
||||
/* finally we go to sleep until our parent kills us
|
||||
with a USR2 signal. We sleep for a short time as on
|
||||
some OSes a signal won't interrupt a sleep! */
|
||||
* with a USR2 signal. We sleep for a short time as on
|
||||
* some OSes a signal won't interrupt a sleep! */
|
||||
while (msleep(20))
|
||||
;
|
||||
}
|
||||
@@ -455,7 +462,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
|
||||
read_int(recv_pipe[0]);
|
||||
close(recv_pipe[0]);
|
||||
if (remote_version >= 24) {
|
||||
if (protocol_version >= 24) {
|
||||
/* send a final goodbye message */
|
||||
write_int(f_out, -1);
|
||||
}
|
||||
@@ -476,9 +483,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
char *dir = NULL;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int am_daemon;
|
||||
extern int module_id;
|
||||
extern int am_sender;
|
||||
extern int read_batch;
|
||||
extern struct file_list *batch_flist;
|
||||
|
||||
@@ -491,31 +496,40 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (argc > 0) {
|
||||
dir = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
if (!am_daemon && !push_dir(dir, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (4)\n",
|
||||
dir,strerror(errno));
|
||||
rprintf(FERROR, "push_dir %s failed: %s (4)\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_mode && !delete_excluded)
|
||||
recv_exclude_list(f_in);
|
||||
|
||||
if (filesfrom_fd >= 0) {
|
||||
/* We're receiving the file info from the sender, so we need
|
||||
* the IO routines to automatically write out the names onto
|
||||
* our f_out socket as we read the list info from the sender.
|
||||
* This avoids both deadlock and extra delays/buffers. */
|
||||
io_set_filesfrom_fds(filesfrom_fd, f_out);
|
||||
filesfrom_fd = -1;
|
||||
}
|
||||
|
||||
if (read_batch)
|
||||
flist = batch_flist;
|
||||
flist = batch_flist;
|
||||
else
|
||||
flist = recv_file_list(f_in);
|
||||
flist = recv_file_list(f_in);
|
||||
if (!flist) {
|
||||
rprintf(FERROR,"server_recv: recv_file_list error\n");
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
|
||||
if (argc > 0) {
|
||||
if (strcmp(dir,".")) {
|
||||
argv[0] += strlen(dir);
|
||||
if (argv[0][0] == '/') argv[0]++;
|
||||
@@ -538,8 +552,6 @@ int child_main(int argc, char *argv[])
|
||||
void start_server(int f_in, int f_out, int argc, char *argv[])
|
||||
{
|
||||
extern int cvs_exclude;
|
||||
extern int am_sender;
|
||||
extern int remote_version;
|
||||
extern int read_batch;
|
||||
|
||||
setup_protocol(f_out, f_in);
|
||||
@@ -547,14 +559,14 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
|
||||
set_nonblocking(f_in);
|
||||
set_nonblocking(f_out);
|
||||
|
||||
if (remote_version >= 23)
|
||||
if (protocol_version >= 23)
|
||||
io_start_multiplex_out(f_out);
|
||||
|
||||
if (am_sender) {
|
||||
if (!read_batch) {
|
||||
recv_exclude_list(f_in);
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
recv_exclude_list(f_in);
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
}
|
||||
do_server_sender(f_in, f_out, argc, argv);
|
||||
} else {
|
||||
@@ -573,8 +585,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
struct file_list *flist = NULL;
|
||||
int status = 0, status2 = 0;
|
||||
char *local_name = NULL;
|
||||
extern int am_sender;
|
||||
extern int remote_version;
|
||||
extern pid_t cleanup_child_pid;
|
||||
extern int write_batch;
|
||||
extern int read_batch;
|
||||
@@ -582,32 +592,34 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
|
||||
cleanup_child_pid = pid;
|
||||
if (read_batch)
|
||||
flist = batch_flist;
|
||||
flist = batch_flist;
|
||||
|
||||
set_nonblocking(f_in);
|
||||
set_nonblocking(f_out);
|
||||
|
||||
setup_protocol(f_out,f_in);
|
||||
|
||||
if (remote_version >= 23)
|
||||
if (protocol_version >= 23)
|
||||
io_start_multiplex_in(f_in);
|
||||
|
||||
|
||||
if (am_sender) {
|
||||
extern int cvs_exclude;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
if (delete_mode && !delete_excluded)
|
||||
if (delete_mode && !delete_excluded)
|
||||
send_exclude_list(f_out);
|
||||
if (remote_filesfrom_file)
|
||||
filesfrom_fd = f_in;
|
||||
if (!read_batch) /* dw -- don't write to pipe */
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (verbose > 3)
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"file list sent\n");
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
if (remote_version >= 24) {
|
||||
/* final goodbye message */
|
||||
if (protocol_version >= 24) {
|
||||
/* final goodbye message */
|
||||
read_int(f_in);
|
||||
}
|
||||
if (pid != -1) {
|
||||
@@ -624,48 +636,37 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
extern int list_only;
|
||||
list_only = 1;
|
||||
}
|
||||
|
||||
|
||||
if (!write_batch)
|
||||
send_exclude_list(f_out);
|
||||
|
||||
send_exclude_list(f_out);
|
||||
|
||||
if (filesfrom_fd >= 0) {
|
||||
io_set_filesfrom_fds(filesfrom_fd, f_out);
|
||||
filesfrom_fd = -1;
|
||||
}
|
||||
|
||||
flist = recv_file_list(f_in);
|
||||
if (!flist || flist->count == 0) {
|
||||
rprintf(FINFO, "client: nothing to do: "
|
||||
"perhaps you need to specify some filenames or "
|
||||
"the --recursive option?\n");
|
||||
"perhaps you need to specify some filenames or "
|
||||
"the --recursive option?\n");
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
|
||||
local_name = get_local_name(flist,argv[0]);
|
||||
|
||||
|
||||
status2 = do_recv(f_in,f_out,flist,local_name);
|
||||
|
||||
|
||||
if (pid != -1) {
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
|
||||
io_flush();
|
||||
wait_process(pid, &status);
|
||||
}
|
||||
|
||||
|
||||
return MAX(status, status2);
|
||||
}
|
||||
|
||||
static char *find_colon(char *s)
|
||||
{
|
||||
char *p, *p2;
|
||||
|
||||
p = strchr(s,':');
|
||||
if (!p) return NULL;
|
||||
|
||||
/* now check to see if there is a / in the string before the : - if there is then
|
||||
discard the colon on the assumption that the : is part of a filename */
|
||||
p2 = strchr(s,'/');
|
||||
if (p2 && p2 < p) return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static int copy_argv (char *argv[])
|
||||
{
|
||||
int i;
|
||||
@@ -700,7 +701,6 @@ static int start_client(int argc, char *argv[])
|
||||
pid_t pid;
|
||||
int f_in,f_out;
|
||||
extern int local_server;
|
||||
extern int am_sender;
|
||||
extern char *shell_cmd;
|
||||
extern int rsync_port;
|
||||
extern int daemon_over_rsh;
|
||||
@@ -708,7 +708,7 @@ static int start_client(int argc, char *argv[])
|
||||
int rc;
|
||||
|
||||
/* Don't clobber argv[] so that ps(1) can still show the right
|
||||
command line. */
|
||||
* command line. */
|
||||
if ((rc = copy_argv(argv)))
|
||||
return rc;
|
||||
|
||||
@@ -734,84 +734,102 @@ static int start_client(int argc, char *argv[])
|
||||
|
||||
if (!read_batch) {
|
||||
p = find_colon(argv[0]);
|
||||
|
||||
if (p) {
|
||||
if (p[1] == ':') { /* double colon */
|
||||
*p = 0;
|
||||
if (!shell_cmd) {
|
||||
return start_socket_client(argv[0], p+2,
|
||||
argc-1, argv+1);
|
||||
if (p) {
|
||||
if (remote_filesfrom_file
|
||||
&& remote_filesfrom_file != files_from + 1
|
||||
&& strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
|
||||
rprintf(FERROR,
|
||||
"--files-from hostname is not transfer hostname\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (p[1] == ':') { /* double colon */
|
||||
*p = 0;
|
||||
if (!shell_cmd) {
|
||||
return start_socket_client(argv[0], p+2,
|
||||
argc-1, argv+1);
|
||||
}
|
||||
p++;
|
||||
daemon_over_rsh = 1;
|
||||
}
|
||||
p++;
|
||||
daemon_over_rsh = 1;
|
||||
}
|
||||
|
||||
if (argc < 1) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (argc < 1) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
am_sender = 0;
|
||||
*p = 0;
|
||||
shell_machine = argv[0];
|
||||
shell_path = p+1;
|
||||
argc--;
|
||||
argv++;
|
||||
am_sender = 0;
|
||||
*p = 0;
|
||||
shell_machine = argv[0];
|
||||
shell_path = p+1;
|
||||
argc--;
|
||||
argv++;
|
||||
} else {
|
||||
am_sender = 1;
|
||||
|
||||
/* rsync:// destination uses rsync server over direct socket */
|
||||
if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
|
||||
char *host, *path;
|
||||
|
||||
host = argv[argc-1] + strlen(URL_PREFIX);
|
||||
p = strchr(host,'/');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
path = p+1;
|
||||
} else {
|
||||
path = "";
|
||||
}
|
||||
p = strchr(host,':');
|
||||
if (p) {
|
||||
rsync_port = atoi(p+1);
|
||||
*p = 0;
|
||||
}
|
||||
return start_socket_client(host, path, argc-1, argv);
|
||||
}
|
||||
|
||||
p = find_colon(argv[argc-1]);
|
||||
if (p && remote_filesfrom_file
|
||||
&& remote_filesfrom_file != files_from + 1
|
||||
&& strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
|
||||
rprintf(FERROR,
|
||||
"--files-from hostname is not transfer hostname\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (!p) {
|
||||
local_server = 1;
|
||||
if (remote_filesfrom_file) {
|
||||
rprintf(FERROR,
|
||||
"--files-from is remote but transfer is local\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
} else if (p[1] == ':') { /* double colon */
|
||||
*p = 0;
|
||||
if (!shell_cmd) {
|
||||
return start_socket_client(argv[argc-1], p+2,
|
||||
argc-1, argv);
|
||||
}
|
||||
p++;
|
||||
daemon_over_rsh = 1;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (local_server) {
|
||||
shell_machine = NULL;
|
||||
shell_path = argv[argc-1];
|
||||
} else {
|
||||
*p = 0;
|
||||
shell_machine = argv[argc-1];
|
||||
shell_path = p+1;
|
||||
}
|
||||
argc--;
|
||||
}
|
||||
} else {
|
||||
am_sender = 1;
|
||||
|
||||
/* rsync:// destination uses rsync server over direct socket */
|
||||
if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
|
||||
char *host, *path;
|
||||
|
||||
host = argv[argc-1] + strlen(URL_PREFIX);
|
||||
p = strchr(host,'/');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
path = p+1;
|
||||
} else {
|
||||
path = "";
|
||||
}
|
||||
p = strchr(host,':');
|
||||
if (p) {
|
||||
rsync_port = atoi(p+1);
|
||||
*p = 0;
|
||||
}
|
||||
return start_socket_client(host, path, argc-1, argv);
|
||||
}
|
||||
|
||||
p = find_colon(argv[argc-1]);
|
||||
if (!p) {
|
||||
local_server = 1;
|
||||
} else if (p[1] == ':') { /* double colon */
|
||||
*p = 0;
|
||||
if (!shell_cmd) {
|
||||
return start_socket_client(argv[argc-1], p+2,
|
||||
argc-1, argv);
|
||||
}
|
||||
p++;
|
||||
daemon_over_rsh = 1;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (local_server) {
|
||||
shell_machine = NULL;
|
||||
shell_path = argv[argc-1];
|
||||
} else {
|
||||
*p = 0;
|
||||
shell_machine = argv[argc-1];
|
||||
shell_path = p+1;
|
||||
}
|
||||
argc--;
|
||||
}
|
||||
} else {
|
||||
am_sender = 1;
|
||||
local_server = 1;
|
||||
shell_path = argv[argc-1];
|
||||
local_server = 1;
|
||||
shell_path = argv[argc-1];
|
||||
}
|
||||
|
||||
if (shell_machine) {
|
||||
@@ -830,7 +848,7 @@ static int start_client(int argc, char *argv[])
|
||||
shell_user?shell_user:"",
|
||||
shell_path?shell_path:"");
|
||||
}
|
||||
|
||||
|
||||
if (!am_sender && argc > 1) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -840,12 +858,12 @@ static int start_client(int argc, char *argv[])
|
||||
extern int list_only;
|
||||
list_only = 1;
|
||||
}
|
||||
|
||||
|
||||
pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
|
||||
&f_in,&f_out);
|
||||
|
||||
/* if we're running an rsync server on the remote host over a
|
||||
remote shell command, we need to do the RSYNCD protocol first */
|
||||
* remote shell command, we need to do the RSYNCD protocol first */
|
||||
if (daemon_over_rsh) {
|
||||
int tmpret;
|
||||
tmpret = start_inband_exchange(shell_user, shell_path,
|
||||
@@ -863,35 +881,38 @@ static int start_client(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
|
||||
static RETSIGTYPE sigusr1_handler(UNUSED(int val))
|
||||
{
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
|
||||
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
|
||||
{
|
||||
extern int log_got_error;
|
||||
if (log_got_error) _exit(RERR_PARTIAL);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
|
||||
static RETSIGTYPE sigchld_handler(UNUSED(int val))
|
||||
{
|
||||
#ifdef WNOHANG
|
||||
int cnt, status;
|
||||
pid_t pid;
|
||||
/* An empty waitpid() loop was put here by Tridge and we could never
|
||||
* get him to explain why he put it in, so rather than taking it
|
||||
* get him to explain why he put it in, so rather than taking it
|
||||
* out we're instead saving the child exit statuses for later use.
|
||||
* The waitpid() loop presumably eliminates all possibility of leaving
|
||||
* zombie children, maybe that's why he did it.
|
||||
*/
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
/* save the child's exit status */
|
||||
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
|
||||
if (pid_stat_table[cnt].pid == 0) {
|
||||
pid_stat_table[cnt].pid = pid;
|
||||
pid_stat_table[cnt].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* save the child's exit status */
|
||||
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
|
||||
if (pid_stat_table[cnt].pid == 0) {
|
||||
pid_stat_table[cnt].pid = pid;
|
||||
pid_stat_table[cnt].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -931,7 +952,7 @@ const char *get_panic_action(void)
|
||||
* should just look at the environment variable, but I'm a bit leery
|
||||
* of a signal sending us into a busy loop.
|
||||
**/
|
||||
static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
|
||||
static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
|
||||
{
|
||||
char cmd_buf[300];
|
||||
int ret;
|
||||
@@ -949,12 +970,10 @@ static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
{
|
||||
extern int am_root;
|
||||
extern int orig_umask;
|
||||
extern int dry_run;
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
int ret;
|
||||
extern int write_batch;
|
||||
int orig_argc;
|
||||
@@ -984,12 +1003,12 @@ int main(int argc,char *argv[])
|
||||
}
|
||||
|
||||
/* we set a 0 umask so that correct file permissions can be
|
||||
carried across */
|
||||
* carried across */
|
||||
orig_umask = (int)umask(0);
|
||||
|
||||
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
|
||||
/* FIXME: We ought to call the same error-handling
|
||||
* code here, rather than relying on getopt. */
|
||||
/* FIXME: We ought to call the same error-handling
|
||||
* code here, rather than relying on getopt. */
|
||||
option_error();
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
@@ -1003,13 +1022,13 @@ int main(int argc,char *argv[])
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* Initialize push_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. */
|
||||
* (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);
|
||||
|
||||
if (write_batch && !am_server) {
|
||||
write_batch_argvs_file(orig_argc, orig_argv);
|
||||
write_batch_argvs_file(orig_argc, orig_argv);
|
||||
}
|
||||
|
||||
if (am_daemon && !am_server)
|
||||
@@ -1039,11 +1058,10 @@ int main(int argc,char *argv[])
|
||||
}
|
||||
|
||||
ret = start_client(argc, argv);
|
||||
if (ret == -1)
|
||||
if (ret == -1)
|
||||
exit_cleanup(RERR_STARTCLIENT);
|
||||
else
|
||||
exit_cleanup(ret);
|
||||
|
||||
exit(ret);
|
||||
/* NOTREACHED */
|
||||
return ret;
|
||||
}
|
||||
|
||||
156
match.c
156
match.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -19,12 +19,9 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
|
||||
extern int remote_version;
|
||||
extern int do_progress;
|
||||
|
||||
typedef unsigned short tag;
|
||||
|
||||
@@ -43,8 +40,8 @@ static int total_matches;
|
||||
extern struct stats stats;
|
||||
|
||||
struct target {
|
||||
tag t;
|
||||
int i;
|
||||
tag t;
|
||||
int i;
|
||||
};
|
||||
|
||||
static struct target *targets;
|
||||
@@ -56,34 +53,33 @@ static int *tag_table;
|
||||
|
||||
static int compare_targets(struct target *t1,struct target *t2)
|
||||
{
|
||||
return((int)t1->t - (int)t2->t);
|
||||
return (int)t1->t - (int)t2->t;
|
||||
}
|
||||
|
||||
|
||||
static void build_hash_table(struct sum_struct *s)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (!tag_table)
|
||||
tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
|
||||
if (!tag_table)
|
||||
tag_table = new_array(int, TABLESIZE);
|
||||
|
||||
targets = (struct target *)malloc(sizeof(targets[0])*s->count);
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
targets = new_array(struct target, s->count);
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
|
||||
for (i=0;i<(int) s->count;i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
}
|
||||
for (i = 0; i < (int)s->count; i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
}
|
||||
|
||||
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
|
||||
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
|
||||
|
||||
for (i=0;i<TABLESIZE;i++)
|
||||
tag_table[i] = NULL_TAG;
|
||||
for (i = 0; i < TABLESIZE; i++)
|
||||
tag_table[i] = NULL_TAG;
|
||||
|
||||
for (i=s->count-1;i>=0;i--) {
|
||||
tag_table[targets[i].t] = i;
|
||||
}
|
||||
for (i = s->count-1; i >= 0; i--)
|
||||
tag_table[targets[i].t] = i;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +115,8 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
stats.matched_data += s->sums[i].len;
|
||||
n += s->sums[i].len;
|
||||
}
|
||||
|
||||
for (j=0;j<n;j+=CHUNK_SIZE) {
|
||||
|
||||
for (j = 0; j < n; j += CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,n-j);
|
||||
sum_update(map_ptr(buf,last_match+j,n1),n1);
|
||||
}
|
||||
@@ -131,7 +127,7 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
else
|
||||
last_match = offset;
|
||||
|
||||
if (buf) {
|
||||
if (buf && do_progress) {
|
||||
show_progress(last_match, buf->file_size);
|
||||
|
||||
if (i == -1) end_progress(buf->file_size);
|
||||
@@ -145,7 +141,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
OFF_T offset, end;
|
||||
int j,k, last_i;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
uint32 s1, s2, sum;
|
||||
schar *map;
|
||||
|
||||
/* last_i is used to encourage adjacent matches, allowing the RLL coding of the
|
||||
@@ -154,36 +150,34 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"hash search b=%ld len=%.0f\n",
|
||||
(long) s->n, (double)len);
|
||||
(long) s->blength, (double)len);
|
||||
|
||||
k = MIN(len, (OFF_T)s->blength);
|
||||
|
||||
/* cast is to make s->n signed; it should always be reasonably
|
||||
* small */
|
||||
k = MIN(len, (OFF_T) s->n);
|
||||
|
||||
map = (schar *)map_ptr(buf,0,k);
|
||||
|
||||
|
||||
sum = get_checksum1((char *)map, k);
|
||||
s1 = sum & 0xFFFF;
|
||||
s2 = sum >> 16;
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "sum=%.8x k=%d\n", sum, k);
|
||||
|
||||
|
||||
offset = 0;
|
||||
|
||||
|
||||
end = len + 1 - s->sums[s->count-1].len;
|
||||
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "hash search s->n=%ld len=%.0f count=%ld\n",
|
||||
(long) s->n, (double) len, (long) s->count);
|
||||
|
||||
rprintf(FINFO, "hash search s->blength=%ld len=%.0f count=%ld\n",
|
||||
(long) s->blength, (double) len, (long) s->count);
|
||||
|
||||
do {
|
||||
tag t = gettag2(s1,s2);
|
||||
int done_csum2 = 0;
|
||||
|
||||
|
||||
j = tag_table[t];
|
||||
if (verbose > 4)
|
||||
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
|
||||
|
||||
|
||||
if (j == NULL_TAG) {
|
||||
goto null_tag;
|
||||
}
|
||||
@@ -192,47 +186,47 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
tag_hits++;
|
||||
for (; j < (int) s->count && targets[j].t == t; j++) {
|
||||
int l, i = targets[j].i;
|
||||
|
||||
|
||||
if (sum != s->sums[i].sum1) continue;
|
||||
|
||||
|
||||
/* also make sure the two blocks are the same length */
|
||||
l = MIN(s->n,len-offset);
|
||||
if (l != s->sums[i].len) continue;
|
||||
l = MIN((OFF_T)s->blength, len-offset);
|
||||
if (l != s->sums[i].len) continue;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"potential match at %.0f target=%d %d sum=%08x\n",
|
||||
(double)offset,j,i,sum);
|
||||
|
||||
|
||||
if (!done_csum2) {
|
||||
map = (schar *)map_ptr(buf,offset,l);
|
||||
get_checksum2((char *)map,l,sum2);
|
||||
done_csum2 = 1;
|
||||
}
|
||||
|
||||
if (memcmp(sum2,s->sums[i].sum2,csum_length) != 0) {
|
||||
|
||||
if (memcmp(sum2,s->sums[i].sum2,s->s2length) != 0) {
|
||||
false_alarms++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we've found a match, but now check to see
|
||||
if last_i can hint at a better match */
|
||||
* if last_i can hint at a better match */
|
||||
for (j++; j < (int) s->count && targets[j].t == t; j++) {
|
||||
int i2 = targets[j].i;
|
||||
if (i2 == last_i + 1) {
|
||||
if (sum != s->sums[i2].sum1) break;
|
||||
if (memcmp(sum2,s->sums[i2].sum2,csum_length) != 0) break;
|
||||
/* we've found an adjacent match - the RLL coder
|
||||
will be happy */
|
||||
if (memcmp(sum2,s->sums[i2].sum2,s->s2length) != 0) break;
|
||||
/* we've found an adjacent match - the RLL coder
|
||||
* will be happy */
|
||||
i = i2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last_i = i;
|
||||
|
||||
|
||||
matched(f,s,buf,offset,i);
|
||||
offset += s->sums[i].len - 1;
|
||||
k = MIN((len-offset), s->n);
|
||||
k = MIN((OFF_T)s->blength, len-offset);
|
||||
map = (schar *)map_ptr(buf,offset,k);
|
||||
sum = get_checksum1((char *)map, k);
|
||||
s1 = sum & 0xFFFF;
|
||||
@@ -240,13 +234,13 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
matches++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
null_tag:
|
||||
/* Trim off the first byte from the checksum */
|
||||
map = (schar *)map_ptr(buf,offset,k+1);
|
||||
s1 -= map[0] + CHAR_OFFSET;
|
||||
s2 -= k * (map[0]+CHAR_OFFSET);
|
||||
|
||||
|
||||
/* Add on the next byte (if there is one) to the checksum */
|
||||
if (k < (len-offset)) {
|
||||
s1 += (map[k]+CHAR_OFFSET);
|
||||
@@ -261,13 +255,13 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
match. The 3 reads are caused by the
|
||||
running match, the checksum update and the
|
||||
literal send. */
|
||||
if (offset > last_match &&
|
||||
offset-last_match >= CHUNK_SIZE+s->n &&
|
||||
(end-offset > CHUNK_SIZE)) {
|
||||
matched(f,s,buf,offset - s->n, -2);
|
||||
if (offset > last_match
|
||||
&& offset-last_match >= CHUNK_SIZE+s->blength
|
||||
&& end-offset > CHUNK_SIZE) {
|
||||
matched(f,s,buf,offset - s->blength, -2);
|
||||
}
|
||||
} while (++offset < end);
|
||||
|
||||
|
||||
matched(f,s,buf,len,-1);
|
||||
map_ptr(buf,len-1,1);
|
||||
}
|
||||
@@ -295,25 +289,25 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
last_match = 0;
|
||||
false_alarms = 0;
|
||||
tag_hits = 0;
|
||||
matches=0;
|
||||
data_transfer=0;
|
||||
matches = 0;
|
||||
data_transfer = 0;
|
||||
|
||||
sum_init();
|
||||
|
||||
if (len > 0 && s->count>0) {
|
||||
build_hash_table(s);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"built hash table\n");
|
||||
|
||||
|
||||
hash_search(f,s,buf,len);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"done hash search\n");
|
||||
} else {
|
||||
OFF_T j;
|
||||
/* by doing this in pieces we avoid too many seeks */
|
||||
for (j=0;j<(len-CHUNK_SIZE);j+=CHUNK_SIZE) {
|
||||
for (j = 0; j < len-CHUNK_SIZE; j += CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
|
||||
matched(f,s,buf,j+n1,-2);
|
||||
}
|
||||
@@ -322,23 +316,21 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
|
||||
sum_end(file_sum);
|
||||
|
||||
if (remote_version >= 14) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
if (write_batch) /* dw */
|
||||
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
if (write_batch) /* dw */
|
||||
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
|
||||
|
||||
if (targets) {
|
||||
free(targets);
|
||||
targets=NULL;
|
||||
}
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
|
||||
false_alarms, tag_hits, matches);
|
||||
|
||||
|
||||
total_tag_hits += tag_hits;
|
||||
total_false_alarms += false_alarms;
|
||||
total_matches += matches;
|
||||
|
||||
541
options.c
541
options.c
@@ -1,18 +1,18 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
*
|
||||
* Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 2000, 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -21,20 +21,21 @@
|
||||
#include "rsync.h"
|
||||
#include "popt.h"
|
||||
|
||||
extern struct exclude_struct **exclude_list;
|
||||
|
||||
int make_backups = 0;
|
||||
|
||||
/**
|
||||
* If True, send the whole file as literal data rather than trying to
|
||||
* If 1, send the whole file as literal data rather than trying to
|
||||
* create an incremental diff.
|
||||
*
|
||||
* If both are 0, then look at whether we're local or remote and go by
|
||||
* that.
|
||||
* If -1, then look at whether we're local or remote and go by that.
|
||||
*
|
||||
* @sa disable_deltas_p()
|
||||
**/
|
||||
int whole_file = 0;
|
||||
int no_whole_file = 0;
|
||||
int whole_file = -1;
|
||||
|
||||
int archive_mode = 0;
|
||||
int copy_links = 0;
|
||||
int preserve_links = 0;
|
||||
int preserve_hard_links = 0;
|
||||
@@ -51,20 +52,24 @@ int ignore_times=0;
|
||||
int delete_mode=0;
|
||||
int delete_excluded=0;
|
||||
int one_file_system=0;
|
||||
int remote_version=0;
|
||||
int protocol_version = PROTOCOL_VERSION;
|
||||
int sparse_files=0;
|
||||
int do_compression=0;
|
||||
int am_root=0;
|
||||
int orig_umask=0;
|
||||
int relative_paths=0;
|
||||
int relative_paths = -1;
|
||||
int implied_dirs = 1;
|
||||
int numeric_ids = 0;
|
||||
int force_delete = 0;
|
||||
int io_timeout = 0;
|
||||
int io_error = 0;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int am_server = 0;
|
||||
int am_sender = 0;
|
||||
char *files_from = NULL;
|
||||
int filesfrom_fd = -1;
|
||||
char *remote_filesfrom_file = NULL;
|
||||
int eol_nulls = 0;
|
||||
int recurse = 0;
|
||||
int am_daemon = 0;
|
||||
int daemon_over_rsh = 0;
|
||||
@@ -73,7 +78,7 @@ int do_progress=0;
|
||||
int keep_partial=0;
|
||||
int safe_symlinks=0;
|
||||
int copy_unsafe_links=0;
|
||||
int block_size=BLOCK_SIZE;
|
||||
int block_size=0;
|
||||
int size_only=0;
|
||||
int bwlimit=0;
|
||||
int delete_after=0;
|
||||
@@ -99,9 +104,10 @@ int no_detach = 0;
|
||||
|
||||
int write_batch = 0;
|
||||
int read_batch = 0;
|
||||
int suffix_specified = 0;
|
||||
int backup_dir_len = 0;
|
||||
int backup_suffix_len;
|
||||
|
||||
char *backup_suffix = BACKUP_SUFFIX;
|
||||
char *backup_suffix = NULL;
|
||||
char *tmpdir = NULL;
|
||||
char *compare_dest = NULL;
|
||||
char *config_file = NULL;
|
||||
@@ -130,43 +136,43 @@ char *bind_address;
|
||||
|
||||
static void print_rsync_version(enum logcode f)
|
||||
{
|
||||
char const *got_socketpair = "no ";
|
||||
char const *hardlinks = "no ";
|
||||
char const *links = "no ";
|
||||
char const *got_socketpair = "no ";
|
||||
char const *hardlinks = "no ";
|
||||
char const *links = "no ";
|
||||
char const *ipv6 = "no ";
|
||||
STRUCT_STAT *dumstat;
|
||||
|
||||
#ifdef HAVE_SOCKETPAIR
|
||||
got_socketpair = "";
|
||||
got_socketpair = "";
|
||||
#endif
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
hardlinks = "";
|
||||
hardlinks = "";
|
||||
#endif
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
links = "";
|
||||
links = "";
|
||||
#endif
|
||||
|
||||
#if INET6
|
||||
ipv6 = "";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
rprintf(f, "%s version %s protocol version %d\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
|
||||
rprintf(f,
|
||||
"Copyright (C) 1996-2002 by Andrew Tridgell and others\n");
|
||||
rprintf(f, "%s version %s protocol version %d\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
|
||||
rprintf(f,
|
||||
"Copyright (C) 1996-2004 by Andrew Tridgell and others\n");
|
||||
rprintf(f, "<http://rsync.samba.org/>\n");
|
||||
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
|
||||
"%shard links, %ssymlinks, batchfiles, \n",
|
||||
(int) (sizeof(OFF_T) * 8),
|
||||
got_socketpair, hardlinks, links);
|
||||
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
|
||||
"%shard links, %ssymlinks, batchfiles, \n",
|
||||
(int) (sizeof(OFF_T) * 8),
|
||||
got_socketpair, hardlinks, links);
|
||||
|
||||
/* Note that this field may not have type ino_t. It depends
|
||||
* on the complicated interaction between largefile feature
|
||||
* macros. */
|
||||
rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n",
|
||||
ipv6,
|
||||
ipv6,
|
||||
(int) (sizeof(dumstat->st_ino) * 8),
|
||||
(int) (sizeof(INO64_T) * 8));
|
||||
#ifdef MAINTAINER_MODE
|
||||
@@ -175,7 +181,7 @@ static void print_rsync_version(enum logcode f)
|
||||
#endif
|
||||
|
||||
#ifdef NO_INT64
|
||||
rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
|
||||
rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
|
||||
#endif
|
||||
|
||||
rprintf(f,
|
||||
@@ -210,9 +216,11 @@ void usage(enum logcode F)
|
||||
rprintf(F," -a, --archive archive mode, equivalent to -rlptgoD\n");
|
||||
rprintf(F," -r, --recursive recurse into directories\n");
|
||||
rprintf(F," -R, --relative use relative path names\n");
|
||||
rprintf(F," --no-relative turn off --relative\n");
|
||||
rprintf(F," --no-implied-dirs don't send implied dirs with -R\n");
|
||||
rprintf(F," -b, --backup make backups (default %s suffix)\n",BACKUP_SUFFIX);
|
||||
rprintf(F," --backup-dir make backups into this directory\n");
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
|
||||
rprintf(F," -l, --links copy symlinks as symlinks\n");
|
||||
rprintf(F," -L, --copy-links copy the referent of symlinks\n");
|
||||
@@ -223,16 +231,15 @@ void usage(enum logcode F)
|
||||
rprintf(F," -o, --owner preserve owner (root only)\n");
|
||||
rprintf(F," -g, --group preserve group\n");
|
||||
rprintf(F," -D, --devices preserve devices (root only)\n");
|
||||
rprintf(F," -t, --times preserve times\n");
|
||||
rprintf(F," -t, --times preserve times\n");
|
||||
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 whole files, no incremental checks\n");
|
||||
rprintf(F," --no-whole-file turn off --whole-file\n");
|
||||
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
|
||||
rprintf(F," -B, --block-size=SIZE checksum blocking size (default %d)\n",BLOCK_SIZE);
|
||||
rprintf(F," -B, --block-size=SIZE checksum blocking size (default %d)\n",BLOCK_SIZE);
|
||||
rprintf(F," -e, --rsh=COMMAND specify the remote shell\n");
|
||||
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
|
||||
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
|
||||
rprintf(F," --existing only update files that already exist\n");
|
||||
rprintf(F," --ignore-existing ignore files that already exist on the receiving side\n");
|
||||
rprintf(F," --delete delete files that don't exist on the sending side\n");
|
||||
@@ -249,23 +256,27 @@ void usage(enum logcode F)
|
||||
rprintf(F," --modify-window=NUM Timestamp window (seconds) for file match (default=%d)\n",modify_window);
|
||||
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
|
||||
rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
|
||||
rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
|
||||
rprintf(F," -P equivalent to --partial --progress\n");
|
||||
rprintf(F," -z, --compress compress file data\n");
|
||||
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
|
||||
rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
|
||||
rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
|
||||
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
|
||||
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --no-detach do not detach from the parent\n");
|
||||
rprintf(F," --address=ADDRESS bind to the specified address\n");
|
||||
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
|
||||
rprintf(F," -0 --from0 file names we read are separated by nulls, not newlines\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --no-detach do not detach from the parent\n");
|
||||
rprintf(F," --address=ADDRESS bind to the specified address\n");
|
||||
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
|
||||
rprintf(F," --blocking-io use blocking IO for the remote shell\n");
|
||||
rprintf(F," --no-blocking-io turn off --blocking-io\n");
|
||||
rprintf(F," --stats give some file transfer stats\n");
|
||||
rprintf(F," --progress show progress during transfer\n");
|
||||
rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
|
||||
rprintf(F," --blocking-io use blocking IO for the remote shell\n");
|
||||
rprintf(F," --no-blocking-io turn off --blocking-io\n");
|
||||
rprintf(F," --stats give some file transfer stats\n");
|
||||
rprintf(F," --progress show progress during transfer\n");
|
||||
rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
|
||||
rprintf(F," --password-file=FILE get password from FILE\n");
|
||||
rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
|
||||
rprintf(F," --write-batch=PREFIX write batch fileset starting with PREFIX\n");
|
||||
@@ -282,93 +293,92 @@ void usage(enum logcode F)
|
||||
rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
|
||||
}
|
||||
|
||||
enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
|
||||
OPT_EXCLUDE_FROM, OPT_DELETE, OPT_DELETE_EXCLUDED, OPT_NUMERIC_IDS,
|
||||
OPT_RSYNC_PATH, OPT_FORCE, OPT_TIMEOUT, OPT_DAEMON, OPT_CONFIG, OPT_PORT,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
|
||||
OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST, OPT_LINK_DEST,
|
||||
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
|
||||
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
|
||||
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
|
||||
OPT_NO_BLOCKING_IO, OPT_WHOLE_FILE, OPT_NO_WHOLE_FILE,
|
||||
OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_IGNORE_EXISTING};
|
||||
enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
|
||||
OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
|
||||
{"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
|
||||
{"suffix", 0, POPT_ARG_STRING, &backup_suffix, OPT_SUFFIX, 0, 0 },
|
||||
{"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
|
||||
{"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
|
||||
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
|
||||
{"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
|
||||
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times , 0, 0, 0 },
|
||||
{"size-only", 0, POPT_ARG_NONE, &size_only , 0, 0, 0 },
|
||||
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
|
||||
{"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
|
||||
{"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
|
||||
{"one-file-system", 'x', POPT_ARG_NONE, &one_file_system , 0, 0, 0 },
|
||||
{"delete", 0, POPT_ARG_NONE, &delete_mode , 0, 0, 0 },
|
||||
{"existing", 0, POPT_ARG_NONE, &only_existing , 0, 0, 0 },
|
||||
{"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing , 0, 0, 0 },
|
||||
{"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
|
||||
{"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 },
|
||||
{"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
|
||||
{"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
|
||||
{"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 },
|
||||
{"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 },
|
||||
{"force", 0, POPT_ARG_NONE, &force_delete , 0, 0, 0 },
|
||||
{"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids , 0, 0, 0 },
|
||||
{"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
|
||||
{"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids, 0, 0, 0 },
|
||||
{"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
|
||||
{"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 },
|
||||
{"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 },
|
||||
{"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 },
|
||||
{"safe-links", 0, POPT_ARG_NONE, &safe_symlinks , 0, 0, 0 },
|
||||
{"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 },
|
||||
{"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
|
||||
{"backup", 'b', POPT_ARG_NONE, &make_backups , 0, 0, 0 },
|
||||
{"dry-run", 'n', POPT_ARG_NONE, &dry_run , 0, 0, 0 },
|
||||
{"sparse", 'S', POPT_ARG_NONE, &sparse_files , 0, 0, 0 },
|
||||
{"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude , 0, 0, 0 },
|
||||
{"update", 'u', POPT_ARG_NONE, &update_only , 0, 0, 0 },
|
||||
{"links", 'l', POPT_ARG_NONE, &preserve_links , 0, 0, 0 },
|
||||
{"copy-links", 'L', POPT_ARG_NONE, ©_links , 0, 0, 0 },
|
||||
{"whole-file", 'W', POPT_ARG_NONE, 0, OPT_WHOLE_FILE, 0, 0 },
|
||||
{"no-whole-file", 0, POPT_ARG_NONE, 0, OPT_NO_WHOLE_FILE, 0, 0 },
|
||||
{"copy-unsafe-links", 0, POPT_ARG_NONE, ©_unsafe_links , 0, 0, 0 },
|
||||
{"perms", 'p', POPT_ARG_NONE, &preserve_perms , 0, 0, 0 },
|
||||
{"owner", 'o', POPT_ARG_NONE, &preserve_uid , 0, 0, 0 },
|
||||
{"group", 'g', POPT_ARG_NONE, &preserve_gid , 0, 0, 0 },
|
||||
{"devices", 'D', POPT_ARG_NONE, &preserve_devices , 0, 0, 0 },
|
||||
{"times", 't', POPT_ARG_NONE, &preserve_times , 0, 0, 0 },
|
||||
{"checksum", 'c', POPT_ARG_NONE, &always_checksum , 0, 0, 0 },
|
||||
{"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 },
|
||||
{"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 },
|
||||
{"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
|
||||
{"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 },
|
||||
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
|
||||
{"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
|
||||
{"copy-links", 'L', POPT_ARG_NONE, ©_links, 0, 0, 0 },
|
||||
{"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },
|
||||
{"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 },
|
||||
{"copy-unsafe-links", 0, POPT_ARG_NONE, ©_unsafe_links, 0, 0, 0 },
|
||||
{"perms", 'p', POPT_ARG_NONE, &preserve_perms, 0, 0, 0 },
|
||||
{"owner", 'o', POPT_ARG_NONE, &preserve_uid, 0, 0, 0 },
|
||||
{"group", 'g', POPT_ARG_NONE, &preserve_gid, 0, 0, 0 },
|
||||
{"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 },
|
||||
{"times", 't', POPT_ARG_NONE, &preserve_times, 0, 0, 0 },
|
||||
{"checksum", 'c', POPT_ARG_NONE, &always_checksum, 0, 0, 0 },
|
||||
{"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
|
||||
{"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 },
|
||||
{"archive", 'a', POPT_ARG_NONE, 0, 'a', 0, 0 },
|
||||
{"server", 0, POPT_ARG_NONE, &am_server , 0, 0, 0 },
|
||||
{"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
|
||||
{"recursive", 'r', POPT_ARG_NONE, &recurse , 0, 0, 0 },
|
||||
{"relative", 'R', POPT_ARG_NONE, &relative_paths , 0, 0, 0 },
|
||||
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd , 0, 0, 0 },
|
||||
{"block-size", 'B', POPT_ARG_INT, &block_size , 0, 0, 0 },
|
||||
{"max-delete", 0, POPT_ARG_INT, &max_delete , 0, 0, 0 },
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout , 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir , 0, 0, 0 },
|
||||
{"compare-dest", 0, POPT_ARG_STRING, &compare_dest , 0, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
|
||||
{"archive", 'a', POPT_ARG_NONE, &archive_mode, 0, 0, 0 },
|
||||
{"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
|
||||
{"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
|
||||
{"recursive", 'r', POPT_ARG_NONE, &recurse, 0, 0, 0 },
|
||||
{"relative", 'R', POPT_ARG_VAL, &relative_paths, 1, 0, 0 },
|
||||
{"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 },
|
||||
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
|
||||
{"block-size", 'B', POPT_ARG_INT, &block_size, 0, 0, 0 },
|
||||
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
|
||||
{"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
|
||||
/* TODO: Should this take an optional int giving the compression level? */
|
||||
{"compress", 'z', POPT_ARG_NONE, &do_compression , 0, 0, 0 },
|
||||
{"daemon", 0, POPT_ARG_NONE, &am_daemon , 0, 0, 0 },
|
||||
{"no-detach", 0, POPT_ARG_NONE, &no_detach , 0, 0, 0 },
|
||||
{"stats", 0, POPT_ARG_NONE, &do_stats , 0, 0, 0 },
|
||||
{"progress", 0, POPT_ARG_NONE, &do_progress , 0, 0, 0 },
|
||||
{"partial", 0, POPT_ARG_NONE, &keep_partial , 0, 0, 0 },
|
||||
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors , 0, 0, 0 },
|
||||
{"blocking-io", 0, POPT_ARG_NONE, &blocking_io , 0, 0, 0 },
|
||||
{"no-blocking-io", 0, POPT_ARG_NONE, 0, OPT_NO_BLOCKING_IO, 0, 0 },
|
||||
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
|
||||
{"config", 0, POPT_ARG_STRING, &config_file , 0, 0, 0 },
|
||||
{"port", 0, POPT_ARG_INT, &rsync_port , 0, 0, 0 },
|
||||
{"log-format", 0, POPT_ARG_STRING, &log_format , 0, 0, 0 },
|
||||
{"bwlimit", 0, POPT_ARG_INT, &bwlimit , 0, 0, 0 },
|
||||
{"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
|
||||
{"daemon", 0, POPT_ARG_NONE, &am_daemon, 0, 0, 0 },
|
||||
{"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 },
|
||||
{"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
|
||||
{"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
|
||||
{"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
|
||||
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
|
||||
{"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
|
||||
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
|
||||
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
|
||||
{"config", 0, POPT_ARG_STRING, &config_file, 0, 0, 0 },
|
||||
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
|
||||
{"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
|
||||
{"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
|
||||
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
|
||||
{"backup-dir", 0, POPT_ARG_STRING, &backup_dir , 0, 0, 0 },
|
||||
{"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links , 0, 0, 0 },
|
||||
{"read-batch", 0, POPT_ARG_STRING, &batch_prefix, OPT_READ_BATCH, 0, 0 },
|
||||
{"write-batch", 0, POPT_ARG_STRING, &batch_prefix, OPT_WRITE_BATCH, 0, 0 },
|
||||
{"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
|
||||
{"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
|
||||
{"read-batch", 0, POPT_ARG_STRING, &batch_prefix, OPT_READ_BATCH, 0, 0 },
|
||||
{"write-batch", 0, POPT_ARG_STRING, &batch_prefix, OPT_WRITE_BATCH, 0, 0 },
|
||||
{"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
|
||||
{"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
|
||||
{"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
|
||||
{"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
|
||||
#ifdef INET6
|
||||
{0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET , 0, 0 },
|
||||
{0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6 , 0, 0 },
|
||||
{0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
|
||||
{0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
|
||||
#endif
|
||||
{0,0,0,0, 0, 0, 0}
|
||||
};
|
||||
@@ -386,7 +396,7 @@ void option_error(void)
|
||||
{
|
||||
if (err_buf[0]) {
|
||||
rprintf(FLOG, "%s", err_buf);
|
||||
rprintf(FERROR, "%s: %s", RSYNC_NAME, err_buf);
|
||||
rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
|
||||
} else {
|
||||
rprintf (FERROR, "Error parsing options: "
|
||||
"option may be supported on client but not on server?\n");
|
||||
@@ -408,7 +418,7 @@ static int check_refuse_options(char *ref, int opt)
|
||||
for (i=0; long_options[i].longName; i++) {
|
||||
if (long_options[i].val == opt) break;
|
||||
}
|
||||
|
||||
|
||||
if (!long_options[i].longName) return 0;
|
||||
|
||||
name = long_options[i].longName;
|
||||
@@ -429,12 +439,12 @@ static int check_refuse_options(char *ref, int opt)
|
||||
|
||||
static int count_args(char const **argv)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
|
||||
while (argv[i] != NULL)
|
||||
i++;
|
||||
|
||||
return i;
|
||||
while (argv[i] != NULL)
|
||||
i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -450,38 +460,31 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
{
|
||||
int opt;
|
||||
char *ref = lp_refuse_options(module_id);
|
||||
poptContext pc;
|
||||
poptContext pc;
|
||||
|
||||
/* TODO: Call poptReadDefaultConfig; handle errors. */
|
||||
/* TODO: Call poptReadDefaultConfig; handle errors. */
|
||||
|
||||
/* The context leaks in case of an error, but if there's a
|
||||
* problem we always exit anyhow. */
|
||||
pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
|
||||
/* The context leaks in case of an error, but if there's a
|
||||
* problem we always exit anyhow. */
|
||||
pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
|
||||
|
||||
while ((opt = poptGetNextOpt(pc)) != -1) {
|
||||
if (ref) {
|
||||
if (check_refuse_options(ref, opt)) return 0;
|
||||
}
|
||||
|
||||
/* most options are handled automatically by popt;
|
||||
* only special cases are returned and listed here. */
|
||||
/* most options are handled automatically by popt;
|
||||
* only special cases are returned and listed here. */
|
||||
|
||||
switch (opt) {
|
||||
case OPT_VERSION:
|
||||
print_rsync_version(FINFO);
|
||||
print_rsync_version(FINFO);
|
||||
exit_cleanup(0);
|
||||
|
||||
case OPT_SUFFIX:
|
||||
/* The value has already been set by popt, but
|
||||
* we need to remember that a suffix was specified
|
||||
* in case a backup-directory is used. */
|
||||
suffix_specified = 1;
|
||||
break;
|
||||
|
||||
|
||||
case OPT_MODIFY_WINDOW:
|
||||
/* The value has already been set by popt, but
|
||||
* we need to remember that we're using a
|
||||
* non-default setting. */
|
||||
/* The value has already been set by popt, but
|
||||
* we need to remember that we're using a
|
||||
* non-default setting. */
|
||||
modify_window_set = 1;
|
||||
break;
|
||||
|
||||
@@ -496,33 +499,23 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE:
|
||||
add_exclude(poptGetOptArg(pc), 0);
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc),
|
||||
ADD_EXCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE:
|
||||
add_exclude(poptGetOptArg(pc), 1);
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc),
|
||||
ADD_INCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE_FROM:
|
||||
add_exclude_file(poptGetOptArg(pc), 1, 0);
|
||||
add_exclude_file(&exclude_list, poptGetOptArg(pc),
|
||||
MISSING_FATAL, ADD_EXCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE_FROM:
|
||||
add_exclude_file(poptGetOptArg(pc), 1, 1);
|
||||
break;
|
||||
|
||||
case OPT_WHOLE_FILE:
|
||||
whole_file = 1;
|
||||
no_whole_file = 0;
|
||||
break;
|
||||
|
||||
case OPT_NO_WHOLE_FILE:
|
||||
no_whole_file = 1;
|
||||
whole_file = 0;
|
||||
break;
|
||||
|
||||
case OPT_NO_BLOCKING_IO:
|
||||
blocking_io = 0;
|
||||
add_exclude_file(&exclude_list, poptGetOptArg(pc),
|
||||
MISSING_FATAL, ADD_INCLUDE);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@@ -533,16 +526,16 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
#if SUPPORT_HARD_LINKS
|
||||
preserve_hard_links=1;
|
||||
#else
|
||||
/* FIXME: Don't say "server" if this is
|
||||
* happening on the client. */
|
||||
/* FIXME: Why do we have the duplicated
|
||||
* rprintf? Everybody who gets this message
|
||||
* ought to send it to the client and also to
|
||||
* the logs. */
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"hard links are not supported on this %s\n",
|
||||
/* FIXME: Don't say "server" if this is
|
||||
* happening on the client. */
|
||||
/* FIXME: Why do we have the duplicated
|
||||
* rprintf? Everybody who gets this message
|
||||
* ought to send it to the client and also to
|
||||
* the logs. */
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"hard links are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
|
||||
rprintf(FERROR, "ERROR: %s", err_buf);
|
||||
return 0;
|
||||
#endif /* SUPPORT_HARD_LINKS */
|
||||
break;
|
||||
@@ -555,18 +548,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
if (frommain) quiet++;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
recurse=1;
|
||||
#if SUPPORT_LINKS
|
||||
preserve_links=1;
|
||||
#endif
|
||||
preserve_perms=1;
|
||||
preserve_times=1;
|
||||
preserve_gid=1;
|
||||
preserve_uid=1;
|
||||
preserve_devices=1;
|
||||
break;
|
||||
|
||||
case OPT_SENDER:
|
||||
if (!am_server) {
|
||||
usage(FERROR);
|
||||
@@ -589,53 +570,120 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
/* popt stores the filename in batch_prefix for us */
|
||||
read_batch = 1;
|
||||
break;
|
||||
|
||||
case OPT_LINK_DEST:
|
||||
#if HAVE_LINK
|
||||
compare_dest = (char *)poptGetOptArg(pc);
|
||||
link_dest = 1;
|
||||
break;
|
||||
#else
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"hard links are not supported on this %s\n",
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"hard links are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
|
||||
rprintf(FERROR, "ERROR: %s", err_buf);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
|
||||
default:
|
||||
/* FIXME: If --daemon is specified, then errors for later
|
||||
* parameters seem to disappear. */
|
||||
snprintf(err_buf, sizeof(err_buf),
|
||||
"%s%s: %s\n",
|
||||
am_server ? "on remote machine: " : "",
|
||||
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(opt));
|
||||
return 0;
|
||||
/* FIXME: If --daemon is specified, then errors for later
|
||||
* parameters seem to disappear. */
|
||||
snprintf(err_buf, sizeof(err_buf),
|
||||
"%s%s: %s\n",
|
||||
am_server ? "on remote machine: " : "",
|
||||
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(opt));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (write_batch && read_batch) {
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"write-batch and read-batch can not be used together\n");
|
||||
rprintf(FERROR,"ERROR: write-batch and read-batch"
|
||||
" can not be used together\n");
|
||||
return 0;
|
||||
rprintf(FERROR,
|
||||
"write-batch and read-batch can not be used together\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (do_compression && (write_batch || read_batch)) {
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"compress can not be used with write-batch or read-batch\n");
|
||||
rprintf(FERROR,"ERROR: compress can not be used with"
|
||||
" write-batch or read-batch\n");
|
||||
return 0;
|
||||
rprintf(FERROR,
|
||||
"compress can not be used with write-batch or read-batch\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
*argv = poptGetArgs(pc);
|
||||
if (*argv)
|
||||
*argc = count_args(*argv);
|
||||
else
|
||||
*argc = 0;
|
||||
if (archive_mode) {
|
||||
if (!files_from)
|
||||
recurse = 1;
|
||||
#if SUPPORT_LINKS
|
||||
preserve_links = 1;
|
||||
#endif
|
||||
preserve_perms = 1;
|
||||
preserve_times = 1;
|
||||
preserve_gid = 1;
|
||||
preserve_uid = 1;
|
||||
preserve_devices = 1;
|
||||
}
|
||||
|
||||
if (relative_paths < 0)
|
||||
relative_paths = files_from? 1 : 0;
|
||||
|
||||
if (!backup_suffix)
|
||||
backup_suffix = backup_dir? "" : BACKUP_SUFFIX;
|
||||
backup_suffix_len = strlen(backup_suffix);
|
||||
if (strchr(backup_suffix, '/') != NULL) {
|
||||
rprintf(FERROR, "--suffix cannot contain slashes: %s\n",
|
||||
backup_suffix);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (backup_dir)
|
||||
backup_dir_len = strlen(backup_dir);
|
||||
else if (!backup_suffix_len) {
|
||||
rprintf(FERROR,
|
||||
"--suffix cannot be a null string without --backup-dir\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (do_progress && !verbose)
|
||||
verbose = 1;
|
||||
|
||||
*argv = poptGetArgs(pc);
|
||||
if (*argv)
|
||||
*argc = count_args(*argv);
|
||||
else
|
||||
*argc = 0;
|
||||
|
||||
if (files_from) {
|
||||
char *colon;
|
||||
if (*argc != 2) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (strcmp(files_from, "-") == 0) {
|
||||
filesfrom_fd = 0;
|
||||
if (am_server)
|
||||
remote_filesfrom_file = "-";
|
||||
}
|
||||
else if ((colon = find_colon(files_from)) != 0) {
|
||||
if (am_server) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
remote_filesfrom_file = colon+1 + (colon[1] == ':');
|
||||
if (strcmp(remote_filesfrom_file, "-") == 0) {
|
||||
rprintf(FERROR, "Invalid --files-from remote filename\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
} else {
|
||||
extern int sanitize_paths;
|
||||
if (sanitize_paths)
|
||||
sanitize_path(strdup(files_from), NULL);
|
||||
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
|
||||
if (filesfrom_fd < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to open files-from file %s",
|
||||
files_from);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -695,13 +743,12 @@ void server_options(char **args,int *argc)
|
||||
if (copy_links)
|
||||
argstr[x++] = 'L';
|
||||
|
||||
assert(whole_file == 0 || whole_file == 1);
|
||||
if (whole_file)
|
||||
if (whole_file > 0)
|
||||
argstr[x++] = 'W';
|
||||
/* We don't need to send --no-whole-file, because it's the
|
||||
* default for remote transfers, and in any case old versions
|
||||
* of rsync will not understand it. */
|
||||
|
||||
|
||||
if (preserve_hard_links)
|
||||
argstr[x++] = 'H';
|
||||
if (preserve_uid)
|
||||
@@ -731,34 +778,34 @@ void server_options(char **args,int *argc)
|
||||
if (do_compression)
|
||||
argstr[x++] = 'z';
|
||||
|
||||
/* this is a complete hack - blame Rusty
|
||||
/* this is a complete hack - blame Rusty
|
||||
|
||||
this is a hack to make the list_only (remote file list)
|
||||
more useful */
|
||||
if (list_only && !recurse)
|
||||
if (list_only && !recurse)
|
||||
argstr[x++] = 'r';
|
||||
|
||||
argstr[x] = 0;
|
||||
|
||||
if (x != 1) args[ac++] = argstr;
|
||||
|
||||
if (block_size != BLOCK_SIZE) {
|
||||
if (block_size) {
|
||||
snprintf(bsize,sizeof(bsize),"-B%d",block_size);
|
||||
args[ac++] = bsize;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_delete && am_sender) {
|
||||
snprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
|
||||
args[ac++] = mdelete;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (batch_prefix != NULL) {
|
||||
char *fmt = "";
|
||||
if (write_batch)
|
||||
fmt = "--write-batch=%s";
|
||||
fmt = "--write-batch=%s";
|
||||
else
|
||||
if (read_batch)
|
||||
fmt = "--read-batch=%s";
|
||||
fmt = "--read-batch=%s";
|
||||
snprintf(fext,sizeof(fext),fmt,batch_prefix);
|
||||
args[ac++] = fext;
|
||||
}
|
||||
@@ -766,16 +813,26 @@ void server_options(char **args,int *argc)
|
||||
if (io_timeout) {
|
||||
snprintf(iotime,sizeof(iotime),"--timeout=%d",io_timeout);
|
||||
args[ac++] = iotime;
|
||||
}
|
||||
}
|
||||
|
||||
if (bwlimit) {
|
||||
snprintf(bw,sizeof(bw),"--bwlimit=%d",bwlimit);
|
||||
args[ac++] = bw;
|
||||
}
|
||||
|
||||
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
|
||||
args[ac++] = "--suffix";
|
||||
args[ac++] = backup_suffix;
|
||||
if (backup_dir) {
|
||||
args[ac++] = "--backup-dir";
|
||||
args[ac++] = backup_dir;
|
||||
}
|
||||
|
||||
/* Only send --suffix if it specifies a non-default value. */
|
||||
if (strcmp(backup_suffix, backup_dir? "" : BACKUP_SUFFIX) != 0) {
|
||||
char *s = new_array(char, 9+backup_suffix_len+1);
|
||||
if (!s)
|
||||
out_of_memory("server_options");
|
||||
/* We use the following syntax to avoid weirdness with '~'. */
|
||||
sprintf(s, "--suffix=%s", backup_suffix);
|
||||
args[ac++] = s;
|
||||
}
|
||||
|
||||
if (delete_mode && !delete_excluded)
|
||||
@@ -788,7 +845,7 @@ void server_options(char **args,int *argc)
|
||||
args[ac++] = "--size-only";
|
||||
|
||||
if (modify_window_set) {
|
||||
snprintf(mwindow,sizeof(mwindow),"--modify-window=%d",
|
||||
snprintf(mwindow,sizeof(mwindow),"--modify-window=%d",
|
||||
modify_window);
|
||||
args[ac++] = mwindow;
|
||||
}
|
||||
@@ -817,7 +874,7 @@ void server_options(char **args,int *argc)
|
||||
if (only_existing && am_sender)
|
||||
args[ac++] = "--existing";
|
||||
|
||||
if (opt_ignore_existing && am_sender)
|
||||
if (opt_ignore_existing && am_sender)
|
||||
args[ac++] = "--ignore-existing";
|
||||
|
||||
if (tmpdir) {
|
||||
@@ -825,14 +882,6 @@ void server_options(char **args,int *argc)
|
||||
args[ac++] = tmpdir;
|
||||
}
|
||||
|
||||
if (backup_dir && am_sender) {
|
||||
/* only the receiver needs this option, if we are the sender
|
||||
* then we need to send it to the receiver.
|
||||
*/
|
||||
args[ac++] = "--backup-dir";
|
||||
args[ac++] = backup_dir;
|
||||
}
|
||||
|
||||
if (compare_dest && am_sender) {
|
||||
/* the server only needs this option if it is not the sender,
|
||||
* and it may be an older version that doesn't know this
|
||||
@@ -842,6 +891,36 @@ void server_options(char **args,int *argc)
|
||||
args[ac++] = compare_dest;
|
||||
}
|
||||
|
||||
if (files_from && (!am_sender || remote_filesfrom_file)) {
|
||||
if (remote_filesfrom_file) {
|
||||
args[ac++] = "--files-from";
|
||||
args[ac++] = remote_filesfrom_file;
|
||||
if (eol_nulls)
|
||||
args[ac++] = "--from0";
|
||||
} else {
|
||||
args[ac++] = "--files-from=-";
|
||||
args[ac++] = "--from0";
|
||||
}
|
||||
}
|
||||
|
||||
*argc = ac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the position of a ':' IF it is not part of a filename (i.e. as
|
||||
* long as it doesn't occur after a slash.
|
||||
*/
|
||||
char *find_colon(char *s)
|
||||
{
|
||||
char *p, *p2;
|
||||
|
||||
p = strchr(s,':');
|
||||
if (!p) return NULL;
|
||||
|
||||
/* now check to see if there is a / in the string before the : - if there is then
|
||||
discard the colon on the assumption that the : is part of a filename */
|
||||
p2 = strchr(s,'/');
|
||||
if (p2 && p2 < p) return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.5.6
|
||||
Version: 2.6.0pre2
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.6.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-%{version}.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
@@ -21,11 +21,18 @@ A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon Sept 11 2000 John H Terpstra <jht@turbolinux.com>
|
||||
* 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
|
||||
|
||||
* 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
|
||||
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)
|
||||
|
||||
@@ -62,23 +69,25 @@ previous package(s).)
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr --mandir=/usr/share/man
|
||||
./configure --prefix=/usr --mandir=%{_mandir}
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,share/man/{man1,man5}}
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man{1,5}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/share/man/man5
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/share/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/share/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %{_mandir}/man1/rsync.1*
|
||||
%attr(-,root,root) %{_mandir}/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
%attr(-,root,root) %doc doc/README-SGML doc/rsync.sgml
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: PVERSION
|
||||
Release: PRELEASE
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-PVERSION.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon Sept 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).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr --mandir=/usr/share/man
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,share/man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/share/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/share/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/share/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
@@ -1,81 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.5.6
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.6.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* 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).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
@@ -1,81 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: PVERSION
|
||||
Release: PRELEASE
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-PVERSION.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* 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).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
@@ -1,81 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.5.6
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.6.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* 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).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1* $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5* $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1*
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
@@ -1,81 +0,0 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: PVERSION
|
||||
Release: PRELEASE
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-PVERSION.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* 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).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1* $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5* $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1*
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
8
params.c
8
params.c
@@ -207,7 +207,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
|
||||
if( i > (bSize - 2) )
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = Realloc( bufr, bSize );
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func);
|
||||
@@ -301,7 +301,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
if( i > (bSize - 2) ) /* Ensure there's space for next char. */
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = Realloc( bufr, bSize );
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
|
||||
@@ -366,7 +366,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
|
||||
if( i > (bSize - 2) ) /* Make sure there's enough room. */
|
||||
{
|
||||
bSize += BUFR_INC;
|
||||
bufr = Realloc( bufr, bSize );
|
||||
bufr = realloc_array( bufr, char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
|
||||
@@ -530,7 +530,7 @@ BOOL pm_process( char *FileName,
|
||||
else /* If we don't have a buffer */
|
||||
{ /* allocate one, then parse, */
|
||||
bSize = BUFR_INC; /* then free. */
|
||||
bufr = (char *)malloc( bSize );
|
||||
bufr = new_array( char, bSize );
|
||||
if( NULL == bufr )
|
||||
{
|
||||
rprintf(FERROR,"%s memory allocation failure.\n", func);
|
||||
|
||||
19
pipe.c
19
pipe.c
@@ -73,9 +73,8 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
close(from_child_pipe[1]);
|
||||
umask(orig_umask);
|
||||
set_blocking(STDIN_FILENO);
|
||||
if (blocking_io) {
|
||||
if (blocking_io > 0)
|
||||
set_blocking(STDOUT_FILENO);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
rprintf(FERROR, "Failed to exec %s : %s\n",
|
||||
command[0], strerror(errno));
|
||||
@@ -99,7 +98,10 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int read_batch; /* dw */
|
||||
extern int read_batch;
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int filesfrom_fd;
|
||||
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
@@ -115,12 +117,12 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
|
||||
am_sender = read_batch ? 0 : !am_sender;
|
||||
am_server = 1;
|
||||
|
||||
if (!am_sender)
|
||||
filesfrom_fd = -1;
|
||||
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
@@ -133,6 +135,9 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
|
||||
child_main(argc, argv);
|
||||
}
|
||||
|
||||
if (!am_sender)
|
||||
filesfrom_fd = -1;
|
||||
|
||||
if (close(from_child_pipe[1]) < 0 ||
|
||||
close(to_child_pipe[0]) < 0) {
|
||||
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
|
||||
@@ -144,5 +149,3 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
104
popt/config.log
104
popt/config.log
@@ -1,104 +0,0 @@
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
configure:592: checking host system type
|
||||
configure:613: checking target system type
|
||||
configure:631: checking build system type
|
||||
configure:665: checking for a BSD compatible install
|
||||
configure:718: checking whether build environment is sane
|
||||
configure:775: checking whether make sets ${MAKE}
|
||||
configure:821: checking for working aclocal
|
||||
configure:834: checking for working autoconf
|
||||
configure:847: checking for working automake
|
||||
configure:860: checking for working autoheader
|
||||
configure:873: checking for working makeinfo
|
||||
configure:891: checking for gcc
|
||||
configure:1004: checking whether the C compiler (gcc ) works
|
||||
configure:1020: gcc -o conftest conftest.c 1>&5
|
||||
configure:1046: checking whether the C compiler (gcc ) is a cross-compiler
|
||||
configure:1051: checking whether we are using GNU C
|
||||
configure:1079: checking whether gcc accepts -g
|
||||
configure:1111: checking for POSIXized ISC
|
||||
configure:1135: checking for gcc
|
||||
configure:1248: checking whether the C compiler (gcc -g -O2 ) works
|
||||
configure:1264: gcc -o conftest -g -O2 conftest.c 1>&5
|
||||
configure:1290: checking whether the C compiler (gcc -g -O2 ) is a cross-compiler
|
||||
configure:1295: checking whether we are using GNU C
|
||||
configure:1323: checking whether gcc accepts -g
|
||||
configure:1355: checking how to run the C preprocessor
|
||||
configure:1436: checking whether gcc needs -traditional
|
||||
configure:1485: checking for gcc option to accept ANSI C
|
||||
configure:1564: checking for function prototypes
|
||||
configure:1795: checking for ranlib
|
||||
configure:1834: checking for ld used by GCC
|
||||
configure:1896: checking if the linker (/usr/bin/ld) is GNU ld
|
||||
configure:1912: checking for BSD-compatible nm
|
||||
configure:1948: checking whether ln -s works
|
||||
ltconfig:603: checking for object suffix
|
||||
ltconfig:604: gcc -c -g -O2 conftest.c 1>&5
|
||||
ltconfig:629: checking for executable suffix
|
||||
ltconfig:630: gcc -o conftest -g -O2 conftest.c 1>&5
|
||||
ltconfig:776: checking if gcc PIC flag -fPIC works
|
||||
ltconfig:777: gcc -c -g -O2 -fPIC -DPIC conftest.c 1>&5
|
||||
ltconfig:829: checking if gcc supports -c -o file.o
|
||||
ltconfig:830: gcc -c -g -O2 -o out/conftest2.o conftest.c 1>&5
|
||||
ltconfig:862: checking if gcc supports -c -o file.lo
|
||||
ltconfig:863: gcc -c -g -O2 -c -o conftest.lo conftest.c 1>&5
|
||||
ltconfig:914: checking if gcc supports -fno-rtti -fno-exceptions
|
||||
ltconfig:915: gcc -c -g -O2 -fno-rtti -fno-exceptions -c conftest.c conftest.c 1>&5
|
||||
ltconfig:958: checking if gcc static flag -static works
|
||||
ltconfig:959: gcc -o conftest -g -O2 -static conftest.c 1>&5
|
||||
GNU ld version 2.10.91 (with BFD 2.10.91.0.2)
|
||||
ltconfig:1635: checking if global_symbol_pipe works
|
||||
ltconfig:1636: gcc -c -g -O2 conftest.c 1>&5
|
||||
ltconfig:1639: eval "/usr/bin/nm -B conftest.o | sed -n -e 's/^.*[ ]\([ABCDGISTW]\)[ ][ ]*\(\)\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2\3 \3/p' > conftest.nm"
|
||||
ltconfig:1691: gcc -o conftest -g -O2 -fno-builtin -fno-rtti -fno-exceptions conftest.c conftstm.o 1>&5
|
||||
configure:2150: checking for a BSD compatible install
|
||||
configure:2231: checking for alloca.h
|
||||
configure:2231: checking for libintl.h
|
||||
configure:2231: checking for mcheck.h
|
||||
configure:2231: checking for unistd.h
|
||||
configure:2268: checking for /usr/ucblib in LIBS
|
||||
configure:2284: checking for GNU xgettext
|
||||
configure:2294: checking for strerror
|
||||
configure:2294: checking for mtrace
|
||||
configure:2347: checking for setreuid
|
||||
configure:2438: checking for working const
|
||||
configure:2513: checking for inline
|
||||
configure:2553: checking for off_t
|
||||
configure:2586: checking for size_t
|
||||
configure:2621: checking for working alloca.h
|
||||
configure:2654: checking for alloca
|
||||
configure:2856: checking for unistd.h
|
||||
configure:2895: checking for getpagesize
|
||||
configure:2948: checking for working mmap
|
||||
configure:3124: checking for argz.h
|
||||
configure:3124: checking for limits.h
|
||||
configure:3124: checking for locale.h
|
||||
configure:3124: checking for nl_types.h
|
||||
configure:3124: checking for malloc.h
|
||||
configure:3124: checking for string.h
|
||||
configure:3124: checking for unistd.h
|
||||
configure:3124: checking for sys/param.h
|
||||
configure:3164: checking for getcwd
|
||||
configure:3164: checking for munmap
|
||||
configure:3164: checking for putenv
|
||||
configure:3164: checking for setenv
|
||||
configure:3164: checking for setlocale
|
||||
configure:3164: checking for strchr
|
||||
configure:3164: checking for strcasecmp
|
||||
configure:3164: checking for strdup
|
||||
configure:3164: checking for __argz_count
|
||||
configure:3164: checking for __argz_stringify
|
||||
configure:3164: checking for __argz_next
|
||||
configure:3283: checking for LC_MESSAGES
|
||||
configure:3316: checking whether NLS is requested
|
||||
configure:3336: checking whether included gettext is requested
|
||||
configure:3355: checking for libintl.h
|
||||
configure:3382: checking for gettext in libc
|
||||
configure:3508: checking for msgfmt
|
||||
configure:3542: checking for dcgettext
|
||||
configure:3597: checking for gmsgfmt
|
||||
configure:3633: checking for xgettext
|
||||
configure:3673: gcc -o conftest -Wall -g -O2 conftest.c 1>&5
|
||||
configure:4131: checking for catalogs to be installed
|
||||
128
progress.c
128
progress.c
@@ -1,19 +1,19 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -28,8 +28,8 @@ static OFF_T start_ofs;
|
||||
|
||||
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
{
|
||||
return (t2->tv_sec - t1->tv_sec) * 1000
|
||||
+ (t2->tv_usec - t1->tv_usec) / 1000;
|
||||
return (t2->tv_sec - t1->tv_sec) * 1000
|
||||
+ (t2->tv_usec - t1->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,75 +43,77 @@ static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
int is_last)
|
||||
{
|
||||
int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
|
||||
unsigned long diff = msdiff(&start_time, now);
|
||||
double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
|
||||
const char *units;
|
||||
/* If we've finished transferring this file, show the time taken;
|
||||
* otherwise show expected time to complete. That's kind of
|
||||
* inconsistent, but people can probably cope. Hopefully we'll
|
||||
* get more consistent and complete progress reporting soon. --
|
||||
* mbp */
|
||||
double remain = is_last
|
||||
? (double) diff / 1000.0
|
||||
: rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
|
||||
int remain_h, remain_m, remain_s;
|
||||
int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
|
||||
unsigned long diff = msdiff(&start_time, now);
|
||||
double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
|
||||
const char *units;
|
||||
/* If we've finished transferring this file, show the time taken;
|
||||
* otherwise show expected time to complete. That's kind of
|
||||
* inconsistent, but people can probably cope. Hopefully we'll
|
||||
* get more consistent and complete progress reporting soon. --
|
||||
* mbp */
|
||||
double remain = is_last ? (double) diff / 1000.0
|
||||
: rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
|
||||
int remain_h, remain_m, remain_s;
|
||||
|
||||
if (rate > 1024*1024) {
|
||||
rate /= 1024.0 * 1024.0;
|
||||
units = "GB/s";
|
||||
} else if (rate > 1024) {
|
||||
rate /= 1024.0;
|
||||
units = "MB/s";
|
||||
} else {
|
||||
units = "kB/s";
|
||||
}
|
||||
if (rate > 1024*1024) {
|
||||
rate /= 1024.0 * 1024.0;
|
||||
units = "GB/s";
|
||||
} else if (rate > 1024) {
|
||||
rate /= 1024.0;
|
||||
units = "MB/s";
|
||||
} else {
|
||||
units = "kB/s";
|
||||
}
|
||||
|
||||
remain_s = (int) remain % 60;
|
||||
remain_m = (int) (remain / 60.0) % 60;
|
||||
remain_h = (int) (remain / 3600.0);
|
||||
|
||||
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
|
||||
(double) ofs, pct, rate, units,
|
||||
remain_h, remain_m, remain_s,
|
||||
is_last ? "\n" : "\r");
|
||||
remain_s = (int) remain % 60;
|
||||
remain_m = (int) (remain / 60.0) % 60;
|
||||
remain_h = (int) (remain / 3600.0);
|
||||
|
||||
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
|
||||
(double) ofs, pct, rate, units,
|
||||
remain_h, remain_m, remain_s,
|
||||
is_last ? "\n" : "\r");
|
||||
}
|
||||
|
||||
void end_progress(OFF_T size)
|
||||
{
|
||||
extern int do_progress, am_server;
|
||||
extern int am_server;
|
||||
|
||||
if (do_progress && !am_server) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
rprint_progress(size, size, &now, True);
|
||||
if (!am_server) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
rprint_progress(size, size, &now, True);
|
||||
}
|
||||
last_ofs = 0;
|
||||
start_ofs = 0;
|
||||
print_time.tv_sec = print_time.tv_usec = 0;
|
||||
start_time.tv_sec = start_time.tv_usec = 0;
|
||||
last_ofs = 0;
|
||||
start_ofs = 0;
|
||||
print_time.tv_sec = print_time.tv_usec = 0;
|
||||
start_time.tv_sec = start_time.tv_usec = 0;
|
||||
}
|
||||
|
||||
void show_progress(OFF_T ofs, OFF_T size)
|
||||
{
|
||||
extern int do_progress, am_server;
|
||||
struct timeval now;
|
||||
extern int am_server;
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
if (!start_time.tv_sec) {
|
||||
gettimeofday(&now, NULL);
|
||||
start_time.tv_sec = now.tv_sec;
|
||||
start_time.tv_usec = now.tv_usec;
|
||||
start_ofs = ofs;
|
||||
if (am_server)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (am_server)
|
||||
return;
|
||||
gettimeofday(&now, NULL);
|
||||
}
|
||||
|
||||
if (!start_time.tv_sec && !start_time.tv_usec) {
|
||||
start_time.tv_sec = now.tv_sec;
|
||||
start_time.tv_usec = now.tv_usec;
|
||||
start_ofs = ofs;
|
||||
}
|
||||
|
||||
if (do_progress
|
||||
&& !am_server
|
||||
&& ofs > last_ofs + 1000
|
||||
&& msdiff(&print_time, &now) > 250) {
|
||||
rprint_progress(ofs, size, &now, False);
|
||||
last_ofs = ofs;
|
||||
print_time.tv_sec = now.tv_sec;
|
||||
print_time.tv_usec = now.tv_usec;
|
||||
if (ofs > last_ofs + 1000 && msdiff(&print_time, &now) > 250) {
|
||||
rprint_progress(ofs, size, &now, False);
|
||||
last_ofs = ofs;
|
||||
print_time.tv_sec = now.tv_sec;
|
||||
print_time.tv_usec = now.tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
296
receiver.c
296
receiver.c
@@ -1,18 +1,18 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -23,7 +23,7 @@
|
||||
extern int verbose;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
extern int remote_version;
|
||||
extern int protocol_version;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int dry_run;
|
||||
@@ -35,7 +35,10 @@ extern int io_error;
|
||||
extern char *tmpdir;
|
||||
extern char *compare_dest;
|
||||
extern int make_backups;
|
||||
extern int do_progress;
|
||||
extern char *backup_dir;
|
||||
extern char *backup_suffix;
|
||||
extern int backup_suffix_len;
|
||||
|
||||
static struct delete_list {
|
||||
DEV64_T dev;
|
||||
@@ -44,9 +47,9 @@ static struct delete_list {
|
||||
static int dlist_len, dlist_alloc_len;
|
||||
|
||||
/* yuck! This function wouldn't have been necessary if I had the sorting
|
||||
algorithm right. Unfortunately fixing the sorting algorithm would introduce
|
||||
a backward incompatibility as file list indexes are sent over the link.
|
||||
*/
|
||||
* algorithm right. Unfortunately fixing the sorting algorithm would introduce
|
||||
* a backward incompatibility as file list indexes are sent over the link.
|
||||
*/
|
||||
static int delete_already_done(struct file_list *flist,int j)
|
||||
{
|
||||
int i;
|
||||
@@ -54,9 +57,9 @@ static int delete_already_done(struct file_list *flist,int j)
|
||||
|
||||
if (link_stat(f_name(flist->files[j]), &st)) return 1;
|
||||
|
||||
for (i=0;i<dlist_len;i++) {
|
||||
for (i = 0; i < dlist_len; i++) {
|
||||
if (st.st_ino == delete_list[i].inode &&
|
||||
st.st_dev == delete_list[i].dev)
|
||||
(DEV64_T)st.st_dev == delete_list[i].dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -67,7 +70,8 @@ static void add_delete_entry(struct file_struct *file)
|
||||
{
|
||||
if (dlist_len == dlist_alloc_len) {
|
||||
dlist_alloc_len += 1024;
|
||||
delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
|
||||
delete_list = realloc_array(delete_list, struct delete_list,
|
||||
dlist_alloc_len);
|
||||
if (!delete_list) out_of_memory("add_delete_entry");
|
||||
}
|
||||
|
||||
@@ -79,31 +83,38 @@ static void add_delete_entry(struct file_struct *file)
|
||||
rprintf(FINFO,"added %s to delete list\n", f_name(file));
|
||||
}
|
||||
|
||||
static void delete_one(struct file_struct *f)
|
||||
static void delete_one(char *fn, int is_dir)
|
||||
{
|
||||
if (!S_ISDIR(f->mode)) {
|
||||
if (robust_unlink(f_name(f)) != 0) {
|
||||
rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno));
|
||||
if (!is_dir) {
|
||||
if (robust_unlink(fn) != 0) {
|
||||
rprintf(FERROR, "delete_one: unlink %s failed: %s\n",
|
||||
full_fname(fn), strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO,"deleting %s\n",f_name(f));
|
||||
rprintf(FINFO, "deleting %s\n", fn);
|
||||
}
|
||||
} else {
|
||||
if (do_rmdir(f_name(f)) != 0) {
|
||||
if (errno != ENOTEMPTY && errno != EEXIST)
|
||||
rprintf(FERROR,"delete_one: rmdir %s: %s\n",
|
||||
f_name(f), strerror(errno));
|
||||
} else {
|
||||
if (do_rmdir(fn) != 0) {
|
||||
if (errno != ENOTEMPTY && errno != EEXIST) {
|
||||
rprintf(FERROR, "delete_one: rmdir %s failed: %s\n",
|
||||
full_fname(fn), strerror(errno));
|
||||
}
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO,"deleting directory %s\n",f_name(f));
|
||||
rprintf(FINFO, "deleting directory %s\n", fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int is_backup_file(char *fn)
|
||||
{
|
||||
int k = strlen(fn) - backup_suffix_len;
|
||||
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
|
||||
}
|
||||
|
||||
|
||||
/* this deletes any files on the receiving side that are not present
|
||||
on the sending side. For version 1.6.4 I have changed the behaviour
|
||||
to match more closely what most people seem to expect of this option */
|
||||
* on the sending side. For version 1.6.4 I have changed the behaviour
|
||||
* to match more closely what most people seem to expect of this option */
|
||||
void delete_files(struct file_list *flist)
|
||||
{
|
||||
struct file_list *local_file_list;
|
||||
@@ -123,10 +134,10 @@ void delete_files(struct file_list *flist)
|
||||
}
|
||||
|
||||
for (j=0;j<flist->count;j++) {
|
||||
if (!S_ISDIR(flist->files[j]->mode) ||
|
||||
if (!S_ISDIR(flist->files[j]->mode) ||
|
||||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
|
||||
|
||||
if (remote_version < 19 &&
|
||||
if (protocol_version < 19 &&
|
||||
delete_already_done(flist, j)) continue;
|
||||
|
||||
name = strdup(f_name(flist->files[j]));
|
||||
@@ -142,20 +153,20 @@ void delete_files(struct file_list *flist)
|
||||
for (i=local_file_list->count-1;i>=0;i--) {
|
||||
if (max_delete && deletion_count > max_delete) break;
|
||||
if (!local_file_list->files[i]->basename) continue;
|
||||
if (remote_version < 19 &&
|
||||
if (protocol_version < 19 &&
|
||||
S_ISDIR(local_file_list->files[i]->mode))
|
||||
add_delete_entry(local_file_list->files[i]);
|
||||
if (-1 == flist_find(flist,local_file_list->files[i])) {
|
||||
char *f = f_name(local_file_list->files[i]);
|
||||
int k = strlen(f) - strlen(backup_suffix);
|
||||
/* Hi Andrew, do we really need to play with backup_suffix here? */
|
||||
if (make_backups && ((k <= 0) ||
|
||||
(strcmp(f+k,backup_suffix) != 0))) {
|
||||
if (make_backups && (backup_dir || !is_backup_file(f))) {
|
||||
(void) make_backup(f);
|
||||
if (verbose)
|
||||
rprintf(FINFO, "deleting %s\n", f);
|
||||
} else {
|
||||
deletion_count++;
|
||||
delete_one(local_file_list->files[i]);
|
||||
int mode = local_file_list->files[i]->mode;
|
||||
delete_one(f, S_ISDIR(mode) != 0);
|
||||
}
|
||||
deletion_count++;
|
||||
}
|
||||
}
|
||||
flist_free(local_file_list);
|
||||
@@ -164,40 +175,63 @@ void delete_files(struct file_list *flist)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_tmpname() - create a tmp filename for a given filename
|
||||
*
|
||||
* If a tmpdir is defined, use that as the directory to
|
||||
* put it in. Otherwise, the tmp filename is in the same
|
||||
* directory as the given name. Note that there may be no
|
||||
* directory at all in the given name!
|
||||
*
|
||||
* The tmp filename is basically the given filename with a
|
||||
* dot prepended, and .XXXXXX appended (for mkstemp() to
|
||||
* put its unique gunk in). Take care to not exceed
|
||||
* either the MAXPATHLEN or NAME_MAX, esp. the last, as
|
||||
* the basename basically becomes 8 chars longer. In that
|
||||
* case, the original name is shortened sufficiently to
|
||||
* make it all fit.
|
||||
*
|
||||
* Of course, there's no real reason for the tmp name to
|
||||
* look like the original, except to satisfy us humans.
|
||||
* As long as it's unique, rsync will work.
|
||||
*/
|
||||
|
||||
static int get_tmpname(char *fnametmp, char *fname)
|
||||
{
|
||||
char *f;
|
||||
int length = 0;
|
||||
int maxname;
|
||||
|
||||
/* open tmp file */
|
||||
if (tmpdir) {
|
||||
f = strrchr(fname,'/');
|
||||
if (f == NULL)
|
||||
f = fname;
|
||||
else
|
||||
f++;
|
||||
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
|
||||
length = strlen(fnametmp);
|
||||
fnametmp[length++] = '/';
|
||||
fnametmp[length] = '\0'; /* always NULL terminated */
|
||||
}
|
||||
|
||||
if ((f = strrchr(fname, '/')) != NULL) {
|
||||
++f;
|
||||
if (!tmpdir) {
|
||||
length = f - fname;
|
||||
/* copy up to and including the slash */
|
||||
strlcpy(fnametmp, fname, length + 1);
|
||||
}
|
||||
snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
f = fname;
|
||||
}
|
||||
fnametmp[length++] = '.';
|
||||
fnametmp[length] = '\0'; /* always NULL terminated */
|
||||
|
||||
f = strrchr(fname,'/');
|
||||
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
|
||||
|
||||
if (strlen(fname)+9 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
if (maxname < 1) {
|
||||
rprintf(FERROR, "temporary filename too long: %s\n", fname);
|
||||
fnametmp[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
*f = 0;
|
||||
snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
|
||||
fname,f+1);
|
||||
*f = '/';
|
||||
} else {
|
||||
snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
|
||||
}
|
||||
strlcpy(fnametmp + length, f, maxname);
|
||||
strcat(fnametmp + length, ".XXXXXX");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -207,23 +241,22 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
OFF_T total_size)
|
||||
{
|
||||
int i;
|
||||
unsigned int n,remainder,len,count;
|
||||
struct sum_struct sum;
|
||||
unsigned int len;
|
||||
OFF_T offset = 0;
|
||||
OFF_T offset2;
|
||||
char *data;
|
||||
static char file_sum1[MD4_SUM_LENGTH];
|
||||
static char file_sum2[MD4_SUM_LENGTH];
|
||||
char *map=NULL;
|
||||
|
||||
count = read_int(f_in);
|
||||
n = read_int(f_in);
|
||||
remainder = read_int(f_in);
|
||||
|
||||
sum_init();
|
||||
|
||||
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
|
||||
|
||||
show_progress(offset, total_size);
|
||||
read_sum_head(f_in, &sum);
|
||||
|
||||
sum_init();
|
||||
|
||||
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
|
||||
if (do_progress)
|
||||
show_progress(offset, total_size);
|
||||
|
||||
if (i > 0) {
|
||||
extern int cleanup_got_literal;
|
||||
@@ -235,63 +268,62 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
|
||||
stats.literal_data += i;
|
||||
cleanup_got_literal = 1;
|
||||
|
||||
|
||||
sum_update(data,i);
|
||||
|
||||
if (fd != -1 && write_file(fd,data,i) != i) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
offset += i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
i = -(i+1);
|
||||
offset2 = i*(OFF_T)n;
|
||||
len = n;
|
||||
if (i == (int) count-1 && remainder != 0)
|
||||
len = remainder;
|
||||
|
||||
offset2 = i*(OFF_T)sum.blength;
|
||||
len = sum.blength;
|
||||
if (i == (int) sum.count-1 && sum.remainder != 0)
|
||||
len = sum.remainder;
|
||||
|
||||
stats.matched_data += len;
|
||||
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
|
||||
i,len,(double)offset2,(double)offset);
|
||||
|
||||
|
||||
if (buf) {
|
||||
map = map_ptr(buf,offset2,len);
|
||||
|
||||
|
||||
see_token(map, len);
|
||||
sum_update(map,len);
|
||||
}
|
||||
|
||||
|
||||
if (fd != -1 && write_file(fd,map,len) != (int) len) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
|
||||
end_progress(total_size);
|
||||
if (do_progress)
|
||||
end_progress(total_size);
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
sum_end(file_sum1);
|
||||
|
||||
if (remote_version >= 14) {
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
}
|
||||
if (fd != -1 &&
|
||||
memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
|
||||
return 0;
|
||||
}
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
}
|
||||
if (fd != -1 && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -302,7 +334,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
*
|
||||
* Receiver process runs on the same host as the generator process. */
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
{
|
||||
{
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname;
|
||||
@@ -315,7 +347,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
struct file_struct *file;
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
extern struct stats stats;
|
||||
extern struct stats stats;
|
||||
extern int preserve_perms;
|
||||
extern int delete_after;
|
||||
extern int orig_umask;
|
||||
@@ -325,12 +357,12 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (1) {
|
||||
cleanup_disable();
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
if (phase==0) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
@@ -342,7 +374,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
@@ -357,8 +389,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
fname = local_name;
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname);
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -370,7 +402,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
|
||||
fnamecmp = fname;
|
||||
|
||||
/* open the file */
|
||||
/* open the file */
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if ((fd1 == -1) && (compare_dest != NULL)) {
|
||||
@@ -382,23 +414,36 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
}
|
||||
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
|
||||
rprintf(FERROR, "fstat %s failed: %s\n",
|
||||
full_fname(fnamecmp), strerror(errno));
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
|
||||
/* this special handling for directories
|
||||
* wouldn't be necessary if robust_rename()
|
||||
* and the underlying robust_unlink could cope
|
||||
* with directories
|
||||
*/
|
||||
rprintf(FERROR,"recv_files: %s is a directory\n",
|
||||
full_fname(fnamecmp));
|
||||
receive_data(f_in, NULL, -1, NULL, file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
fd1 = -1;
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !preserve_perms) {
|
||||
/* if the file exists already and we aren't perserving
|
||||
presmissions then act as though the remote end sent
|
||||
us the file permissions we already have */
|
||||
/* if the file exists already and we aren't preserving
|
||||
* permissions then act as though the remote end sent
|
||||
* us the file permissions we already have */
|
||||
file->mode = st.st_mode;
|
||||
}
|
||||
|
||||
@@ -419,46 +464,47 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
strlcpy(template, fnametmp, sizeof(template));
|
||||
|
||||
/* 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. */
|
||||
* 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 &&
|
||||
* 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, orig_umask) == 0) {
|
||||
strlcpy(fnametmp, template, sizeof(fnametmp));
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR,"mkstemp %s failed: %s\n",fnametmp,strerror(errno));
|
||||
rprintf(FERROR, "mkstemp %s failed: %s\n",
|
||||
full_fname(fnametmp), strerror(errno));
|
||||
receive_data(f_in,buf,-1,NULL,file->length);
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
|
||||
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname);
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
}
|
||||
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
|
||||
|
||||
log_recv(file, &initial_stats);
|
||||
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) {
|
||||
close(fd1);
|
||||
}
|
||||
close(fd2);
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
@@ -469,7 +515,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
fname);
|
||||
full_fname(fname));
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
@@ -487,8 +533,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
if (preserve_hard_links)
|
||||
do_hard_links();
|
||||
|
||||
/* now we need to fix any directory permissions that were
|
||||
modified during the transfer */
|
||||
/* now we need to fix any directory permissions that were
|
||||
* modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
@@ -497,7 +543,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
87
rsync.c
87
rsync.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -43,8 +43,8 @@ void free_sums(struct sum_struct *s)
|
||||
|
||||
|
||||
/*
|
||||
* delete a file or directory. If force_delete is set then delete
|
||||
* recursively
|
||||
* delete a file or directory. If force_delete is set then delete
|
||||
* recursively
|
||||
*/
|
||||
int delete_file(char *fname)
|
||||
{
|
||||
@@ -67,29 +67,31 @@ int delete_file(char *fname)
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
rprintf(FERROR,"delete_file: unlink(%s) : %s\n", fname, strerror(errno));
|
||||
rprintf(FERROR, "delete_file: unlink %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
|
||||
if (!force_delete || !recurse ||
|
||||
if (!force_delete || !recurse ||
|
||||
(errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now we do a recsursive delete on the directory ... */
|
||||
d = opendir(fname);
|
||||
if (!d) {
|
||||
rprintf(FERROR,"delete_file: opendir(%s): %s\n",
|
||||
fname,strerror(errno));
|
||||
rprintf(FERROR, "delete_file: opendir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (di=readdir(d); di; di=readdir(d)) {
|
||||
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
|
||||
char *dname = d_name(di);
|
||||
if (strcmp(dname,".")==0 ||
|
||||
strcmp(dname,"..")==0)
|
||||
if (strcmp(dname,".") == 0
|
||||
|| strcmp(dname,"..") == 0)
|
||||
continue;
|
||||
snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
|
||||
if (verbose > 0)
|
||||
@@ -98,12 +100,19 @@ int delete_file(char *fname)
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errno) {
|
||||
rprintf(FERROR, "delete_file: readdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
|
||||
if (do_rmdir(fname) != 0) {
|
||||
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -124,7 +133,7 @@ static int is_in_group(gid_t gid)
|
||||
/* treat failure (-1) as if not member of any group */
|
||||
ngroups = getgroups(0, 0);
|
||||
if (ngroups > 0) {
|
||||
gidset = (GETGROUPS_T *) malloc(ngroups * sizeof(GETGROUPS_T));
|
||||
gidset = new_array(GETGROUPS_T, ngroups);
|
||||
ngroups = getgroups(ngroups, gidset);
|
||||
}
|
||||
}
|
||||
@@ -145,7 +154,7 @@ static int is_in_group(gid_t gid)
|
||||
}
|
||||
|
||||
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
int report)
|
||||
int report)
|
||||
{
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
@@ -155,7 +164,8 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
if (!st) {
|
||||
if (link_stat(fname,&st2) != 0) {
|
||||
rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
|
||||
rprintf(FERROR, "stat %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
st = &st2;
|
||||
@@ -167,8 +177,8 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
because some filesystems can't do it */
|
||||
if (set_modtime(fname,file->modtime) != 0 &&
|
||||
!S_ISDIR(st->st_mode)) {
|
||||
rprintf(FERROR,"failed to set times on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
rprintf(FERROR, "failed to set times on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
} else {
|
||||
updated = 1;
|
||||
@@ -189,7 +199,8 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
change_gid?file->gid:st->st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
unless have the privilege */
|
||||
rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno));
|
||||
rprintf(FERROR, "chown %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
@@ -203,17 +214,17 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
if (!S_ISLNK(st->st_mode)) {
|
||||
if (st->st_mode != file->mode) {
|
||||
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,file->mode) != 0) {
|
||||
rprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
if (do_chmod(fname,(file->mode & CHMOD_BITS)) != 0) {
|
||||
rprintf(FERROR, "failed to set permissions on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (verbose > 1 && report) {
|
||||
if (updated)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
@@ -226,6 +237,15 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
void sig_int(void)
|
||||
{
|
||||
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
|
||||
* for a password, then our cleanup's sending of a SIGUSR1
|
||||
* signal to all our children may kill ssh before it has a
|
||||
* chance to restore the tty settings (i.e. turn echo back
|
||||
* on). By sleeping for a short time, ssh gets a bigger
|
||||
* chance to do the right thing. If child processes are
|
||||
* not ssh waiting for a password, then this tiny delay
|
||||
* shouldn't hurt anything. */
|
||||
msleep(400);
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
@@ -240,17 +260,18 @@ void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
|
||||
/* move tmp file over real file */
|
||||
if (robust_rename(fnametmp,fname) != 0) {
|
||||
if (errno == EXDEV) {
|
||||
/* rename failed on cross-filesystem link.
|
||||
/* rename failed on cross-filesystem link.
|
||||
Copy the file instead. */
|
||||
if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
|
||||
rprintf(FERROR,"copy %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
rprintf(FERROR, "copy %s -> \"%s\": %s\n",
|
||||
full_fname(fnametmp), fname,
|
||||
strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
} else {
|
||||
rprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
rprintf(FERROR,"rename %s -> \"%s\": %s\n",
|
||||
full_fname(fnametmp), fname, strerror(errno));
|
||||
}
|
||||
do_unlink(fnametmp);
|
||||
} else {
|
||||
|
||||
137
rsync.h
137
rsync.h
@@ -24,6 +24,7 @@
|
||||
|
||||
#define BLOCK_SIZE 700
|
||||
#define RSYNC_RSH_ENV "RSYNC_RSH"
|
||||
#define RSYNC_RSH_IO_ENV "RSYNC_RSH_IO"
|
||||
|
||||
#define RSYNC_NAME "rsync"
|
||||
#define RSYNCD_SYSCONF "/etc/rsyncd.conf"
|
||||
@@ -50,20 +51,28 @@
|
||||
#define SAME_TIME (1<<7)
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
#define PROTOCOL_VERSION 26
|
||||
#define PROTOCOL_VERSION 27
|
||||
|
||||
/* 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
|
||||
* people writing them to make sure that they don't send us anything
|
||||
* we won't understand.
|
||||
*
|
||||
* There are two possible explanations for the limit at thirty: either
|
||||
* to allow new major-rev versions that do not interoperate with us,
|
||||
* and (more likely) so that we can detect an attempt to connect rsync
|
||||
* to a non-rsync server, which is unlikely to begin by sending a byte
|
||||
* between 15 and 30. */
|
||||
#define MIN_PROTOCOL_VERSION 15
|
||||
#define MAX_PROTOCOL_VERSION 30
|
||||
* Interoperation with old but supported protocol versions
|
||||
* should cause a warning to be printed. At a future date
|
||||
* the old protocol will become the minimum and
|
||||
* compatibility code removed.
|
||||
*
|
||||
* There are two possible explanations for the limit at
|
||||
* MAX_PROTOCOL_VERSION: either to allow new major-rev versions that
|
||||
* do not interoperate with us, and (more likely) so that we can
|
||||
* detect an attempt to connect rsync to a non-rsync server, which is
|
||||
* unlikely to begin by sending a byte between MIN_PROTOCL_VERSION and
|
||||
* MAX_PROTOCOL_VERSION. */
|
||||
|
||||
#define MIN_PROTOCOL_VERSION 17
|
||||
#define OLD_PROTOCOL_VERSION 20
|
||||
#define MAX_PROTOCOL_VERSION 40
|
||||
|
||||
#define RSYNC_PORT 873
|
||||
|
||||
@@ -73,10 +82,23 @@
|
||||
#define MAX_MAP_SIZE (256*1024)
|
||||
#define IO_BUFFER_SIZE (4092)
|
||||
|
||||
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
|
||||
#define IOERR_VANISHED (1<<1)
|
||||
|
||||
#define MAX_ARGS 1000
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
|
||||
#define NO_EXCLUDES 0
|
||||
#define SERVER_EXCLUDES 1
|
||||
#define ALL_EXCLUDES 2
|
||||
|
||||
#define MISSING_OK 0
|
||||
#define MISSING_FATAL 1
|
||||
|
||||
#define ADD_INCLUDE 1
|
||||
#define ADD_EXCLUDE 0
|
||||
|
||||
/* Log values. I *think* what these mean is: FLOG goes to the server
|
||||
* logfile; FERROR and FINFO try to end up on the client, with
|
||||
* different levels of filtering. */
|
||||
@@ -86,9 +108,7 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* The default RSYNC_RSH is always set in config.h, either to "remsh",
|
||||
* "rsh", or otherwise something specified by the user. HAVE_REMSH
|
||||
* controls parameter munging for HP/UX, etc. */
|
||||
/* The default RSYNC_RSH is always set in config.h. */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -106,6 +126,10 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MALLOC_H) && (defined(HAVE_MALLINFO) || !defined(HAVE_STDLIB_H))
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
@@ -114,10 +138,6 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -174,20 +194,10 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FNMATCH
|
||||
#include <fnmatch.h>
|
||||
#else
|
||||
#include "lib/fnmatch.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
/* these are needed for the uid/gid mapping code */
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
@@ -273,6 +283,17 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#define NO_INT64
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_LONG == 8)
|
||||
#define uint64 unsigned long
|
||||
#elif (SIZEOF_INT == 8)
|
||||
#define uint64 unsigned int
|
||||
#elif HAVE_LONGLONG
|
||||
#define uint64 unsigned long long
|
||||
#else
|
||||
/* As long as it gets... */
|
||||
#define uint64 unsigned off_t
|
||||
#endif
|
||||
|
||||
/* Starting from protocol version 26, we always use 64-bit
|
||||
* ino_t and dev_t internally, even if this platform does not
|
||||
* allow files to have 64-bit inums. That's because the
|
||||
@@ -304,8 +325,8 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
* cope with platforms on which this is an unsigned int or even a
|
||||
* struct. Later.
|
||||
*/
|
||||
#define INO64_T int64
|
||||
#define DEV64_T int64
|
||||
#define INO64_T uint64
|
||||
#define DEV64_T uint64
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -322,11 +343,17 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
/* the length of the md4 checksum */
|
||||
#define MD4_SUM_LENGTH 16
|
||||
#define SUM_LENGTH 16
|
||||
#define SHORT_SUM_LENGTH 2
|
||||
#define BLOCKSUM_BIAS 10
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
#ifndef NAME_MAX
|
||||
#define NAME_MAX 255
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
@@ -385,23 +412,35 @@ struct sum_struct {
|
||||
OFF_T flength; /**< total file length */
|
||||
size_t count; /**< how many chunks */
|
||||
size_t remainder; /**< flength % block_length */
|
||||
size_t n; /**< block_length */
|
||||
size_t blength; /**< block_length */
|
||||
size_t s2length; /**< sum2_length */
|
||||
struct sum_buf *sums; /**< points to info for each chunk */
|
||||
};
|
||||
|
||||
struct map_struct {
|
||||
char *p;
|
||||
int fd,p_size,p_len;
|
||||
OFF_T file_size, p_offset, p_fd_offset;
|
||||
char *p; /* Window pointer */
|
||||
int fd; /* File Descriptor */
|
||||
int p_size; /* Window size at allocation */
|
||||
int p_len; /* Window size after fill */
|
||||
/* p_size and p_len could be
|
||||
* consolodated by using a local
|
||||
* variable in map_ptr() */
|
||||
int status; /* first errno from read errors */
|
||||
OFF_T file_size; /* File size (from stat) */
|
||||
OFF_T p_offset; /* Window start */
|
||||
OFF_T p_fd_offset; /* offset of cursor in fd ala lseek */
|
||||
};
|
||||
|
||||
#define MATCHFLG_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
|
||||
#define MATCHFLG_WILD2 (1<<1) /* pattern has '**' */
|
||||
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with '**' */
|
||||
#define MATCHFLG_ABS_PATH (1<<3) /* path-match on absolute path */
|
||||
struct exclude_struct {
|
||||
char *pattern;
|
||||
int regular_exp;
|
||||
int fnmatch_flags;
|
||||
int match_flags;
|
||||
int include;
|
||||
int directory;
|
||||
int local;
|
||||
int slash_cnt;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
@@ -428,6 +467,7 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "lib/mdfour.h"
|
||||
#include "lib/wildmatch.h"
|
||||
#include "lib/permstring.h"
|
||||
#include "lib/addrinfo.h"
|
||||
|
||||
@@ -442,11 +482,13 @@ int asprintf(char **ptr, const char *format, ...);
|
||||
int vasprintf(char **ptr, const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_VSNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list args);
|
||||
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define vsnprintf rsync_vsnprintf
|
||||
int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
|
||||
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define snprintf rsync_snprintf
|
||||
int snprintf(char *str,size_t count,const char *fmt,...);
|
||||
#endif
|
||||
|
||||
@@ -497,6 +539,16 @@ extern int errno;
|
||||
#define S_IWUSR 0200
|
||||
#endif
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS 0777
|
||||
#endif
|
||||
|
||||
#ifndef S_ISVTX
|
||||
#define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#define CHMOD_BITS (S_ISUID | S_ISGID | S_ISVTX | ACCESSPERMS)
|
||||
|
||||
#ifndef _S_IFMT
|
||||
#define _S_IFMT 0170000
|
||||
#endif
|
||||
@@ -560,9 +612,6 @@ extern int errno;
|
||||
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS 0777
|
||||
#endif
|
||||
/* Initial mask on permissions given to temporary files. Mask off setuid
|
||||
bits and group access because of potential race-condition security
|
||||
holes, and mask other access because mode 707 is bizarre */
|
||||
@@ -579,6 +628,10 @@ extern int errno;
|
||||
|
||||
#endif
|
||||
|
||||
/* Convenient wrappers for malloc and realloc. Use them. */
|
||||
#define new(type) ((type *)malloc(sizeof(type)))
|
||||
#define new_array(type, num) ((type *)_new_array(sizeof(type), (num)))
|
||||
#define realloc_array(ptr, type, num) ((type *)_realloc_array((ptr), sizeof(type), (num)))
|
||||
|
||||
/* use magic gcc attributes to catch format errors */
|
||||
void rprintf(enum logcode , const char *, ...)
|
||||
@@ -595,6 +648,10 @@ void rsyserr(enum logcode, int, const char *, ...)
|
||||
#define inet_ntoa rep_inet_ntoa
|
||||
#endif
|
||||
|
||||
/* Make sure that the O_BINARY flag is defined. */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char *d, const char *s, size_t bufsize);
|
||||
|
||||
319
rsync.yo
319
rsync.yo
@@ -25,7 +25,7 @@ greatly speed up file transfers when the destination file already
|
||||
exists.
|
||||
|
||||
The rsync remote-update protocol allows rsync to transfer just the
|
||||
differences between two sets of files across the network link, using
|
||||
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.
|
||||
|
||||
@@ -35,7 +35,7 @@ itemize(
|
||||
it() support for copying links, devices, owners, groups and permissions
|
||||
it() exclude and exclude-from options similar to GNU tar
|
||||
it() a CVS exclude mode for ignoring the same files that CVS would ignore
|
||||
it() can use any transparent remote shell, including rsh or ssh
|
||||
it() can use any transparent remote shell, including ssh or rsh
|
||||
it() does not require root privileges
|
||||
it() pipelining of file transfers to minimize latency costs
|
||||
it() support for anonymous or authenticated rsync servers (ideal for
|
||||
@@ -51,8 +51,8 @@ itemize(
|
||||
source nor destination path contains a : separator
|
||||
|
||||
it() for copying from the local machine to a remote machine using
|
||||
a remote shell program as the transport (such as rsh or
|
||||
ssh). This is invoked when the destination path contains a
|
||||
a remote shell program as the transport (such as ssh or
|
||||
rsh). This is invoked when the destination path contains a
|
||||
single : separator.
|
||||
|
||||
it() for copying from a remote machine to the local machine
|
||||
@@ -93,9 +93,9 @@ See the file README for installation instructions.
|
||||
|
||||
Once installed, you can use rsync to any machine that you can access via
|
||||
a remote shell (as well as some that you can access using the rsync
|
||||
daemon-mode protocol). For remote transfers, rsync typically uses rsh
|
||||
daemon-mode protocol). For remote transfers, a modern rsync uses ssh
|
||||
for its communications, but it may have been configured to use a
|
||||
different remote shell by default, such as ssh.
|
||||
different remote shell by default, such as rsh or remsh.
|
||||
|
||||
You can also specify any remote shell you like, either by using the -e
|
||||
command line option, or by setting the RSYNC_RSH environment variable.
|
||||
@@ -115,7 +115,7 @@ Perhaps the best way to explain the syntax is some examples:
|
||||
|
||||
quote(rsync *.c foo:src/)
|
||||
|
||||
this would transfer all files matching the pattern *.c from the
|
||||
This would transfer all files matching the pattern *.c from the
|
||||
current directory to the directory src on the machine foo. If any of
|
||||
the files already exist on the remote system then the rsync
|
||||
remote-update protocol is used to update the file by sending only the
|
||||
@@ -123,7 +123,7 @@ differences. See the tech report for details.
|
||||
|
||||
quote(rsync -avz foo:src/bar /data/tmp)
|
||||
|
||||
this would recursively transfer all files from the directory src/bar on the
|
||||
This would recursively transfer all files from the directory src/bar on the
|
||||
machine foo into the /data/tmp/bar directory on the local machine. The
|
||||
files are transferred in "archive" mode, which ensures that symbolic
|
||||
links, devices, attributes, permissions, ownerships etc are preserved
|
||||
@@ -132,12 +132,17 @@ size of data portions of the transfer.
|
||||
|
||||
quote(rsync -avz foo:src/bar/ /data/tmp)
|
||||
|
||||
a trailing slash on the source changes this behavior to transfer
|
||||
all files from the directory src/bar on the machine foo into the
|
||||
/data/tmp/. A trailing / on a source name means "copy the
|
||||
contents of this directory". Without a trailing slash it means "copy
|
||||
the directory". This difference becomes particularly important when
|
||||
using the --delete option.
|
||||
A trailing slash on the source changes this behavior to avoid creating an
|
||||
additional directory level at the destination. You can think of a trailing
|
||||
/ on a source as meaning "copy the contents of this directory" as opposed
|
||||
to "copy the directory by name", but in both cases the attributes of the
|
||||
containing directory are transferred to the containing directory on the
|
||||
destination. In other words, each of the following commands copies the
|
||||
files in the same way, including their setting of the attributes of
|
||||
/dest/foo:
|
||||
|
||||
quote(rsync -avz /src/foo /dest)
|
||||
quote(rsync -avz /src/foo/ /dest/foo)
|
||||
|
||||
You can also use rsync in local-only mode, where both the source and
|
||||
destination don't have a ':' in the name. In this case it behaves like
|
||||
@@ -145,7 +150,7 @@ an improved copy command.
|
||||
|
||||
quote(rsync somehost.mydomain.com::)
|
||||
|
||||
this would list all the anonymous rsync modules available on the host
|
||||
This would list all the anonymous rsync modules available on the host
|
||||
somehost.mydomain.com. (See the following section for more details.)
|
||||
|
||||
|
||||
@@ -189,8 +194,8 @@ users. On those systems using --password-file is recommended.
|
||||
manpagesection(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
|
||||
|
||||
It is sometimes useful to be able to set up file transfers using rsync
|
||||
server capabilities on the remote machine, while still using rsh or
|
||||
ssh for transport. This is especially useful when you want to connect
|
||||
server capabilities on the remote machine, while still using ssh or
|
||||
rsh for transport. This is especially useful when you want to connect
|
||||
to a remote machine via ssh (for encryption or to get through a
|
||||
firewall), but you still want to have access to the rsync server
|
||||
features (see RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM,
|
||||
@@ -229,18 +234,8 @@ user is root (e.g. chroot, setuid/setgid, etc.). There is no need to
|
||||
configure inetd or the services map to include the rsync server port
|
||||
if you run an rsync server only via a remote shell program.
|
||||
|
||||
To run an rsync server out of a single-use ssh key, use the
|
||||
"command=em(COMMAND)" syntax in the remote user's
|
||||
authorized_keys entry, where command would be
|
||||
|
||||
quote(rsync --server --daemon .)
|
||||
|
||||
NOTE: rsync's argument parsing expects the trailing ".", so make sure
|
||||
that it's there. If you want to use a rsyncd.conf(5)-style
|
||||
configuration file other than the default, you can added a
|
||||
--config option to the em(command):
|
||||
|
||||
quote(rsync --server --daemon --config=em(file) .)
|
||||
To run an rsync server out of a single-use ssh key, see this section
|
||||
in the rsyncd.conf(5) man page.
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
|
||||
@@ -251,7 +246,7 @@ files and mail folders, I use a cron job that runs
|
||||
|
||||
quote(rsync -Cavz . arvidsjaur:backup)
|
||||
|
||||
each night over a PPP link to a duplicate directory on my machine
|
||||
each night over a PPP connection to a duplicate directory on my machine
|
||||
"arvidsjaur".
|
||||
|
||||
To synchronize my samba source trees I use the following Makefile
|
||||
@@ -266,7 +261,7 @@ quote( get:nl()
|
||||
sync: get put)
|
||||
|
||||
this allows me to sync with a CVS directory at the other end of the
|
||||
link. I then do cvs operations on the remote machine, which saves a
|
||||
connection. I then do cvs operations on the remote machine, which saves a
|
||||
lot of time as the remote cvs protocol isn't very efficient.
|
||||
|
||||
I mirror a directory between my "old" and "new" ftp sites with the
|
||||
@@ -288,9 +283,11 @@ verb(
|
||||
-a, --archive archive mode, equivalent to -rlptgoD
|
||||
-r, --recursive recurse into directories
|
||||
-R, --relative use relative path names
|
||||
-b, --backup make backups (default ~ suffix)
|
||||
--no-relative turn off --relative
|
||||
--no-implied-dirs don't send implied dirs with -R
|
||||
-b, --backup make backups (see --suffix)
|
||||
--backup-dir make backups into this directory
|
||||
--suffix=SUFFIX define backup suffix
|
||||
--suffix=SUFFIX define backup suffix (default ~ w/o --backup-dir)
|
||||
-u, --update update only (don't overwrite newer files)
|
||||
-l, --links copy symlinks as symlinks
|
||||
-L, --copy-links copy the referent of symlinks
|
||||
@@ -310,7 +307,6 @@ verb(
|
||||
-B, --block-size=SIZE checksum blocking size (default 700)
|
||||
-e, --rsh=COMMAND specify the remote shell to use
|
||||
--rsync-path=PATH specify path to rsync on the remote machine
|
||||
-C, --cvs-exclude auto ignore files in the same way CVS does
|
||||
--existing only update files that already exist
|
||||
--ignore-existing ignore files that already exist on the receiving side
|
||||
--delete delete files that don't exist on the sending side
|
||||
@@ -330,10 +326,13 @@ verb(
|
||||
--link-dest=DIR create hardlinks to DIR for unchanged files
|
||||
-P equivalent to --partial --progress
|
||||
-z, --compress compress file data
|
||||
-C, --cvs-exclude auto ignore files in the same way CVS does
|
||||
--exclude=PATTERN exclude files matching PATTERN
|
||||
--exclude-from=FILE exclude patterns listed in FILE
|
||||
--include=PATTERN don't exclude files matching PATTERN
|
||||
--include-from=FILE don't exclude patterns listed in FILE
|
||||
--files-from=FILE read FILE for list of source-file names
|
||||
-0 --from0 file names we read are separated by nulls, not newlines
|
||||
--version print version number
|
||||
--daemon run as a rsync daemon
|
||||
--no-detach do not detach from the parent
|
||||
@@ -431,11 +430,27 @@ machine. If instead you used
|
||||
verb(rsync -R foo/bar/foo.c remote:/tmp/)
|
||||
|
||||
then a file called /tmp/foo/bar/foo.c would be created on the remote
|
||||
machine. The full path name is preserved.
|
||||
machine -- the full path name is preserved.
|
||||
|
||||
dit(bf(-b, --backup)) With this option preexisting destination files are
|
||||
renamed with a ~ extension as each file is transferred. You can
|
||||
control the backup suffix using the --suffix option.
|
||||
dit(bf(--no-relative)) Turn off the --relative option. This is only
|
||||
needed if you want to use --files-from without its implied --relative
|
||||
file processing.
|
||||
|
||||
dit(bf(--no-implied-dirs)) When combined with the --relative option, the
|
||||
implied directories in each path are not explicitly duplicated as part
|
||||
of the transfer. This makes the transfer more optimal and also allows
|
||||
the two sides to have non-matching symlinks in the implied part of the
|
||||
path. For instance, if you transfer the file "/path/foo/file" with -R,
|
||||
the default is for rsync to ensure that "/path" and "/path/foo" on the
|
||||
destination exactly match the directories/symlinks of the source. Using
|
||||
the --no-implied-dirs option would omit both of these implied dirs,
|
||||
which means that if "/path" was a real directory on one machine and a
|
||||
symlink of the other machine, rsync would not try to change this.
|
||||
|
||||
dit(bf(-b, --backup)) With this option, preexisting destination files are
|
||||
renamed as each file is transferred or deleted. You can control where the
|
||||
backup file goes and what (if any) suffix gets appended using the
|
||||
--backup-dir and --suffix options.
|
||||
|
||||
dit(bf(--backup-dir=DIR)) In combination with the --backup option, this
|
||||
tells rsync to store all backups in the specified directory. This is
|
||||
@@ -445,9 +460,8 @@ specify a backup suffix using the --suffix option
|
||||
will keep their original filenames).
|
||||
|
||||
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
|
||||
backup suffix used with the -b option. The default is a ~.
|
||||
If --backup-dir and --suffix are both specified,
|
||||
the SUFFIX is appended to the filename even in the backup directory.
|
||||
backup suffix used with the --backup (-b) option. The default suffix is a ~
|
||||
if no --backup-dir was specified, otherwise it is an empty string.
|
||||
|
||||
dit(bf(-u, --update)) This forces rsync to skip any files for which the
|
||||
destination file already exists and has a date later than the source
|
||||
@@ -488,8 +502,13 @@ the source and target are on the local machine.
|
||||
dit(bf(--no-whole-file)) Turn off --whole-file, for use when it is the
|
||||
default.
|
||||
|
||||
dit(bf(-p, --perms)) This option causes rsync to update the remote
|
||||
permissions to be the same as the local permissions.
|
||||
dit(bf(-p, --perms)) This option causes rsync to set the destination
|
||||
permissions to be the same as the source permissions.
|
||||
|
||||
Without this option, each new file gets its permissions set based on the
|
||||
source file's permissions and the umask at the receiving end, while all
|
||||
other files (including updated files) retain their existing permissions
|
||||
(which is the same behavior as other file-copy utilities, such as cp).
|
||||
|
||||
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
|
||||
destination file to be the same as the source file. On most systems,
|
||||
@@ -579,8 +598,8 @@ the rsync algorithm. See the technical report for details.
|
||||
|
||||
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
|
||||
remote shell program to use for communication between the local and
|
||||
remote copies of rsync. Typically, rsync is configured to use rsh by
|
||||
default, but you may prefer to use ssh because of its high security.
|
||||
remote copies of rsync. Typically, rsync is configured to use ssh by
|
||||
default, but you may prefer to use rsh on a local network.
|
||||
|
||||
If this option is used with bf([user@]host::module/path), then the
|
||||
remote shell em(COMMMAND) will be used to run an rsync server on the
|
||||
@@ -607,35 +626,6 @@ rsync on the remote machine. Useful when it's not in your path. Note
|
||||
that this is the full path to the binary, not just the directory that
|
||||
the binary is in.
|
||||
|
||||
dit(bf(--exclude=PATTERN)) This option allows you to selectively 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 --exclude options on the command line as you like
|
||||
to build up the list of files to exclude.
|
||||
|
||||
See the section on exclude patterns for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--exclude-from=FILE)) This option is similar to the --exclude
|
||||
option, but instead it adds all exclude patterns listed in the file
|
||||
FILE to the exclude list. Blank lines in FILE and lines starting with
|
||||
';' or '#' are ignored.
|
||||
If em(FILE) is bf(-) the list will be read from standard input.
|
||||
|
||||
|
||||
dit(bf(--include=PATTERN)) This option tells rsync to not exclude the
|
||||
specified pattern of filenames. This is useful as it allows you to
|
||||
build up quite complex exclude/include rules.
|
||||
|
||||
See the section of exclude patterns for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--include-from=FILE)) This specifies a list of include patterns
|
||||
from a file.
|
||||
If em(FILE) is bf(-) the list will be read from standard input.
|
||||
|
||||
|
||||
dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
|
||||
broad range of files that you often don't want to transfer between
|
||||
systems. It uses the same algorithm that CVS uses to determine if
|
||||
@@ -654,24 +644,73 @@ Finally, any file is ignored if it is in the same directory as a
|
||||
.cvsignore file and matches one of the patterns listed therein. See
|
||||
the bf(cvs(1)) manual for more information.
|
||||
|
||||
dit(bf(--csum-length=LENGTH)) By default the primary checksum used in
|
||||
rsync is a very strong 16 byte MD4 checksum. In most cases you will
|
||||
find that a truncated version of this checksum is quite efficient, and
|
||||
this will decrease the size of the checksum data sent over the link,
|
||||
making things faster.
|
||||
dit(bf(--exclude=PATTERN)) This option allows you to selectively exclude
|
||||
certain files from the list of files to be transferred. This is most
|
||||
useful in combination with a recursive transfer.
|
||||
|
||||
You can choose the number of bytes in the truncated checksum using the
|
||||
--csum-length option. Any value less than or equal to 16 is valid.
|
||||
You may use as many --exclude options on the command line as you like
|
||||
to build up the list of files to exclude.
|
||||
|
||||
Note that if you use this option then you run the risk of ending up
|
||||
with an incorrect target file. The risk with a value of 16 is
|
||||
microscopic and can be safely ignored (the universe will probably end
|
||||
before it fails) but with smaller values the risk is higher.
|
||||
See the EXCLUDE PATTERNS section for information on the syntax of
|
||||
this option.
|
||||
|
||||
Current versions of rsync actually use an adaptive algorithm for the
|
||||
checksum length by default, using a 16 byte file checksum to determine
|
||||
if a 2nd pass is required with a longer block checksum. Only use this
|
||||
option if you have read the source code and know what you are doing.
|
||||
dit(bf(--exclude-from=FILE)) This option is similar to the --exclude
|
||||
option, but instead it adds all exclude patterns listed in the file
|
||||
FILE to the exclude list. Blank lines in FILE and lines starting with
|
||||
';' or '#' are ignored.
|
||||
If em(FILE) is bf(-) the list will be read from standard input.
|
||||
|
||||
dit(bf(--include=PATTERN)) This option tells rsync to not exclude the
|
||||
specified pattern of filenames. This is useful as it allows you to
|
||||
build up quite complex exclude/include rules.
|
||||
|
||||
See the EXCLUDE PATTERNS section for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--include-from=FILE)) This specifies a list of include patterns
|
||||
from a file.
|
||||
If em(FILE) is bf(-) the list will be read from standard input.
|
||||
|
||||
dit(bf(--files-from=FILE)) Using this option allows you to specify the
|
||||
exact list of files to transfer (as read from the specified FILE or "-"
|
||||
for stdin). It also tweaks the default behavior of rsync to make
|
||||
transferring just the specified files and directories easier. For
|
||||
instance, the --relative option is enabled by default when this option
|
||||
is used (use --no-relative if you want to turn that off), all
|
||||
directories specified in the list are created on the destination (rather
|
||||
than being noisily skipped without -r), and the -a (--archive) option's
|
||||
behavior does not imply -r (--recursive) -- specify it explicitly, if
|
||||
you want it.
|
||||
|
||||
The file names that are read from the FILE are all relative to the
|
||||
source dir -- any leading slashes are removed and no ".." references are
|
||||
allowed to go higher than the source dir. For example, take this
|
||||
command:
|
||||
|
||||
quote(rsync -a --files-from=/tmp/foo /usr remote:/backup)
|
||||
|
||||
If /tmp/foo contains the string "bin" (or even "/bin"), the /usr/bin
|
||||
directory will be created as /backup/bin on the remote host (but the
|
||||
contents of the /usr/bin dir would not be sent unless you specified -r
|
||||
or the names were explicitly listed in /tmp/foo). Also keep in mind
|
||||
that the effect of the (enabled by default) --relative option is to
|
||||
duplicate only the path info that is read from the file -- it does not
|
||||
force the duplication of the source-spec path (/usr in this case).
|
||||
|
||||
In addition, the --files-from file can be read from the remote host
|
||||
instead of the local host if you specify a "host:" in front of the file
|
||||
(the host must match one end of the transfer). As a short-cut, you can
|
||||
specify just a prefix of ":" to mean "use the remote end of the
|
||||
transfer". For example:
|
||||
|
||||
quote(rsync -a --files-from=:/path/file-list src:/ /tmp/copy)
|
||||
|
||||
This would copy all the files specified in the /path/file-list file that
|
||||
was located on the remote "src" host.
|
||||
|
||||
dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
|
||||
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
|
||||
This affects --exclude-from, --include-from, and --files-from.
|
||||
|
||||
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
|
||||
scratch directory when creating temporary copies of the files
|
||||
@@ -695,10 +734,12 @@ dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest) but
|
||||
also will create hard links from em(DIR) to the destination directory for
|
||||
unchanged files. Files with changed ownership or permissions will not be
|
||||
linked.
|
||||
Like bf(--compare-dest) if DIR is a relative path, it is relative
|
||||
to the destination directory.
|
||||
|
||||
dit(bf(-z, --compress)) With this option, rsync compresses any data from
|
||||
the files that it sends to the destination machine. This
|
||||
option is useful on slow links. The compression method used is the
|
||||
option is useful on slow connections. The compression method used is the
|
||||
same method that gzip uses.
|
||||
|
||||
Note this this option typically achieves better compression ratios
|
||||
@@ -759,11 +800,10 @@ dit(bf(--port=PORT)) This specifies an alternate TCP port number to use
|
||||
rather than the default port 873.
|
||||
|
||||
dit(bf(--blocking-io)) This tells rsync to use blocking IO when launching
|
||||
a remote shell transport. If -e or --rsh are not specified or are set to
|
||||
the default "rsh", this defaults to blocking IO, otherwise it defaults to
|
||||
non-blocking IO. You may find the --blocking-io option is needed for some
|
||||
remote shells that can't handle non-blocking IO. (Note that ssh prefers
|
||||
non-blocking IO.)
|
||||
a remote shell transport. If the remote shell is either rsh or remsh,
|
||||
rsync defaults to using
|
||||
blocking IO, otherwise it defaults to using non-blocking IO. (Note that
|
||||
ssh prefers non-blocking IO.)
|
||||
|
||||
dit(bf(--no-blocking-io)) Turn off --blocking-io, for use when it is the
|
||||
default.
|
||||
@@ -786,9 +826,7 @@ make a subsequent transfer of the rest of the file much faster.
|
||||
dit(bf(--progress)) This option tells rsync to print information
|
||||
showing the progress of the transfer. This gives a bored user
|
||||
something to watch.
|
||||
|
||||
This option is normally combined with -v. Using this option without
|
||||
the -v option will produce weird results on your display.
|
||||
Implies --verbose without incrementing verbosity.
|
||||
|
||||
dit(bf(-P)) The -P option is equivalent to --partial --progress. I
|
||||
found myself typing that combination quite often so I created an
|
||||
@@ -825,13 +863,20 @@ The exclude and include patterns specified to rsync allow for flexible
|
||||
selection of which files to transfer and which files to skip.
|
||||
|
||||
rsync builds an ordered list of include/exclude options as specified on
|
||||
the command line. When a filename is encountered, rsync checks the
|
||||
the command line. Rsync checks each file and directory
|
||||
name against each exclude/include pattern in turn. The first matching
|
||||
pattern is acted on. If it is an exclude pattern, then that file is
|
||||
skipped. If it is an include pattern then that filename is not
|
||||
skipped. If no matching include/exclude pattern is found then the
|
||||
filename is not skipped.
|
||||
|
||||
The filenames matched against the exclude/include patterns
|
||||
are relative to the destination directory, or "top
|
||||
directory", so patterns should not include the path elements
|
||||
of the source or destination directories. The only way in
|
||||
which a pattern will match the absolute path of a file or
|
||||
directory is if the source path is the root directory.
|
||||
|
||||
Note that when used with -r (which is implied by -a), every subcomponent of
|
||||
every path is visited from top down, so include/exclude patterns get
|
||||
applied recursively to each subcomponent.
|
||||
@@ -843,13 +888,18 @@ each. To add multiple patterns use the --include-from and
|
||||
The patterns can take several forms. The rules are:
|
||||
|
||||
itemize(
|
||||
|
||||
it() if the pattern starts with a / then it is matched against the
|
||||
start of the filename, otherwise it is matched against the end of
|
||||
the filename. Thus "/foo" would match a file called "foo" at the base of
|
||||
the tree. On the other hand, "foo" would match any file called "foo"
|
||||
the filename.
|
||||
This is the equivalent of a leading ^ in regular expressions.
|
||||
Thus "/foo" would match a file called "foo" at the top of the
|
||||
transferred tree.
|
||||
On the other hand, "foo" would match any file called "foo"
|
||||
anywhere in the tree because the algorithm is applied recursively from
|
||||
top down; it behaves as if each path component gets a turn at being the
|
||||
end of the file name.
|
||||
The leading / does not make the pattern an absolute pathname.
|
||||
|
||||
it() if the pattern ends with a / then it will only match a
|
||||
directory, not a file, link or device.
|
||||
@@ -858,15 +908,15 @@ itemize(
|
||||
*?[ then expression matching is applied using the shell filename
|
||||
matching rules. Otherwise a simple string match is used.
|
||||
|
||||
it() if the pattern includes a double asterisk "**" then all wildcards in
|
||||
the pattern will match slashes, otherwise they will stop at slashes.
|
||||
it() the double asterisk pattern "**" will match slashes while a
|
||||
single asterisk pattern "*" will stop at slashes.
|
||||
|
||||
it() if the pattern contains a / (not counting a trailing /) then it
|
||||
is matched against the full filename, including any leading
|
||||
directory. If the pattern doesn't contain a / then it is matched
|
||||
only against the final component of the filename. Again, remember
|
||||
that the algorithm is applied recursively so "full filename" can
|
||||
actually be any portion of a path.
|
||||
it() if the pattern contains a / (not counting a trailing /) or a "**"
|
||||
then it is matched against the full filename, including any leading
|
||||
directory. If the pattern doesn't contain a / or a "**", then it is
|
||||
matched only against the final component of the filename. Again,
|
||||
remember that the algorithm is applied recursively so "full filename" can
|
||||
actually be any portion of a path below the starting directory.
|
||||
|
||||
it() if the pattern starts with "+ " (a plus followed by a space)
|
||||
then it is always considered an include pattern, even if specified as
|
||||
@@ -880,8 +930,9 @@ itemize(
|
||||
include/exclude list is reset, removing all previously defined patterns.
|
||||
)
|
||||
|
||||
The +/- rules are most useful in exclude lists, allowing you to have a
|
||||
single exclude list that contains both include and exclude options.
|
||||
The +/- rules are most useful in a list that was read from a file, allowing
|
||||
you to have a single exclude list that contains both include and exclude
|
||||
options.
|
||||
|
||||
If you end an exclude list with --exclude '*', note that since the
|
||||
algorithm is applied recursively that unless you explicitly include
|
||||
@@ -894,12 +945,12 @@ Here are some exclude/include examples:
|
||||
|
||||
itemize(
|
||||
it() --exclude "*.o" would exclude all filenames matching *.o
|
||||
it() --exclude "/foo" would exclude a file in the base directory called foo
|
||||
it() --exclude "/foo" would exclude a file called foo in the top directory
|
||||
it() --exclude "foo/" would exclude any directory called foo
|
||||
it() --exclude "/foo/*/bar" would exclude any file called bar two
|
||||
levels below a base directory called foo
|
||||
levels below a directory called foo in the top directory
|
||||
it() --exclude "/foo/**/bar" would exclude any file called bar two
|
||||
or more levels below a base directory called foo
|
||||
or more levels below a directory called foo in the top directory
|
||||
it() --include "*/" --include "*.c" --exclude "*" would include all
|
||||
directories and C source files
|
||||
it() --include "foo/" --include "foo/bar.c" --exclude "*" would include
|
||||
@@ -953,11 +1004,11 @@ once, instead of sending the same data to every host individually.
|
||||
Example:
|
||||
|
||||
verb(
|
||||
$ rsync --write_batch=pfx -a /source/dir/ /adest/dir/
|
||||
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
|
||||
$ rcp pfx.rsync_* remote:
|
||||
$ rsh remote rsync --read_batch=pfx -a /bdest/dir/
|
||||
$ ssh remote rsync --read-batch=pfx -a /bdest/dir/
|
||||
# or alternatively
|
||||
$ rsh remote ./pfx.rsync_argvs /bdest/dir/
|
||||
$ ssh remote ./pfx.rsync_argvs /bdest/dir/
|
||||
)
|
||||
|
||||
In this example, rsync is used to update /adest/dir/ with /source/dir/
|
||||
@@ -1029,7 +1080,7 @@ for its transport. The way to diagnose this problem is to run your
|
||||
remote shell like this:
|
||||
|
||||
verb(
|
||||
rsh remotehost /bin/true > out.dat
|
||||
ssh remotehost /bin/true > out.dat
|
||||
)
|
||||
|
||||
then look at out.dat. If everything is working correctly then out.dat
|
||||
@@ -1047,24 +1098,26 @@ show why each individual file is included or excluded.
|
||||
manpagesection(EXIT VALUES)
|
||||
|
||||
startdit()
|
||||
dit(bf(RERR_SYNTAX 1)) Syntax or usage error
|
||||
dit(bf(RERR_PROTOCOL 2)) Protocol incompatibility
|
||||
dit(bf(RERR_FILESELECT 3)) Errors selecting input/output files, dirs
|
||||
|
||||
dit(bf(RERR_UNSUPPORTED 4)) Requested action not supported: an attempt
|
||||
dit(bf(0)) Success
|
||||
dit(bf(1)) Syntax or usage error
|
||||
dit(bf(2)) Protocol incompatibility
|
||||
dit(bf(3)) Errors selecting input/output files, dirs
|
||||
dit(bf(4)) Requested action not supported: an attempt
|
||||
was made to manipulate 64-bit files on a platform that cannot support
|
||||
them; or an option was speciifed that is supported by the client and
|
||||
not by the server.
|
||||
|
||||
dit(bf(RERR_SOCKETIO 10)) Error in socket IO
|
||||
dit(bf(RERR_FILEIO 11)) Error in file IO
|
||||
dit(bf(RERR_STREAMIO 12)) Error in rsync protocol data stream
|
||||
dit(bf(RERR_MESSAGEIO 13)) Errors with program diagnostics
|
||||
dit(bf(RERR_IPC 14)) Error in IPC code
|
||||
dit(bf(RERR_SIGNAL 20)) Received SIGUSR1 or SIGINT
|
||||
dit(bf(RERR_WAITCHILD 21)) Some error returned by waitpid()
|
||||
dit(bf(RERR_MALLOC 22)) Error allocating core memory buffers
|
||||
dit(bf(RERR_TIMEOUT 30)) Timeout in data send/receive
|
||||
dit(bf(5)) Error starting client-server protocol
|
||||
dit(bf(10)) Error in socket IO
|
||||
dit(bf(11)) Error in file IO
|
||||
dit(bf(12)) Error in rsync protocol data stream
|
||||
dit(bf(13)) Errors with program diagnostics
|
||||
dit(bf(14)) Error in IPC code
|
||||
dit(bf(20)) Received SIGUSR1 or SIGINT
|
||||
dit(bf(21)) Some error returned by waitpid()
|
||||
dit(bf(22)) Error allocating core memory buffers
|
||||
dit(bf(23)) Partial transfer due to error
|
||||
dit(bf(24)) Partial transfer due to vanished source files
|
||||
dit(bf(30)) Timeout in data send/receive
|
||||
enddit()
|
||||
|
||||
manpagesection(ENVIRONMENT VARIABLES)
|
||||
|
||||
@@ -176,15 +176,17 @@ was run as root. This complements the "uid" option. The default is gid -2,
|
||||
which is normally the group "nobody".
|
||||
|
||||
dit(bf(exclude)) The "exclude" option allows you to specify a space
|
||||
separated list of patterns to add to the exclude list. This is equivalent
|
||||
to the client specifying these patterns with the --exclude option, except
|
||||
that the exclude list is not passed to the client and thus only applies on
|
||||
separated list of patterns to add to the exclude list.
|
||||
This is only superficially equivalent
|
||||
to the client specifying these patterns with the --exclude option.
|
||||
Only one "exclude" option may be specified, but
|
||||
you can use "-" and "+" before patterns to specify exclude/include.
|
||||
|
||||
Because this exclude list is not passed to the client it only applies on
|
||||
the server: that is, it excludes files received by a client when receiving
|
||||
from a server and files deleted on a server when sending to a server, but
|
||||
it doesn't exclude files sent from a client when sending to a server or
|
||||
files deleted on a client when receiving from a server.
|
||||
Only one "exclude" option may be specified, but
|
||||
you can use "-" and "+" before patterns to specify exclude/include.
|
||||
|
||||
Note that this option is not designed with strong security in
|
||||
mind, it is quite possible that a client may find a way to bypass this
|
||||
@@ -193,24 +195,25 @@ cannot be accessed then use the uid/gid options in combination with
|
||||
file permissions.
|
||||
|
||||
dit(bf(exclude from)) The "exclude from" option specifies a filename
|
||||
on the server that contains exclude patterns, one per line. This is
|
||||
equivalent to the client specifying the --exclude-from option with a
|
||||
equivalent file except that it applies only on the server. See also
|
||||
the "exclude" option above.
|
||||
on the server that contains exclude patterns, one per line.
|
||||
This is only superficially equivalent
|
||||
to the client specifying the --exclude-from option with an equivalent file.
|
||||
See the "exclude" option above.
|
||||
|
||||
dit(bf(include)) The "include" option allows you to specify a space
|
||||
separated list of patterns which rsync should not exclude. This is
|
||||
equivalent to the client specifying these patterns with the --include
|
||||
option except that it applies only on the server. This is useful as it
|
||||
only superficially equivalent to the client specifying these patterns
|
||||
with the --include option because it applies only on the server.
|
||||
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 also the "exclude" option above.
|
||||
patterns to switch include/exclude. See the "exclude" option above.
|
||||
|
||||
dit(bf(include from)) The "include from" option specifies a filename
|
||||
on the server that contains include patterns, one per line. This is
|
||||
equivalent to the client specifying the --include-from option with a
|
||||
equivalent file except that it applies only on the server. See also
|
||||
the "exclude" option above.
|
||||
only superficially equivalent to the client specifying the
|
||||
--include-from option with a equivalent file.
|
||||
See the "exclude" option above.
|
||||
|
||||
dit(bf(auth users)) The "auth users" option specifies a comma and
|
||||
space separated list of usernames that will be allowed to connect to
|
||||
@@ -389,13 +392,39 @@ It should be good enough for most purposes but if you want really top
|
||||
quality security then I recommend that you run rsync over ssh.
|
||||
|
||||
Also note that the rsync server protocol does not currently provide any
|
||||
encryption of the data that is transferred over the link. Only
|
||||
encryption of the data that is transferred over the connection. Only
|
||||
authentication is provided. Use ssh as the transport if you want
|
||||
encryption.
|
||||
|
||||
Future versions of rsync may support SSL for better authentication and
|
||||
encryption, but that is still being investigated.
|
||||
|
||||
manpagesection(RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
|
||||
|
||||
If rsync is run with both the --daemon and --rsh (-e) options, it will
|
||||
spawn an rsync daemon using a remote shell connection. Several
|
||||
configuration options will not be available unless the remote user is
|
||||
root (e.g. chroot, setuid/setgid, etc.). There is no need to configure
|
||||
inetd or the services map to include the rsync server port if you run an
|
||||
rsync server only via a remote shell program.
|
||||
|
||||
ADVANCED: To run an rsync server out of a single-use ssh key, use the
|
||||
"command=em(COMMAND)" syntax in the remote user's authorized_keys entry,
|
||||
where command would be
|
||||
|
||||
quote(rsync --server --daemon .)
|
||||
|
||||
NOTE: rsync's argument parsing expects the trailing ".", so make sure
|
||||
that it's there. If you want to use a rsyncd.conf(5)-style
|
||||
configuration file other than the default, you can added a
|
||||
--config option to the em(command):
|
||||
|
||||
quote(rsync --server --daemon --config=em(file) .)
|
||||
|
||||
Note that the "--server" here is the internal option that rsync uses to
|
||||
run the remote version of rsync that it communicates with, and thus you
|
||||
should not be using the --server option under normal circumstances.
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
|
||||
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
|
||||
|
||||
270
sender.c
270
sender.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int remote_version;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int io_error;
|
||||
@@ -37,6 +36,25 @@ extern int am_server;
|
||||
**/
|
||||
|
||||
|
||||
void read_sum_head(int f, struct sum_struct *sum)
|
||||
{
|
||||
extern int protocol_version;
|
||||
|
||||
sum->count = read_int(f);
|
||||
sum->blength = read_int(f);
|
||||
if (protocol_version < 27) {
|
||||
sum->s2length = csum_length;
|
||||
} else {
|
||||
sum->s2length = read_int(f);
|
||||
if (sum->s2length > MD4_SUM_LENGTH) {
|
||||
rprintf(FERROR, "Invalid checksum length %ld\n",
|
||||
(long)sum->s2length);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
sum->remainder = read_int(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the checksums for a buffer
|
||||
**/
|
||||
@@ -46,27 +64,27 @@ static struct sum_struct *receive_sums(int f)
|
||||
int i;
|
||||
OFF_T offset = 0;
|
||||
|
||||
s = (struct sum_struct *)malloc(sizeof(*s));
|
||||
s = new(struct sum_struct);
|
||||
if (!s) out_of_memory("receive_sums");
|
||||
|
||||
s->count = read_int(f);
|
||||
s->n = read_int(f);
|
||||
s->remainder = read_int(f);
|
||||
read_sum_head(f, s);
|
||||
|
||||
s->sums = NULL;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"count=%ld n=%ld rem=%ld\n",
|
||||
(long) s->count, (long) s->n, (long) s->remainder);
|
||||
rprintf(FINFO, "count=%ld n=%ld rem=%ld\n",
|
||||
(long) s->count, (long) s->blength,
|
||||
(long) s->remainder);
|
||||
|
||||
if (s->count == 0)
|
||||
if (s->count == 0)
|
||||
return(s);
|
||||
|
||||
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
|
||||
s->sums = new_array(struct sum_buf, s->count);
|
||||
if (!s->sums) out_of_memory("receive_sums");
|
||||
|
||||
for (i=0; i < (int) s->count;i++) {
|
||||
for (i = 0; i < (int) s->count; i++) {
|
||||
s->sums[i].sum1 = read_int(f);
|
||||
read_buf(f,s->sums[i].sum2,csum_length);
|
||||
read_buf(f, s->sums[i].sum2, s->s2length);
|
||||
|
||||
s->sums[i].offset = offset;
|
||||
s->sums[i].i = i;
|
||||
@@ -74,13 +92,13 @@ static struct sum_struct *receive_sums(int f)
|
||||
if (i == (int) s->count-1 && s->remainder != 0) {
|
||||
s->sums[i].len = s->remainder;
|
||||
} else {
|
||||
s->sums[i].len = s->n;
|
||||
s->sums[i].len = s->blength;
|
||||
}
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i,s->sums[i].len,(double)s->sums[i].offset,s->sums[i].sum1);
|
||||
rprintf(FINFO, "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i, s->sums[i].len, (double)s->sums[i].offset, s->sums[i].sum1);
|
||||
}
|
||||
|
||||
s->flength = offset;
|
||||
@@ -90,17 +108,17 @@ static struct sum_struct *receive_sums(int f)
|
||||
|
||||
|
||||
|
||||
void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
{
|
||||
void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
{
|
||||
int fd = -1;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *buf = NULL;
|
||||
STRUCT_STAT st;
|
||||
char fname[MAXPATHLEN];
|
||||
char fname[MAXPATHLEN];
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
extern struct stats stats;
|
||||
extern struct stats stats;
|
||||
struct stats initial_stats;
|
||||
extern int write_batch; /* dw */
|
||||
extern int read_batch; /* dw */
|
||||
@@ -111,26 +129,26 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
int done; /* dw */
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files starting\n");
|
||||
rprintf(FINFO, "send_files starting\n");
|
||||
|
||||
while (1) {
|
||||
int offset=0;
|
||||
int offset = 0;
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
if (phase == 0) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out,-1);
|
||||
write_int(f_out, -1);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files phase=%d\n",phase);
|
||||
rprintf(FINFO, "send_files phase=%d\n", phase);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
|
||||
rprintf(FERROR, "Invalid file index %d (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
@@ -142,26 +160,26 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->basedir) {
|
||||
strlcpy(fname,file->basedir,MAXPATHLEN);
|
||||
strlcpy(fname, file->basedir, MAXPATHLEN);
|
||||
if (strlen(fname) == MAXPATHLEN-1) {
|
||||
io_error = 1;
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "send_files failed on long-named directory %s\n",
|
||||
fname);
|
||||
full_fname(fname));
|
||||
return;
|
||||
}
|
||||
strlcat(fname,"/",MAXPATHLEN);
|
||||
strlcat(fname, "/", MAXPATHLEN);
|
||||
offset = strlen(file->basedir)+1;
|
||||
}
|
||||
strlcat(fname,f_name(file),MAXPATHLEN);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname+offset);
|
||||
strlcat(fname, f_name(file), MAXPATHLEN);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname+offset);
|
||||
}
|
||||
write_int(f_out,i);
|
||||
write_int(f_out, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -169,129 +187,135 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"receive_sums failed\n");
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "receive_sums failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (write_batch)
|
||||
write_batch_csum_info(&i,flist->count,s);
|
||||
|
||||
write_batch_csum_info(&i, flist->count, s);
|
||||
|
||||
if (!read_batch) {
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
if (errno == ENOENT) {
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(FINFO, "file has vanished: %s\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "send_files failed to open %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
}
|
||||
free_sums(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* map the local file */
|
||||
if (do_fstat(fd,&st) != 0) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
|
||||
if (do_fstat(fd, &st) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "fstat failed: %s\n", strerror(errno));
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
buf = map_file(fd, st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files mapped %s of size %.0f\n",
|
||||
fname,(double)st.st_size);
|
||||
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
|
||||
fname, (double)st.st_size);
|
||||
|
||||
write_int(f_out, i);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
if (write_batch)
|
||||
write_batch_delta_file((char *)&i,sizeof(i));
|
||||
write_batch_delta_file((char *)&i, sizeof(i));
|
||||
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
write_sum_head(f_out, s);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
if (!read_batch)
|
||||
rprintf(FINFO,"calling match_sums %s\n",fname);
|
||||
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname+offset);
|
||||
|
||||
if (verbose > 2 && !read_batch)
|
||||
rprintf(FINFO, "calling match_sums %s\n", fname);
|
||||
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname+offset);
|
||||
}
|
||||
|
||||
set_compression(fname);
|
||||
|
||||
if (read_batch) { /* dw */
|
||||
/* read checksums originally computed on sender side */
|
||||
read_batch_csum_info(i, s, &checksums_match);
|
||||
if (checksums_match) {
|
||||
read_batch_delta_file( (char *) &j, sizeof(int) );
|
||||
if (j != i) { /* if flist index entries don't match*/
|
||||
rprintf(FINFO,"index mismatch in send_files\n");
|
||||
rprintf(FINFO,"read index = %d flist ndx = %d\n",j,i);
|
||||
close_batch_delta_file();
|
||||
close_batch_csums_file();
|
||||
exit_cleanup(1);
|
||||
}
|
||||
else {
|
||||
write_int(f_out,j);
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
done=0;
|
||||
while (!done) {
|
||||
read_batch_delta_file( (char *) &buff_len, sizeof(int) );
|
||||
write_int(f_out,buff_len);
|
||||
if (buff_len == 0) {
|
||||
done = 1;
|
||||
}
|
||||
else {
|
||||
if (buff_len > 0) {
|
||||
read_batch_delta_file(buff, buff_len);
|
||||
write_buf(f_out,buff,buff_len);
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
read_batch_delta_file( buff, MD4_SUM_LENGTH);
|
||||
write_buf(f_out, buff, MD4_SUM_LENGTH);
|
||||
if (read_batch) { /* dw */
|
||||
/* read checksums originally computed on sender side */
|
||||
read_batch_csum_info(i, s, &checksums_match);
|
||||
if (checksums_match) {
|
||||
read_batch_delta_file( (char *) &j, sizeof(int) );
|
||||
if (j != i) { /* if flist index entries don't match*/
|
||||
rprintf(FINFO, "index mismatch in send_files\n");
|
||||
rprintf(FINFO, "read index = %d flist ndx = %d\n", j, i);
|
||||
close_batch_delta_file();
|
||||
close_batch_csums_file();
|
||||
exit_cleanup(1);
|
||||
} else {
|
||||
write_int(f_out, j);
|
||||
write_sum_head(f_out, s);
|
||||
done = 0;
|
||||
while (!done) {
|
||||
read_batch_delta_file( (char *) &buff_len, sizeof(int) );
|
||||
write_int(f_out, buff_len);
|
||||
if (buff_len == 0) {
|
||||
done = 1;
|
||||
} else {
|
||||
if (buff_len > 0) {
|
||||
read_batch_delta_file(buff, buff_len);
|
||||
write_buf(f_out, buff, buff_len);
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
read_batch_delta_file( buff, MD4_SUM_LENGTH);
|
||||
write_buf(f_out, buff, MD4_SUM_LENGTH);
|
||||
|
||||
} /* j=i */
|
||||
} else { /* not checksum match */
|
||||
rprintf (FINFO,"readbatch & checksums don't match\n");
|
||||
rprintf (FINFO,"filename=%s is being skipped\n",
|
||||
fname);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
log_send(file, &initial_stats);
|
||||
}
|
||||
} /* j=i */
|
||||
} else { /* not checksum match */
|
||||
rprintf (FINFO, "readbatch & checksums don't match\n");
|
||||
rprintf (FINFO, "filename=%s is being skipped\n", fname);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
match_sums(f_out, s, buf, st.st_size);
|
||||
log_send(file, &initial_stats);
|
||||
}
|
||||
|
||||
if (!read_batch) { /* dw */
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd);
|
||||
if (buf) {
|
||||
j = unmap_file(buf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR,
|
||||
"read errors mapping %s: (%d) %s\n",
|
||||
full_fname(fname), j, strerror(j));
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
free_sums(s);
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sender finished %s\n",fname);
|
||||
rprintf(FINFO, "sender finished %s\n", fname);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send files finished\n");
|
||||
rprintf(FINFO, "send files finished\n");
|
||||
|
||||
match_report();
|
||||
|
||||
write_int(f_out,-1);
|
||||
write_int(f_out, -1);
|
||||
if (write_batch || read_batch) { /* dw */
|
||||
close_batch_csums_file();
|
||||
close_batch_delta_file();
|
||||
close_batch_csums_file();
|
||||
close_batch_delta_file();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
18
socket.c
18
socket.c
@@ -374,6 +374,15 @@ int is_a_socket(int fd)
|
||||
}
|
||||
|
||||
|
||||
static RETSIGTYPE sigchld_handler(UNUSED(int val))
|
||||
{
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
#ifdef WNOHANG
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void start_accept_loop(int port, int (*fn)(int, int))
|
||||
{
|
||||
int s;
|
||||
@@ -419,14 +428,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
|
||||
if (fd == -1) continue;
|
||||
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
|
||||
/* we shouldn't have any children left hanging around
|
||||
but I have had reports that on Digital Unix zombies
|
||||
are produced, so this ensures that they are reaped */
|
||||
#ifdef WNOHANG
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
#endif
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
int ret;
|
||||
|
||||
@@ -85,14 +85,10 @@ int do_open(char *pathname, int flags, mode_t mode)
|
||||
if (dry_run) return -1;
|
||||
CHECK_RO
|
||||
}
|
||||
#ifdef O_BINARY
|
||||
/* for Windows */
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
/* some systems can't handle a double / */
|
||||
if (pathname[0] == '/' && pathname[1] == '/') pathname++;
|
||||
|
||||
return open(pathname, flags, mode);
|
||||
return open(pathname, flags | O_BINARY, mode);
|
||||
}
|
||||
|
||||
#if HAVE_CHMOD
|
||||
|
||||
28
t_stub.c
28
t_stub.c
@@ -27,8 +27,10 @@
|
||||
**/
|
||||
|
||||
int modify_window = 0;
|
||||
int module_id = -1;
|
||||
struct exclude_struct **server_exclude_list;
|
||||
|
||||
void rprintf(enum logcode UNUSED(code), const char *format, ...)
|
||||
void rprintf(UNUSED(enum logcode code), const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
@@ -42,3 +44,27 @@ int modify_window = 0;
|
||||
code, file, line);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int check_exclude(UNUSED(struct exclude_struct **list), UNUSED(char *name),
|
||||
UNUSED(int name_is_dir))
|
||||
{
|
||||
/* This function doesn't really get called in this test context, so
|
||||
* just return 0. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *lp_name(UNUSED(int mod))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL lp_use_chroot(UNUSED(int mod))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *lp_path(UNUSED(int mod))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ int dry_run, read_only, list_only, verbose;
|
||||
int preserve_perms = 0;
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "usage: t_unsafe LINKDEST SRCDIR\n");
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
test_skipped "Known minor bug in this code"
|
||||
|
||||
set -x
|
||||
|
||||
# Build some hardlinks
|
||||
@@ -44,13 +42,12 @@ checkit "$RSYNC -avv \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$
|
||||
# Make sure each file was only copied once...
|
||||
if [ `grep -c '^name1$' "$outfile"` != 1 ]
|
||||
then
|
||||
test_xfail "name1 was not copied exactly once"
|
||||
test_fail "name1 was not copied exactly once"
|
||||
fi
|
||||
if [ `grep -c '^name2$' "$outfile"` != 1 ]
|
||||
if [ `grep -c '^name2 -> ' "$outfile"` != 1 ]
|
||||
then
|
||||
test_xfail "name2 was not copied exactly once"
|
||||
test_fail "name2 was not copied exactly once"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
|
||||
75
testsuite/exclude.test
Normal file
75
testsuite/exclude.test
Normal file
@@ -0,0 +1,75 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2003 by Wayne Davison <wayned@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync handling of exclude/include directives.
|
||||
|
||||
# Test some of the more obscure wildcard handling of exclude/include
|
||||
# processing.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
set -x
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
chkdir="$scratchdir/chk"
|
||||
|
||||
makepath "$fromdir/foo/down/to/you"
|
||||
makepath "$fromdir/bar/down/to/foo/too"
|
||||
makepath "$fromdir/mid/for/foo/and/that/is/who"
|
||||
echo kept >"$fromdir/foo/file1"
|
||||
echo removed >"$fromdir/foo/file2"
|
||||
echo keeper >"$fromdir/bar/down/to/foo/file1"
|
||||
echo gone >"$fromdir/bar/down/to/foo/file3"
|
||||
echo lost >"$fromdir/bar/down/to/foo/file4"
|
||||
echo smashed >"$fromdir/bar/down/to/foo/to"
|
||||
echo expunged >"$fromdir/mid/for/foo/extra"
|
||||
echo retained >"$fromdir/mid/for/foo/keep"
|
||||
ln -s too "$fromdir/bar/down/to/foo/sym"
|
||||
|
||||
# Setup our test exclude/include file.
|
||||
|
||||
excl="$scratchdir/exclude-from"
|
||||
cat >"$excl" <<EOF
|
||||
# If the second line of these two lines does anything, it's a bug.
|
||||
+ **/bar
|
||||
- /bar
|
||||
# This should match against the whole path, not just the name.
|
||||
+ foo**too
|
||||
# This should float at the end of the path.
|
||||
- foo/*/
|
||||
# Test some normal excludes. Competing lines are paired.
|
||||
+ t[o]/
|
||||
- to
|
||||
+ file4
|
||||
- file[2-9]
|
||||
- /mid/for/foo/extra
|
||||
EOF
|
||||
|
||||
# Create the chk dir with what we expect to be excluded
|
||||
|
||||
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
|
||||
|
||||
sleep 1 # Ensures that the rm commands will tweak the directory times.
|
||||
|
||||
rm -r "$chkdir"/foo/down
|
||||
rm -r "$chkdir"/mid/for/foo/and
|
||||
rm "$chkdir"/foo/file[235-9]
|
||||
rm "$chkdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo/file[235-9]
|
||||
rm "$chkdir"/mid/for/foo/extra
|
||||
|
||||
# Un-tweak the directory times in our first (weak) exclude test (though
|
||||
# it's a good test of the --existing option).
|
||||
$RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, test if rsync excludes the same files.
|
||||
|
||||
checkit "$RSYNC -avv --exclude-from=$excl \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
|
||||
|
||||
exit 0
|
||||
@@ -27,6 +27,12 @@ RSYNC="$rsync_bin"
|
||||
# Berkley's nice.
|
||||
PATH="$PATH:/usr/ucb"
|
||||
|
||||
if diff -u $srcdir/testsuite/rsync.fns $srcdir/testsuite/rsync.fns >/dev/null 2>&1; then
|
||||
diffopt="-u"
|
||||
else
|
||||
diffopt="-c"
|
||||
fi
|
||||
|
||||
runtest() {
|
||||
echo $ECHO_N "Test $1: $ECHO_C"
|
||||
if eval "$2"
|
||||
@@ -157,7 +163,7 @@ checkit() {
|
||||
echo ""
|
||||
for f in `cd "$2"; find . -type f -print `
|
||||
do
|
||||
diff -c "$2"/"$f" "$3"/"$f" || failed=YES
|
||||
diff $diffopt "$2"/"$f" "$3"/"$f" || failed=YES
|
||||
done
|
||||
|
||||
echo "-------------"
|
||||
@@ -165,7 +171,7 @@ checkit() {
|
||||
echo ""
|
||||
( cd "$2" && rsync_ls_lR . ) > ${TMP}/ls-from
|
||||
( cd "$3" && rsync_ls_lR . ) > ${TMP}/ls-to
|
||||
diff -c ${TMP}/ls-from ${TMP}/ls-to || failed=YES
|
||||
diff $diffopt ${TMP}/ls-from ${TMP}/ls-to || failed=YES
|
||||
if [ -z "${failed}" ] ; then
|
||||
return 0
|
||||
else
|
||||
|
||||
@@ -23,8 +23,21 @@ if ! [ "`ssh -o'BatchMode yes' localhost echo yes`" = "yes" ]; then
|
||||
test_skipped "Skipping SSH tests because ssh conection to localhost not authorised"
|
||||
fi
|
||||
|
||||
# Added by Steve Bonds Feb 2 2003
|
||||
# Without this, there are no files in the ${FROM} directory, so rsync has
|
||||
# nothing to do.
|
||||
hands_setup
|
||||
|
||||
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
# Added by Steve Bonds Feb 2 2003
|
||||
# I assumed that "F1" was intended to hold a single file for testing if
|
||||
# rsync could detect a renamed file over ssh. Without this line below
|
||||
# it was unset so the "mv" tried to move a parent directory into a
|
||||
# subdirectory of itself. There is probably a better way of pulling out
|
||||
# a sample file to rename.
|
||||
F1=`ls ${TO} | head -5 | tail -1`
|
||||
|
||||
mv ${TO}/${F1} ${TO}/ThisShouldGo
|
||||
|
||||
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
@@ -15,7 +15,7 @@ set -x
|
||||
"//a//" "////" \
|
||||
"/Users/Wierd Macintosh Name/// Ooh, translucent plastic/" \
|
||||
> "$scratchdir/slash.out"
|
||||
diff -c "$scratchdir/slash.out" - <<EOF
|
||||
diff $diffopt "$scratchdir/slash.out" - <<EOF
|
||||
/usr/local/bin
|
||||
/usr/local/bin
|
||||
/usr/local/bin
|
||||
@@ -25,5 +25,3 @@ diff -c "$scratchdir/slash.out" - <<EOF
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
|
||||
19
testsuite/wildmatch.test
Normal file
19
testsuite/wildmatch.test
Normal file
@@ -0,0 +1,19 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2003 by Wayne Davison <wayned@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test the wildmatch functionality
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
set -x
|
||||
|
||||
"$TOOLDIR/wildtest" >"$scratchdir/wild.out"
|
||||
diff $diffopt "$scratchdir/wild.out" - <<EOF
|
||||
No wildmatch errors found.
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
3
tls.c
3
tls.c
@@ -124,7 +124,8 @@ static void list_file (const char *fname)
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf (stderr, "usage: " PROGRAM " DIR ...\n"
|
||||
|
||||
84
token.c
84
token.c
@@ -51,7 +51,7 @@ void set_compression(char *fname)
|
||||
strlower(fname);
|
||||
|
||||
for (tok=strtok(dont," ");tok;tok=strtok(NULL," ")) {
|
||||
if (fnmatch(tok, fname, 0) == 0) {
|
||||
if (wildmatch(tok, fname)) {
|
||||
compression_level = 0;
|
||||
break;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ static int simple_recv_token(int f,char **data)
|
||||
int n;
|
||||
|
||||
if (!buf) {
|
||||
buf = (char *)malloc(CHUNK_SIZE);
|
||||
buf = new_array(char, CHUNK_SIZE);
|
||||
if (!buf) out_of_memory("simple_recv_token");
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ static int simple_recv_token(int f,char **data)
|
||||
static void simple_send_token(int f,int token,
|
||||
struct map_struct *buf,OFF_T offset,int n)
|
||||
{
|
||||
extern int write_batch; /* dw */
|
||||
int hold_int; /* dw */
|
||||
extern int write_batch;
|
||||
int hold_int;
|
||||
|
||||
if (n > 0) {
|
||||
int l = 0;
|
||||
@@ -100,8 +100,8 @@ static void simple_send_token(int f,int token,
|
||||
write_int(f,n1);
|
||||
write_buf(f,map_ptr(buf,offset+l,n1),n1);
|
||||
if (write_batch) {
|
||||
write_batch_delta_file( (char *) &n1, sizeof(int) );
|
||||
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
|
||||
write_batch_delta_file( (char *) &n1, sizeof(int) );
|
||||
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
|
||||
}
|
||||
l += n1;
|
||||
}
|
||||
@@ -110,8 +110,8 @@ static void simple_send_token(int f,int token,
|
||||
if (token != -2) {
|
||||
write_int(f,-(token+1));
|
||||
if (write_batch) {
|
||||
hold_int = -(token+1);
|
||||
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
|
||||
hold_int = -(token+1);
|
||||
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,12 @@ static void simple_send_token(int f,int token,
|
||||
|
||||
#define MAX_DATA_COUNT 16383 /* fit 14 bit count into 2 bytes with flags */
|
||||
|
||||
/* zlib.h says that if we want to be able to compress something in a single
|
||||
* call, avail_out must be at least 0.1% larger than avail_in plus 12 bytes.
|
||||
* We'll add in 0.1%+16, just to be safe (and we'll avoid floating point,
|
||||
* to ensure that this is a compile-time value). */
|
||||
#define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
|
||||
|
||||
/* For coding runs of tokens */
|
||||
static int last_token = -1;
|
||||
static int run_start;
|
||||
@@ -138,6 +144,14 @@ static z_stream tx_strm;
|
||||
/* Output buffer */
|
||||
static char *obuf;
|
||||
|
||||
/* We want obuf to be able to hold both MAX_DATA_COUNT+2 bytes as well as
|
||||
* AVAIL_OUT_SIZE(CHUNK_SIZE) bytes, so make sure that it's large enough. */
|
||||
#if MAX_DATA_COUNT+2 > AVAIL_OUT_SIZE(CHUNK_SIZE)
|
||||
#define OBUF_SIZE (MAX_DATA_COUNT+2)
|
||||
#else
|
||||
#define OBUF_SIZE AVAIL_OUT_SIZE(CHUNK_SIZE)
|
||||
#endif
|
||||
|
||||
/* Send a deflated token */
|
||||
static void
|
||||
send_deflated_token(int f, int token,
|
||||
@@ -145,8 +159,8 @@ send_deflated_token(int f, int token,
|
||||
{
|
||||
int n, r;
|
||||
static int init_done, flush_pending;
|
||||
extern int write_batch; /* dw */
|
||||
char temp_byte; /* dw */
|
||||
extern int write_batch;
|
||||
char temp_byte;
|
||||
|
||||
if (last_token == -1) {
|
||||
/* initialization */
|
||||
@@ -160,7 +174,7 @@ send_deflated_token(int f, int token,
|
||||
rprintf(FERROR, "compression init failed\n");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
|
||||
if ((obuf = new_array(char, OBUF_SIZE)) == NULL)
|
||||
out_of_memory("send_deflated_token");
|
||||
init_done = 1;
|
||||
} else
|
||||
@@ -179,26 +193,26 @@ send_deflated_token(int f, int token,
|
||||
n = last_token - run_start;
|
||||
if (r >= 0 && r <= 63) {
|
||||
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
if (write_batch) { /* dw */
|
||||
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
if (write_batch) {
|
||||
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
}
|
||||
} else {
|
||||
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
|
||||
write_int(f, run_start);
|
||||
if (write_batch) { /* dw */
|
||||
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
|
||||
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
|
||||
write_batch_delta_file((char *)&run_start,sizeof(run_start));
|
||||
if (write_batch) {
|
||||
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
|
||||
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
|
||||
write_batch_delta_file((char *)&run_start,sizeof(run_start));
|
||||
}
|
||||
}
|
||||
if (n != 0) {
|
||||
write_byte(f, n);
|
||||
write_byte(f, n >> 8);
|
||||
if (write_batch) { /* dw */
|
||||
write_batch_delta_file((char *)&n,sizeof(char));
|
||||
temp_byte = (char) n >> 8;
|
||||
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
|
||||
if (write_batch) {
|
||||
write_batch_delta_file((char *)&n,sizeof(char));
|
||||
temp_byte = (char)(n >> 8);
|
||||
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
|
||||
}
|
||||
}
|
||||
last_run_end = last_token;
|
||||
@@ -258,8 +272,8 @@ send_deflated_token(int f, int token,
|
||||
obuf[0] = DEFLATED_DATA + (n >> 8);
|
||||
obuf[1] = n;
|
||||
write_buf(f, obuf, n+2);
|
||||
if (write_batch) /* dw */
|
||||
write_batch_delta_file(obuf,n+2);
|
||||
if (write_batch)
|
||||
write_batch_delta_file(obuf,n+2);
|
||||
}
|
||||
}
|
||||
} while (nb != 0 || tx_strm.avail_out == 0);
|
||||
@@ -269,9 +283,9 @@ send_deflated_token(int f, int token,
|
||||
if (token == -1) {
|
||||
/* end of file - clean up */
|
||||
write_byte(f, END_FLAG);
|
||||
if (write_batch) { /* dw */
|
||||
temp_byte = END_FLAG;
|
||||
write_batch_delta_file((char *)&temp_byte,sizeof(temp_byte));
|
||||
if (write_batch) {
|
||||
temp_byte = END_FLAG;
|
||||
write_batch_delta_file((char *)&temp_byte,sizeof(temp_byte));
|
||||
}
|
||||
|
||||
} else if (token != -2) {
|
||||
@@ -280,7 +294,7 @@ send_deflated_token(int f, int token,
|
||||
tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
|
||||
tx_strm.avail_in = toklen;
|
||||
tx_strm.next_out = (Bytef *) obuf;
|
||||
tx_strm.avail_out = MAX_DATA_COUNT;
|
||||
tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
r = deflate(&tx_strm, Z_INSERT_ONLY);
|
||||
if (r != Z_OK || tx_strm.avail_in != 0) {
|
||||
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
|
||||
@@ -322,8 +336,8 @@ recv_deflated_token(int f, char **data)
|
||||
rprintf(FERROR, "inflate init failed\n");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|
||||
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
|
||||
if (!(cbuf = new_array(char, MAX_DATA_COUNT))
|
||||
|| !(dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE))))
|
||||
out_of_memory("recv_deflated_token");
|
||||
init_done = 1;
|
||||
} else {
|
||||
@@ -352,9 +366,9 @@ recv_deflated_token(int f, char **data)
|
||||
/* check previous inflated stuff ended correctly */
|
||||
rx_strm.avail_in = 0;
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
r = inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
|
||||
/*
|
||||
* Z_BUF_ERROR just means no progress was
|
||||
* made, i.e. the decompressor didn't have
|
||||
@@ -408,9 +422,9 @@ recv_deflated_token(int f, char **data)
|
||||
|
||||
case r_inflating:
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
r = inflate(&rx_strm, Z_NO_FLUSH);
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
@@ -465,7 +479,7 @@ static void see_deflate_token(char *buf, int len)
|
||||
}
|
||||
}
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
r = inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate (token) returned %d\n", r);
|
||||
|
||||
@@ -29,7 +29,8 @@ int preserve_perms = 0;
|
||||
*
|
||||
* Test harness; not linked into release.
|
||||
**/
|
||||
int main(int argc, char **argv)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ static struct idlist *gidlist;
|
||||
|
||||
static struct idlist *add_list(int id, char *name)
|
||||
{
|
||||
struct idlist *list = (struct idlist *)malloc(sizeof(list[0]));
|
||||
struct idlist *list = new(struct idlist);
|
||||
if (!list) out_of_memory("add_list");
|
||||
list->next = NULL;
|
||||
list->name = strdup(name);
|
||||
@@ -241,7 +241,7 @@ void recv_uid_list(int f, struct file_list *flist)
|
||||
id = read_int(f);
|
||||
while (id != 0) {
|
||||
int len = read_byte(f);
|
||||
name = (char *)malloc(len+1);
|
||||
name = new_array(char, len+1);
|
||||
if (!name) out_of_memory("recv_uid_list");
|
||||
read_sbuf(f, name, len);
|
||||
if (!list) {
|
||||
@@ -264,7 +264,7 @@ void recv_uid_list(int f, struct file_list *flist)
|
||||
id = read_int(f);
|
||||
while (id != 0) {
|
||||
int len = read_byte(f);
|
||||
name = (char *)malloc(len+1);
|
||||
name = new_array(char, len+1);
|
||||
if (!name) out_of_memory("recv_uid_list");
|
||||
read_sbuf(f, name, len);
|
||||
if (!list) {
|
||||
|
||||
124
util.c
124
util.c
@@ -345,9 +345,10 @@ int robust_unlink(char *fname)
|
||||
counter = 1;
|
||||
} while (((rc = access(path, 0)) == 0) && (counter != start));
|
||||
|
||||
if (verbose > 0)
|
||||
if (verbose > 0) {
|
||||
rprintf(FINFO,"renaming %s to %s because of text busy\n",
|
||||
fname, path);
|
||||
fname, path);
|
||||
}
|
||||
|
||||
/* maybe we should return rename()'s exit status? Nah. */
|
||||
if (do_rename(fname, path) != 0) {
|
||||
@@ -458,14 +459,31 @@ int lock_range(int fd, int offset, int len)
|
||||
return fcntl(fd,F_SETLK,&lock) == 0;
|
||||
}
|
||||
|
||||
static int exclude_server_path(char *arg)
|
||||
{
|
||||
char *s;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
|
||||
if (server_exclude_list) {
|
||||
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
|
||||
*s = '\0';
|
||||
if (check_exclude(server_exclude_list, arg, 1)) {
|
||||
/* We must leave arg truncated! */
|
||||
return 1;
|
||||
}
|
||||
*s++ = '/';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
|
||||
if (!*s) s = ".";
|
||||
argv[*argc] = strdup(s);
|
||||
s = argv[*argc] = strdup(s);
|
||||
exclude_server_path(s);
|
||||
(*argc)++;
|
||||
return;
|
||||
#else
|
||||
extern int sanitize_paths;
|
||||
glob_t globbuf;
|
||||
@@ -473,20 +491,21 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
|
||||
if (!*s) s = ".";
|
||||
|
||||
argv[*argc] = strdup(s);
|
||||
s = argv[*argc] = strdup(s);
|
||||
if (sanitize_paths) {
|
||||
sanitize_path(argv[*argc], NULL);
|
||||
sanitize_path(s, NULL);
|
||||
}
|
||||
|
||||
memset(&globbuf, 0, sizeof(globbuf));
|
||||
glob(argv[*argc], 0, NULL, &globbuf);
|
||||
if (!exclude_server_path(s))
|
||||
glob(s, 0, NULL, &globbuf);
|
||||
if (globbuf.gl_pathc == 0) {
|
||||
(*argc)++;
|
||||
globfree(&globbuf);
|
||||
return;
|
||||
}
|
||||
for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
|
||||
if (i == 0) free(argv[*argc]);
|
||||
if (i == 0) free(s);
|
||||
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
|
||||
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
|
||||
}
|
||||
@@ -495,29 +514,31 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine is only used in daemon mode. */
|
||||
void glob_expand(char *base1, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
char *s = argv[*argc];
|
||||
char *p, *q;
|
||||
char *base = base1;
|
||||
int base_len = strlen(base);
|
||||
|
||||
if (!s || !*s) return;
|
||||
|
||||
if (strncmp(s, base, strlen(base)) == 0) {
|
||||
s += strlen(base);
|
||||
}
|
||||
if (strncmp(s, base, base_len) == 0)
|
||||
s += base_len;
|
||||
|
||||
s = strdup(s);
|
||||
if (!s) out_of_memory("glob_expand");
|
||||
|
||||
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
|
||||
base_len++;
|
||||
|
||||
q = s;
|
||||
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
|
||||
/* split it at this point */
|
||||
*p = 0;
|
||||
glob_expand_one(q, argv, argc, maxargs);
|
||||
q = p+strlen(base);
|
||||
q = p + base_len;
|
||||
}
|
||||
|
||||
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
|
||||
@@ -538,13 +559,6 @@ void strlower(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
void *Realloc(void *p, int size)
|
||||
{
|
||||
if (!p) return (void *)malloc(size);
|
||||
return (void *)realloc(p, size);
|
||||
}
|
||||
|
||||
|
||||
void clean_fname(char *name)
|
||||
{
|
||||
char *p;
|
||||
@@ -648,7 +662,7 @@ void sanitize_path(char *p, char *reldir)
|
||||
}
|
||||
allowdotdot = 0;
|
||||
if ((*p == '.') && (*(p+1) == '.') &&
|
||||
((*(p+2) == '/') || (*(p+2) == '\0'))) {
|
||||
((*(p+2) == '/') || (*(p+2) == '\0'))) {
|
||||
/* ".." component followed by slash or end */
|
||||
if ((depth > 0) && (sanp == start)) {
|
||||
/* allow depth levels of .. at the beginning */
|
||||
@@ -699,7 +713,7 @@ void sanitize_path(char *p, char *reldir)
|
||||
}
|
||||
|
||||
|
||||
static char curr_dir[MAXPATHLEN];
|
||||
char curr_dir[MAXPATHLEN];
|
||||
|
||||
/**
|
||||
* Like chdir() but can be reversed with pop_dir() if @p save is set.
|
||||
@@ -725,7 +739,7 @@ char *push_dir(char *dir, int save)
|
||||
|
||||
if (*dir == '/') {
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir));
|
||||
} else {
|
||||
} else if (dir[0] != '.' || dir[1] != '\0') {
|
||||
strlcat(curr_dir,"/", sizeof(curr_dir));
|
||||
strlcat(curr_dir,dir, sizeof(curr_dir));
|
||||
}
|
||||
@@ -753,6 +767,52 @@ int pop_dir(char *dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a quoted string with the full pathname of the indicated filename.
|
||||
* The string " (in MODNAME)" may also be appended. The returned pointer
|
||||
* remains valid until the next time full_fname() is called.
|
||||
**/
|
||||
char *full_fname(char *fn)
|
||||
{
|
||||
extern int module_id;
|
||||
static char *result = NULL;
|
||||
char *m1, *m2, *m3;
|
||||
char *p1, *p2;
|
||||
|
||||
if (result)
|
||||
free(result);
|
||||
|
||||
if (*fn == '/')
|
||||
p1 = p2 = "";
|
||||
else {
|
||||
p1 = curr_dir;
|
||||
p2 = "/";
|
||||
}
|
||||
if (module_id >= 0) {
|
||||
m1 = " (in ";
|
||||
m2 = lp_name(module_id);
|
||||
m3 = ")";
|
||||
if (*p1) {
|
||||
if (!lp_use_chroot(module_id)) {
|
||||
char *p = lp_path(module_id);
|
||||
if (*p != '/' || p[1])
|
||||
p1 += strlen(p);
|
||||
}
|
||||
if (!*p1)
|
||||
p2++;
|
||||
else
|
||||
p1++;
|
||||
}
|
||||
else
|
||||
fn++;
|
||||
} else
|
||||
m1 = m2 = m3 = "";
|
||||
|
||||
asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** We need to supply our own strcmp function for file list comparisons
|
||||
to ensure that signed/unsigned usage is consistent between machines. */
|
||||
int u_strcmp(const char *cs1, const char *cs2)
|
||||
@@ -941,3 +1001,23 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define MALLOC_MAX 0x40000000
|
||||
|
||||
void *_new_array(unsigned int size, unsigned long num)
|
||||
{
|
||||
if (num >= MALLOC_MAX/size)
|
||||
return NULL;
|
||||
return malloc(size * num);
|
||||
}
|
||||
|
||||
void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
|
||||
{
|
||||
if (num >= MALLOC_MAX/size)
|
||||
return NULL;
|
||||
/* No realloc should need this, but just in case... */
|
||||
if (!ptr)
|
||||
return malloc(size * num);
|
||||
return realloc(ptr, size * num);
|
||||
}
|
||||
|
||||
157
wildtest.c
Normal file
157
wildtest.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
** wildmatch test suite.
|
||||
*/
|
||||
|
||||
/*#define COMPARE_WITH_FNMATCH*/
|
||||
|
||||
#define WILD_TEST_ITERATIONS
|
||||
#include "lib/wildmatch.c"
|
||||
|
||||
#include "popt.h"
|
||||
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
#include <fnmatch.h>
|
||||
|
||||
int fnmatch_errors = 0;
|
||||
#endif
|
||||
|
||||
int wildmatch_errors = 0;
|
||||
|
||||
typedef char bool;
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
int output_iterations = 0;
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
|
||||
{"iterations", 'i', POPT_ARG_NONE, &output_iterations, 0, 0, 0},
|
||||
{0,0,0,0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* match just at the start of string (anchored tests) */
|
||||
static void
|
||||
run_test(int line, bool matches, bool same_as_fnmatch,
|
||||
const char *text, const char *pattern)
|
||||
{
|
||||
bool matched;
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
bool fn_matched;
|
||||
int flags = strstr(pattern, "**")? 0 : FNM_PATHNAME;
|
||||
#else
|
||||
same_as_fnmatch = 0; /* Get rid of unused-variable compiler warning. */
|
||||
#endif
|
||||
|
||||
matched = wildmatch(pattern, text);
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
fn_matched = !fnmatch(pattern, text, flags);
|
||||
#endif
|
||||
if (matched != matches) {
|
||||
printf("wildmatch failure on line %d:\n %s\n %s\n expected %s match\n",
|
||||
line, text, pattern, matches? "a" : "NO");
|
||||
wildmatch_errors++;
|
||||
}
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
if (fn_matched != (matches ^ !same_as_fnmatch)) {
|
||||
printf("fnmatch disagreement on line %d:\n %s\n %s\n expected %s match\n",
|
||||
line, text, pattern, matches ^ !same_as_fnmatch? "a" : "NO");
|
||||
fnmatch_errors++;
|
||||
}
|
||||
#endif
|
||||
if (output_iterations) {
|
||||
printf("%d: \"%s\" iterations = %d\n", line, pattern,
|
||||
wildmatch_iteration_count);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char buf[2048], *s, *string[2], *end[2];
|
||||
FILE *fp;
|
||||
int opt, line, i, flag[2];
|
||||
poptContext pc = poptGetContext("wildtest", argc, (const char**)argv,
|
||||
long_options, 0);
|
||||
|
||||
while ((opt = poptGetNextOpt(pc)) != -1) {
|
||||
switch (opt) {
|
||||
default:
|
||||
fprintf(stderr, "%s: %s\n",
|
||||
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(opt));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((fp = fopen("wildtest.txt", "r")) == NULL) {
|
||||
fprintf(stderr, "Unable to open wildtest.txt.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
line = 0;
|
||||
while (fgets(buf, sizeof buf, fp)) {
|
||||
line++;
|
||||
if (*buf == '#' || *buf == '\n')
|
||||
continue;
|
||||
for (s = buf, i = 0; i <= 1; i++) {
|
||||
if (*s == '1')
|
||||
flag[i] = 1;
|
||||
else if (*s == '0')
|
||||
flag[i] = 0;
|
||||
else
|
||||
flag[i] = -1;
|
||||
if (*++s != ' ' && *s != '\t')
|
||||
flag[i] = -1;
|
||||
if (flag[i] < 0) {
|
||||
fprintf(stderr, "Invalid flag syntax on line %d of wildtest.txt:%s\n",
|
||||
line, buf);
|
||||
exit(1);
|
||||
}
|
||||
while (*++s == ' ' || *s == '\t') {}
|
||||
}
|
||||
for (i = 0; i <= 1; i++) {
|
||||
if (*s == '\'' || *s == '"' || *s == '`') {
|
||||
char quote = *s++;
|
||||
string[i] = s;
|
||||
while (*s && *s != quote) s++;
|
||||
if (!*s) {
|
||||
fprintf(stderr, "Unmatched quote on line %d of wildtest.txt:%s\n",
|
||||
line, buf);
|
||||
exit(1);
|
||||
}
|
||||
end[i] = s;
|
||||
}
|
||||
else {
|
||||
if (!*s || *s == '\n') {
|
||||
fprintf(stderr, "Not enough strings on line %d of wildtest.txt:%s\n",
|
||||
line, buf);
|
||||
exit(1);
|
||||
}
|
||||
string[i] = s;
|
||||
while (*++s && *s != ' ' && *s != '\t' && *s != '\n') {}
|
||||
end[i] = s;
|
||||
}
|
||||
while (*++s == ' ' || *s == '\t') {}
|
||||
}
|
||||
*end[0] = *end[1] = '\0';
|
||||
run_test(line, flag[0], flag[1], string[0], string[1]);
|
||||
}
|
||||
|
||||
if (!wildmatch_errors)
|
||||
fputs("No", stdout);
|
||||
else
|
||||
printf("%d", wildmatch_errors);
|
||||
printf(" wildmatch error%s found.\n", wildmatch_errors == 1? "" : "s");
|
||||
|
||||
#ifdef COMPARE_WITH_FNMATCH
|
||||
if (!fnmatch_errors)
|
||||
fputs("No", stdout);
|
||||
else
|
||||
printf("%d", fnmatch_errors);
|
||||
printf(" fnmatch error%s found.\n", fnmatch_errors == 1? "" : "s");
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
161
wildtest.txt
Normal file
161
wildtest.txt
Normal file
@@ -0,0 +1,161 @@
|
||||
# Input is in the following format (all items white-space separated):
|
||||
#
|
||||
# The first two items are 1 or 0 indicating if the wildmat call is expected to
|
||||
# succeed and if fnmatch works the same way as wildmat, respectively. After
|
||||
# that is a text string for the match, and a pattern string. Strings can be
|
||||
# quoted (if desired) in either double or single quotes, as well as backticks.
|
||||
#
|
||||
# MATCH FNMATCH_SAME "text to match" 'pattern to use'
|
||||
|
||||
# Basic wildmat features
|
||||
1 1 foo foo
|
||||
0 1 foo bar
|
||||
1 1 '' ""
|
||||
1 1 foo ???
|
||||
0 1 foo ??
|
||||
1 1 foo *
|
||||
1 1 foo f*
|
||||
0 1 foo *f
|
||||
1 1 foo *foo*
|
||||
1 1 foobar *ob*a*r*
|
||||
1 1 aaaaaaabababab *ab
|
||||
1 1 foo* foo\*
|
||||
0 1 foobar foo\*bar
|
||||
1 1 f\oo f\\oo
|
||||
1 1 ball *[al]?
|
||||
0 1 ten [ten]
|
||||
1 1 ten **[!te]
|
||||
0 1 ten **[!ten]
|
||||
1 1 ten t[a-g]n
|
||||
0 1 ten t[!a-g]n
|
||||
1 1 ton t[!a-g]n
|
||||
1 1 ton t[^a-g]n
|
||||
1 1 a]b a[]]b
|
||||
1 1 a-b a[]-]b
|
||||
1 1 a]b a[]-]b
|
||||
0 1 aab a[]-]b
|
||||
1 1 aab a[]a-]b
|
||||
1 1 ] ]
|
||||
|
||||
# Extended slash-matching features
|
||||
0 1 foo/baz/bar foo*bar
|
||||
1 1 foo/baz/bar foo**bar
|
||||
0 1 foo/bar foo?bar
|
||||
0 1 foo/bar foo[/]bar
|
||||
0 1 foo/bar f[^eiu][^eiu][^eiu][^eiu][^eiu]r
|
||||
1 1 foo-bar f[^eiu][^eiu][^eiu][^eiu][^eiu]r
|
||||
0 1 foo **/foo
|
||||
1 1 /foo **/foo
|
||||
1 1 bar/baz/foo **/foo
|
||||
0 1 bar/baz/foo */foo
|
||||
0 0 foo/bar/baz **/bar*
|
||||
1 1 deep/foo/bar/baz **/bar/*
|
||||
1 1 foo/bar/baz **/bar**
|
||||
1 1 foo/bar/baz/x */bar/**
|
||||
0 0 deep/foo/bar/baz/x */bar/**
|
||||
1 1 deep/foo/bar/baz/x **/bar/*/*
|
||||
|
||||
# Various additional tests
|
||||
0 1 acrt a[c-c]st
|
||||
1 1 acrt a[c-c]rt
|
||||
0 1 ] [!]-]
|
||||
1 1 a [!]-]
|
||||
0 1 '' \
|
||||
0 1 \ \
|
||||
0 1 /\ */\
|
||||
1 1 /\ */\\
|
||||
1 1 foo foo
|
||||
1 1 @foo @foo
|
||||
0 1 foo @foo
|
||||
1 1 [ab] \[ab]
|
||||
1 1 [ab] [[]ab]
|
||||
1 1 [ab] [[:]ab]
|
||||
0 1 [ab] [[::]ab]
|
||||
1 1 [ab] [[:digit]ab]
|
||||
1 1 [ab] [\[:]ab]
|
||||
1 1 ?a?b \??\?b
|
||||
1 1 abc \a\b\c
|
||||
0 1 foo ''
|
||||
1 1 foo/bar/baz/to **/t[o]
|
||||
|
||||
# Character class tests
|
||||
1 1 a1B [[:alpha:]][[:digit:]][[:upper:]]
|
||||
0 1 a [[:digit:][:upper:][:space:]]
|
||||
1 1 A [[:digit:][:upper:][:space:]]
|
||||
1 1 1 [[:digit:][:upper:][:space:]]
|
||||
0 1 1 [[:digit:][:upper:][:spaci:]]
|
||||
1 1 ' ' [[:digit:][:upper:][:space:]]
|
||||
0 1 . [[:digit:][:upper:][:space:]]
|
||||
1 1 . [[:digit:][:punct:][:space:]]
|
||||
1 1 5 [[:xdigit:]]
|
||||
1 1 f [[:xdigit:]]
|
||||
1 1 D [[:xdigit:]]
|
||||
1 1 _ [[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]
|
||||
#1 1 <20> [^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]
|
||||
1 1 [^[:alnum:][:alpha:][:blank:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]
|
||||
1 1 . [^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]
|
||||
1 1 5 [a-c[:digit:]x-z]
|
||||
1 1 b [a-c[:digit:]x-z]
|
||||
1 1 y [a-c[:digit:]x-z]
|
||||
0 1 q [a-c[:digit:]x-z]
|
||||
|
||||
# Additional tests, including some malformed wildmats
|
||||
1 1 ] [\\-^]
|
||||
0 1 [ [\\-^]
|
||||
1 1 - [\-_]
|
||||
1 1 ] [\]]
|
||||
0 1 \] [\]]
|
||||
0 1 \ [\]]
|
||||
0 1 ab a[]b
|
||||
0 1 a[]b a[]b
|
||||
0 1 ab[ ab[
|
||||
0 1 ab [!
|
||||
0 1 ab [-
|
||||
1 1 - [-]
|
||||
0 1 - [a-
|
||||
0 1 - [!a-
|
||||
1 1 - [--A]
|
||||
1 1 5 [--A]
|
||||
1 1 ' ' '[ --]'
|
||||
1 1 $ '[ --]'
|
||||
1 1 - '[ --]'
|
||||
0 1 0 '[ --]'
|
||||
1 1 - [---]
|
||||
1 1 - [------]
|
||||
0 1 j [a-e-n]
|
||||
1 1 - [a-e-n]
|
||||
1 1 a [!------]
|
||||
0 1 [ []-a]
|
||||
1 1 ^ []-a]
|
||||
0 1 ^ [!]-a]
|
||||
1 1 [ [!]-a]
|
||||
1 1 ^ [a^bc]
|
||||
1 1 -b] [a-]b]
|
||||
0 1 \ [\]
|
||||
1 1 \ [\\]
|
||||
0 1 \ [!\\]
|
||||
1 1 G [A-\\]
|
||||
0 1 aaabbb b*a
|
||||
0 1 aabcaa *ba*
|
||||
1 1 , [,]
|
||||
1 1 , [\\,]
|
||||
1 1 \ [\\,]
|
||||
1 1 - [,-.]
|
||||
0 1 + [,-.]
|
||||
0 1 -.] [,-.]
|
||||
1 1 2 [\1-\3]
|
||||
1 1 3 [\1-\3]
|
||||
0 1 4 [\1-\3]
|
||||
1 1 \ [[-\]]
|
||||
1 1 [ [[-\]]
|
||||
1 1 ] [[-\]]
|
||||
0 1 - [[-\]]
|
||||
|
||||
# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
|
||||
1 1 -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1 -*-*-*-*-*-*-12-*-*-*-m-*-*-*
|
||||
0 1 -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1 -*-*-*-*-*-*-12-*-*-*-m-*-*-*
|
||||
0 1 -adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1 -*-*-*-*-*-*-12-*-*-*-m-*-*-*
|
||||
1 1 /adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1 /*/*/*/*/*/*/12/*/*/*/m/*/*/*
|
||||
0 1 /adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1 /*/*/*/*/*/*/12/*/*/*/m/*/*/*
|
||||
1 1 abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt **/*a*b*g*n*t
|
||||
0 1 abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz **/*a*b*g*n*t
|
||||
@@ -213,7 +213,7 @@ uIntf *v; /* working area: values in order of bit length */
|
||||
|
||||
/* compute minimum size table less than or equal to l bits */
|
||||
z = g - w;
|
||||
z = z > (uInt)l ? l : z; /* table size upper limit */
|
||||
z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */
|
||||
if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
|
||||
{ /* too few codes for k-w bit table */
|
||||
f -= a + 1; /* deduct codes from patterns left */
|
||||
@@ -400,7 +400,7 @@ uIntf *bl; /* literal desired/actual bit depth */
|
||||
uIntf *bd; /* distance desired/actual bit depth */
|
||||
inflate_huft * FAR *tl; /* literal/length tree result */
|
||||
inflate_huft * FAR *td; /* distance tree result */
|
||||
z_streamp z; /* for memory allocation */
|
||||
UNUSED(z_streamp z); /* for memory allocation */
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
/* build fixed tables if not already */
|
||||
|
||||
Reference in New Issue
Block a user