Compare commits

...

391 Commits

Author SHA1 Message Date
Martin Pool
bbd6f4ba8e Document --no-detach. 2001-12-05 13:10:24 +00:00
Martin Pool
2a951cd2f9 Fix help message for --address option 2001-12-05 13:06:26 +00:00
Martin Pool
a538066d5a Add --no-detach option for W32, daemontools, etc. 2001-12-05 13:03:16 +00:00
Martin Pool
c10b0bdd50 Doc 2001-12-05 13:02:11 +00:00
Martin Pool
431efc8979 Doc. 2001-12-05 12:56:06 +00:00
Martin Pool
2d6dbe290c Change back to using sockaddr_storage rather than sockaddr_in. If
sockaddr_storage is not defined, then supply our own definition that
will hopefully satisfy RFC2553 but also compile on all supported
platforms.

Thankyou to YOSHIFUJI Hideaki, SUMIKAWA Munechika and Jun-ichiro
"itojun" Hagino.
2001-12-05 12:48:46 +00:00
Martin Pool
c33e3e3967 Suggestions from KAME IPv6 newsletter. 2001-12-05 12:25:36 +00:00
Martin Pool
71b3374bd5 Note from tpot that sighup should have standard behaviour of reinitializing. 2001-12-05 00:58:20 +00:00
David Dykstra
de343e3cce Don't print out the directory name twice in verbose mode; it was being
printed a second time when the modification time of the directory was
being set, and that time around recv_files() calls recv_generator() with
an f_out of -1 so check that before printing the directory name.
2001-12-03 18:37:33 +00:00
Martin Pool
384958ed3d Note about crash from Ayamura KIKUCHI 2001-12-02 22:47:30 +00:00
Martin Pool
1cd5beeb06 batch reindent 2001-12-02 22:28:50 +00:00
Martin Pool
4c70e359d0 Bump version 2001-12-02 22:26:09 +00:00
Martin Pool
f9c3005bff Fix FP usage. 2001-12-02 14:12:03 +00:00
Martin Pool
9147074d8b Oops, units bug. 2001-12-02 13:58:03 +00:00
Martin Pool
7007bddaef Show time-remaining as hh:mm:ss. 2001-12-02 13:45:38 +00:00
Martin Pool
2f8dc29182 Update notes 2001-12-02 13:22:55 +00:00
Martin Pool
6066594bbe Improved estimation algorithm for time-to-complete. 2001-12-02 13:07:07 +00:00
Martin Pool
40c0289176 Typo fix by Tom Schmidt 2001-12-02 13:02:17 +00:00
Martin Pool
acf1af0cd9 const-cast required for silly UNICOS headers 2001-12-02 12:37:48 +00:00
Martin Pool
62791bdfa2 Also estimate time remaining. 2001-12-02 08:56:25 +00:00
Martin Pool
47f1218d69 Progress indicator now shows estimated rate of transfer (e.g. kB/s).
Based on a patch from Rik Faith, but modified to make sure we do only
one rprintf call, and that we never end up with two copies of the line
printed out.
2001-12-02 08:38:51 +00:00
Martin Pool
1179355dab Revert change from 1.39, because it causes a crash because of
attempting to free a static string.  (Thankyou to Paul Mackerras.)
There's still a small leak here.
2001-12-02 08:16:15 +00:00
Martin Pool
3d807132e4 Fix test suite breakage in calling tls.
Clean up test directory on completion.
2001-12-02 07:22:54 +00:00
Martin Pool
42d0b4c280 Bump version 2001-12-02 07:21:55 +00:00
Martin Pool
d313ae7d23 Move old news from release 2.5.0. 2001-12-02 07:17:50 +00:00
Martin Pool
28a69e25ea More notes from email. 2001-12-02 07:07:43 +00:00
Martin Pool
ad911a7ac3 Typo fix from Matt Kraai <kraai@debian.org> 2001-12-02 06:17:33 +00:00
Martin Pool
5575de140d Add note about device major/minor numbers, and about ACLs 2001-12-02 05:12:39 +00:00
David Dykstra
a5ce1eb1af Add "$(OBJS): config.h" so everything will rebuild if config.h changes. 2001-11-30 22:21:20 +00:00
Martin Pool
76a78cd8bc Add message to ignore warnings about mktemp 2001-11-30 22:06:29 +00:00
rsync-bugs
0b25efc12a Modified file stored as well 2001-11-30 00:31:06 +00:00
rsync-bugs
64cae087b6 preparing for release of 2.5.0 2001-11-30 00:29:46 +00:00
Martin Pool
b7cc59c503 Spec file needs to be generated from a template to include the version
number.
2001-11-30 00:29:20 +00:00
rsync-bugs
7eb8d18a99 preparing for release of 2.5.0 2001-11-30 00:23:11 +00:00
Martin Pool
e7bf3e5e87 Last bug fix for 2.5.0? Make the documentation for -a point out that
it does not in fact propagate hardlinsk.
2001-11-30 00:17:53 +00:00
Martin Pool
5aafd07b37 Note error cases that we ought to improve. 2001-11-30 00:16:14 +00:00
Martin Pool
053f3a831d Note other supported platforms 2001-11-30 00:15:32 +00:00
Martin Pool
a2d2e5c047 Add notes on things to do mentioned on the list in the last few months. 2001-11-29 01:31:31 +00:00
Martin Pool
dd3a922035 IPv6 support is now merged. 2001-11-29 00:23:29 +00:00
Martin Pool
0e916c6038 Just include rsync.h rather than all the individual headers.
(Suggestion from Dave Dykstra.)
2001-11-29 00:15:20 +00:00
Martin Pool
87fcb63975 No need to test for memcmp, because even broken ones are good enough
for our purposes.  (Patch from Dave Dykstra.)
2001-11-29 00:08:36 +00:00
Martin Pool
68b2cc5538 Show version when configuring.
If we don't seem to have an ANSI compiler, then omit a warning as soon
as that is discovered, because it is likely to break later configure
tests.  This doesn't seem to catch the particular HP-UX compiler I was
after, which is non-ANSI but only emits a warning on this configure
test.  Nevertheless probably better to have it in.
2001-11-29 00:04:48 +00:00
Martin Pool
4dcf3697ff Add list of platforms that build. 2001-11-28 07:49:32 +00:00
Martin Pool
ea77525546 Note half-baked Darwin IPv6 support. 2001-11-28 07:12:09 +00:00
Martin Pool
17d5a07ec2 Put back the --disable-ipv6 option. This should only be needed if
your platform seems to support ipv6, but actually it breaks.  This
seems to be the case for "powerpc-apple-darwin1.4".
2001-11-28 06:52:04 +00:00
Martin Pool
3966b9c609 Call this 2.4.7pre4 2001-11-28 04:32:33 +00:00
Martin Pool
1c47fbd96b Note on HP-UX's bundled so-called C compiler. 2001-11-28 04:10:39 +00:00
Martin Pool
1691bdcafc HP's cpp apparently can't handle whitespace before #include 2001-11-28 03:12:20 +00:00
Martin Pool
6a5ef41fb3 HP's cpp chokes on preprocessor directives that have whitespace before
the '#'.  Off to the Implant Office with you!
2001-11-28 02:55:20 +00:00
Martin Pool
09b6f4b00d Fix inet_ntop/pton names 2001-11-28 01:29:41 +00:00
Martin Pool
7067b0aa28 Protect AF_INET6 references with #ifdef INET6 2001-11-28 00:36:32 +00:00
Martin Pool
112e731150 Fix sh 2001-11-27 07:59:34 +00:00
Martin Pool
1336e41460 Show symlink targets 2001-11-27 07:56:33 +00:00
Martin Pool
7c1b7890d3 Be a bit more verbose 2001-11-27 07:54:48 +00:00
Martin Pool
dd0700b025 mtime and ownership of symlinks can be random, so don't print them. 2001-11-27 07:54:03 +00:00
Martin Pool
04d8e8b25f Be a bit more verbose 2001-11-27 07:32:42 +00:00
Martin Pool
3723efcb1d Try to fix headers for UNICOS 2001-11-27 07:23:58 +00:00
Martin Pool
054b40b6fa Unbreak recursive ls test 2001-11-27 07:19:37 +00:00
Martin Pool
6773a7798f Oops, fix bash syntax 2001-11-27 07:09:47 +00:00
Martin Pool
2d4c8e5945 The size of anything but a regular file is probably not worth thinking
about.
2001-11-27 07:07:36 +00:00
Martin Pool
087173c887 When producing a ls-style permissions string, also handle
sticky/setuid/setgid bits the same way as GNU ls.
2001-11-27 07:05:33 +00:00
Martin Pool
57835c00ad Use tls rather than the OS's ls(1) so that we have more chance of
reproducible results.
2001-11-27 06:51:51 +00:00
Martin Pool
4ed886ae6e Also list permissions, ownership, size, and mtime. 2001-11-27 06:45:47 +00:00
Martin Pool
740819ef7b Split code to generate "rwx-----" strings into lib/permstring.c so it
can be reused in tls.
2001-11-27 06:43:17 +00:00
Martin Pool
829230689e Build getaddr/nameinfo into lib/. 2001-11-27 06:41:38 +00:00
Martin Pool
77ba4cc2f9 make clean can rm config.cache but not config.h, or it wil jam.
Build getaddr/nameinfo into lib/.

Split code to generate "rwx-----" strings into lib/permstring.c so it
can be reused in tls.
2001-11-27 06:39:02 +00:00
Martin Pool
e94989fe4d Try to fix LIBOBJ detection of ntop/pton. 2001-11-27 06:17:33 +00:00
Martin Pool
c11b88061f Fix missing parameter in log call. 2001-11-27 06:01:05 +00:00
Martin Pool
647c5433f8 Make clean should also remove the autoconf cache etc. 2001-11-27 05:35:14 +00:00
Martin Pool
8f694072a5 Add Paul Vixie's implementation of inet_ntop and inet_pton for
platforms that don't have them.
2001-11-27 05:22:23 +00:00
Martin Pool
9a689986c6 Look in -lresolv for inet_ntop 2001-11-27 04:53:08 +00:00
Martin Pool
3174b31d96 Check for inet_ntop and inet_pton, which may be missing. 2001-11-27 03:49:53 +00:00
Martin Pool
4eb61975b7 Explain IPv6 merge. 2001-11-27 02:28:36 +00:00
David Dykstra
76e26e1042 Better fix for case of excluded symlinks that point nowhere when using
--copy-links.  The readlink_stat() does need to be done in the normal case
before checking the exclude patterns because it needs to know whether or
not a file is a directory in order to properly handle a trailing slash
in an exclude pattern.  This fix makes make_file() go ahead and call
readlink_stat() but then if the latter returns an ENOENT and copy_links is
on then it will only print an error if the path is not excluded.
2001-11-26 19:15:53 +00:00
Martin Pool
9069dfd005 Fix rename of global option 2001-11-26 08:21:30 +00:00
Martin Pool
2be5d2daad Remove kame cruft 2001-11-26 08:21:14 +00:00
Martin Pool
22cd0063e5 Attempted clean up some of the IPv6 tests. 2001-11-26 08:20:13 +00:00
Martin Pool
3d2e458a4d Fix a small memory leak that was causing an Insure warning. 2001-11-26 07:58:47 +00:00
Martin Pool
a57568d716 Oops, no C++ comments. 2001-11-26 07:47:59 +00:00
Martin Pool
61f543cade Kill a function for jra. 2001-11-26 07:11:55 +00:00
Martin Pool
b8771f9615 Try to be better about handling the results of getaddrinfo(): when
opening an inbound socket, we might get several address results,
e.g. for the machine's ipv4 and ipv6 name.

If binding a wildcard, then any one of them should do.  If an address
was specified but it's insufficiently specific then that's not our
fault.

However, some of the advertized addresses may not work because e.g. we
don't have IPv6 support in the kernel.  In that case go on and try all
addresses until one succeeds.
2001-11-26 07:10:06 +00:00
Martin Pool
d5d4b28220 Put the new address family option into an options struct. We have too
many globals already.

Better error messages for network-related failures.
2001-11-26 04:52:19 +00:00
Martin Pool
a037edaccd Silly autoconf 2001-11-26 01:49:33 +00:00
Martin Pool
356bbb8351 Check for -lnsl, -lsocket, etc, *before* looking for getaddrinfo,
because on Solaris (for one) it's not in libc.
2001-11-26 01:15:12 +00:00
Martin Pool
1f0fa9318a Remove highly suspicious redefinition of sockaddr structure -- there
seems no point using anything but the platform's native definition,
and if we can't get that from the system headers we're hosed anyhow.
2001-11-26 00:41:11 +00:00
Martin Pool
15c1707887 Remove check for buggy getaddrinfo for the time being -- it's unclear
how this is supposed to help.

Check for netdb.h
2001-11-26 00:23:29 +00:00
Martin Pool
9dec7aa9c1 Make some of the headers used by the KAME getaddrinfo implementation
be conditional -- they are missing on e.g. Solaris.  Not sure if this
will fix it.
2001-11-25 09:30:36 +00:00
Martin Pool
bc3d7454e0 Fix KAME patch to use proper autoconf AC_MSG macros rather than just echo/exit. 2001-11-24 05:38:35 +00:00
Martin Pool
56901bc7c3 Call this pre3. 2001-11-24 05:33:35 +00:00
Martin Pool
5c7f570b16 IPv6 is off by default. 2001-11-24 05:31:40 +00:00
Martin Pool
4f6e5fe323 IPv6 is off by default -- it seems to break header files on too many systems. 2001-11-24 05:30:27 +00:00
Martin Pool
7d682ffea7 Note IPv6 and nohang patches. 2001-11-24 05:13:12 +00:00
Martin Pool
cef40af209 Get rid of rule disliked by Sun Make. 2001-11-24 05:06:07 +00:00
Martin Pool
a358449ab1 Set rsync version in configure.in
Show IPv6 availability in --version.
2001-11-24 04:57:41 +00:00
Martin Pool
8ef6b72514 Fix Makefile syntax problem when LIBOBJS is defined. 2001-11-24 04:33:07 +00:00
Martin Pool
620bbabc61 Try to get IPv6 support, unless --disable-ipv6 is explicitly specified. 2001-11-24 04:29:37 +00:00
Martin Pool
7ef6aa6405 Improved error messages. 2001-11-24 04:22:20 +00:00
Martin Pool
7ad1d4fd66 Rebuild if headers changed. 2001-11-24 04:16:18 +00:00
Martin Pool
bf5c2bf604 More autoconf fixes. 2001-11-24 04:12:54 +00:00
Martin Pool
b8fe70a516 Ignore trash 2001-11-23 07:37:26 +00:00
Martin Pool
06963d0fca Merge KAME.net IPv6 patch: you can now (in theory) pass IPv6 hostnames
or literal IP addresses to rsync, and if your platform supports them
they will be used.  Also there are -4 and -6 command-line options to
choose the default address type.  Thankyou!
2001-11-23 07:35:49 +00:00
David Dykstra
b964901f7d Fix to make_file() to exit earlier if a file is excluded, because doing
readlink_stat() on an excluded file can be a problem when using the
--copy-links option (also known as -L) and the excluded file is a symlink
that points nowhere.
2001-11-16 19:19:44 +00:00
Martin Pool
b52c1d9d3a Document chroot confusion. 2001-11-09 06:58:39 +00:00
Martin Pool
a24e12e6dd More notes. 2001-09-12 14:35:39 +00:00
Martin Pool
3c6cd53b23 Think think. 2001-09-12 14:20:44 +00:00
Martin Pool
4f69fe59c7 Start to wrap up all thoughts on what should happen for rsync 3. 2001-09-12 08:51:24 +00:00
Martin Pool
d2e02b7d96 Fix from Marc Espie to make included-popt work with VPATH builds. 2001-09-12 08:46:29 +00:00
Andrew Tridgell
a57873b710 fixed check for timeout in generator
the generator can easily make no progress for a long time, so don't do
timeout processing checks
2001-09-09 04:42:09 +00:00
Andrew Tridgell
30ce7e8a64 64-bit files depends on the size of OFF_T, not off64_t 2001-09-09 04:41:14 +00:00
Andrew Tridgell
f0af1e5ec6 debian stable screws up largefile support for fcntl locking. This adds
a test for the screwup and disables largefile support
2001-09-08 12:48:50 +00:00
Martin Pool
f7ca98bdc4 Doc. 2001-09-07 07:57:10 +00:00
Martin Pool
7df0935a51 Add a little implementation of ls(1) so that we can look at all and
only the attributes of files that rsync is meant to synchronize.

Test cases should depend on testing tools.
2001-09-07 07:52:34 +00:00
Martin Pool
f22ee86517 Add a little implementation of ls(1) so that we can look at all and
only the attributes of files that rsync is meant to synchronize.
2001-09-07 07:52:09 +00:00
Martin Pool
8f98c608b9 Remove test trace stuff. 2001-09-07 07:50:31 +00:00
Martin Pool
32c58f06e0 Try to exit 0 if nothing fails. 2001-09-07 07:49:34 +00:00
Martin Pool
040f7b6595 Update copyright notice. 2001-09-07 07:35:08 +00:00
Martin Pool
d2476f0db3 Debug exit status -- on Sun1/cc all the tests pass, but make sees an
exit status of 1. ???
2001-09-06 13:12:28 +00:00
Martin Pool
952cf8f4f3 Oops, some machines don't have which. 2001-09-06 13:07:52 +00:00
Martin Pool
a138e47560 Oops, some machines don't have which. 2001-09-06 13:04:48 +00:00
Martin Pool
7d6916547f See if head(1) works -- broken on some systems? 2001-09-06 06:34:24 +00:00
Martin Pool
6cd7888e46 You cannot do "export VAR=VALUE" all on one line; the export must be
separate from the assignment.  (SCO SysV)
2001-09-06 06:30:09 +00:00
Martin Pool
1d54358e52 Fix selective definition of *snprintf. (Welcome to mbp's breakage world.) 2001-09-06 06:27:02 +00:00
Martin Pool
4c80c473ed More testsuite cleanups. Now I hope we cope without 'cp -a', though
we still need 'cp -p'.
2001-09-06 06:21:15 +00:00
Martin Pool
571a4b2654 BSD machines don't seem to have head(1). 2001-09-06 06:06:13 +00:00
Martin Pool
501972bf72 Split the 'longdir' test into its own script, and make it work without
'mkdir -p'.
2001-09-06 05:57:27 +00:00
Martin Pool
99cdaff70d Add a makepath() function to cope with machines that do not have
'mkdir -p'.  (Stone knives and bearskins...)
2001-09-06 05:52:40 +00:00
Martin Pool
c36b5017b8 Doc.
Look at $whichtests to run just a subset -- good for calling from Make.
2001-09-06 05:50:48 +00:00
Martin Pool
a4cf6bec19 Fix comment. 2001-09-06 04:56:55 +00:00
Martin Pool
0154b302ce Fiddle umask again. 2001-09-06 04:56:02 +00:00
Martin Pool
ec99e9da81 Clean up output a little. 2001-09-06 02:30:06 +00:00
Martin Pool
e052b21f32 Set umask so that symlinks will have the right permissions on BSD. 2001-09-06 02:26:21 +00:00
Martin Pool
b2f0246498 For log messages containing ridiculously long strings that might
overflow a buffer rsync no longer aborts, but rather prints an
ellipsis at the end of the string.  (Patch from Ed Santiago.)
2001-09-04 03:12:55 +00:00
Martin Pool
c1659c79ef Clean up from rsync+ patch; fix compiler warning. 2001-08-31 09:27:35 +00:00
Martin Pool
4a7cb3e8a8 Fix sh syntax for FreeBSD. 2001-08-31 09:26:34 +00:00
Martin Pool
0de40240bb If we're using built-in *printf functions, then provide prototypes. 2001-08-31 09:23:06 +00:00
Martin Pool
d79c77caca Cope on machines without INADDR_LOOPBACK. 2001-08-31 08:22:00 +00:00
Martin Pool
2b106d0b3a Ignore test tmp dir. 2001-08-31 08:16:23 +00:00
Martin Pool
8fef024528 Run the daemon test using faked tcp connections. 2001-08-31 08:13:57 +00:00
Martin Pool
6963e540db Grammar fix. 2001-08-31 08:12:35 +00:00
Martin Pool
3ef526f5fa Add comment about handling of 'use chroot' 2001-08-31 08:08:42 +00:00
Martin Pool
eecd22ff7b Merge in the LIBSMB_PROG idea from samba, so that you can do
RSYNC_CONNECT_PROG='./rsync --daemon' ./rsync -vvvvvv  localhost::

to test as a daemon without actually having to listen on a port.
2001-08-31 07:06:13 +00:00
Martin Pool
add7e8fb6b Doc.
Try to give a better error message when there is a remote option error.
2001-08-31 06:48:35 +00:00
Martin Pool
f6e09367a7 Option should be --recursive, not --recurse. (This is what it was in
--help and 2.4.6.)
2001-08-31 06:29:45 +00:00
Martin Pool
3aae15ecfb Fix rsyncd.conf generation. 2001-08-31 05:49:16 +00:00
Martin Pool
f5ad6eb18d Fix message. 2001-08-31 05:48:19 +00:00
Martin Pool
7f1b717ac7 Show rsync version before doing anything else. 2001-08-31 05:45:49 +00:00
Martin Pool
55bdb41632 Skip SSH tests if $rsync_enable_ssh_tests is not set 2001-08-31 05:41:45 +00:00
David Dykstra
7c06e407ec The --compare-dest option was not listed as accepting a string parameter
like it was supposed to.  There should probably be a testsuite test for
--compare-dest.
2001-08-30 16:24:03 +00:00
Martin Pool
c13ad7ec47 fix bashism 2001-08-30 08:28:53 +00:00
Martin Pool
d2094cc33d Split out generic functions for starting rsyncd. 2001-08-30 07:14:57 +00:00
Martin Pool
c3469aed19 Notes on an interactive shell for rsync. 2001-08-30 07:11:46 +00:00
Martin Pool
232ce2b2c8 Start testing daemon functionality 2001-08-30 07:10:45 +00:00
Martin Pool
882582b307 Run all scripts in the testsuite/ directory, not just named ones. I'd
like to make this script not rsync-specific if possible.
2001-08-30 07:10:20 +00:00
Martin Pool
ebaa0489b4 Abandoned 2001-08-30 06:56:57 +00:00
Martin Pool
1a1c244dc3 Obsolete 2001-08-30 06:54:59 +00:00
Martin Pool
320989b05d On BSD, this seemed to always exit after test failure. Try different
shell syntax.
2001-08-30 06:54:15 +00:00
Martin Pool
9d682a8dc1 More debug output for testing SSH. 2001-08-30 06:51:58 +00:00
Martin Pool
37c3cf430d Try using diff -c' not diff -u' because the latter seems to be
broken on SCO2.
2001-08-30 06:35:48 +00:00
Martin Pool
751411c40d Use rsync source rather than /etc for files because things in /etc
might be protected or missing on some systems.
2001-08-29 09:38:28 +00:00
Martin Pool
6a46226b3a BSD doesn't have /etc/resolv.conf or /etc/inittab, and hands.test was
trying to use them as a source of noise.
2001-08-29 09:27:43 +00:00
Martin Pool
42e66aa24c Apparently `set -x' in the shell works on some Bourne shells, but not SCO. 2001-08-29 09:24:35 +00:00
Martin Pool
5cb1f5c795 Apparently '!' to invert a pipeline result doesn't work on UnixWare. 2001-08-29 09:23:19 +00:00
Martin Pool
12b9c8409e Return the *number of tests that failed*, so that it will show up
nicely in the overall summary.
2001-08-29 09:20:35 +00:00
Martin Pool
e8ca590142 Cleanup check_logs feature.
`ps ax' is not portable -- don't use it to generate random text.  Use
`ls -lR' instead.
2001-08-29 09:18:45 +00:00
Martin Pool
863dff5179 Cleanup check_logs feature. 2001-08-29 09:15:17 +00:00
Martin Pool
3fedd74ba2 Clean up Phil's test more.
Make the checkit() routine more generic.

Split out ssh tests.
2001-08-29 09:13:01 +00:00
Martin Pool
78ffe4787f $RSYNC and similar variables must be set to absolute path so that it
can be passed to --rsync-path.

Add a nopersist=yes option that makes runtests bomb out as soon as one
test fails -- this is good if you're watching the trace output.
2001-08-29 09:12:05 +00:00
Martin Pool
a4b4af889b $RSYNC must be set to absolute path so that it can be passed to --rsync-path 2001-08-29 09:11:14 +00:00
Martin Pool
d286ee98b9 Count overall failure if some expected scripts were missing. 2001-08-29 08:48:00 +00:00
Martin Pool
42be591878 Remove testtmp directory on 'clean'.
Run test scripts in POSIX mode to try to catch portability problems.
2001-08-29 08:46:18 +00:00
Martin Pool
3a4c683f04 More test case work:
* make sure to build rsync before running 'make check'

 * Put back in the loglevel concept from the samba scripts.  If >8,
   then turn on shell tracing.

 * Allow tests to return 77 if they want to count as 'skipped'.

 * Add more docs.

 * Mangle Phil's script to get ready to run on non-Linux systems: we
   need to not use shell functions, cp -a, etc.  Not there yet.
2001-08-29 08:13:19 +00:00
Martin Pool
e7d29902a6 Redraft testsuite driver script to unify 'make check', 'make
installcheck' and buildfarm tests.

Add note from discussion with Tim about finding files/directories
under different circumstances.  Now works (?) with VPATH build.
2001-08-29 07:33:27 +00:00
Martin Pool
64bd756832 Add comment: cyeoh says that getpass is deprecated, because it may
return a truncated password on some systems, and it is not in the LSB.
2001-08-29 07:23:30 +00:00
David Dykstra
8642efd0d6 The --with-rsync-path configure option was using the wrong configure
variable "$with_rsync_name" instead of "$with_rsync_path".
2001-08-27 16:23:41 +00:00
Martin Pool
063393d62d Only use the "@RSYNC EXIT" tag if we're talking to a client about
version 25.  This prevents it appearing and messing up the module list
when an old client connects to a 2.4.7 server.
2001-08-23 06:14:54 +00:00
Martin Pool
7a55d06e0d Allow the server to terminate the module list by just closing the
socket, rather than sending a proper EXIT command.  Keep the
global-variable hack to do this, but try to make it only apply in the
specific case where that occurs, not on all lines we read.
2001-08-22 04:15:50 +00:00
Martin Pool
6f82f7a6f6 Add a little more protocol documentation. 2001-08-22 04:14:05 +00:00
Martin Pool
33d213bb37 Note about cross-testing different versions. 2001-08-22 04:09:07 +00:00
Martin Pool
a426e396c4 Return 1 if any tests failed so that the build farm can pick it up. 2001-08-21 14:06:52 +00:00
Martin Pool
fafeb69cb6 Change test directory again. 2001-08-21 13:44:08 +00:00
Martin Pool
b9277bdb6a Don't look at $srcdir if it's not set. (Why isn't it set??) 2001-08-21 13:26:30 +00:00
Martin Pool
b53713d322 Show trace while testing. 2001-08-21 13:20:53 +00:00
Martin Pool
2f22174f21 Try again to find the right directory on both local and farm builds. 2001-08-21 13:10:18 +00:00
Martin Pool
d820215b35 More test suite stuff 2001-08-21 13:00:55 +00:00
Martin Pool
ea4a03762a Print source directory. 2001-08-21 12:49:23 +00:00
Martin Pool
46ef7d1dc8 Update notes; add idea about rsyncsh 2001-08-18 23:50:27 +00:00
Martin Pool
e340a8203e Export autoconf settings to test scripts. Use this to cope with
systems that don't use "echo -n".
2001-08-17 01:57:42 +00:00
Martin Pool
3459d319d1 Set up scratch directory for tests. 2001-08-17 01:44:13 +00:00
Martin Pool
09ec75a629 Don't pause at end of tests. 2001-08-17 01:43:13 +00:00
Martin Pool
4df7868d39 Try to fix "make check" directory path.
Don't wait for input at end of tests.
2001-08-17 01:34:31 +00:00
Martin Pool
bc888e05da Find the right directory to run the test components. 2001-08-17 00:58:21 +00:00
Martin Pool
26c7f120e6 Try to get test scripts to run properly. 2001-08-17 00:51:20 +00:00
Martin Pool
5b7be6ee4a Show number of passed/failed/skipped tests. 2001-08-16 09:37:54 +00:00
Martin Pool
951351a537 Don't print test headers unless the test is about to run. 2001-08-16 09:35:21 +00:00
Martin Pool
0b21c485ec Note test suite.
Note autoconf2.52 is required.
2001-08-16 09:16:08 +00:00
Martin Pool
068a7221ce Move Phil Hand's test under the control of the master test suite. 2001-08-16 09:13:37 +00:00
Martin Pool
a4772a4dbc Start to unify the "make check" and build farm test suites 2001-08-16 09:08:29 +00:00
Martin Pool
2ee91aedb1 Use set -x until this script works properly. 2001-08-16 08:13:13 +00:00
Martin Pool
d95447229b Fix typo. 2001-08-16 08:12:55 +00:00
Martin Pool
40ec33b604 Gave directory its proper name 2001-08-16 07:08:26 +00:00
Martin Pool
35e3b2d555 fix filename 2001-08-16 06:27:51 +00:00
Martin Pool
aa9c2df9d9 Updated directory name for rsync tests 2001-08-16 06:24:56 +00:00
Martin Pool
f472cdf017 Try to execute rsync --version as part of the test suite -- see if
this works on the farm.
2001-08-16 05:44:17 +00:00
Martin Pool
1dc587af1b Fix cast warning. 2001-08-15 08:52:10 +00:00
Martin Pool
aeb6292d0d Try to get tests to run with old buildfarm clients 2001-08-15 08:06:26 +00:00
Martin Pool
7d91d5a619 Check that gethostbyname does actually return AF_INET addresses, since
that's all we can handle.

Also, try a new method of handling in_addr and hostent that will
hopefully work on Cray machines without 32-bit types.
2001-08-15 07:52:28 +00:00
Martin Pool
7169bb4aa9 Fix a bug introduced in 1.119, whereby strings like
"mirror.aarnet.edu.au::" were not properly digested.

It wasn't even my bug! :-)
2001-08-15 07:50:07 +00:00
Martin Pool
2db52650fc Fix another format cast. 2001-08-15 06:50:46 +00:00
Martin Pool
c1f62a573a Use socklen_t for getpeername, since we hopefully now have it defined
on all platforms.
2001-08-15 06:47:40 +00:00
Martin Pool
08a740ff43 Fix casts when some variables are printed out. 2001-08-15 06:41:24 +00:00
Martin Pool
b67381d0dc Drop dead variables introduced in rsync+ patch. 2001-08-15 06:38:23 +00:00
Martin Pool
07e9500818 Fix trace message which was missing a parameter.
Drop dead variable introduced in rsync+ patch.
2001-08-15 06:34:28 +00:00
Martin Pool
c77cf82206 Add the start of a buildfarm test suite for rsync. It doesn't do much
yet -- I just want to see if it runs.
2001-08-15 05:47:57 +00:00
Martin Pool
f8014b864e Typo. Shouldn't depend on assert(). 2001-08-15 05:47:29 +00:00
Martin Pool
d58911fb37 Better error messages for DNS. 2001-08-15 05:08:07 +00:00
Martin Pool
b335d74565 Fix bug in --address handling. 2001-08-15 05:07:29 +00:00
Martin Pool
3405fe45f4 Note UNICOS works again 2001-08-14 02:28:12 +00:00
Martin Pool
095efec1d6 Spec file from Jason Haar that works on RedHat 7.1. Not tested by me yet. 2001-08-14 02:24:09 +00:00
Martin Pool
7ca6e85649 Commit getconf/socklen_t/largefile patch suggested by Albert Chin.
This is tested on
  Solaris 2.5.2, 2.6, 7, 8/SPARC, HP-UX 10.20, 11.00,
  Tru64 UNIX 4.0D, 5.0A, IRIX 6.2, 6.5, AIX 4.3.2
and it works ok.

This patch *requires* autoconf 2.52.
2001-08-14 02:18:04 +00:00
Martin Pool
74be4fc399 Remove incorrect news message 2001-08-14 02:14:09 +00:00
Martin Pool
3b4b1984ef Update version message to mention batch files. 2001-08-14 02:08:17 +00:00
Martin Pool
6902ed178b Merge across rsync+ patch; add a little documentation to the manpage. More documentation would be better. 2001-08-14 02:04:47 +00:00
Martin Pool
fab9a9c547 Another try at socklen_t: just check for it, and otherwise use int.
The HP manual says this will work on old HP/UX versions; I'm not sure
about other systems.  Possibly it will break on old BSD-derived
systems with 32-bit int, 64-bit size_t and no socklen_t, if there are
any such.
2001-08-08 10:04:40 +00:00
Andrew Tridgell
376acbfad5 don't need to lookup our own name in open_socket_in() 2001-08-08 08:55:24 +00:00
Martin Pool
12458878c2 Try various different types as replacements for socklen_t until we
find one that works.  This helps on platforms like HP/UX and UNICOS
where the argument to getsockopt is neither socklen_t nor int.
2001-08-08 08:11:50 +00:00
Martin Pool
546434f867 Two more instances of socklen_t. 2001-08-06 12:31:23 +00:00
Martin Pool
ac2a1a449d Use socklen_t if defined, or otherwise int. This tries to fix
warnings on platforms (e.g. AIX) where this type is defined and not
int.
2001-08-06 12:27:04 +00:00
Martin Pool
e1bd49d6f3 Try to fix "infinite loop" warning on AIX and other compilers. (We
exit on a signal.)
2001-08-06 12:25:45 +00:00
Martin Pool
ab94af5c6f Correct over-zealous edit for UNICOS. 2001-08-06 12:23:50 +00:00
Martin Pool
c88ca682ef Fix for UNICOS CC: first argument to readlink must not be const, or we
get an error.
2001-08-06 12:16:20 +00:00
Martin Pool
fc990e81cb Document autoconf updates. 2001-08-06 08:51:48 +00:00
Martin Pool
e2ba16ccea Fix check for ino_t to work with both autoconf2.50 and autoconf2.13. 2001-08-06 08:49:19 +00:00
Martin Pool
76d4988d06 Fix m4 quoting to make autoconf2.50 happy. I checked it still works
on 2.13.  See "info:(autoconf)New Macros".
2001-08-06 08:41:13 +00:00
Martin Pool
25ea348bd1 Summarize all the changes since 2.4.6 so we have them in one place. 2001-08-06 04:31:05 +00:00
Andrew Tridgell
8ca5756339 updated config scripts from subversion 2001-07-22 02:39:06 +00:00
Andrew Tridgell
029c171330 reap children in sigchld handler 2001-07-17 10:48:31 +00:00
Andrew Tridgell
8f04bb36e7 prevent nasty error msgs when listing shares 2001-07-17 10:45:54 +00:00
Andrew Tridgell
b7334b4c31 removed remnant test code for cray 2001-06-28 05:07:15 +00:00
Andrew Tridgell
a7f8404ecd fixed md4 on 64 bit boxes 2001-06-26 03:09:14 +00:00
Andrew Tridgell
6c65e14634 applied simple nohang patch from Wayne Davison 2001-06-26 01:20:42 +00:00
David Dykstra
ddd491d45e Improve the description of --with-default-rsync. 2001-06-22 20:36:43 +00:00
Andrew Tridgell
5d78a10232 allow shell wildcards in auth users lines 2001-06-22 10:16:04 +00:00
Martin Pool
4d66e00afa If binding to a low-numbered port fails with EACCES, then the error
message should explain that you probably need to be root.

(Why leave off the final S?  Kernighan must have been a *really* slow
typist.)
2001-06-21 06:19:00 +00:00
Martin Pool
531d06b824 Fix from Wayne Davison:
The --cvs-exclude option is broken in the CVS version of rsync
  because of a cut-and-paste-induced bug in exclude.c:

  This bug could cause the sending rsync to crash when it dereferenced
  a NULL pointer.
2001-06-21 06:15:34 +00:00
David Dykstra
c6a7f2f48a Simplify the --with-rsync-path option implementation. Can directly pass
the double-quotes to AC_DEFINE_UNQUOTED instead of having a separate step.
2001-06-13 16:47:22 +00:00
David Dykstra
d4e4cbe105 Use 3rd parameter in AC_DEFINE and AC_DEFINE_UNQUOTED to avoid having to
manually put the defines into acconfig.h.
2001-06-12 21:35:26 +00:00
David Dykstra
41bd28fee3 Add --with-rsync-path option. 2001-06-12 19:33:41 +00:00
David Dykstra
a1a440c23e Make --whole-file the default when source and target are on the local machine. 2001-05-29 14:37:54 +00:00
David Dykstra
089e73f8d6 Ran rsync.yo through yodl2man to produce rsync.1. I found that the string
"file(s)" in rsync.yo was being improperly translated by yodl2man so I
changed it to just "files".
2001-05-24 18:01:56 +00:00
David Dykstra
2c5548d25e Add --ignore-errors documentation. 2001-05-22 14:33:38 +00:00
Andrew Tridgell
65c2a918d4 forgot 1 place that used slprintf 2001-05-07 08:59:48 +00:00
Andrew Tridgell
8950ac03f8 imported new snprintf.c from samba, got rid of slprintf 2001-05-07 06:59:37 +00:00
Andrew Tridgell
26ef00bd3c no space after -I or Tru64 barfs 2001-05-06 13:25:11 +00:00
Andrew Tridgell
efe3037cf5 use _S_IFLNK not S_IFLNK 2001-05-02 11:13:21 +00:00
Andrew Tridgell
f62c17e378 use mkstemp on systems where it is secure 2001-05-02 08:33:18 +00:00
Andrew Tridgell
0f62178580 better pid file location 2001-05-02 05:05:12 +00:00
Andrew Tridgell
81c99202d3 use %.0f instead of %ld 2001-04-13 12:25:19 +00:00
David Dykstra
3473b5b4d8 Add the words "on destination machine" to the --compare-dist description
in rsync.yo.  Re-ran yodl2man which I see pulled in a few other changes
from rsync.yo that hadn't yet made it into rsync.1.
2001-03-23 15:12:52 +00:00
Andrew Tridgell
ba35824322 "rsync error" is better than "transfer error", especially for -h 2001-03-23 03:46:56 +00:00
Andrew Tridgell
6afe7f23b0 got rid of dependency on alloca in popt 2001-03-23 03:44:50 +00:00
Andrew Tridgell
19b27a485e improved error handling again. Now we report messages for the remote
shell failing and propogate errors in a better fashion
2001-03-23 01:26:04 +00:00
Andrew Tridgell
ff81e809f4 new error handling system
we now give a non-0 exit code if *any* of the files we have been asked
to transfer fail to transfer
2001-03-22 07:36:51 +00:00
Andrew Tridgell
fd2dd2aa23 better error msg for "invalid uid" and "invalid gid" 2001-03-21 23:44:48 +00:00
Andrew Tridgell
82ed910630 i hate makefiles that automatically run configure
:)
2001-03-21 23:36:23 +00:00
Andrew Tridgell
90ba34e27c I came up with a new way of avoiding the error handling lockup bug in
rsync. It isn't pretty, but it does work and should completely avoid
that class of lockup.
2001-03-21 13:12:44 +00:00
Martin Pool
8ee3d639b2 Check for alloca.h and mcheck.h, as included popt needs to know about
them.
2001-03-20 05:26:27 +00:00
Martin Pool
0c5a792ac7 Oops, fix edit mistake. 2001-03-19 08:19:11 +00:00
Martin Pool
2af27ad9aa More accurately, the uid/gid is set to -2, not "nobody". 2001-03-17 01:35:59 +00:00
Martin Pool
3b2b534567 Add some todo comments. 2001-03-17 01:34:22 +00:00
Martin Pool
3fa64fd008 Don't unconditionally define _LARGEFILE_SOURCE, but instead include
some autoconf-2.13 macros that make the appropriate settings.  Thanks
to Albert Chin <china@thewrittenword.com> and Paul Eggert
<eggert@twinsun.com>.
2001-03-17 01:06:34 +00:00
Martin Pool
b557c4c7eb Define _LARGE_FILES to turn on LFS support on AIX (and some others?).
See http://www.rs6000.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/genprogc/prg_lrg_files.htm

Thanks to Todd Willeat <TWilleat@MHP.SMHS.com>
2001-03-16 05:23:33 +00:00
Martin Pool
0882faa2b2 Doc. 2001-03-16 02:11:53 +00:00
Martin Pool
3cd5eb3b3b Add my name and a suggestion to read the FAQ for unanswered questions. 2001-02-27 01:49:19 +00:00
Martin Pool
4ff3d9d6b4 Explain that the mktemp warning is harmless.
If the autoconf inputs are changed, then try to reconfigure.  Don't
worry if we can't do it, though.
2001-02-27 01:46:34 +00:00
Martin Pool
26c08b6c21 Add some brief notes on how to install. 2001-02-24 01:45:21 +00:00
Martin Pool
4db4149283 popt-1.5 is const-correct. 2001-02-24 01:39:19 +00:00
Martin Pool
1ac15cd8ad Upgrade from including popt1.2 to a version of popt1.5 trimmed down to
include only source and build from our Makefile.
Don't scan for libpopt if we're using our own; this makes
autoconf confused.
2001-02-24 01:37:48 +00:00
Martin Pool
b348deae3d Upgrade from popt 1.2 to a cut-down 1.5 2001-02-24 01:32:22 +00:00
Martin Pool
18c71e96f8 Doc. 2001-02-23 01:45:46 +00:00
Martin Pool
f0f5767f15 Change from getopt to popt -- requires const-correctness on arguments. 2001-02-23 01:44:56 +00:00
Martin Pool
15b7b73d7d Change from getopt to popt.
Add comments.
Show listening port number in startup log message.
2001-02-23 01:44:04 +00:00
Martin Pool
e420b9d854 Change from getopt to popt.
Add comment.
2001-02-23 01:02:55 +00:00
Martin Pool
2855f61f4a Change from getopt to popt.
Include more details in --version output: say whether symlinks and
hardlinks are supported.
When hardlink support is missing, explain whether the problem is on
the client or server.
When a bad option is encountered, don't just print it to stderr but
send it to the rsync log mechanism.  (However, server errors currently
seem to get lost in transit because of bugs in logging.)
2001-02-23 01:02:31 +00:00
Martin Pool
2d1ebe9c72 Change from getopt to popt.
Automatically build included libpopt if there is none on the system,
or if --with-included-popt is specified.
Add --enable-debug.
2001-02-23 00:48:11 +00:00
Martin Pool
c485a357cc Change from getopt to popt.
Automatically build included libpopt if there is none on the system.
2001-02-23 00:47:09 +00:00
Martin Pool
5013576705 Change from getopt to popt. 2001-02-23 00:45:07 +00:00
Martin Pool
8886f8d0e6 Add comments.
Better error message in the case of eof on read_timeout.
2001-02-22 13:02:39 +00:00
Martin Pool
fcb6d28d0b Note about multiplexing. 2001-02-22 13:01:27 +00:00
Martin Pool
62402cb14b Check in built-in copy of libpopt in preparation for switching
from getopt
2001-02-22 13:01:09 +00:00
Martin Pool
305ab1331b Doc. 2001-02-21 08:25:07 +00:00
Martin Pool
8212336aaa More explanation of return values. 2001-02-21 08:16:45 +00:00
Martin Pool
3e3dcd624f Better message grammar. 2001-02-21 07:18:50 +00:00
Martin Pool
b30b3bb899 Call this 2.4.6dev so that we don't get bug reports claiming to be
about 2.4.6.
2001-02-14 22:59:03 +00:00
Martin Pool
55b64e4b5e Add table of exit values, from errcode.h. 2001-02-14 22:47:28 +00:00
Martin Pool
e411463442 Document shortcoming of "unrecognised option" message. 2001-02-08 03:28:19 +00:00
Martin Pool
660c6fbdaa Include strerror message when there's a socket error. 2001-01-08 10:25:00 +00:00
Martin Pool
ce6c7c6318 Improved error message. 2001-01-08 03:39:53 +00:00
Martin Pool
fa994de488 Ignore generated files that are not stored in CVS. 2001-01-08 03:39:32 +00:00
Martin Pool
2348926995 Typo fix from Jim Meyering 2001-01-08 01:10:58 +00:00
David Dykstra
735a816e54 Better explain how the --blocking-io option works. 2001-01-05 17:57:11 +00:00
Martin Pool
a1b1b1da46 Add comments. 2000-11-15 05:53:45 +00:00
Martin Pool
c3563c46ed Doc. 2000-11-15 03:16:06 +00:00
Martin Pool
0c80cd8ee9 In --version, say whether we have socketpair() or not 2000-11-10 03:41:47 +00:00
Martin Pool
b79f79e3aa Ignore dummy output file 2000-11-10 03:41:17 +00:00
Martin Pool
af642a61b3 If an error occurs, print an explanatory string rather
than just an RERR code.
2000-11-10 03:28:15 +00:00
Martin Pool
ef1aa91039 Doc. 2000-11-10 03:17:08 +00:00
Martin Pool
1960e2280c Drop dead variable. 2000-11-09 09:45:19 +00:00
Martin Pool
7c1b4daa6f Document getsockopt POSIX confusion. 2000-11-09 09:27:34 +00:00
Martin Pool
7a24c346b0 Print a warning message in the version if the platform cannot support 32-bit ints 2000-11-09 09:05:14 +00:00
Martin Pool
64c2cf8fea Better error messages 2000-11-09 09:02:16 +00:00
Martin Pool
81d538ce23 Better error messages when unlink fails 2000-11-08 09:45:16 +00:00
Martin Pool
e327acece4 Better error messages when unlink fails 2000-11-08 09:32:11 +00:00
Martin Pool
4e40377ac2 Better error messages when unlink fails 2000-11-08 09:32:10 +00:00
Martin Pool
eeb1568fd5 Correct license name. Note new address of pserver. Correct documentation. 2000-11-02 11:38:13 +00:00
Martin Pool
0ba481368c Add some comments. 2000-11-02 11:37:34 +00:00
Andrew Tridgell
38bf526fc5 fix bug in handling of : 2000-10-31 10:59:50 +00:00
Martin Pool
bc363ea983 Display a warning about pointlessly using --rsh with clientserver mode. 2000-10-31 01:05:42 +00:00
Martin Pool
84f69dad19 Draft documentation of the client-server protocol. 2000-10-26 08:05:36 +00:00
Martin Pool
4a13b9d57a Print strerror when a system error occurs; add a new function rsyserr
to do this.  This is not used in every case yet -- I've just changed a
few cases that were causing trouble.  Please convert others as you see them.
2000-10-26 07:31:29 +00:00
Martin Pool
a039749b4c Print strerror when a system error occurs; add a new function rsyserr
to do this.  This is not used in every case yet -- I've just changed a
few cases that were causing trouble.  Please convert others as you see them.
2000-10-26 07:24:18 +00:00
David Dykstra
15b84e142a Make sure the log file is always opened before root privileges (if any)
are given up.
2000-10-25 19:57:42 +00:00
David Dykstra
45a8354004 When running as --daemon in the background and using a "log file" rsyncd.conf
directive, close the log file every time it is open when going to sleep on
the socket.  This allows the log file to get cleaned out by another process.
2000-10-24 18:50:08 +00:00
Andrew Tridgell
c32d024071 don't clobber argv[0], so ps shows the right thing 2000-10-19 00:47:48 +00:00
David Dykstra
205c27ac67 Add note in "secrets file" section to see "strict modes". 2000-10-13 13:49:31 +00:00
Martin Pool
f5c2081302 Clear up conditions for running as root. 2000-10-13 03:28:12 +00:00
Martin Pool
e6c64e7933 Oops: manpage updates should go into the yodl source. 2000-10-13 03:25:07 +00:00
Martin Pool
a036580649 Quick list of things to do. 2000-10-11 00:57:27 +00:00
Martin Pool
796d484b44 Clearer "nothing to do" message. 2000-10-10 01:26:55 +00:00
Martin Pool
1f52f4c407 Get rid of const modifiers; they're problematic with old compilers. 2000-10-09 03:48:47 +00:00
Martin Pool
d567322fbc include/exclude cluestick: with -vv, print out whether files are
included or excluded and why.
2000-10-09 03:46:38 +00:00
John H Terpstra
3ff1e677a1 Added provision for packaging for Linux Standards Base compliant Linux systems. 2000-09-11 18:04:35 +00:00
Andrew Tridgell
ef325f0cf4 neater getconf test 2000-09-06 07:15:37 +00:00
rsync-bugs
3d8810c928 preparing for release of 2.4.6 2000-09-06 02:47:00 +00:00
Andrew Tridgell
d153974ee2 README update 2000-09-06 02:39:45 +00:00
Andrew Tridgell
5b56cc19fb added --modify-window option from David Bolen <db3l@fitlinxx.com> 2000-09-06 02:12:13 +00:00
Andrew Tridgell
c48b22c858 minor man page update 2000-09-06 01:27:46 +00:00
Andrew Tridgell
65d0a49f5c removed spurious error message 2000-09-06 00:48:52 +00:00
Andrew Tridgell
6a48ca56eb added LFS support for Solaris 8 2000-09-05 23:21:27 +00:00
Andrew Tridgell
a20aa42ac4 a simple fix to the memory problems with the string pool patch. The
string pools conflict with the lastdir memory saving tricks.
2000-08-31 23:01:28 +00:00
Andrew Tridgell
e92ee12893 make sure we don't chew too much CPU when the outgoing fd is full 2000-08-29 05:07:08 +00:00
Andrew Tridgell
5c66303ad6 some string_area cleanups 2000-08-29 04:47:39 +00:00
Andrew Tridgell
27e3e9c906 detect list_only a bit earlier 2000-08-29 04:46:50 +00:00
Andrew Tridgell
f0b36a48c8 the 2nd half of the hack 2000-08-29 04:46:27 +00:00
Andrew Tridgell
25cf88936f a hack to make listing remote sites (by leaving off a target) more
useful
2000-08-29 04:45:49 +00:00
Andrew Tridgell
ae682c3e11 got rid of some unused variables 2000-08-19 15:25:05 +00:00
rsync-bugs
99994aef3e preparing for release of 2.4.5 2000-08-19 13:10:57 +00:00
Andrew Tridgell
78043d1969 man page updates 2000-08-19 13:04:48 +00:00
Andrew Tridgell
43e46b4cf6 allow 0.0.0.0/0 syntax in hosts allow/deny
patch from Charles Levert <charles@comm.polymtl.ca>
2000-08-19 13:04:29 +00:00
Andrew Tridgell
9ec16c83be added msleep() function 2000-08-19 12:53:51 +00:00
Andrew Tridgell
a24c687094 sleep for a smaller time while waiting for a process to exit 2000-08-19 12:53:24 +00:00
Andrew Tridgell
60cb2f9016 added "ignore nonreadable" option (useful for hiding files in public archives) 2000-08-19 12:53:00 +00:00
Andrew Tridgell
ac1a0994b6 added an explicit noexcludes flag to make_file()
this fixes a bug with --backup-dir and -x

added "ignore nonreadable" option (useful for hiding files in public archives)
2000-08-19 12:52:39 +00:00
Andrew Tridgell
f2cbf44ba5 added an explicit noexcludes flag to make_file() 2000-08-19 12:51:26 +00:00
Andrew Tridgell
dab552237e I don't like automatic header dependencies 2000-08-19 12:51:00 +00:00
Andrew Tridgell
2201ba580e added MacOS support to config.guess (from wsanchez@apple.com) 2000-08-19 12:09:52 +00:00
Andrew Tridgell
b7c33e3bde fixed backup_dir bug introduced with recent memory handling patches 2000-08-19 11:06:04 +00:00
Andrew Tridgell
82980a2384 fixed timing problem with cleanup and io_flush() by using non-blocking
waitpid()
2000-08-16 08:34:18 +00:00
David Dykstra
b6a30afc98 Undo last setting of blocking_io. I hadn't reviewed the code well enough;
turns out that when client is talking to a server daemon it never executes
this leg of code.  Oops.  The people who said it made a difference when
they changed the code must have been wrong.
2000-08-04 21:26:17 +00:00
David Dykstra
ed91f3e418 Turn on blocking_io when starting client of rsync server daemon. 2000-08-04 21:18:23 +00:00
David Dykstra
60c8d7bc7f Enable --compare-dest to work in combination with --always-checksum.
Problem and suggested patch from Dean Scothern dino@cricinfo.com (although
I re-wrote the patch).
2000-08-04 21:11:46 +00:00
rsync-bugs
5783c065ba preparing for release of 2.4.4 2000-07-29 05:05:38 +00:00
Andrew Tridgell
adc19c987b fix from T.J.Adye@rl.ac.uk for final goodbye message with new protocol 2000-07-29 04:58:24 +00:00
Andrew Tridgell
3d38277706 optimisations from Rich Salz <rsalz@caveosystems.com> 2000-07-29 04:52:05 +00:00
Andrew Tridgell
64c704f0b9 added blocking-io docs 2000-07-29 04:41:19 +00:00
Andrew Tridgell
69c6522734 added *.bz2 and *.tbz to default dont compress list 2000-06-24 13:20:21 +00:00
Andrew Tridgell
0f8f98c8ff added insure debug support 2000-06-24 13:19:53 +00:00
Andrew Tridgell
e384bfbdcb if the remote shell is rsh then use blocking IO 2000-06-24 13:19:25 +00:00
Andrew Tridgell
08e5094d7f added some comments on blocking-io 2000-06-23 13:54:29 +00:00
Andrew Tridgell
4b3977bf00 get rid of annoying symlink error messages 2000-06-23 13:54:08 +00:00
Andrew Tridgell
c80ccabb0c added --blocking-io option 2000-06-23 13:50:18 +00:00
David Dykstra
ef5d23ebcd Add --bwlimit option contributed by Matthew Demicco and Jamie Gritton. 2000-06-06 21:13:05 +00:00
David Dykstra
27b9a19be0 Do better job at describing exclude/include in man page. Based on suggestions
from Harry Putnam <reader@newsguy.com>.
2000-05-19 14:58:28 +00:00
Andrew Tridgell
14175f1e77 fixed bug in replacement inet_aton() 2000-04-19 05:49:15 +00:00
Andrew Tridgell
269833af78 test was the wrong way around 2000-04-19 05:44:43 +00:00
Andrew Tridgell
fca3ef06cd autoconf test for broken solaris inet_aton() 2000-04-19 05:33:39 +00:00
Andrew Tridgell
07a14ef8b2 by default don't gzip .iso images 2000-04-19 05:33:06 +00:00
rsync-bugs
21cde2888c preparing for release of 2.4.3 2000-04-09 02:53:57 +00:00
Andrew Tridgell
4a7481889c use 1 second sleeps in the sleep loop as some OSes (NT for example)
don't get interrupted during a sleep.
2000-04-09 02:32:57 +00:00
Andrew Tridgell
0adb99b9dc don't pprint the IO timeout message if we are a server or daemon (can
cause recursive error messages)
2000-04-09 02:32:18 +00:00
Andrew Tridgell
36349ea0be a very simple fix - if I'd only thought if it last week :)
rsh relies on stdin being blocking
ssh relies on stdout being non-blocking

what we've done before is to set both stdin and stdout to either
blocking or non-blocking. Now I set stdin to blocking and stdout to
non-blocking. This seems to fix all cases I've tested.
2000-04-09 02:16:42 +00:00
rsync-bugs
ec3f7d1b61 preparing for release of 2.4.2 2000-03-30 14:24:37 +00:00
Andrew Tridgell
f0359dd00d went back to non-blokcing IO
it looks like ssh is willing to accept a non-blocking fd when used as
a transport, this seems to avoid the Solaris socketpair bug
2000-03-30 14:15:00 +00:00
Andrew Tridgell
ef55c686bc add a --ignore-errors option 2000-03-21 04:06:04 +00:00
David Dykstra
5f7ce2041c Describe symbolic link handling when writing to a "use chroot = no" module. 2000-02-25 17:02:45 +00:00
David Dykstra
328fcf113a Somebody was confused into thinking that "Here are some examples" in the
section on exclude/include was supposed to be about "+/-" so I changed
the statement to "Here are some exclude/include examples".
2000-02-22 19:47:44 +00:00
David Dykstra
24c857f1de Change socketpair test to verify that it works rather than just exists,
because I have an obscure system (Amdahl's UTS 2.1.2) in which socketpair()
exists but is broken.
2000-02-22 15:55:40 +00:00
David Dykstra
a784e10d00 Move the checking for -lsocket -lnsl ahead of the checking for most of
the functions, especially "socketpair" so that socket-related functions will
be properly discovered on SVR4-based systems such as Solaris.  Problem
discovered by Kenji Miyake <kenji@miyake.org>
2000-02-15 22:44:18 +00:00
rsync-bugs
7eb6bf0397 preparing for release of 2.4.1 2000-01-30 01:02:59 +00:00
Andrew Tridgell
49d6fdc036 patch from Jim Delahanty <mail_us@swbell.net> to ensure files are
deleted after being backed up in a rename operation
2000-01-30 00:56:43 +00:00
Andrew Tridgell
8b35435f7c another hang-at-end fix. It looks like we are more sensiitive to
these with socketpairs. The receiver now sleeps until it gets a signal
to tell it to exit

also fixed test.sh to use the current version remotely
2000-01-30 00:50:19 +00:00
Andrew Tridgell
8ada751890 damn.
with the new error handling code it is possible for rsync to get stuck
on the final transaction, leaving it hung.

looks like 2.4.1 will be pretty soon
2000-01-29 23:49:36 +00:00
84 changed files with 9655 additions and 3046 deletions

View File

@@ -1,21 +1,13 @@
.ignore
.cvsignore
ID
Makefile
a
b
config.cache
config.h
config.log
config.status
dist.tar.gz
rsync
rsync-*
rsync.aux
rsync.dvi
rsync.log
tech_report.aux
tech_report.dvi
tech_report.log
tech_report.ps
test
shconfig
testdir
tests-dont-exist
testtmp
tls
zlib/dummy

42
INSTALL Normal file
View File

@@ -0,0 +1,42 @@
To build and install rsync
$ ./configure
$ make
# make install
You may set the installation directory and other parameters by options
to ./configure. To see them, use:
$ ./configure --help
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
the --with-included-popt option is passed to ./configure.
HP-UX NOTES
-----------
The HP-UX 10.10 "bundled" C compiler seems not to be able to cope with
ANSI C. You may see this error message in config.log if ./configure
fails:
(Bundled) cc: "configure", line 2162: error 1705: Function prototypes are an ANSI feature.
Install gcc or HP's "ANSI/C Compiler".
MAC OSX NOTES
-------------
Mac OS X (Darwin) seems to have an IPv6 stack, but it does not
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.

View File

@@ -9,6 +9,7 @@ mandir=@mandir@
LIBS=@LIBS@
CC=@CC@
CFLAGS=@CFLAGS@
LDFLAGS=@LDFLAGS@
INSTALLCMD=@INSTALL@
@@ -16,20 +17,28 @@ srcdir=@srcdir@
VPATH=$(srcdir)
SHELL=/bin/sh
VERSION=@VERSION@
.SUFFIXES:
.SUFFIXES: .c .o
HEADS=byteorder.h config.h errcode.h proto.h rsync.h version.h \
lib/fnmatch.h lib/getopt.h lib/mdfour.h
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o
LIBOBJ=lib/fnmatch.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 \
zlib/zutil.o zlib/adler32.o
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o batch.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ)
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
tls_OBJ = tls.o syscall.o lib/permstring.o
# Programs we must have to run the test cases
CHECK_PROGS = rsync tls
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
@@ -53,9 +62,20 @@ install-strip:
$(MAKE) INSTALLCMD='$(INSTALLCMD) -s' install
rsync: $(OBJS)
@echo "Please ignore warnings below about mktemp -- it is used in a safe way"
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
$(OBJS): $(HEADS)
$(OBJS): config.h
tls: $(tls_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(tls_OBJ) $(LIBS)
Makefile: Makefile.in configure config.status
echo "WARNING: You need to run ./config.status --recheck"
# don't actually run autoconf, just issue a warning
configure: configure.in
echo "WARNING: you need to rerun autoconf"
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
@@ -67,11 +87,12 @@ proto:
cat *.c lib/compat.c | awk -f mkproto.awk > proto.h
clean:
rm -f *~ $(OBJS) rsync
rm -f *~ $(OBJS) rsync $(TLS_OBJ) tls
rm -rf ./testtmp
rm -f config.cache
distclean: clean
rm -f config.h config.cache config.status Makefile
rm -f Makefile config.h config.status
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
@@ -80,3 +101,34 @@ finddead:
nm *.o */*.o |grep 'U ' | awk '{print $$2}' | sort -u > nmused.txt
nm *.o */*.o |grep 'T ' | awk '{print $$3}' | sort -u > nmfns.txt
comm -13 nmused.txt nmfns.txt
# 'check' is the GNU name, 'test' is the name for everybody else :-)
.PHONY: check test
test: check
# There seems to be no standard way to specify some variables as
# exported from a Makefile apart from listing them like this.
# TODO: Tests that depend on built test aide programs like tls need to
# know where the build directory is.
# This depends on building rsync; if we need any helper programs it
# should depend on them too.
# We try to run the scripts with POSIX mode on, in the hope that will
# catch Bash-isms earlier even if we're running on GNU. Of course, we
# might lose in the future where POSIX diverges from old sh.
check: all $(CHECK_PROGS)
POSIXLY_CORRECT=1 TLS=`pwd`/tls rsync_bin=`pwd`/rsync srcdir="$(srcdir)" $(srcdir)/runtests.sh
# 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.
installcheck: $(CHECK_PROGS)
POSIXLY_CORRECT=1 TLS=`pwd`/tls rsync_bin="$(bindir)/rsync" srcdir="$(srcdir)" $(srcdir)/runtests.sh
# TODO: Add 'dist' target; need to know which files will be included

23
NEWS Normal file
View File

@@ -0,0 +1,23 @@
rsync 2.5.1 (sometime in 2001?)
ENHANCEMENTS:
* --progress and -P now show estimated data transfer rate (in a
multiple of bytes/s) and estimated time to completion. Based
on a patch by 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. Thanks to Max Bowsher and Jos Backus.
BUG FIXES:
* Correct string<->address parsing for both IPv4 and 6. Thankyou
to YOSHIFUJI Hideaki, SUMIKAWA Munechika and Jun-ichiro "itojun"
Hagino.
* rsync.1 typo fix by Matt Kraai.
* Fix for segfault in rsyncd.conf parser by Paul Mackerras.
* Test suite typo fixes Tom Schmidt.

114
OLDNEWS Normal file
View File

@@ -0,0 +1,114 @@
rsync 2.5.0 (2001-11-30)
ANNOUNCEMENTS
* Martin Pool <mbp@samba.org> is now a co-maintainer.
NEW FEATURES
* Support for LSB-compliant packaging <http://www.linuxbase.org/>
* Shell wildcards are allowed in "auth users" lines.
* Merged UNC rsync+ patch to support creation of standalone patch
sets. By Bert J. Dempsey and Debra Weiss, updated by Jos
Backus. <http://www.ils.unc.edu/i2dsi/unc_rsync+.html>
* IPv6 support based on a patch from KAME.net, on systems
including modern versions of Linux, Solaris, and HP-UX. Also
includes IPv6 compatibility functions for old OSs by the
Internet Software Consortium, Paul Vixie, the OpenSSH
portability project, and OpenBSD.
ENHANCEMENTS
* Include/exclude cluestick: with -vv, print out whether files are
included or excluded and why.
* Many error messages have more friendly explanations and more
details.
* Manual page improvements plus scanty protocol documentation.
* When running as --daemon in the background and using a "log
file" rsyncd.conf directive, close the log file every time it is
open when going to sleep on the socket. This allows the log
file to get cleaned out by another process.
* Change to using libpopt rather than getopt for processing
options. This makes the code cleaner and the behaviour more
consistent across platforms. popt is included and built if not
installed on the platform.
* More details in --version, including note about whether 64-bit
files, symlinks and hardlinks are supported.
* MD4 code may use less CPU cycles.
* Use mkstemp on systems where it is secure. If we use mktemp,
explain that we do it in a secure way.
* --whole-file is the default when source and target are on the
local machine.
BUG FIXES:
* Fix for various bugs causing rsync to hang.
* Attempt to fix Large File Summit support on AIX.
* 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
* For log messages containing ridiculously long strings that might
overflow a buffer rsync no longer aborts, but rather prints an
ellipsis at the end of the string. (Patch from Ed Santiago.)
PLATFORMS:
* 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.
* Platforms thought to work in this release:
Cray SV1 UNICOS 10.0.0.8 cc
Debian Linux 2.2 UltraSparc gcc
Debian Linux testing/unstable ARM gcc
FreeBSD 3.3-RELEASE i386 cc
FreeBSD 4.1.1-RELEASE i386 cc
FreeBSD 4.3-STABLE i386 cc
HP PA-RISC HP-UX 10.20 gcc
HP PA-RISC HP-UX 11.11 cc
IRIX 6.5 MIPS cc
IRIX 6.5 MIPS gcc
Mac OS X PPC (--disable-ipv6) cc
NetBSD 1.5 i386 gcc
NetBSD Current i386 cc
OpenBSD 2.5 Sparc gcc
OpenBSD 2.9 i386 cc
OpenBSD Current i386 cc
RedHat 6.2 i386 gcc
RedHat 6.2 i386 insure++
RedHat 7.0 i386 gcc
RedHat 7.1 i386 (Kernel 2.4.10) gcc
Slackware 8.0 i686 (Kernel 2.4.10)
Solaris 8 UltraSparc cc
Solaris 8 UltraSparc gcc
Solaris 8 i386 gcc
SuSE 7.1 i386 gcc2.95.2
SuSE 7.1 ppc gcc2.95.2
i386-pc-sco3.2v5.0.5 cc
i386-pc-sco3.2v5.0.5 gcc
powerpc-ibm-aix4.3.3.0 cc
i686-unknown-sysv5UnixWare7.1.0 gcc
i686-unknown-sysv5UnixWare7.1.0 cc
TESTING:
* 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.

25
README
View File

@@ -90,11 +90,14 @@ Options
SETUP
-----
Rsync uses rsh or ssh for communication. It does not need to be setuid
and requires no special privileges for installation. It does not
require a inetd entry or a daemon. You must, however, have a working
rsh or ssh system. Using ssh is recommended for its security
features.
Rsync normally uses rsh or ssh for communication. It does not need to
be setuid and requires no special privileges for installation. You
must, however, have a working rsh or ssh system. Using ssh is
recommended for its security features.
Alternatively, rsync can run in `daemon' mode, listening on a socket.
This is generally used for public file distribution, although
authentication and access control are available.
To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type
@@ -125,8 +128,7 @@ There is a mailing list for the discussion of rsync and its
applications. It is open to anyone to join. I will announce new
versions on this list.
To join the mailing list send mail to listproc@samba.org with
no subject and a body of "subscribe rsync Your Name".
To join the mailing list see the web page at http://lists.samba.org/
To send mail to everyone on the list send it to rsync@samba.org
@@ -153,19 +155,20 @@ If you want to get the very latest version of rsync direct from the
source code repository then you can use anonymous cvs. You will need a
recent version of cvs then use the following commands:
cvs -d :pserver:cvs@cvs.samba.org:/cvsroot login
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login
Password: cvs
cvs -d :pserver:cvs@cvs.samba.org:/cvsroot co rsync
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co rsync
Look at the cvs documentation for more details.
Look at the cvs documentation, or http://samba.org/cvs.html, for more
details.
COPYRIGHT
---------
Rsync was written by Andrew Tridgell and Paul Mackerras, and is
available under the Gnu Public License.
available under the GNU General Public License.
tridge@samba.org
paulus@cs.anu.edu.au

160
TODO Normal file
View File

@@ -0,0 +1,160 @@
-*- indented-text -*-
URGENT ---------------------------------------------------------------
IMPORTANT ------------------------------------------------------------
Cross-test versions
Part of the regression suite should be making sure that we don't
break backwards compatibility: old clients vs new servers and so
on. Ideally we would test the cross product of versions.
It might be sufficient to test downloads from well-known public
rsync servers running different versions of rsync. This will give
some testing and also be the most common case for having different
versions and not being able to upgrade.
use chroot
If the platform doesn't support it, then don't even try.
If running as non-root, then don't fail, just give a warning.
(There was a thread about this a while ago?)
http://lists.samba.org/pipermail/rsync/2001-August/thread.html
http://lists.samba.org/pipermail/rsync/2001-September/thread.html
--files-from
Avoids traversal. Better option than a pile of --include statements
for people who want to generate the file list using a find(1)
command or a script.
Performance
Traverse just one directory at a time. Tridge says it's possible.
Can possibly also be smarter about memory use while looking for hard
links by reducing the refcount as we find alternative names.
IPv6
Implement suggestions from http://www.kame.net/newsletter/19980604/
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
If a host has multiple addresses, then listen try to connect to all
in order until we get through. (getaddrinfo may return multiple
addresses.) This is kind of implemented already.
Possibly also when starting as a server we may need to listen on
multiple passive addresses. This might be a bit harder, because we
may need to select on all of them. Hm.
Define a syntax for IPv6 literal addresses. Since they include
colons, they tend to break most naming systems, including ours.
Based on the HTTP IPv6 syntax, I think we should use
rsync://[::1]/foo/bar
[::1]::bar
which should just take a small change to the parser code.
Errors
If we hang or get SIGINT, then explain where we were up to. Perhaps
have a static buffer that contains the current function name, or
some kind of description of what we were trying to do. This is a
little easier on people than needing to run strace/truss.
"The dungeon collapses! You are killed." Rather than "unexpected
eof" give a message that is more detailed if possible and also more
helpful.
File attributes
Device major/minor numbers should be at least 32 bits each. See
http://lists.samba.org/pipermail/rsync/2001-November/005357.html
Transfer ACLs. Need to think of a standard representation.
Probably better not to even try to convert between NT and POSIX.
Possibly can share some code with Samba.
Empty directories
With the current common --include '*/' --exclude '*' pattern, people
can end up with many empty directories. We might avoid this by
lazily creating such directories.
zlib
Perhaps don't use our own zlib. Will we actually be incompatible,
or just be slightly less efficient?
logging
Perhaps flush stdout after each filename, so that people trying to
monitor progress in a log file can do so more easily. See
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48108
PLATFORMS ------------------------------------------------------------
Win32
Don't detach, because this messes up --srvany.
http://sources.redhat.com/ml/cygwin/2001-08/msg00234.html
According to "Effective TCP/IP Programming" (??) close() on a socket
has incorrect behaviour on Windows -- it sends a RST packet to the
other side, which gives a "connection reset by peer" error. On that
platform we should probably do shutdown() instead. However, on Unix
we are correct to call close(), because shutdown() discards
untransmitted data.
BUILD FARM -----------------------------------------------------------
Add machines
AMDAHL UTS (Dave Dykstra)
Cygwin (on different versions of Win32?)
HP-UX variants (via HP?)
SCO
NICE -----------------------------------------------------------------
SIGHUP
Re-read config file (just exec() ourselves) rather than exiting.
--no-detach and --no-fork options
Very useful for debugging. Also good when running under a
daemon-monitoring process that tries to restart the service when the
parent exits.
hang/timeout friendliness
On
internationalization
Change to using gettext(). Probably need to ship this for platforms
that don't have it.
Solicit translations.
Does anyone care?
rsyncsh
Write a small emulation of interactive ftp as a Pythonn program
that calls rsync. Commands such as "cd", "ls", "ls *.c" etc map
fairly directly into rsync commands: it just needs to remember the
current host, directory and so on. We can probably even do
completion of remote filenames.

View File

@@ -68,6 +68,7 @@ static int match_address(char *addr, char *tok)
mask = ntohl(mask);
} else {
int bits = atoi(p+1);
if (bits == 0) return 1;
if (bits <= 0 || bits > 32) {
rprintf(FERROR,"malformed mask in %s\n", tok);
return 0;

View File

@@ -1,13 +1,10 @@
#undef HAVE_BROKEN_READDIR
#undef HAVE_ERRNO_DECL
#undef HAVE_LONGLONG
#undef HAVE_OFF64_T
#undef HAVE_REMSH
#undef HAVE_UNSIGNED_CHAR
#undef HAVE_UTIMBUF
#undef ino_t
#undef HAVE_CONNECT
#undef HAVE_SHORT_INO_T
#undef HAVE_GETOPT_LONG
#undef REPLACE_INET_NTOA
#undef REPLACE_INET_ATON
#undef HAVE_GETTIMEOFDAY_TZ
#undef ENABLE_IPV6
#undef HAVE_SOCKADDR_LEN
#undef HAVE_SOCKETPAIR

48
aclocal.m4 vendored
View File

@@ -21,3 +21,51 @@ AC_DEFUN(AC_VALIDATE_CACHE_SYSTEM_TYPE, [
ac_cv_build_system_type="$build"
ac_cv_target_system_type="$target"
])
dnl Check for socklen_t: historically on BSD it is an int, and in
dnl POSIX 1g it is a type of its own, but some platforms use different
dnl types for the argument to getsockopt, getpeername, etc. So we
dnl have to test to find something that will work.
dnl This is no good, because passing the wrong pointer on C compilers is
dnl likely to only generate a warning, not an error. We don't call this at
dnl the moment.
AC_DEFUN([TYPE_SOCKLEN_T],
[
AC_CHECK_TYPE([socklen_t], ,[
AC_MSG_CHECKING([for socklen_t equivalent])
AC_CACHE_VAL([rsync_cv_socklen_t_equiv],
[
# Systems have either "struct sockaddr *" or
# "void *" as the second argument to getpeername
rsync_cv_socklen_t_equiv=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
AC_TRY_COMPILE([
#include <sys/types.h>
#include <sys/socket.h>
int getpeername (int, $arg2 *, $t *);
],[
$t len;
getpeername(0,0,&len);
],[
rsync_cv_socklen_t_equiv="$t"
break
])
done
done
if test "x$rsync_cv_socklen_t_equiv" = x; then
AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
fi
])
AC_MSG_RESULT($rsync_cv_socklen_t_equiv)
AC_DEFINE_UNQUOTED(socklen_t, $rsync_cv_socklen_t_equiv,
[type to use in place of socklen_t if not defined])],
[#include <sys/types.h>
#include <sys/socket.h>])
])

View File

@@ -1,5 +1,6 @@
/*
Copyright (C) Andrew Tridgell 1998
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2000 by Andrew Tridgell
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
@@ -85,7 +86,7 @@ static int get_secret(int module, char *user, char *secret, int len)
if (fd == -1) return 0;
if (do_stat(fname, &st) == -1) {
rprintf(FERROR,"stat(%s) : %s\n", fname, strerror(errno));
rsyserr(FERROR, errno, "stat(%s)", fname);
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
@@ -135,7 +136,6 @@ static int get_secret(int module, char *user, char *secret, int len)
static char *getpassf(char *filename)
{
char buffer[100];
int len=0;
int fd=0;
STRUCT_STAT st;
int ok = 1;
@@ -145,13 +145,13 @@ static char *getpassf(char *filename)
if (!filename) return NULL;
if ( (fd=open(filename,O_RDONLY)) == -1) {
rprintf(FERROR,"could not open password file \"%s\"\n",filename);
rsyserr(FERROR, errno, "could not open password file \"%s\"",filename);
if (envpw) rprintf(FERROR,"falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
if (do_stat(filename, &st) == -1) {
rprintf(FERROR,"stat(%s) : %s\n", filename, strerror(errno));
rsyserr(FERROR, errno, "stat(%s)", filename);
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FERROR,"password file must not be other-accessible\n");
@@ -170,7 +170,7 @@ static char *getpassf(char *filename)
if (envpw) rprintf(FERROR,"RSYNC_PASSWORD environment variable ignored\n");
buffer[sizeof(buffer)-1]='\0';
if ( (len=read(fd,buffer,sizeof(buffer)-1)) > 0)
if (read(fd,buffer,sizeof(buffer)-1) > 0)
{
char *p = strtok(buffer,"\n\r");
close(fd);
@@ -234,12 +234,12 @@ char *auth_server(int fd, int module, char *addr, char *leader)
if (sscanf(line,"%99s %29s", user, pass) != 2) {
return NULL;
}
users = strdup(users);
if (!users) return NULL;
for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
if (strcmp(tok, user) == 0) break;
if (fnmatch(tok, user, 0) == 0) break;
}
free(users);
@@ -272,6 +272,9 @@ void auth_client(int fd, char *user, char *challenge)
if (!user || !*user) return;
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. */
pass = getpass("Password: ");
}

View File

@@ -39,11 +39,11 @@ static int make_simple_backup(char *fname)
return 0;
}
slprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix);
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) {
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
return 0;
}
} else if (verbose > 1) {
@@ -92,9 +92,9 @@ static int make_bak_dir(char *fname,char *bak_path)
while(strncmp(bak_path,"./",2)==0) bak_path += 2;
if(bak_path[strlen(bak_path)-1]!='/') {
slprintf(fullpath,sizeof(fullpath),"%s/",bak_path);
snprintf(fullpath,sizeof(fullpath),"%s/",bak_path);
} else {
slprintf(fullpath,sizeof(fullpath),"%s",bak_path);
snprintf(fullpath,sizeof(fullpath),"%s",bak_path);
}
p=fullpath;
q=&fullpath[strlen(fullpath)]; /* End of bak_path string */
@@ -134,10 +134,14 @@ static int robust_move(char *src, char *dst)
int failed;
while (keep_trying) {
if (keep_path_extfs)
failed = copy_file (src, dst, 0755);
else
if (keep_path_extfs) {
failed = copy_file(src, dst, 0755);
if (!failed) {
do_unlink(src);
}
} else {
failed = robust_rename (src, dst);
}
if (failed) {
if (verbose > 2)
@@ -193,7 +197,10 @@ static int keep_backup(char *fname)
if (do_stat (fname, &st)) return 1;
#endif
file = make_file (0, fname);
file = make_file(-1, fname, NULL, 1);
/* the file could have disappeared */
if (!file) return 1;
/* make a complete pathname for backup file */
if (strlen(backup_dir) + strlen(fname) > (MAXPATHLEN - 1)) {
@@ -201,7 +208,7 @@ static int keep_backup(char *fname)
return 0;
}
slprintf(keep_name, sizeof (keep_name), "%s/%s", backup_dir, fname);
snprintf(keep_name, sizeof (keep_name), "%s/%s", backup_dir, fname);
#ifdef HAVE_MKNOD

593
batch.c Normal file
View File

@@ -0,0 +1,593 @@
/* -*- c-file-style: "linux" -*-
Weiss 1/1999
Batch utilities for rsync.
*/
#include "rsync.h"
#include <time.h>
char rsync_flist_file[27] = "rsync_flist.";
char rsync_csums_file[27] = "rsync_csums.";
char rsync_delta_file[27] = "rsync_delta.";
char rsync_argvs_file[27] = "rsync_argvs.";
char batch_file_ext[15];
int fdb;
int fdb_delta;
int fdb_open;
int fdb_close;
struct file_list *batch_flist;
void create_batch_file_ext()
{
struct tm *timeptr;
time_t elapsed_seconds;
/* Save run date and time to use for batch file extensions */
time(&elapsed_seconds);
timeptr = localtime(&elapsed_seconds);
sprintf(batch_file_ext, "%4d%02d%02d%02d%02d%02d",
timeptr->tm_year + 1900, timeptr->tm_mon + 1,
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min,
timeptr->tm_sec);
}
void set_batch_file_ext(char *ext)
{
strcpy(batch_file_ext, ext);
}
void write_batch_flist_file(char *buff, int bytes_to_write)
{
if (fdb_open) {
/* Set up file extension */
strcat(rsync_flist_file, batch_file_ext);
/* Open batch flist file for writing; create it if it doesn't exist */
fdb =
do_open(rsync_flist_file, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_flist_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Write buffer to batch flist file */
if (write(fdb, buff, bytes_to_write) == -1) {
rprintf(FERROR, "Batch file %s write error: %s\n",
rsync_flist_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
if (fdb_close) {
close(fdb);
}
}
void write_batch_flist_info(int flist_count, struct file_struct **fptr)
{
int i;
int bytes_to_write;
/* Write flist info to batch file */
bytes_to_write = sizeof(unsigned) +
sizeof(time_t) +
sizeof(OFF_T) +
sizeof(mode_t) +
sizeof(INO_T) +
(2 * sizeof(dev_t)) + sizeof(uid_t) + sizeof(gid_t);
fdb_open = 1;
fdb_close = 0;
for (i = 0; i < flist_count; i++) {
write_batch_flist_file((char *) fptr[i], bytes_to_write);
write_char_bufs(fptr[i]->basename);
write_char_bufs(fptr[i]->dirname);
write_char_bufs(fptr[i]->basedir);
write_char_bufs(fptr[i]->link);
if (i == flist_count - 1) {
fdb_close = 1;
}
write_char_bufs(fptr[i]->sum);
}
}
void write_char_bufs(char *buf)
{
/* Write the size of the string which will follow */
char b[4];
if (buf != NULL)
SIVAL(b, 0, strlen(buf));
else {
SIVAL(b, 0, 0);
}
write_batch_flist_file(b, sizeof(int));
/* Write the string if there is one */
if (buf != NULL) {
write_batch_flist_file(buf, strlen(buf));
}
}
void write_batch_argvs_file(int orig_argc, int argc, char **argv)
{
int fdb;
int i;
char buff[256];
strcat(rsync_argvs_file, batch_file_ext);
/* Open batch argvs file for writing; create it if it doesn't exist */
fdb = do_open(rsync_argvs_file, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE | S_IEXEC);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_argvs_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
buff[0] = '\0';
/* Write argvs info to batch file */
for (i = argc - orig_argc; i < argc; i++) {
/* FIXME: This apparently crashes if rsync is run with
* just "rsync -F". I think directly manipulating
* argv[] is probably bogus -- what if -F is part of a
* run of several short options? */
if (!strcmp(argv[i], "-F")) { /* safer to change it here than script */
strncat(buff, "-f ", 3); /* chg to -f + ext to get ready for remote */
strncat(buff, batch_file_ext,
strlen(batch_file_ext));
} else {
strncat(buff, argv[i], strlen(argv[i]));
}
if (i < (argc - 1)) {
strncat(buff, " ", 1);
}
}
if (!write(fdb, buff, strlen(buff))) {
rprintf(FERROR, "Batch file %s write error: %s\n",
rsync_argvs_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
close(fdb);
}
struct file_list *create_flist_from_batch()
{
unsigned char flags;
fdb_open = 1;
fdb_close = 0;
batch_flist = (struct file_list *) malloc(sizeof(batch_flist[0]));
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);
if (!batch_flist->files) {
out_of_memory("create_flist_from_batch"); /* dw -- will exit */
}
for (flags = read_batch_flags(); flags; flags = read_batch_flags()) {
int i = batch_flist->count;
if (i >= batch_flist->malloced) {
if (batch_flist->malloced < 1000)
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);
if (!batch_flist->files)
out_of_memory("create_flist_from_batch");
}
read_batch_flist_info(&batch_flist->files[i]);
batch_flist->files[i]->flags = flags;
batch_flist->count++;
}
return batch_flist;
}
int read_batch_flist_file(char *buff, int len)
{
int bytes_read;
if (fdb_open) {
/* Set up file extension */
strcat(rsync_flist_file, batch_file_ext);
/* Open batch flist file for reading */
fdb = do_open(rsync_flist_file, O_RDONLY, 0);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_flist_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Read flist batch file */
bytes_read = read(fdb, buff, len);
if (bytes_read == -1) {
rprintf(FERROR, "Batch file %s read error: %s\n",
rsync_flist_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
if (bytes_read == 0) { /* EOF */
close(fdb);
}
return bytes_read;
}
unsigned char read_batch_flags()
{
int flags;
if (read_batch_flist_file((char *) &flags, 4)) {
return 1;
} else {
return 0;
}
}
void read_batch_flist_info(struct file_struct **fptr)
{
int int_str_len;
char char_str_len[4];
char buff[256];
struct file_struct *file;
file = (struct file_struct *) malloc(sizeof(*file));
if (!file)
out_of_memory("read_batch_flist_info");
memset((char *) file, 0, sizeof(*file));
(*fptr) = file;
read_batch_flist_file((char *) &file->modtime, sizeof(time_t));
read_batch_flist_file((char *) &file->length, sizeof(OFF_T));
read_batch_flist_file((char *) &file->mode, sizeof(mode_t));
read_batch_flist_file((char *) &file->inode, sizeof(INO_T));
read_batch_flist_file((char *) &file->dev, sizeof(dev_t));
read_batch_flist_file((char *) &file->rdev, sizeof(dev_t));
read_batch_flist_file((char *) &file->uid, sizeof(uid_t));
read_batch_flist_file((char *) &file->gid, sizeof(gid_t));
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file->basename = strdup(buff);
} else {
file->basename = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].dirname = strdup(buff);
} else {
file[0].dirname = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].basedir = strdup(buff);
} else {
file[0].basedir = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].link = strdup(buff);
} else {
file[0].link = NULL;
}
read_batch_flist_file(char_str_len, sizeof(char_str_len));
int_str_len = IVAL(char_str_len, 0);
if (int_str_len > 0) {
read_batch_flist_file(buff, int_str_len);
buff[int_str_len] = '\0';
file[0].sum = strdup(buff);
} else {
file[0].sum = NULL;
}
}
void write_batch_csums_file(char *buff, int bytes_to_write)
{
static int fdb_open = 1;
if (fdb_open) {
/* Set up file extension */
strcat(rsync_csums_file, batch_file_ext);
/* Open batch csums file for writing; create it if it doesn't exist */
fdb =
do_open(rsync_csums_file, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_csums_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Write buffer to batch csums file */
if (write(fdb, buff, bytes_to_write) == -1) {
rprintf(FERROR, "Batch file %s write error: %s\n",
rsync_csums_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
}
void close_batch_csums_file()
{
close(fdb);
}
void write_batch_csum_info(int *flist_entry, int flist_count,
struct sum_struct *s)
{
int i;
int int_zero = 0;
extern int csum_length;
fdb_open = 1;
/* Write csum info to batch file */
write_batch_csums_file((char *) flist_entry, sizeof(int));
write_batch_csums_file((char *) (s ? &s->count : &int_zero),
sizeof(int));
if (s) {
for (i = 0; i < s->count; i++) {
write_batch_csums_file((char *) &s->sums[i].sum1,
sizeof(uint32));
if ((*flist_entry == flist_count - 1)
&& (i == s->count - 1)) {
fdb_close = 1;
}
write_batch_csums_file(s->sums[i].sum2,
csum_length);
}
}
}
int read_batch_csums_file(char *buff, int len)
{
static int fdb_open = 1;
int bytes_read;
if (fdb_open) {
/* Set up file extension */
strcat(rsync_csums_file, batch_file_ext);
/* Open batch flist file for reading */
fdb = do_open(rsync_csums_file, O_RDONLY, 0);
if (fdb == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_csums_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
fdb_open = 0;
}
/* Read csums batch file */
bytes_read = read(fdb, buff, len);
if (bytes_read == -1) {
rprintf(FERROR, "Batch file %s read error: %s\n",
rsync_csums_file, strerror(errno));
close(fdb);
exit_cleanup(1);
}
return bytes_read;
}
void read_batch_csum_info(int flist_entry, struct sum_struct *s,
int *checksums_match)
{
int i;
int file_flist_entry;
int file_chunk_ct;
uint32 file_sum1;
char file_sum2[SUM_LENGTH];
extern int csum_length;
read_batch_csums_file((char *) &file_flist_entry, sizeof(int));
if (file_flist_entry != flist_entry) {
rprintf(FINFO, "file_list_entry NE flist_entry\n");
rprintf(FINFO, "file_flist_entry = %d flist_entry = %d\n",
file_flist_entry, flist_entry);
close(fdb);
exit_cleanup(1);
} else {
read_batch_csums_file((char *) &file_chunk_ct,
sizeof(int));
*checksums_match = 1;
for (i = 0; i < file_chunk_ct; i++) {
read_batch_csums_file((char *) &file_sum1,
sizeof(uint32));
read_batch_csums_file(file_sum2, csum_length);
if ((s->sums[i].sum1 != file_sum1) ||
(memcmp
(s->sums[i].sum2, file_sum2,
csum_length) != 0)) {
*checksums_match = 0;
}
} /* end for */
}
}
void write_batch_delta_file(char *buff, int bytes_to_write)
{
static int fdb_delta_open = 1;
if (fdb_delta_open) {
/* Set up file extension */
strcat(rsync_delta_file, batch_file_ext);
/* Open batch delta file for writing; create it if it doesn't exist */
fdb_delta =
do_open(rsync_delta_file, O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE);
if (fdb_delta == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_delta_file, strerror(errno));
close(fdb_delta);
exit_cleanup(1);
}
fdb_delta_open = 0;
}
/* Write buffer to batch delta file */
if (write(fdb_delta, buff, bytes_to_write) == -1) {
rprintf(FERROR, "Batch file %s write error: %s\n",
rsync_delta_file, strerror(errno));
close(fdb_delta);
exit_cleanup(1);
}
}
void close_batch_delta_file()
{
close(fdb_delta);
}
int read_batch_delta_file(char *buff, int len)
{
static int fdb_delta_open = 1;
int bytes_read;
if (fdb_delta_open) {
/* Set up file extension */
strcat(rsync_delta_file, batch_file_ext);
/* Open batch flist file for reading */
fdb_delta = do_open(rsync_delta_file, O_RDONLY, 0);
if (fdb_delta == -1) {
rprintf(FERROR, "Batch file %s open error: %s\n",
rsync_delta_file, strerror(errno));
close(fdb_delta);
exit_cleanup(1);
}
fdb_delta_open = 0;
}
/* Read delta batch file */
bytes_read = read(fdb_delta, buff, len);
if (bytes_read == -1) {
rprintf(FERROR, "Batch file %s read error: %s\n",
rsync_delta_file, strerror(errno));
close(fdb_delta);
exit_cleanup(1);
}
return bytes_read;
}
void show_flist(int index, struct file_struct **fptr)
{
/* for debugging show_flist(flist->count, flist->files * */
int i;
for (i = 0; i < index; i++) {
rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
rprintf(FINFO, "flist->modtime=%#lx\n",
(long unsigned) fptr[i]->modtime);
rprintf(FINFO, "flist->length=%.0f\n",
(double) fptr[i]->length);
rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
rprintf(FINFO, "flist->basename=%s\n", fptr[i]->basename);
if (fptr[i]->dirname)
rprintf(FINFO, "flist->dirname=%s\n",
fptr[i]->dirname);
if (fptr[i]->basedir)
rprintf(FINFO, "flist->basedir=%s\n",
fptr[i]->basedir);
}
}
void show_argvs(int argc, char *argv[])
{
/* for debugging * */
int i;
rprintf(FINFO, "BATCH.C:show_argvs,argc=%d\n", argc);
for (i = 0; i < argc; i++) {
/* if (argv[i]) */
rprintf(FINFO, "i=%d,argv[i]=%s\n", i, argv[i]);
}
}

View File

@@ -1,5 +1,6 @@
/*
Copyright (C) Andrew Tridgell 1996
/* -*- 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
@@ -32,13 +33,26 @@ static struct map_struct *cleanup_buf;
static int cleanup_pid = 0;
extern int io_error;
pid_t cleanup_child_pid = -1;
/*
* Code is one of the RERR_* codes from errcode.h.
*/
void _exit_cleanup(int code, const char *file, int line)
{
extern int keep_partial;
if (code == 0 && io_error) code = RERR_FILEIO;
extern int log_got_error;
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
if (cleanup_child_pid != -1) {
int status;
if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code) code = status;
}
}
if (cleanup_got_literal && cleanup_fname && keep_partial) {
char *fname = cleanup_fname;
@@ -61,6 +75,10 @@ void _exit_cleanup(int code, const char *file, int line)
}
}
if (code == 0 && (io_error || log_got_error)) {
code = RERR_PARTIAL;
}
if (code) log_exit(code, file, line);
exit(code);

View File

@@ -1,5 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1998
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 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
@@ -16,7 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* the socket based protocol for setting up a connection wit rsyncd */
/* the socket based protocol for setting up a connection with rsyncd */
#include "rsync.h"
@@ -27,6 +29,10 @@ extern int rsync_port;
char *auth_user;
int sanitize_paths = 0;
/*
* Run a client connected to an rsyncd. The alternative to this
* function for remote-shell connections is do_cmd.
*/
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
int fd, i;
@@ -36,10 +42,29 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
char *p, *user=NULL;
extern int remote_version;
extern int am_sender;
extern struct in_addr socket_address;
extern char *shell_cmd;
extern int kludge_around_eof;
extern char *bind_address;
if (argc == 0 && !am_sender) {
extern int list_only;
list_only = 1;
}
/* This is just a friendliness enhancement: if the connection
* is to an rsyncd then there is no point specifying the -e option.
* Note that this is only set if the -e was explicitly specified,
* not if the environment variable just happens to be set.
* See http://lists.samba.org/pipermail/rsync/2000-September/002744.html
*/
if (shell_cmd) {
rprintf(FERROR, "WARNING: --rsh or -e option ignored when "
"connecting to rsync daemon\n");
/* continue */
}
if (*path == '/') {
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
rprintf(FERROR,"ERROR: The remote path must start with a module name not a /\n");
return -1;
}
@@ -53,7 +78,8 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
if (!user) user = getenv("USER");
if (!user) user = getenv("LOGNAME");
fd = open_socket_out(host, rsync_port, &socket_address);
fd = open_socket_out_wrapped (host, rsync_port, bind_address,
global_opts.af_hint);
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
@@ -82,6 +108,10 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
io_printf(fd,"%s\n",path);
if (p) *p = '/';
/* Old servers may just drop the connection here,
rather than sending a proper EXIT command. Yuck. */
kludge_around_eof = remote_version < 25;
while (1) {
if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
@@ -93,8 +123,12 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
}
if (strcmp(line,"@RSYNCD: OK") == 0) break;
if (strcmp(line,"@RSYNCD: EXIT") == 0) exit(0);
rprintf(FINFO,"%s\n", line);
}
kludge_around_eof = False;
for (i=0;i<sargc;i++) {
io_printf(fd,"%s\n", sargs[i]);
@@ -117,7 +151,7 @@ static int rsync_module(int fd, int i)
char *argv[MAX_ARGS];
char **argp;
char line[MAXPATHLEN];
uid_t uid = (uid_t)-2;
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
char *p;
char *addr = client_addr(fd);
@@ -172,7 +206,7 @@ static int rsync_module(int fd, int i)
if (!name_to_uid(p, &uid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid uid %s\n", p);
io_printf(fd,"@ERROR: invalid uid\n");
io_printf(fd,"@ERROR: invalid uid %s\n", p);
return -1;
}
uid = atoi(p);
@@ -182,12 +216,19 @@ static int rsync_module(int fd, int i)
if (!name_to_gid(p, &gid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid gid %s\n", p);
io_printf(fd,"@ERROR: invalid gid\n");
io_printf(fd,"@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. */
p = lp_include_from(i);
add_exclude_file(p, 1, 1);
@@ -201,24 +242,36 @@ static int rsync_module(int fd, int i)
p = lp_exclude(i);
add_exclude_line(p);
log_open();
log_init();
if (use_chroot) {
/*
* XXX: The 'use chroot' flag is a fairly reliable
* source of confusion, because it fails under two
* important circumstances: running as non-root,
* running on Win32 (or possibly others). On the
* other hand, if you are running as root, then it
* might be better to always use chroot.
*
* So, perhaps if we can't chroot we should just issue
* a warning, unless a "require chroot" flag is set,
* in which case we fail.
*/
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
rsyserr(FERROR, errno, "chroot %s failed", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
@@ -227,13 +280,13 @@ static int rsync_module(int fd, int i)
if (am_root) {
if (setgid(gid)) {
rprintf(FERROR,"setgid %d failed\n", gid);
rsyserr(FERROR, errno, "setgid %d failed", (int) gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid)) {
rprintf(FERROR,"setuid %d failed\n", uid);
rsyserr(FERROR, errno, "setuid %d failed", (int) uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
@@ -291,7 +344,8 @@ static int rsync_module(int fd, int i)
}
}
ret = parse_arguments(argc, argv, 0);
argp = argv;
ret = parse_arguments(&argc, (const char ***) &argp, 0);
if (request) {
if (*auth_user) {
@@ -306,22 +360,27 @@ static int rsync_module(int fd, int i)
free(request);
}
#if !TRIDGE
#ifndef DEBUG
/* don't allow the logs to be flooded too fast */
if (verbose > 1) verbose = 1;
#endif
argc -= optind;
argp = argv + optind;
optind = 0;
if (remote_version < 23) {
if (remote_version == 22 || (remote_version > 17 && am_sender))
io_start_multiplex_out(fd);
}
/* 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();
option_error();
exit_cleanup(RERR_UNSUPPORTED);
}
if (lp_timeout(i)) {
@@ -340,10 +399,14 @@ 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));
if (remote_version >= 25)
io_printf(fd,"@RSYNCD: EXIT\n");
}
/* this is called when a socket connection is established to a client
@@ -363,7 +426,7 @@ static int start_daemon(int fd)
set_socket_options(fd,"SO_KEEPALIVE");
set_socket_options(fd,lp_socket_options());
set_nonblocking(fd);
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
@@ -438,15 +501,21 @@ int daemon_main(void)
return start_daemon(STDIN_FILENO);
}
become_daemon();
if (!global_opts.no_detach)
become_daemon();
if (!lp_load(config_file, 1)) {
exit_cleanup(RERR_SYNTAX);
}
log_open();
log_init();
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
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??? */
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
char pidbuf[16];
@@ -456,10 +525,10 @@ int daemon_main(void)
if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
0666 & ~orig_umask)) == -1) {
cleanup_set_pid(0);
rprintf(FLOG,"failed to create pid file %s\n", pid_file);
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
exit_cleanup(RERR_FILEIO);
}
slprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
snprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
write(fd, pidbuf, strlen(pidbuf));
close(fd);
}

View File

@@ -36,6 +36,9 @@ extern int checksum_seed;
extern int remote_version;
extern int verbose;
extern int read_batch; /* dw */
extern int write_batch; /* dw */
void setup_protocol(int f_out,int f_in)
{
if (remote_version == 0) {
@@ -55,12 +58,11 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
if (verbose > 2)
rprintf(FINFO, "local_version=%d remote_version=%d\n",
PROTOCOL_VERSION, remote_version);
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 {

752
config.guess vendored
View File

File diff suppressed because it is too large Load Diff

549
config.sub vendored
View File

@@ -1,6 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc.
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc.
timestamp='2001-06-08'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
@@ -25,6 +29,8 @@
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
@@ -45,30 +51,73 @@
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
if [ x$1 = x ]
then
echo Configuration name missing. 1>&2
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
echo "or $0 ALIAS" 1>&2
echo where ALIAS is a recognized configuration type. 1>&2
exit 1
fi
me=`echo "$0" | sed -e 's,.*/,,'`
# First pass through any local machine types.
case $1 in
*local*)
echo $1
exit 0
;;
*)
;;
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit 0 ;;
--version | -v )
echo "$version" ; exit 0 ;;
--help | --h* | -h )
echo "$usage"; exit 0 ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit 0;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
linux-gnu*)
nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -94,15 +143,33 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple)
-apple | -axis)
os=
basic_machine=$1
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
;;
-scout)
;;
-wrs)
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco5)
os=sco3.2v5
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
@@ -121,6 +188,9 @@ case $os in
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -143,26 +213,50 @@ case $os in
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
| 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \
| alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
| i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
| mips64 | mipsel | mips64el | mips64orion | mips64orionel \
| mipstx39 | mipstx39el \
| sparc | sparclet | sparclite | sparc64 | v850)
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
| arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
| pyramid | mn10200 | mn10300 | tron | a29k \
| 580 | i960 | h8300 \
| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
| hppa64 \
| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
| alphaev6[78] \
| we32k | ns16k | clipper | i370 | sh | sh[34] \
| powerpc | powerpcle \
| 1750a | dsp16xx | pdp10 | pdp11 \
| mips16 | mips64 | mipsel | mips64el \
| mips64orion | mips64orionel | mipstx39 | mipstx39el \
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
| mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \
| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
| v850 | c4x \
| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
| pj | pjl | h8500 | z8k)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i[34567]86)
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
@@ -171,27 +265,52 @@ case $basic_machine in
exit 1
;;
# Recognize the basic CPU types with company name.
vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
# FIXME: clean up the formatting here.
vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
| arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
| power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
| xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \
| alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
| ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
| sparc64-* | mips64-* | mipsel-* \
| mips64el-* | mips64orion-* | mips64orionel-* \
| mipstx39-* | mipstx39el-* \
| f301-*)
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
| xmp-* | ymp-* \
| x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
| hppa2.0n-* | hppa64-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
| alphaev6[78]-* \
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
| clipper-* | orion-* \
| sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \
| powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
| mips16-* | mips64-* | mipsel-* \
| mips64el-* | mips64orion-* | mips64orionel-* \
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
| mipstx39-* | mipstx39el-* | mcore-* \
| f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
| [cjt]90-* \
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
| thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
| bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
a29khif)
basic_machine=a29k-amd
os=-udi
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
@@ -207,20 +326,24 @@ case $basic_machine in
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-cbm
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-cbm
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-cbm
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
os=-bsd
;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -257,13 +380,16 @@ case $basic_machine in
basic_machine=cray2-cray
os=-unicos
;;
[ctj]90-cray)
basic_machine=c90-cray
[cjt]90)
basic_machine=${basic_machine}-cray
os=-unicos
;;
crds | unos)
basic_machine=m68k-crds
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@@ -297,6 +423,10 @@ case $basic_machine in
encore | umax | mmax)
basic_machine=ns32k-encore
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
os=-ose
;;
fx2800)
basic_machine=i860-alliant
;;
@@ -307,6 +437,10 @@ case $basic_machine in
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
@@ -315,6 +449,14 @@ case $basic_machine in
basic_machine=h8300-hitachi
os=-hms
;;
h8300xray)
basic_machine=h8300-hitachi
os=-xray
;;
h8500hms)
basic_machine=h8500-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
@@ -330,13 +472,30 @@ case $basic_machine in
basic_machine=m68k-hp
os=-hpux
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
hp9k6[0-9][0-9] | hp6[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
basic_machine=hppa1.1-hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
@@ -345,27 +504,42 @@ case $basic_machine in
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
;;
hppro)
basic_machine=hppa1.1-hp
os=-proelf
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i[34567]86v32)
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i[34567]86v4*)
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i[34567]86v)
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i[34567]86sol2)
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
basic_machine=i386-unknown
os=-vsta
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
@@ -391,9 +565,17 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
mipsel*-linux*)
basic_machine=mipsel-unknown
os=-linux-gnu
@@ -408,10 +590,34 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netbsd386)
basic_machine=i386-unknown
os=-netbsd
;;
netwinder)
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
@@ -424,6 +630,10 @@ case $basic_machine in
basic_machine=mips-sony
os=-newsos
;;
necv70)
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
basic_machine=m68k-next
case $os in
@@ -449,9 +659,32 @@ case $basic_machine in
basic_machine=i960-intel
os=-nindy
;;
mon960)
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
;;
os68k)
basic_machine=m68k-none
os=-os68k
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
@@ -469,28 +702,28 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pentium | p5 | k5 | nexen)
pentium | p5 | k5 | k6 | nexgen)
basic_machine=i586-pc
;;
pentiumpro | p6 | k6 | 6x86)
pentiumpro | p6 | 6x86 | athlon)
basic_machine=i686-pc
;;
pentiumii | pentium2)
basic_machine=i786-pc
basic_machine=i686-pc
;;
pentium-* | p5-* | k5-* | nexen-*)
pentium-* | p5-* | k5-* | k6-* | nexgen-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | k6-* | 6x86-*)
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=rs6000-ibm
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
;;
@@ -505,12 +738,24 @@ case $basic_machine in
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
sa29200)
basic_machine=a29k-amd
os=-udi
;;
sequent)
basic_machine=i386-sequent
;;
@@ -518,6 +763,10 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
sparclite-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
@@ -525,6 +774,13 @@ case $basic_machine in
spur)
basic_machine=spur-unknown
;;
st2000)
basic_machine=m68k-tandem
;;
stratus)
basic_machine=i860-stratus
os=-sysv4
;;
sun2)
basic_machine=m68000-sun
;;
@@ -565,10 +821,22 @@ case $basic_machine in
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
t3e)
basic_machine=t3e-cray
os=-unicos
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tx39)
basic_machine=mipstx39-unknown
;;
@@ -586,6 +854,10 @@ case $basic_machine in
basic_machine=a29k-nyu
os=-sym1
;;
v810 | necv810)
basic_machine=v810-nec
os=-none
;;
vaxv)
basic_machine=vax-dec
os=-sysv
@@ -609,6 +881,18 @@ case $basic_machine in
basic_machine=a29k-wrs
os=-vxworks
;;
w65*)
basic_machine=w65-wdc
os=-none
;;
w89k-*)
basic_machine=hppa1.1-winbond
os=-proelf
;;
windows32)
basic_machine=i386-pc
os=-windows32-msvcrt
;;
xmp)
basic_machine=xmp-cray
os=-unicos
@@ -616,6 +900,10 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@@ -623,6 +911,15 @@ case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
basic_machine=hppa1.1-winbond
;;
op50n)
basic_machine=hppa1.1-oki
;;
op60c)
basic_machine=hppa1.1-oki
;;
mips)
if [ x$os = x-linux-gnu ]; then
basic_machine=mips-unknown
@@ -639,13 +936,20 @@ case $basic_machine in
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sparc)
sh3 | sh4)
basic_machine=sh-unknown
;;
sparc | sparcv9 | sparcv9b)
basic_machine=sparc-sun
;;
cydra)
@@ -657,6 +961,19 @@ case $basic_machine in
orion105)
basic_machine=clipper-highlevel
;;
mac | mpw | mac-mpw)
basic_machine=m68k-apple
;;
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
c4x*)
basic_machine=c4x-none
os=-coff
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
@@ -710,14 +1027,36 @@ case $os in
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -rhapsody* \
| -openstep*)
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto*)
os=-nto-qnx
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
@@ -727,6 +1066,12 @@ case $os in
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
@@ -742,12 +1087,18 @@ case $os in
-acis*)
os=-aos
;;
-386bsd)
os=-bsd
;;
-ctix* | -uts*)
os=-sysv
;;
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
@@ -773,9 +1124,18 @@ case $os in
# This must come after -sysvr4.
-sysv*)
;;
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-none)
;;
*)
@@ -801,9 +1161,15 @@ case $basic_machine in
*-acorn)
os=-riscix1.2
;;
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
@@ -822,6 +1188,15 @@ case $basic_machine in
# default.
# os=-sunos4
;;
m68*-cisco)
os=-aout
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
@@ -834,6 +1209,15 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-wec)
os=-proelf
;;
*-winbond)
os=-proelf
;;
*-oki)
os=-proelf
;;
*-hp)
os=-hpux
;;
@@ -894,9 +1278,21 @@ case $basic_machine in
*-masscomp)
os=-rtu
;;
f301-fujitsu)
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
os=-coff
;;
*-*bug)
os=-coff
;;
*-apple)
os=-macos
;;
*-atari*)
os=-mint
;;
*)
os=-none
;;
@@ -918,9 +1314,15 @@ case $basic_machine in
-aix*)
vendor=ibm
;;
-beos*)
vendor=be
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
@@ -936,7 +1338,7 @@ case $basic_machine in
-genix*)
vendor=ns
;;
-mvs*)
-mvs* | -opened*)
vendor=ibm
;;
-ptx*)
@@ -948,9 +1350,26 @@ case $basic_machine in
-aux*)
vendor=apple
;;
-hms*)
vendor=hitachi
;;
-mpw* | -macos*)
vendor=apple
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:

View File

@@ -1,20 +1,199 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(byteorder.h)
AC_INIT()
AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.52)
# compile with optimisation and without debugging by default
CFLAGS=${CFLAGS-"-O"}
RSYNC_VERSION=2.5.1pre2
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
AC_CANONICAL_SYSTEM
AC_VALIDATE_CACHE_SYSTEM_TYPE
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
LDFLAGS=${LDFLAGS-""}
AC_CANONICAL_TARGET([])
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_CC_STDC
AC_SUBST(SHELL)
if test "$xac_cv_prog_cc_stdc" = xno
then
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
fi
# compile with optimisation and without debugging by default, unless
# --debug is given. We must decide this before testing the compiler.
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug],
[including debugging symbols and features (default yes)]),
[], [])
if test x"$enable_debug" = x"no"
then
AC_MSG_RESULT(no)
CFLAGS=${CFLAGS-"-O"}
else
AC_MSG_RESULT([yes])
# leave CFLAGS alone; AC_PROG_CC will try to include -g if it can
AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
dnl CFLAGS=${CFLAGS-"-g"}
fi
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
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\")],
[ RSYNC_PATH="$with_rsync_path" ],
[ RSYNC_PATH="rsync" ])
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [ ])
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH)
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [ ])
# arrgh. libc in the current debian stable screws up the largefile
# stuff, getting byte range locking wrong
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
AC_TRY_RUN([
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
struct flock lock;
int status;
int fd = open("conftest.dat", O_CREAT|O_RDWR, 0600);
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 1;
lock.l_pid = 0;
fcntl(fd,F_SETLK,&lock);
if (fork() == 0) {
lock.l_start = 1;
exit(fcntl(fd,F_SETLK,&lock) == 0);
}
wait(&status);
unlink("conftest.dat");
exit(WEXITSTATUS(status));
}
],
rsync_cv_HAVE_BROKEN_LARGEFILE=yes,rsync_cv_HAVE_BROKEN_LARGEFILE=no,rsync_cv_HAVE_BROKEN_LARGEFILE=cross)])
if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
AC_SYS_LARGEFILE
fi
ipv6type=unknown
ipv6lib=none
ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
if test "x$enable_ipv6" != xno
then
AC_MSG_CHECKING([ipv6 stack type])
for i in inria kame linux-glibc linux-inet6 toshiba v6d zeta; do
case $i in
inria)
# http://www.kame.net/
AC_EGREP_CPP(yes, [
#include <netinet/in.h>
#ifdef IPV6_INRIA_VERSION
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])
])
;;
kame)
# http://www.kame.net/
AC_EGREP_CPP(yes, [
#include <netinet/in.h>
#ifdef __KAME__
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
linux-glibc)
# http://www.v6.linux.or.jp/
AC_EGREP_CPP(yes, [
#include <features.h>
#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
yes
#endif],
[ipv6type=$i;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
linux-inet6)
# http://www.v6.linux.or.jp/
if test -d /usr/inet6 -o -f /usr/inet6/lib/libinet6.a; then
ipv6type=$i
ipv6lib=inet6
ipv6libdir=/usr/inet6/lib
ipv6trylibc=yes;
AC_DEFINE(INET6, 1, [true if you have IPv6])
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
toshiba)
AC_EGREP_CPP(yes, [
#include <sys/param.h>
#ifdef _TOSHIBA_INET6
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
v6d)
AC_EGREP_CPP(yes, [
#include </usr/local/v6/include/sys/v6config.h>
#ifdef __V6D__
yes
#endif],
[ipv6type=$i;
ipv6lib=v6;
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
zeta)
AC_EGREP_CPP(yes, [
#include <sys/param.h>
#ifdef _ZETA_MINAMI_INET6
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
AC_DEFINE(INET6, 1, [true if you have IPv6])])
;;
esac
if test "$ipv6type" != "unknown"; then
break
fi
done
AC_MSG_RESULT($ipv6type)
AC_SEARCH_LIBS(getaddrinfo, inet6)
fi
AC_C_BIGENDIAN
AC_HEADER_DIRENT
@@ -23,7 +202,8 @@ AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h)
AC_CHECK_HEADERS(glob.h)
AC_CHECK_HEADERS(glob.h alloca.h mcheck.h sys/sysctl.h arpa/inet.h arpa/nameser.h)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -38,131 +218,22 @@ AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_PID_T
AC_TYPE_GETGROUPS
AC_STRUCT_ST_RDEV
AC_CHECK_TYPE(ino_t,unsigned)
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_TYPE([ino_t], [unsigned])
TYPE_SOCKLEN_T
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
rsync_cv_errno=yes,rsync_cv_have_errno_decl=no)])
if test x"$rsync_cv_errno" = x"yes"; then
AC_DEFINE(HAVE_ERRNO_DECL)
fi
AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
AC_CHECK_FUNCS(memmove lchown vsnprintf snprintf setsid glob strpbrk)
AC_CHECK_FUNCS(strlcat strlcpy inet_aton socketpair)
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)
fi
# sometimes getopt_long cannot parse same arguments twice
# e.g. on certain versions of CygWin32
AC_CACHE_CHECK([for working getopt_long],rsync_cv_HAVE_GETOPT_LONG,[
AC_TRY_RUN([#include <getopt.h>
main() {
int i, x = 0; char *argv[] = { "x", "--xx" };
struct option o[] = {{"xx", 0, 0, 1}, {0,0,0,0}};
getopt_long(2, argv, "x", o, &i) == 1 ? x++ : 0; optind = 0;
getopt_long(2, argv, "x", o, &i) == 1 ? x++ : 0;
exit(x == 2 ? 0 : 1);
}], rsync_cv_HAVE_GETOPT_LONG=yes,rsync_cv_HAVE_GETOPT_LONG=no,
rsync_cv_HAVE_GETOPT_LONG=cross)])
if test x"$rsync_cv_HAVE_GETOPT_LONG" = x"yes"; then
AC_DEFINE(HAVE_GETOPT_LONG)
fi
AC_CACHE_CHECK([for long long],rsync_cv_HAVE_LONGLONG,[
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
rsync_cv_HAVE_LONGLONG=yes,rsync_cv_HAVE_LONGLONG=no,rsync_cv_HAVE_LONGLONG=cross)])
if test x"$rsync_cv_HAVE_LONGLONG" = x"yes"; then
AC_DEFINE(HAVE_LONGLONG)
fi
AC_CACHE_CHECK([for off64_t],rsync_cv_HAVE_OFF64_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/stat.h>
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }],
rsync_cv_HAVE_OFF64_T=yes,rsync_cv_HAVE_OFF64_T=no,rsync_cv_HAVE_OFF64_T=cross)])
if test x"$rsync_cv_HAVE_OFF64_T" = x"yes"; then
AC_DEFINE(HAVE_OFF64_T)
fi
AC_CACHE_CHECK([for short ino_t],rsync_cv_HAVE_SHORT_INO_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
rsync_cv_HAVE_SHORT_INO_T=yes,rsync_cv_HAVE_SHORT_INO_T=no,rsync_cv_HAVE_SHORT_INO_T=cross)])
if test x"$rsync_cv_HAVE_SHORT_INO_T" = x"yes"; then
AC_DEFINE(HAVE_SHORT_INO_T)
fi
AC_CACHE_CHECK([for unsigned char],rsync_cv_HAVE_UNSIGNED_CHAR,[
AC_TRY_RUN([#include <stdio.h>
main() { char c; c=250; exit((c > 0)?0:1); }],
rsync_cv_HAVE_UNSIGNED_CHAR=yes,rsync_cv_HAVE_UNSIGNED_CHAR=no,rsync_cv_HAVE_UNSIGNED_CHAR=cross)])
if test x"$rsync_cv_HAVE_UNSIGNED_CHAR" = x"yes"; then
AC_DEFINE(HAVE_UNSIGNED_CHAR)
fi
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
AC_TRY_RUN([#include <sys/types.h>
#include <dirent.h>
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) exit(0); exit(1);} ],
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR)
fi
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no,rsync_cv_HAVE_UTIMBUF=cross)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF)
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
AC_TRY_RUN([
#include <sys/time.h>
#include <unistd.h>
main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}],
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no,rsync_cv_HAVE_GETTIMEOFDAY_TZ=cross)])
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ)
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
exit(1);}],
rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA)
AC_DEFINE(HAVE_ERRNO_DECL, 1, [ ])
fi
# The following test taken from the cvs sources
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
# These need checks to be before checks for any other functions that
# might be in the same libraries.
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
# libsocket.so which has a bad implementation of gethostbyname (it
# only looks in /etc/hosts), so we only look for -lsocket if we need
@@ -191,11 +262,36 @@ if test x"$ac_cv_func_connect" = x"no"; then
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
AC_DEFINE(HAVE_CONNECT)
AC_DEFINE(HAVE_CONNECT, 1, [ ])
fi
fi
#
AC_CHECK_LIB(resolv, inet_ntop)
AC_MSG_NOTICE([Looking in libraries: $LIBS])
AC_CHECK_FUNC(inet_ntop, , AC_LIBOBJ(lib/inet_ntop))
AC_CHECK_FUNC(inet_pton, , AC_LIBOBJ(lib/inet_pton))
AC_CHECK_FUNC(getaddrinfo, , AC_LIBOBJ(lib/getaddrinfo))
AC_CHECK_FUNC(getnameinfo, , AC_LIBOBJ(lib/getnameinfo))
AC_CHECK_MEMBER([struct sockaddr.sa_len],
[ AC_DEFINE(HAVE_SOCKADDR_LEN) ],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
])
AC_MSG_CHECKING(struct sockaddr_storage)
AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/socket.h>],
[struct sockaddr_storage x;],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOCKADDR_STORAGE),
AC_MSG_RESULT(no))
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
#
AC_CHECK_FUNCS(strcasecmp)
@@ -203,6 +299,198 @@ if test x"$ac_cv_func_strcasecmp" = x"no"; then
AC_CHECK_LIB(resolv, strcasecmp)
fi
dnl At the moment we don't test for a broken memcmp(), because all we
dnl need to do is test for equality, not comparison, and it seems that
dnl every platform has a memcmp that can do at least that.
dnl AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
AC_CHECK_FUNCS(memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk)
AC_CHECK_FUNCS(strlcat strlcpy mtrace)
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
#include <sys/types.h>
#include <sys/socket.h>
main() {
int fd[2];
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
}],
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
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])
fi
AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"
then
AC_MSG_RESULT($srcdir/popt)
BUILD_POPT='$(popt_OBJS)'
CFLAGS="$CFLAGS -I$srcdir/popt"
else
AC_MSG_RESULT(no)
fi
AC_CACHE_CHECK([for long long],rsync_cv_HAVE_LONGLONG,[
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
rsync_cv_HAVE_LONGLONG=yes,rsync_cv_HAVE_LONGLONG=no,rsync_cv_HAVE_LONGLONG=cross)])
if test x"$rsync_cv_HAVE_LONGLONG" = x"yes"; then
AC_DEFINE(HAVE_LONGLONG, 1, [ ])
fi
AC_CACHE_CHECK([for off64_t],rsync_cv_HAVE_OFF64_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/stat.h>
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }],
rsync_cv_HAVE_OFF64_T=yes,rsync_cv_HAVE_OFF64_T=no,rsync_cv_HAVE_OFF64_T=cross)])
if test x"$rsync_cv_HAVE_OFF64_T" = x"yes"; then
AC_DEFINE(HAVE_OFF64_T, 1, [ ])
fi
AC_CACHE_CHECK([for short ino_t],rsync_cv_HAVE_SHORT_INO_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
rsync_cv_HAVE_SHORT_INO_T=yes,rsync_cv_HAVE_SHORT_INO_T=no,rsync_cv_HAVE_SHORT_INO_T=cross)])
if test x"$rsync_cv_HAVE_SHORT_INO_T" = x"yes"; then
AC_DEFINE(HAVE_SHORT_INO_T, 1, [ ])
fi
AC_CACHE_CHECK([for unsigned char],rsync_cv_HAVE_UNSIGNED_CHAR,[
AC_TRY_RUN([#include <stdio.h>
main() { char c; c=250; exit((c > 0)?0:1); }],
rsync_cv_HAVE_UNSIGNED_CHAR=yes,rsync_cv_HAVE_UNSIGNED_CHAR=no,rsync_cv_HAVE_UNSIGNED_CHAR=cross)])
if test x"$rsync_cv_HAVE_UNSIGNED_CHAR" = x"yes"; then
AC_DEFINE(HAVE_UNSIGNED_CHAR, 1, [ ])
fi
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
AC_TRY_RUN([#include <sys/types.h>
#include <dirent.h>
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) exit(0); exit(1);} ],
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR, 1, [ ])
fi
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no,rsync_cv_HAVE_UTIMBUF=cross)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF, 1, [ ])
fi
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
AC_TRY_RUN([
#include <sys/time.h>
#include <unistd.h>
main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}],
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no,rsync_cv_HAVE_GETTIMEOFDAY_TZ=cross)])
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ, 1, [ ])
fi
AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
AC_TRY_RUN([
#include <sys/types.h>
#include <stdarg.h>
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
va_start(ap, format);
len = vsnprintf(0, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
exit(0);
}
main() { foo("hello"); }
],
rsync_cv_HAVE_C99_VSNPRINTF=yes,rsync_cv_HAVE_C99_VSNPRINTF=no,rsync_cv_HAVE_C99_VSNPRINTF=cross)])
if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [ ])
fi
AC_CACHE_CHECK([for secure mkstemp],rsync_cv_HAVE_SECURE_MKSTEMP,[
AC_TRY_RUN([#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
main() {
struct stat st;
char tpl[20]="/tmp/test.XXXXXX";
int fd = mkstemp(tpl);
if (fd == -1) exit(1);
unlink(tpl);
if (fstat(fd, &st) != 0) exit(1);
if ((st.st_mode & 0777) != 0600) exit(1);
exit(0);
}],
rsync_cv_HAVE_SECURE_MKSTEMP=yes,
rsync_cv_HAVE_SECURE_MKSTEMP=no,
rsync_cv_HAVE_SECURE_MKSTEMP=cross)])
if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [ ])
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
exit(0);}],
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA, 1, [ ])
fi
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip;
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
AC_DEFINE(REPLACE_INET_ATON, 1, [ ])
fi
#
# The following test was mostly taken from the tcl/tk plus patches
#
@@ -232,6 +520,7 @@ fi
AC_SUBST(OBJ_SAVE)
AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_SUBST(BUILD_POPT)
AC_OUTPUT(Makefile lib/dummy zlib/dummy)
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT

82
csprotocol.txt Normal file
View File

@@ -0,0 +1,82 @@
This is kind of informal and may be wrong, but it helped me. It's
basically a summary of clientserver.c and authenticate.c.
-- Martin Pool <mbp@samba.org>
$Id$
This is the protocol used for rsync --daemon; i.e. connections to port
873 rather than invocations over a remote shell.
When the server accepts a connection, it prints a greeting
@RSYNCD: <version>
where <version> is the numeric version; currently 24. It follows this
with a free text message-of-the-day. It expects to see a similar
greeting back from the client.
The server is now in the connected state. The client can either send
the command
#list
to get a listing of modules, or the name of a module. After this, the
connection is now bound to a particular module. Access per host for
this module is now checked, as is per-module connection limits.
If authentication is required to use this module, the server will say
@RSYNCD: AUTHREQD <challenge>
where <challenge> is a random string of base64 characters. The client
must respond with
<user> <response>
where <user> is the username they claim to be, and <response> is the
base64 form of the MD4 hash of challenge+password.
At this point the server applies all remaining constraints before
handing control to the client, including switching uid/gid, setting up
include and exclude lists, moving to the root of the module, and doing
chroot.
If the login is acceptable, then the server will respond with
@RSYNCD: OK
The client now writes some rsync options, as if it were remotely
executing the command. The server parses these arguments as if it had
just been invoked with them, but they're added to the existing state.
So if the client specifies a list of files to be included or excluded,
they'll defer to existing limits specified in the server
configuration.
At this point the client and server both switch to using a
multiplexing layer across the socket. The main point of this is to
allow the server to asynchronously pass errors back, while still
allowing streamed and pipelined data.
Unfortunately, the multiplex protocol is not used at every stage. We
start up in plain socket mode and then change over by calling
io_start_buffering. Of course both the client and the server have to
do this at the same point.
The server then talks to the client as normal across the socket,
passing checksums, file lists and so on. For documentation of that,
stay tuned (or write it yourself!).
------------
Protocol version changes
25 (2001-08-20, 2.4.7pre2)
Send an explicit "@RSYNC EXIT" command at the end of the
module listing. We never intentionally end the transmission
by just closing the socket anymore.

View File

@@ -1,4 +1,26 @@
/* error codes returned by rsync */
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2000 by Andrew Tridgell
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.
*/
/*
* error codes returned by rsync. If you change these, please also update the
* string mappings in log.c
*/
#define RERR_SYNTAX 1 /* syntax or usage error */
#define RERR_PROTOCOL 2 /* protocol incompatibility */
@@ -14,5 +36,22 @@
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#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_TIMEOUT 30 /* timeout in data send/receive */
/* Although it doesn't seem to be specified anywhere,
* ssh and the shell seem to return these values:
*
* 124 if the command exited with status 255
* 125 if the command is killed by a signal
* 126 if the command cannot be run
* 127 if the command is not found
*
* and we could use this to give a better explanation if the remote
* command is not found.
*/
#define RERR_CMD_FAILED 124
#define RERR_CMD_KILLED 125
#define RERR_CMD_RUN 126
#define RERR_CMD_NOTFOUND 127

View File

@@ -1,6 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 1996 by Paul Mackerras
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
@@ -20,6 +21,8 @@
/* a lot of this stuff was originally derived from GNU tar, although
it has now changed so much that it is hard to tell :) */
/* include/exclude cluestick added by Martin Pool <mbp@samba.org> */
#include "rsync.h"
extern int verbose;
@@ -28,7 +31,7 @@ extern int delete_mode;
static struct exclude_struct **exclude_list;
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(char *pattern, int include)
static struct exclude_struct *make_exclude(const char *pattern, int include)
{
struct exclude_struct *ret;
@@ -84,8 +87,8 @@ static void free_exclude(struct exclude_struct *ex)
free(ex);
}
static int check_one_exclude(char *name,struct exclude_struct *ex,
STRUCT_STAT *st)
static int check_one_exclude(char *name, struct exclude_struct *ex,
STRUCT_STAT *st)
{
char *p;
int match_start=0;
@@ -121,32 +124,62 @@ static int check_one_exclude(char *name,struct exclude_struct *ex,
}
int check_exclude(char *name,struct exclude_struct **local_exclude_list,
static void report_exclude_result(char const *name,
struct exclude_struct const *ent,
STRUCT_STAT const *st)
{
/* 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 ? "/" : "");
}
/*
* 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 n;
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++)
if (check_one_exclude(name,exclude_list[n],st))
return !exclude_list[n]->include;
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++)
if (check_one_exclude(name,local_exclude_list[n],st))
return !local_exclude_list[n]->include;
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;
}
}
}
return 0;
}
void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
{
int len=0;
if (list && *list)
@@ -174,12 +207,12 @@ void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
(*list)[len+1] = NULL;
}
void add_exclude(char *pattern, int include)
void add_exclude(const char *pattern, int include)
{
add_exclude_list(pattern,&exclude_list, include);
}
struct exclude_struct **make_exclude_list(char *fname,
struct exclude_struct **make_exclude_list(const char *fname,
struct exclude_struct **list1,
int fatal, int include)
{
@@ -188,7 +221,10 @@ struct exclude_struct **make_exclude_list(char *fname,
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
rsyserr(FERROR, errno,
"failed to open %s file %s",
include ? "include" : "exclude",
fname);
exit_cleanup(RERR_FILEIO);
}
return list;
@@ -210,7 +246,7 @@ struct exclude_struct **make_exclude_list(char *fname,
}
void add_exclude_file(char *fname,int fatal,int include)
void add_exclude_file(const char *fname, int fatal, int include)
{
if (!fname || !*fname) return;
@@ -222,6 +258,12 @@ void send_exclude_list(int f)
{
int i;
extern int remote_version;
extern int list_only, recurse;
/* this is a complete hack - blame Rusty */
if (list_only && !recurse) {
add_exclude("/*/*", 0);
}
if (!exclude_list) {
write_int(f,0);
@@ -356,7 +398,7 @@ void add_cvs_excludes(void)
add_exclude(cvs_ignore_list[i], 0);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
slprintf(fname,sizeof(fname), "%s/.cvsignore",p);
snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
add_exclude_file(fname,0,0);
}

204
flist.c
View File

@@ -1,6 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 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
@@ -47,33 +48,78 @@ extern int remote_version;
extern int io_error;
extern int sanitize_paths;
extern int read_batch;
extern int write_batch;
static char topsrcname[MAXPATHLEN];
static struct exclude_struct **local_exclude_list;
static struct file_struct null_file;
static void clean_flist(struct file_list *flist, int strip_root);
static struct string_area *string_area_new(int size)
{
struct string_area *a;
if (size <= 0) size = ARENA_SIZE;
a = malloc(sizeof(*a));
if (!a) out_of_memory("string_area_new");
a->current = a->base = malloc(size);
if (!a->current) out_of_memory("string_area_new buffer");
a->end = a->base + size;
a->next = NULL;
return a;
}
static void string_area_free(struct string_area *a)
{
struct string_area *next;
for ( ; a ; a = next) {
next = a->next;
free(a->base);
}
}
static char *string_area_malloc(struct string_area **ap, int size)
{
char *p;
struct string_area *a;
/* does the request fit into the current space? */
a = *ap;
if (a->current + size >= a->end) {
/* no; get space, move new string_area to front of the list */
a = string_area_new(size > ARENA_SIZE ? size : ARENA_SIZE);
a->next = *ap;
*ap = a;
}
/* have space; do the "allocation." */
p = a->current;
a->current += size;
return p;
}
static char *string_area_strdup(struct string_area **ap, const char *src)
{
char* dest = string_area_malloc(ap, strlen(src) + 1);
return strcpy(dest, src);
}
static void list_file_entry(struct file_struct *f)
{
char perms[11] = "----------";
char *perm_map = "rwxrwxrwx";
int i;
char perms[11];
if (!f->basename)
/* this can happen if duplicate names were removed */
return;
for (i=0;i<9;i++) {
if (f->mode & (1<<i)) perms[9-i] = perm_map[8-i];
}
if (S_ISLNK(f->mode)) perms[0] = 'l';
if (S_ISDIR(f->mode)) perms[0] = 'd';
if (S_ISBLK(f->mode)) perms[0] = 'b';
if (S_ISCHR(f->mode)) perms[0] = 'c';
if (S_ISSOCK(f->mode)) perms[0] = 's';
if (S_ISFIFO(f->mode)) perms[0] = 'p';
permstring(perms, f->mode);
if (preserve_links && S_ISLNK(f->mode)) {
rprintf(FINFO,"%s %11.0f %s %s -> %s\n",
perms,
@@ -98,7 +144,7 @@ int readlink_stat(const char *Path, STRUCT_STAT *Buffer, char *Linkbuf)
}
if (S_ISLNK(Buffer->st_mode)) {
int l;
if ((l = readlink(Path,Linkbuf,MAXPATHLEN-1)) == -1) {
if ((l = readlink((char *) Path, Linkbuf, MAXPATHLEN-1))== -1) {
return -1;
}
Linkbuf[l] = 0;
@@ -130,14 +176,18 @@ 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
*/
static int match_file_name(char *fname,STRUCT_STAT *st)
static int check_exclude_file(int f,char *fname,STRUCT_STAT *st)
{
if (check_exclude(fname,local_exclude_list,st)) {
if (verbose > 2)
rprintf(FINFO,"excluding file %s\n",fname);
return 0;
}
return 1;
extern int delete_excluded;
/* f is set to -1 when calculating deletion file list */
if ((f == -1) && delete_excluded) {
return 0;
}
if (check_exclude(fname,local_exclude_list,st)) {
return 1;
}
return 0;
}
/* used by the one_file_system code */
@@ -153,7 +203,7 @@ static void set_filesystem(char *fname)
static int to_wire_mode(mode_t mode)
{
if (S_ISLNK(mode) && (S_IFLNK != 0120000)) {
if (S_ISLNK(mode) && (_S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | 0120000;
}
return (int)mode;
@@ -161,8 +211,8 @@ static int to_wire_mode(mode_t mode)
static mode_t from_wire_mode(int mode)
{
if ((mode & (_S_IFMT)) == 0120000 && (S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | S_IFLNK;
if ((mode & (_S_IFMT)) == 0120000 && (_S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | _S_IFLNK;
}
return (mode_t)mode;
}
@@ -413,8 +463,12 @@ static int skip_filesystem(char *fname, STRUCT_STAT *st)
return (st2.st_dev != filesystem_dev);
}
#define STRDUP(ap, p) (ap ? string_area_strdup(ap, p) : strdup(p))
#define MALLOC(ap, i) (ap ? string_area_malloc(ap, i) : malloc(i))
/* create a file_struct for a named file */
struct file_struct *make_file(int f, char *fname)
struct file_struct *make_file(int f, char *fname, struct string_area **ap,
int noexcludes)
{
struct file_struct *file;
STRUCT_STAT st;
@@ -422,7 +476,7 @@ struct file_struct *make_file(int f, char *fname)
char *p;
char cleaned_name[MAXPATHLEN];
char linkbuf[MAXPATHLEN];
extern int delete_excluded;
extern int module_id;
strlcpy(cleaned_name, fname, MAXPATHLEN);
cleaned_name[MAXPATHLEN-1] = 0;
@@ -435,12 +489,24 @@ struct file_struct *make_file(int f, char *fname)
memset(sum,0,SUM_LENGTH);
if (readlink_stat(fname,&st,linkbuf) != 0) {
int save_errno = errno;
if ((errno == ENOENT) && copy_links && !noexcludes) {
/* symlink pointing nowhere, see if excluded */
memset((char *)&st, 0, sizeof(st));
if (check_exclude_file(f,fname,&st)) {
/* file is excluded anyway, ignore silently */
return NULL;
}
}
io_error = 1;
rprintf(FERROR,"readlink %s: %s\n",
fname,strerror(errno));
fname,strerror(save_errno));
return NULL;
}
/* we use noexcludes from backup.c */
if (noexcludes) goto skip_excludes;
if (S_ISDIR(st.st_mode) && !recurse) {
rprintf(FINFO,"skipping directory %s\n",fname);
return NULL;
@@ -451,10 +517,15 @@ struct file_struct *make_file(int f, char *fname)
return NULL;
}
/* f is set to -1 when calculating deletion file list */
if (((f != -1) || !delete_excluded) && !match_file_name(fname,&st))
if (check_exclude_file(f,fname,&st))
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);
@@ -471,11 +542,11 @@ struct file_struct *make_file(int f, char *fname)
file->dirname = strdup(fname);
lastdir = file->dirname;
}
file->basename = strdup(p+1);
file->basename = STRDUP(ap, p+1);
*p = '/';
} else {
file->dirname = NULL;
file->basename = strdup(fname);
file->basename = STRDUP(ap, fname);
}
file->modtime = st.st_mtime;
@@ -491,12 +562,12 @@ struct file_struct *make_file(int f, char *fname)
#if SUPPORT_LINKS
if (S_ISLNK(st.st_mode)) {
file->link = strdup(linkbuf);
file->link = STRDUP(ap, linkbuf);
}
#endif
if (always_checksum) {
file->sum = (char *)malloc(MD4_SUM_LENGTH);
file->sum = (char *)MALLOC(ap, MD4_SUM_LENGTH);
if (!file->sum) out_of_memory("md4 sum");
/* drat. we have to provide a null checksum for non-regular
files in order to be compatible with earlier versions
@@ -533,7 +604,7 @@ void send_file_name(int f,struct file_list *flist,char *fname,
{
struct file_struct *file;
file = make_file(f,fname);
file = make_file(f,fname, &flist->string_area, 0);
if (!file) return;
@@ -549,6 +620,9 @@ void send_file_name(int f,struct file_list *flist,char *fname,
out_of_memory("send_file_name");
}
if (write_batch) /* dw */
file->flags = FLAG_DELETE;
if (strcmp(file->basename,"")) {
flist->files[flist->count++] = file;
send_file_entry(file,f,base_flags);
@@ -623,7 +697,6 @@ static void send_directory(int f,struct file_list *flist,char *dir)
}
struct file_list *send_file_list(int f,int argc,char *argv[])
{
int i,l;
@@ -635,19 +708,14 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (verbose && recurse && !am_server && f != -1) {
rprintf(FINFO,"building file list ... ");
if (verbose > 1)
rprintf(FINFO, "\n");
rflush(FINFO);
}
start_write = stats.total_written;
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist) out_of_memory("send_file_list");
flist->count=0;
flist->malloced = 1000;
flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
flist->malloced);
if (!flist->files) out_of_memory("send_file_list");
flist = flist_new();
if (f != -1) {
io_start_buffering(f);
@@ -783,6 +851,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
io_end_buffering(f);
stats.flist_size = stats.total_written - start_write;
stats.num_files = flist->count;
if (write_batch) /* dw */
write_batch_flist_info(flist->count, flist->files);
}
if (verbose > 2)
@@ -860,9 +930,10 @@ struct file_list *recv_file_list(int f)
}
/* if protocol version is >= 17 then recv the io_error flag */
if (f != -1 && remote_version >= 17) {
if (f != -1 && remote_version >= 17 && !read_batch) { /* dw-added readbatch */
extern int module_id;
if (lp_ignore_errors(module_id)) {
extern int ignore_errors;
if (lp_ignore_errors(module_id) || ignore_errors) {
read_int(f);
} else {
io_error |= read_int(f);
@@ -934,10 +1005,32 @@ void free_file(struct file_struct *file)
if (file->basename) free(file->basename);
if (file->link) free(file->link);
if (file->sum) free(file->sum);
memset((char *)file, 0, sizeof(*file));
*file = null_file;
}
/*
* allocate a new file list
*/
struct file_list *flist_new()
{
struct file_list *flist;
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist) out_of_memory("send_file_list");
flist->count=0;
flist->malloced = 1000;
flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
flist->malloced);
if (!flist->files) out_of_memory("send_file_list");
#if ARENA_SIZE > 0
flist->string_area = string_area_new(0);
#else
flist->string_area = NULL;
#endif
return flist;
}
/*
* free up all elements in a flist
*/
@@ -945,11 +1038,14 @@ void flist_free(struct file_list *flist)
{
int i;
for (i=1;i<flist->count;i++) {
free_file(flist->files[i]);
if (!flist->string_area)
free_file(flist->files[i]);
free(flist->files[i]);
}
memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count);
free(flist->files);
if (flist->string_area)
string_area_free(flist->string_area);
memset((char *)flist, 0, sizeof(*flist));
free(flist);
}
@@ -978,7 +1074,13 @@ static void clean_flist(struct file_list *flist, int strip_root)
if (verbose > 1 && !am_server)
rprintf(FINFO,"removing duplicate name %s from file list %d\n",
f_name(flist->files[i-1]),i-1);
free_file(flist->files[i]);
/* 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. XXX can i use a bit in the flags field? */
if (flist->string_area)
flist->files[i][0] = null_file;
else
free_file(flist->files[i]);
}
}
@@ -1006,10 +1108,10 @@ static void clean_flist(struct file_list *flist, int strip_root)
for (i=0;i<flist->count;i++) {
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n",
getpid(), i,
(int) getpid(), i,
NS(flist->files[i]->dirname),
NS(flist->files[i]->basename),
flist->files[i]->mode,
(int) flist->files[i]->mode,
(double)flist->files[i]->length);
}
}

View File

@@ -1,5 +1,6 @@
/*
Copyright (C) Andrew Tridgell 1996
/* -*- 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
@@ -35,6 +36,8 @@ extern int size_only;
extern int io_timeout;
extern int remote_version;
extern int always_checksum;
extern int modify_window;
extern char *compare_dest;
/* choose whether to skip a particular file */
@@ -49,6 +52,15 @@ static int skip_file(char *fname,
of the file time to determine whether to sync */
if (always_checksum && S_ISREG(st->st_mode)) {
char sum[MD4_SUM_LENGTH];
char fnamecmpdest[MAXPATHLEN];
if (compare_dest != NULL) {
if (access(fname, 0) != 0) {
snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
compare_dest,fname);
fname = fnamecmpdest;
}
}
file_checksum(fname,sum,st->st_size);
if (remote_version < 21) {
return (memcmp(sum,file->sum,2) == 0);
@@ -65,7 +77,7 @@ static int skip_file(char *fname,
return 0;
}
return (st->st_mtime == file->modtime);
return (cmp_modtime(st->st_mtime,file->modtime) == 0);
}
@@ -165,6 +177,15 @@ static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
}
/*
* Acts on file number I from FLIST, whose name is fname.
*
* First fixes up permissions, then generates checksums for the file.
*
* (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;
@@ -203,10 +224,17 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
}
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. */
if (dry_run) return;
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) != 0) {
rprintf(FERROR,"unlink %s : %s\n",fname,strerror(errno));
rprintf(FERROR,"recv_generator: unlink %s: %s\n",
fname,strerror(errno));
return;
}
statret = -1;
@@ -215,11 +243,13 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
if (!(relative_paths && errno==ENOENT &&
create_directory_path(fname)==0 &&
do_mkdir(fname,file->mode)==0)) {
rprintf(FERROR,"mkdir %s : %s (2)\n",
rprintf(FERROR,"recv_generator: mkdir %s: %s (2)\n",
fname,strerror(errno));
}
}
if (set_perms(fname,file,NULL,0) && verbose)
/* 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))
rprintf(FINFO,"%s/\n",fname);
return;
}
@@ -246,8 +276,8 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
return;
}
}
delete_file(fname);
}
delete_file(fname);
if (do_symlink(file->link,fname) != 0) {
rprintf(FERROR,"symlink %s -> %s : %s\n",
fname,file->link,strerror(errno));
@@ -301,7 +331,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
if ((statret == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
int saveerrno = errno;
slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
statret = link_stat(fnamecmpbuf,&st);
if (!S_ISREG(st.st_mode))
statret = -1;
@@ -333,7 +363,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
return;
}
if (update_only && st.st_mtime > file->modtime && fnamecmp == fname) {
if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
if (verbose > 1)
rprintf(FINFO,"%s is newer\n",fname);
return;
@@ -401,6 +431,11 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
rprintf(FINFO,"generator starting pid=%d count=%d\n",
(int)getpid(),flist->count);
/* 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 */
io_timeout = 0;
for (i = 0; i < flist->count; i++) {
struct file_struct *file = flist->files[i];
mode_t saved_mode = file->mode;
@@ -411,6 +446,8 @@ 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? */
}
recv_generator(local_name?local_name:f_name(file),
@@ -428,11 +465,6 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
write_int(f,-1);
/* 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 */
io_timeout = 0;
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 */

229
io.c
View File

@@ -1,6 +1,8 @@
/*
Copyright (C) Andrew Tridgell 1996
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2001 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
Copyright (C) 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
@@ -32,24 +34,29 @@ static int io_multiplexing_in;
static int multiplex_in_fd;
static int multiplex_out_fd;
static time_t last_io;
static int eof_error=1;
static int no_flush;
extern int bwlimit;
extern int verbose;
extern int io_timeout;
extern struct stats stats;
static int buffer_f_in = -1;
/** Ignore EOF errors while reading a module listing if the remote
version is 24 or less. */
int kludge_around_eof = False;
static int io_error_fd = -1;
static void read_loop(int fd, char *buf, int len);
void setup_readbuffer(int f_in)
{
buffer_f_in = f_in;
}
static void check_timeout(void)
{
extern int am_server, am_daemon;
time_t t;
err_list_push();
if (!io_timeout) return;
@@ -61,8 +68,10 @@ static void check_timeout(void)
t = time(NULL);
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
if (!am_server && !am_daemon) {
rprintf(FERROR,"io timeout after %d seconds - exiting\n",
(int)(t-last_io));
}
exit_cleanup(RERR_TIMEOUT);
}
}
@@ -81,6 +90,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 = -1;
read_loop(fd, buf, 4);
@@ -102,21 +113,68 @@ static void read_error_fd(void)
}
static int no_flush;
static void whine_about_eof (void)
{
/**
It's almost always an error to get an EOF when we're trying
to read from the network, because the protocol is
self-terminating.
However, there is one unfortunate cases where it is not,
which is rsync <2.4.6 sending a list of modules on a
server, since the list is terminated by closing the socket.
So, for the section of the program where that is a problem
(start_socket_client), kludge_around_eof is True and we
just exit.
*/
/* read from a socket with IO timeout. return the number of
bytes read. If no bytes can be read then exit, never return
a number <= 0 */
static int read_timeout(int fd, char *buf, int len)
if (kludge_around_eof)
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);
}
}
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));
exit_cleanup(RERR_STREAMIO);
}
/*!
* Read from a socket with IO timeout. return the number of bytes
* read. If no bytes can be read then exit, never return a number <= 0.
*
* TODO: If the remote shell connection fails, then current versions
* actually report an "unexpected EOF" error here. Since it's a
* fairly common mistake to try to use rsh when ssh is required, we
* should trap that: if we fail to read any data at all, we should
* 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, int len)
{
int n, ret=0;
io_flush();
while (ret == 0) {
/* until we manage to read *something* */
fd_set fds;
struct timeval tv;
int fd_count = fd+1;
int count;
FD_ZERO(&fds);
FD_SET(fd, &fds);
@@ -130,11 +188,16 @@ static int read_timeout(int fd, char *buf, int len)
errno = 0;
if (select(fd_count, &fds, NULL, NULL, &tv) < 1) {
count = select(fd_count, &fds, NULL, NULL, &tv);
if (count == 0) {
check_timeout();
}
if (count <= 0) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
check_timeout();
continue;
}
@@ -153,33 +216,27 @@ static int read_timeout(int fd, char *buf, int len)
if (io_timeout)
last_io = time(NULL);
continue;
} else if (n == 0) {
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);
}
if (n == -1 && errno == EINTR) {
continue;
}
if (n == 0) {
if (eof_error) {
rprintf(FERROR,"unexpected EOF in read_timeout\n");
}
exit_cleanup(RERR_STREAMIO);
}
/* this prevents us trying to write errors on a dead socket */
io_multiplexing_close();
rprintf(FERROR,"read error: %s\n", strerror(errno));
exit_cleanup(RERR_STREAMIO);
}
return ret;
}
/* continue trying to read len bytes - don't return until len
has been read */
static void read_loop(int fd, char *buf, int len)
/*! Continue trying to read len bytes - don't return until len has
been read. */
static void read_loop (int fd, char *buf, int len)
{
while (len) {
int n = read_timeout(fd, buf, len);
@@ -189,16 +246,20 @@ static void read_loop(int fd, char *buf, int len)
}
}
/* read from the file descriptor handling multiplexing -
return number of bytes read
never return <= 0 */
/**
* Read from the file descriptor handling multiplexing - return number
* of bytes read.
*
* Never returns <= 0.
*/
static int read_unbuffered(int fd, char *buf, int len)
{
static int remaining;
int tag, ret=0;
char line[1024];
if (!io_multiplexing_in || fd != multiplex_in_fd)
if (!io_multiplexing_in || fd != multiplex_in_fd)
return read_timeout(fd, buf, len);
while (ret == 0) {
@@ -210,7 +271,7 @@ static int read_unbuffered(int fd, char *buf, int len)
continue;
}
read_loop(fd, line, 4);
read_loop (fd, line, 4);
tag = IVAL(line, 0);
remaining = tag & 0xFFFFFF;
@@ -244,7 +305,7 @@ static int read_unbuffered(int fd, char *buf, int len)
/* do a buffered read from fd. don't return until all N bytes
have been read. If all N can't be read then exit with an error */
static void readfd(int fd,char *buffer,int N)
static void readfd (int fd, char *buffer, int N)
{
int ret;
int total=0;
@@ -252,7 +313,7 @@ static void readfd(int fd,char *buffer,int N)
while (total < N) {
io_flush();
ret = read_unbuffered(fd,buffer + total,N-total);
ret = read_unbuffered (fd, buffer + total, N-total);
total += ret;
}
@@ -302,22 +363,18 @@ void read_buf(int f,char *buf,int len)
void read_sbuf(int f,char *buf,int 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;
}
/* write len bytes to fd, possibly reading from buffer_f_in if set
in order to unclog the pipe. don't return until all len
bytes have been written */
/* write len bytes to fd */
static void writefd_unbuffered(int fd,char *buf,int len)
{
int total = 0;
@@ -325,6 +382,8 @@ static void writefd_unbuffered(int fd,char *buf,int len)
int fd_count, count;
struct timeval tv;
err_list_push();
no_flush++;
while (total < len) {
@@ -349,11 +408,14 @@ static void writefd_unbuffered(int fd,char *buf,int len)
&w_fds,NULL,
&tv);
if (count == 0) {
check_timeout();
}
if (count <= 0) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
check_timeout();
continue;
}
@@ -363,18 +425,39 @@ static void writefd_unbuffered(int fd,char *buf,int len)
if (FD_ISSET(fd, &w_fds)) {
int ret, n = len-total;
ret = write(fd,buf+total,n?n:1);
ret = write(fd,buf+total,n);
if (ret == -1 && errno == EINTR) {
continue;
}
if (ret == -1 &&
(errno == EWOULDBLOCK || errno == EAGAIN)) {
msleep(1);
continue;
}
if (ret <= 0) {
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
rprintf(FERROR,
"error writing %d unbuffered bytes"
" - exiting: %s\n", len,
strerror(errno));
exit_cleanup(RERR_STREAMIO);
}
/* Sleep after writing to limit I/O bandwidth */
if (bwlimit)
{
tv.tv_sec = 0;
tv.tv_usec = ret * 1000 / bwlimit;
while (tv.tv_usec > 1000000)
{
tv.tv_sec++;
tv.tv_usec -= 1000000;
}
select(0, NULL, NULL, NULL, &tv);
}
total += ret;
if (io_timeout)
@@ -426,6 +509,9 @@ static void mplex_write(int fd, enum logcode code, char *buf, int len)
void io_flush(void)
{
int fd = multiplex_out_fd;
err_list_push();
if (!io_buffer_count || no_flush) return;
if (io_multiplexing_out) {
@@ -436,6 +522,8 @@ void io_flush(void)
io_buffer_count = 0;
}
/* XXX: fd is ignored, which seems a little strange. */
void io_end_buffering(int fd)
{
io_flush();
@@ -449,6 +537,8 @@ static void writefd(int fd,char *buf,int len)
{
stats.total_written += len;
err_list_push();
if (!io_buffer || fd != multiplex_out_fd) {
writefd_unbuffered(fd, buf, len);
return;
@@ -475,6 +565,11 @@ void write_int(int f,int32 x)
writefd(f,b,4);
}
/*
* Note: int64 may actually be a 32-bit type if ./configure couldn't find any
* 64-bit types on this platform.
*/
void write_longint(int f, int64 x)
{
extern int remote_version;
@@ -509,10 +604,10 @@ void write_byte(int f,unsigned char c)
write_buf(f,(char *)&c,1);
}
int read_line(int f, char *buf, int maxlen)
{
eof_error = 0;
while (maxlen) {
buf[0] = 0;
read_buf(f, buf, 1);
@@ -531,8 +626,6 @@ int read_line(int f, char *buf, int maxlen)
return 0;
}
eof_error = 1;
return 1;
}
@@ -544,7 +637,7 @@ void io_printf(int fd, const char *format, ...)
int len;
va_start(ap, format);
len = vslprintf(buf, sizeof(buf), format, ap);
len = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len < 0) exit_cleanup(RERR_STREAMIO);
@@ -581,21 +674,9 @@ int io_multiplex_write(enum logcode code, char *buf, int len)
return 1;
}
/* write a message to the special error fd */
int io_error_write(int f, enum logcode code, char *buf, int len)
{
if (f == -1) return 0;
mplex_write(f, code, buf, len);
return 1;
}
/* stop output multiplexing */
void io_multiplexing_close(void)
{
io_multiplexing_out = 0;
}
void io_close_input(int fd)
{
buffer_f_in = -1;
}

View File

@@ -95,21 +95,6 @@
}
#endif
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#if WORDS_BIGENDIAN
slprintf(buf, 18, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
slprintf(buf, 18, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif
#ifndef HAVE_STRLCPY
/* like strncpy but does not 0 fill the buffer and always null
@@ -118,6 +103,7 @@
{
size_t len = strlen(s);
size_t ret = len;
if (bufsize <= 0) return 0;
if (len >= bufsize) len = bufsize-1;
memcpy(d, s, len);
d[len] = 0;
@@ -146,7 +132,23 @@
}
#endif
#ifndef HAVE_INET_ATON
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#if WORDS_BIGENDIAN
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif
#ifdef REPLACE_INET_ATON
int inet_aton(const char *cp, struct in_addr *inp)
{
unsigned int a1, a2, a3, a4;
@@ -154,12 +156,12 @@
if (strcmp(cp, "255.255.255.255") == 0) {
inp->s_addr = (unsigned) -1;
return 1;
return 0;
}
if (sscanf(cp, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4 ||
a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255) {
return 1;
return 0;
}
ret = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;

View File

@@ -1,751 +0,0 @@
#include "../rsync.h"
#ifndef HAVE_GETOPT_LONG
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
Free Software Foundation, Inc.
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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#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 defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This is for other GNU distributions with internationalized messages.
The GNU C Library itself does not yet support such messages. */
#if HAVE_LIBINTL_H
# include <libintl.h>
#else
# define gettext(msgid) (msgid)
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
#if !defined (__STDC__) || !__STDC__
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
#endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Initialize the internal data when the first call is made. */
static const char *
_getopt_initialize (optstring)
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (posixly_correct != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
optarg = NULL;
if (optind == 0)
optstring = _getopt_initialize (optstring);
if (nextchar == NULL || *nextchar == '\0')
{
/* Advance to the next ARGV-element. */
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
/* The special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
/* Decode the current option-ARGV-element. */
/* Check whether the ARGV-element is a long option.
If long_only and the ARGV-element has the form "-f", where f is
a valid short option, don't consider it an abbreviated form of
a long option that starts with f. Otherwise there would be no
way to give the -f short option.
On the other hand, if there's a long option "fubar" and
the ARGV-element is "-fu", do consider that an abbreviation of
the long option, just like "--fu", and not "-f" with arg "u".
This distinction seems to be the most useful approach. */
if (longopts != NULL
&& (argv[optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
char *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
/* Test all long options for either exact match
or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
if (nameend - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, gettext ("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
else
{
if (opterr)
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
gettext ("%s: option `--%s' doesn't allow an argument\n"),
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
gettext ("%s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], pfound->name);
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr,
gettext ("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, gettext ("%s: unrecognized option `--%s'\n"),
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, gettext ("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next short option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
if (posixly_correct)
/* 1003.2 specifies the format of this message. */
fprintf (stderr, gettext ("%s: illegal option -- %c\n"),
argv[0], c);
else
fprintf (stderr, gettext ("%s: invalid option -- %c\n"),
argv[0], c);
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = NULL;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr,
gettext ("%s: option requires an argument -- %c\n"),
argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
#else /* HAVE_GETOPT_LONG */
void getopt_dummy(void) {}
#endif

View File

@@ -1,129 +0,0 @@
/* Declarations for getopt.
Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if defined (__STDC__) && __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if defined (__STDC__) && __STDC__
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

184
lib/inet_ntop.c Normal file
View File

@@ -0,0 +1,184 @@
/*
* Copyright (C) 1996-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "rsync.h"
#define NS_INT16SZ 2
#define NS_IN6ADDRSZ 16
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static const char *inet_ntop4(const unsigned char *src, char *dst,
size_t size);
#ifdef AF_INET6
static const char *inet_ntop6(const unsigned char *src, char *dst,
size_t size);
#endif
/* char *
* isc_net_ntop(af, src, dst, size)
* convert a network format address to presentation format.
* return:
* pointer to presentation format address (`dst'), or NULL (see errno).
* author:
* Paul Vixie, 1996.
*/
const char *
inet_ntop(int af, const void *src, char *dst, size_t size)
{
switch (af) {
case AF_INET:
return (inet_ntop4(src, dst, size));
#ifdef AF_INET6
case AF_INET6:
return (inet_ntop6(src, dst, size));
#endif
default:
errno = EAFNOSUPPORT;
return (NULL);
}
/* NOTREACHED */
}
/* const char *
* inet_ntop4(src, dst, size)
* format an IPv4 address
* return:
* `dst' (as a const)
* notes:
* (1) uses no statics
* (2) takes a unsigned char* not an in_addr as input
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop4(const unsigned char *src, char *dst, size_t size)
{
static const char *fmt = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
{
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
}
/* const char *
* isc_inet_ntop6(src, dst, size)
* convert IPv6 binary address into presentation (printable) format
* author:
* Paul Vixie, 1996.
*/
#ifdef AF_INET6
static const char *
inet_ntop6(const unsigned char *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct { int base, len; } best, cur;
unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
int i;
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, '\0', sizeof words);
for (i = 0; i < NS_IN6ADDRSZ; i++)
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
} else {
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
/*
* Format the result.
*/
tp = tmp;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len)) {
if (i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp,
sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
tp += sprintf(tp, "%x", words[i]);
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) ==
(NS_IN6ADDRSZ / NS_INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
}
#endif /* AF_INET6 */

210
lib/inet_pton.c Normal file
View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 1996-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "rsync.h"
#define NS_INT16SZ 2
#define NS_INADDRSZ 4
#define NS_IN6ADDRSZ 16
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static int inet_pton4(const char *src, unsigned char *dst);
static int inet_pton6(const char *src, unsigned char *dst);
/* int
* isc_net_pton(af, src, dst)
* convert from presentation format (which usually means ASCII printable)
* to network format (which is usually some kind of binary format).
* return:
* 1 if the address was valid for the specified address family
* 0 if the address wasn't valid (`dst' is untouched in this case)
* -1 if some other error occurred (`dst' is untouched in this case, too)
* author:
* Paul Vixie, 1996.
*/
int
inet_pton(int af,
const char *src,
void *dst)
{
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
#ifdef INET6
case AF_INET6:
return (inet_pton6(src, dst));
#endif
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
}
/* int
* inet_pton4(src, dst)
* like inet_aton() but without all the hexadecimal and shorthand.
* return:
* 1 if `src' is a valid dotted quad, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton4(src, dst)
const char *src;
unsigned char *dst;
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[NS_INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr(digits, ch)) != NULL) {
unsigned int new = *tp * 10 + (pch - digits);
if (new > 255)
return (0);
*tp = new;
if (! saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return (0);
memcpy(dst, tmp, NS_INADDRSZ);
return (1);
}
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
#ifdef INET6
static int
inet_pton6(src, dst)
const char *src;
unsigned char *dst;
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned int val;
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
return (0);
colonp = tp;
continue;
}
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += NS_INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if (saw_xdigit) {
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
memcpy(dst, tmp, NS_IN6ADDRSZ);
return (1);
}
#endif

View File

@@ -28,30 +28,23 @@
static struct mdfour *m;
#define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z)))
#define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)))
#define H(X,Y,Z) ((X)^(Y)^(Z))
#ifdef LARGE_INT32
#define lshift(x,s) ((((x)<<(s))&0xFFFFFFFF) | (((x)>>(32-(s)))&0xFFFFFFFF))
#else
#define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s))))
#endif
#define MASK32 (0xffffffff)
#define ROUND1(a,b,c,d,k,s) a = lshift((uint32)(a + F(b,c,d) + X[k]), s)
#define ROUND2(a,b,c,d,k,s) a = lshift((uint32)(a + G(b,c,d) + X[k] + 0x5A827999),s)
#define ROUND3(a,b,c,d,k,s) a = lshift((uint32)(a + H(b,c,d) + X[k] + 0x6ED9EBA1),s)
#define F(X,Y,Z) ((((X)&(Y)) | ((~(X))&(Z))))
#define G(X,Y,Z) ((((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))))
#define H(X,Y,Z) (((X)^(Y)^(Z)))
#define lshift(x,s) (((((x)<<(s))&MASK32) | (((x)>>(32-(s)))&MASK32)))
#define ROUND1(a,b,c,d,k,s) a = lshift((a + F(b,c,d) + M[k])&MASK32, s)
#define ROUND2(a,b,c,d,k,s) a = lshift((a + G(b,c,d) + M[k] + 0x5A827999)&MASK32,s)
#define ROUND3(a,b,c,d,k,s) a = lshift((a + H(b,c,d) + M[k] + 0x6ED9EBA1)&MASK32,s)
/* this applies md4 to 64 byte chunks */
static void mdfour64(uint32 *M)
{
int j;
uint32 AA, BB, CC, DD;
uint32 X[16];
uint32 A,B,C,D;
for (j=0;j<16;j++)
X[j] = M[j];
A = m->A; B = m->B; C = m->C; D = m->D;
AA = A; BB = B; CC = C; DD = D;
@@ -64,6 +57,7 @@ static void mdfour64(uint32 *M)
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
@@ -82,15 +76,11 @@ static void mdfour64(uint32 *M)
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
A += AA; B += BB; C += CC; D += DD;
A += AA; B += BB;
C += CC; D += DD;
#ifdef LARGE_INT32
A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
#endif
for (j=0;j<16;j++)
X[j] = 0;
A &= MASK32; B &= MASK32;
C &= MASK32; D &= MASK32;
m->A = A; m->B = B; m->C = C; m->D = D;
}

61
lib/permstring.c Normal file
View File

@@ -0,0 +1,61 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 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.
*/
#include "rsync.h"
/**
* Produce a string representation of Unix mode bits like that used by
* ls(1).
*
* @param buf buffer of at least 11 characters
**/
void permstring(char *perms,
int mode)
{
static const char *perm_map = "rwxrwxrwx";
int i;
strcpy(perms, "----------");
for (i=0;i<9;i++) {
if (mode & (1<<i)) perms[9-i] = perm_map[8-i];
}
/* Handle setuid/sticky bits. You might think the indices are
* off by one, but remember there's a type char at the
* start. */
if (mode & S_ISUID)
perms[3] = (mode & S_IXUSR) ? 's' : 'S';
if (mode & S_ISGID)
perms[6] = (mode & S_IXGRP) ? 's' : 'S';
if (mode & S_ISVTX)
perms[9] = (mode & S_IXOTH) ? 't' : 'T';
if (S_ISLNK(mode)) perms[0] = 'l';
if (S_ISDIR(mode)) perms[0] = 'd';
if (S_ISBLK(mode)) perms[0] = 'b';
if (S_ISCHR(mode)) perms[0] = 'c';
if (S_ISSOCK(mode)) perms[0] = 's';
if (S_ISFIFO(mode)) perms[0] = 'p';
}

3
lib/permstring.h Normal file
View File

@@ -0,0 +1,3 @@
#define PERMSTRING_SIZE 11
void permstring(char *perms, int mode);

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,11 @@
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
and Karl Auer */
/* some fixes
*
* Copyright (C) 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
@@ -77,8 +82,6 @@ struct parm_struct
unsigned flags;
};
static BOOL bLoaded = False;
#ifndef GLOBAL_NAME
#define GLOBAL_NAME "global"
#endif
@@ -134,6 +137,7 @@ typedef struct
char *dont_compress;
int timeout;
int max_connections;
BOOL ignore_nonreadable;
} service;
@@ -162,9 +166,10 @@ static service sDefault =
NULL, /* include from */
"%o %h [%a] %m (%u) %f %l", /* log format */
NULL, /* refuse options */
"*.gz *.tgz *.zip *.z *.rpm *.deb", /* dont compress */
"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz", /* dont compress */
0, /* timeout */
0 /* max connections */
0, /* max connections */
False /* ignore nonreadable */
};
@@ -262,6 +267,7 @@ static struct parm_struct parm_table[] =
{"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},
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable, NULL, 0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
@@ -340,6 +346,7 @@ FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
@@ -377,14 +384,28 @@ static void init_service(service *pservice)
copy_service(pservice,&sDefault);
}
static void string_set(char **s, char *v)
/**
* Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
* be initialized when this is called, either to NULL or a malloc'd
* string.
*
* @fixme There is a small leak here in that sometimes the existing
* value will be dynamically allocated, and the old copy is lost.
* However, we can't always deallocate the old value, because in the
* case of sDefault, it points to a static string. It would be nice
* to have either all-strdup'd values, or to never need to free
* memory.
**/
static void string_set(char **s, const char *v)
{
if (!v) {
*s = NULL;
return;
}
*s = strdup(v);
if (!*s) exit_cleanup(RERR_MALLOC);
if (!*s)
exit_cleanup(RERR_MALLOC);
}
@@ -730,8 +751,6 @@ BOOL lp_load(char *pszFname, int globals_only)
iServiceIndex = -1;
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
bLoaded = True;
return (bRetval);
}

265
log.c
View File

@@ -1,5 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1998
/* -*- 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
@@ -17,18 +19,121 @@
*/
/*
logging and utility functions
Logging and utility functions.
tridge, May 1998
Mapping to human-readable messages added by Martin Pool
<mbp@samba.org>, Oct 2000.
*/
#include "rsync.h"
static char *logfname;
static FILE *logfile;
static int log_error_fd = -1;
int log_got_error=0;
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_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 , "partial transfer" },
{ 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 }
};
/*
* Map from rsync error code to name, or return NULL.
*/
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;
}
struct err_list {
struct err_list *next;
char *buf;
int len;
int written; /* how many bytes we have written so far */
};
static struct err_list *err_list_head;
static struct err_list *err_list_tail;
/* add an error message to the pending error list */
static void err_list_add(int code, char *buf, int len)
{
struct err_list *el;
el = (struct err_list *)malloc(sizeof(*el));
if (!el) exit_cleanup(RERR_MALLOC);
el->next = NULL;
el->buf = malloc(len+4);
if (!el->buf) exit_cleanup(RERR_MALLOC);
memcpy(el->buf+4, buf, len);
SIVAL(el->buf, 0, ((code+MPLEX_BASE)<<24) | len);
el->len = len+4;
el->written = 0;
if (err_list_tail) {
err_list_tail->next = el;
} else {
err_list_head = el;
}
err_list_tail = el;
}
/* try to push errors off the error list onto the wire */
void err_list_push(void)
{
if (log_error_fd == -1) return;
while (err_list_head) {
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 */
if (n == -1) break;
if (n > 0) {
el->written += n;
}
if (el->written == el->len) {
free(el->buf);
err_list_head = el->next;
if (!err_list_head) err_list_tail = NULL;
free(el);
}
}
}
static void logit(int priority, char *buf)
{
if (logfile) {
if (logfname) {
if (!logfile)
log_open();
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
@@ -37,12 +142,11 @@ static void logit(int priority, char *buf)
}
}
void log_open(void)
void log_init(void)
{
static int initialised;
int options = LOG_PID;
time_t t;
char *logf;
if (initialised) return;
initialised = 1;
@@ -54,13 +158,13 @@ void log_open(void)
localtime(&t);
/* optionally use a log file instead of syslog */
logf = lp_log_file();
if (logf && *logf) {
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logf, "a");
umask(old_umask);
return;
logfname = lp_log_file();
if (logfname) {
if (*logfname) {
log_open();
return;
}
logfname = NULL;
}
#ifdef LOG_NDELAY
@@ -78,11 +182,30 @@ void log_open(void)
#endif
}
void log_open()
{
if (logfname && !logfile) {
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
}
}
void log_close()
{
if (logfile) {
fclose(logfile);
logfile = NULL;
}
}
/* setup the error file descriptor - used when we are a server
that is receiving files */
void set_error_fd(int fd)
{
log_error_fd = fd;
set_nonblocking(log_error_fd);
}
/* this is the underlying (unformatted) rsync debugging function. Call
@@ -106,12 +229,14 @@ void rwrite(enum logcode code, char *buf, int len)
return;
}
/* first try to pass it off the our sibling */
if (am_server && io_error_write(log_error_fd, code, buf, len)) {
/* first try to pass it off to our sibling */
if (am_server && log_error_fd != -1) {
err_list_add(code, buf, len);
err_list_push();
return;
}
/* then try to pass it to the other end */
/* if that fails, try to pass it to the other end */
if (am_server && io_multiplex_write(code, buf, len)) {
return;
}
@@ -125,7 +250,7 @@ void rwrite(enum logcode code, char *buf, int len)
depth++;
log_open();
log_init();
logit(priority, buf);
depth--;
@@ -133,6 +258,7 @@ void rwrite(enum logcode code, char *buf, int len)
}
if (code == FERROR) {
log_got_error = 1;
f = stderr;
}
@@ -151,22 +277,86 @@ void rwrite(enum logcode code, char *buf, int len)
}
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
void rprintf(enum logcode code, const char *format, ...)
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
va_start(ap, format);
len = vslprintf(buf, sizeof(buf), format, ap);
len = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
/* Deal with buffer overruns. Instead of panicking, just
* truncate the resulting string. Note that some vsnprintf()s
* return -1 on truncation, e.g., glibc 2.0.6 and earlier. */
if (len > sizeof(buf)-1 || len < 0) {
const char ellipsis[] = "[...]";
/* Reset length, and zero-terminate the end of our buffer */
len = sizeof(buf)-1;
buf[len] = '\0';
/* Copy the ellipsis to the end of the string, but give
* us one extra character:
*
* v--- null byte at buf[sizeof(buf)-1]
* abcdefghij0
* -> abcd[...]00 <-- now two null bytes at end
*
* If the input format string has a trailing newline,
* we copy it into that extra null; if it doesn't, well,
* all we lose is one byte. */
strncpy(buf+len-sizeof(ellipsis), ellipsis, sizeof(ellipsis));
if (format[strlen(format)-1] == '\n') {
buf[len-1] = '\n';
}
}
rwrite(code, buf, len);
}
/* This is like rprintf, but it also tries to print some
* representation of the error code. Normally errcode = errno.
*
* Unlike rprintf, this always adds a newline and there should not be
* one in the format string.
*
* Note that since strerror might involve dynamically loading a
* message catalog we need to call it once before chroot-ing. */
void rsyserr(enum logcode code, int errcode, const char *format, ...)
{
va_list ap;
char buf[1024];
int len, sys_len;
char *sysmsg;
va_start(ap, format);
len = vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
sysmsg = strerror(errcode);
sys_len = strlen(sysmsg);
if (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++;
rwrite(code, buf, len);
}
void rflush(enum logcode code)
{
FILE *f = NULL;
@@ -226,18 +416,18 @@ static void log_formatted(enum logcode code,
case 'h': if (am_daemon) n = client_name(0); break;
case 'a': if (am_daemon) n = client_addr(0); break;
case 'l':
slprintf(buf2,sizeof(buf2),"%.0f",
snprintf(buf2,sizeof(buf2),"%.0f",
(double)file->length);
n = buf2;
break;
case 'p':
slprintf(buf2,sizeof(buf2),"%d",
snprintf(buf2,sizeof(buf2),"%d",
(int)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'f':
slprintf(buf2, sizeof(buf2), "%s/%s",
snprintf(buf2, sizeof(buf2), "%s/%s",
file->basedir?file->basedir:"",
f_name(file));
clean_fname(buf2);
@@ -256,7 +446,7 @@ static void log_formatted(enum logcode code,
b = stats.total_read -
initial_stats->total_read;
}
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
n = buf2;
break;
case 'c':
@@ -267,7 +457,7 @@ static void log_formatted(enum logcode code,
b = stats.total_read -
initial_stats->total_read;
}
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
n = buf2;
break;
}
@@ -321,7 +511,15 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
}
}
/* called when the transfer is interrupted for some reason */
/*
* Called when the transfer is interrupted for some reason.
*
* Code is one of the RERR_* codes from errcode.h, or terminating
* successfully.
*/
void log_exit(int code, const char *file, int line)
{
if (code == 0) {
@@ -331,11 +529,20 @@ void log_exit(int code, const char *file, int line)
(double)stats.total_read,
(double)stats.total_size);
} else {
rprintf(FLOG,"transfer interrupted (code %d) at %s(%d)\n",
code, file, line);
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);
}
}
/* log the incoming transfer of a file for interactive use, this
will be called at the end where the client was run

222
main.c
View File

@@ -1,6 +1,8 @@
/*
Copyright (C) Andrew Tridgell 1996
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) Paul Mackerras 1996
Copyright (C) 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
@@ -25,6 +27,25 @@ struct stats stats;
extern int verbose;
/****************************************************************************
wait for a process to exit, calling io_flush while waiting
****************************************************************************/
void wait_process(pid_t pid, int *status)
{
while (waitpid(pid, status, WNOHANG) == 0) {
msleep(20);
io_flush();
}
/* 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);
@@ -105,15 +126,19 @@ static void report(int f)
}
static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
/* Start the remote shell. cmd may be NULL to use the default. */
static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
{
char *args[100];
int i,argc=0, ret;
int i,argc=0;
pid_t ret;
char *tok,*dir=NULL;
extern int local_server;
extern char *rsync_path;
extern int blocking_io;
extern int read_batch;
if (!local_server) {
if (!read_batch && !local_server) { /* dw -- added read_batch */
if (!cmd)
cmd = getenv(RSYNC_RSH_ENV);
if (!cmd)
@@ -144,6 +169,9 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f
args[argc++] = rsync_path;
server_options(args,&argc);
if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
}
args[argc++] = ".";
@@ -161,6 +189,8 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f
}
if (local_server) {
if (read_batch)
create_flist_from_batch();
ret = local_child(argc, args, f_in, f_out);
} else {
ret = piped_child(args,f_in,f_out);
@@ -236,6 +266,7 @@ 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());
@@ -267,7 +298,12 @@ 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 */
read_int(f_in);
}
io_flush();
exit_cleanup(0);
}
@@ -283,6 +319,7 @@ 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);
@@ -318,15 +355,21 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
set_error_fd(error_pipe[1]);
recv_files(f_in,flist,local_name,recv_pipe[1]);
io_flush();
report(f_in);
write_int(recv_pipe[1],1);
close(recv_pipe[1]);
io_flush();
_exit(0);
/* 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! */
while (msleep(20))
;
}
close(recv_pipe[1]);
close(error_pipe[1]);
io_close_input(f_in);
if (f_in != f_out) close(f_in);
io_start_buffering(f_out);
@@ -335,7 +378,15 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
generate_files(f_out,flist,local_name,recv_pipe[0]);
read_int(recv_pipe[0]);
close(recv_pipe[0]);
if (remote_version >= 24) {
/* send a final goodbye message */
write_int(f_out, -1);
}
io_flush();
kill(pid, SIGUSR2);
wait_process(pid, &status);
return status;
}
@@ -352,6 +403,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
extern int am_daemon;
extern int module_id;
extern int am_sender;
extern int read_batch; /* dw */
extern struct file_list *batch_flist; /* dw */
if (verbose > 2)
rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
@@ -377,7 +430,10 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
if (delete_mode && !delete_excluded)
recv_exclude_list(f_in);
flist = recv_file_list(f_in);
if (read_batch) /* dw */
flist = batch_flist;
else
flist = recv_file_list(f_in);
if (!flist) {
rprintf(FERROR,"server_recv: recv_file_list error\n");
exit_cleanup(RERR_FILESELECT);
@@ -401,16 +457,22 @@ 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; /* dw */
setup_protocol(f_out, f_in);
set_nonblocking(f_in);
set_nonblocking(f_out);
if (remote_version >= 23)
io_start_multiplex_out(f_out);
if (am_sender) {
recv_exclude_list(f_in);
if (cvs_exclude)
if (!read_batch) { /* dw */
recv_exclude_list(f_in);
if (cvs_exclude)
add_cvs_excludes();
}
do_server_sender(f_in, f_out, argc, argv);
} else {
do_server_recv(f_in, f_out, argc, argv);
@@ -418,14 +480,29 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
exit_cleanup(0);
}
int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
/*
* This is called once the connection has been negotiated. It is used
* for rsyncd, remote-shell, and local connections.
*/
int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
{
struct file_list *flist;
int status = 0, status2 = 0;
char *local_name = NULL;
extern int am_sender;
extern int list_only;
extern int remote_version;
extern pid_t cleanup_child_pid;
extern int write_batch; /* dw */
extern int read_batch; /* dw */
extern struct file_list *batch_flist; /* dw */
cleanup_child_pid = pid;
if (read_batch)
flist = batch_flist; /* dw */
set_nonblocking(f_in);
set_nonblocking(f_out);
setup_protocol(f_out,f_in);
@@ -440,14 +517,19 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
add_cvs_excludes();
if (delete_mode && !delete_excluded)
send_exclude_list(f_out);
flist = send_file_list(f_out,argc,argv);
if (!read_batch) /* dw -- don't write to pipe */
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 */
read_int(f_in);
}
if (pid != -1) {
if (verbose > 3)
rprintf(FINFO,"client_run waiting on %d\n",pid);
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
io_flush();
wait_process(pid, &status);
}
@@ -455,13 +537,19 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
exit_cleanup(status);
}
if (argc == 0) list_only = 1;
if (argc == 0) {
extern int list_only;
list_only = 1;
}
send_exclude_list(f_out);
if (!write_batch) /* dw */
send_exclude_list(f_out);
flist = recv_file_list(f_in);
if (!flist || flist->count == 0) {
rprintf(FINFO,"client: nothing to do\n");
rprintf(FINFO, "client: nothing to do: "
"perhaps you need to specify some filenames or "
"the --recursive option?\n");
exit_cleanup(0);
}
@@ -471,12 +559,12 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
if (pid != -1) {
if (verbose > 3)
rprintf(FINFO,"client_run2 waiting on %d\n",pid);
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
io_flush();
wait_process(pid, &status);
}
return status | status2;
return MAX(status, status2);
}
static char *find_colon(char *s)
@@ -494,18 +582,49 @@ static char *find_colon(char *s)
return p;
}
static int copy_argv (char *argv[])
{
int i;
for (i = 0; argv[i]; i++) {
if (!(argv[i] = strdup(argv[i]))) {
rprintf (FERROR, "out of memory at %s(%d)\n",
__FILE__, __LINE__);
return RERR_MALLOC;
}
}
return 0;
}
/*
* Start a client for either type of remote connection. Work out
* whether the arguments request a remote shell or rsyncd connection,
* and call the appropriate connection function, then run_client.
*/
static int start_client(int argc, char *argv[])
{
char *p;
char *shell_machine = NULL;
char *shell_path = NULL;
char *shell_user = NULL;
int pid, ret;
int ret;
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 whole_file;
extern int read_batch;
int rc;
/* Don't clobber argv[] so that ps(1) can still show the right
command line. */
if ((rc = copy_argv (argv)))
return rc;
if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
char *host, *path;
@@ -526,7 +645,8 @@ static int start_client(int argc, char *argv[])
return start_socket_client(host, path, argc-1, argv+1);
}
p = find_colon(argv[0]);
if (!read_batch) { /* dw */
p = find_colon(argv[0]);
if (p) {
if (p[1] == ':') {
@@ -551,6 +671,8 @@ static int start_client(int argc, char *argv[])
p = find_colon(argv[argc-1]);
if (!p) {
local_server = 1;
/* disable "rsync algorithm" when both sides local */
whole_file = 1;
} else if (p[1] == ':') {
*p = 0;
return start_socket_client(argv[argc-1], p+2, argc-1, argv);
@@ -571,7 +693,12 @@ static int start_client(int argc, char *argv[])
}
argc--;
}
} else {
am_sender = 1; /* dw */
local_server = 1; /* dw */
shell_path = argv[argc-1]; /* dw */
}
if (shell_machine) {
p = strchr(shell_machine,'@');
if (p) {
@@ -593,6 +720,11 @@ static int start_client(int argc, char *argv[])
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
if (argc == 0 && !am_sender) {
extern int list_only;
list_only = 1;
}
pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
@@ -609,6 +741,18 @@ static RETSIGTYPE sigusr1_handler(int val) {
exit_cleanup(RERR_SIGNAL);
}
static RETSIGTYPE sigusr2_handler(int val) {
extern int log_got_error;
if (log_got_error) _exit(RERR_PARTIAL);
_exit(0);
}
static RETSIGTYPE sigchld_handler(int val) {
#ifdef WNOHANG
while (waitpid(-1, NULL, WNOHANG) > 0) ;
#endif
}
int main(int argc,char *argv[])
{
extern int am_root;
@@ -616,8 +760,17 @@ int main(int argc,char *argv[])
extern int dry_run;
extern int am_daemon;
extern int am_server;
int ret;
extern int read_batch; /* dw */
extern int write_batch; /* dw */
extern char *batch_ext; /* dw */
int orig_argc; /* dw */
orig_argc = argc; /* dw */
signal(SIGUSR1, sigusr1_handler);
signal(SIGUSR2, sigusr2_handler);
signal(SIGCHLD, sigchld_handler);
starttime = time(NULL);
am_root = (getuid() == 0);
@@ -633,15 +786,13 @@ int main(int argc,char *argv[])
carried across */
orig_umask = (int)umask(0);
if (!parse_arguments(argc, argv, 1)) {
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
/* FIXME: We ought to call the same error-handling
* code here, rather than relying on getopt. */
option_error();
exit_cleanup(RERR_SYNTAX);
}
argc -= optind;
argv += optind;
optind = 0;
signal(SIGCHLD,SIG_IGN);
signal(SIGINT,SIGNAL_CAST sig_int);
signal(SIGPIPE,SIGNAL_CAST sig_int);
signal(SIGHUP,SIGNAL_CAST sig_int);
@@ -653,6 +804,15 @@ int main(int argc,char *argv[])
that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL,0);
if (write_batch) { /* dw */
create_batch_file_ext();
write_batch_argvs_file(orig_argc, argc, argv);
}
if (read_batch) { /* dw */
set_batch_file_ext(batch_ext);
}
if (am_daemon) {
return daemon_main();
}
@@ -673,9 +833,13 @@ int main(int argc,char *argv[])
#endif
if (am_server) {
set_nonblocking(STDIN_FILENO);
set_nonblocking(STDOUT_FILENO);
start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
}
return start_client(argc, argv);
ret = start_client(argc, argv);
exit_cleanup(ret);
return ret;
}

View File

@@ -260,6 +260,7 @@ static void hash_search(int f,struct sum_struct *s,
void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
{
char file_sum[MD4_SUM_LENGTH];
extern int write_batch; /* dw */
last_match = 0;
false_alarms = 0;
@@ -295,6 +296,8 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
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) {

570
options.c
View File

@@ -1,5 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1998
/* -*- 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
@@ -16,10 +18,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* options parsing code */
#include "rsync.h"
#include "popt.h"
int make_backups = 0;
int whole_file = 0;
@@ -52,7 +52,7 @@ int io_error = 0;
int read_only = 0;
int module_id = -1;
int am_server = 0;
int am_sender=0;
int am_sender = 0;
int recurse = 0;
int am_daemon=0;
int do_stats=0;
@@ -62,9 +62,23 @@ int safe_symlinks=0;
int copy_unsafe_links=0;
int block_size=BLOCK_SIZE;
int size_only=0;
int bwlimit=0;
int delete_after=0;
int only_existing=0;
int max_delete=0;
int ignore_errors=0;
#ifdef _WIN32
int modify_window=2;
#else
int modify_window=0;
#endif
int blocking_io=0;
/** Global options set from command line. **/
struct global_opts global_opts;
int read_batch=0; /* dw */
int write_batch=0; /* dw */
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
@@ -73,7 +87,7 @@ char *config_file = RSYNCD_CONF;
char *shell_cmd = NULL;
char *log_format = NULL;
char *password_file = NULL;
char *rsync_path = RSYNC_NAME;
char *rsync_path = RSYNC_PATH;
char *backup_dir = NULL;
int rsync_port = RSYNC_PORT;
@@ -82,12 +96,58 @@ int quiet = 0;
int always_checksum = 0;
int list_only = 0;
struct in_addr socket_address = {INADDR_ANY};
char *batch_ext = NULL;
static int modify_window_set;
/** Local address to bind. As a character string because it's
* interpreted by the IPv6 layer: should be a numeric IP4 or ip6
* address, or a hostname. **/
char *bind_address;
static void print_rsync_version(int f)
{
char const *got_socketpair = "no ";
char const *hardlinks = "no ";
char const *links = "no ";
char const *ipv6 = "no ";
#ifdef HAVE_SOCKETPAIR
got_socketpair = "";
#endif
#if SUPPORT_HARD_LINKS
hardlinks = "";
#endif
#if SUPPORT_LINKS
links = "";
#endif
#if INET6
ipv6 = "";
#endif
rprintf(f, "%s version %s protocol version %d\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
rprintf(f,
"Copyright (C) 1996-2001 by Andrew Tridgell and others\n");
rprintf(f, "<http://rsync.samba.org/>\n");
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
"%shard links, %ssymlinks, batchfiles, %sIPv6\n\n",
(int) (sizeof(OFF_T) * 8),
got_socketpair, hardlinks, links, ipv6);
#ifdef NO_INT64
rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
#endif
}
void usage(enum logcode F)
{
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
VERSION);
print_rsync_version(F);
rprintf(F,"rsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
@@ -133,6 +193,7 @@ void usage(enum logcode F)
rprintf(F," --delete delete files that don't exist on the sending side\n");
rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
rprintf(F," --delete-after delete after transferring, not before\n");
rprintf(F," --ignore-errors delete even if there are IO errors\n");
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
rprintf(F," --partial keep partially transferred files\n");
rprintf(F," --force force deletion of directories even if not empty\n");
@@ -140,6 +201,7 @@ void usage(enum logcode F)
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
rprintf(F," --size-only only use file size when determining if a file should be transferred\n");
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," -P equivalent to --partial --progress\n");
@@ -150,105 +212,134 @@ void usage(enum logcode F)
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," --address bind to the specified address\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," --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," -f --read-batch=EXT read batch file\n");
rprintf(F," -F --write-batch write batch file\n");
rprintf(F," -h, --help show this help screen\n");
#ifdef INET6
rprintf(F," -4 prefer IPv4\n");
rprintf(F," -6 prefer IPv6\n");
#endif
rprintf(F,"\n");
rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
rprintf(F,"See http://rsync.samba.org/ for updates and bug reports\n");
rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
}
enum {OPT_VERSION, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
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_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR};
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
OPT_MODIFY_WINDOW};
static char *short_options = "oblLWHpguDCtcahvqrRIxnSe:B:T:zP";
static struct option long_options[] = {
{"version", 0, 0, OPT_VERSION},
{"server", 0, 0, OPT_SERVER},
{"sender", 0, 0, OPT_SENDER},
{"existing", 0, 0, OPT_EXISTING},
{"delete", 0, 0, OPT_DELETE},
{"delete-excluded", 0, 0, OPT_DELETE_EXCLUDED},
{"force", 0, 0, OPT_FORCE},
{"numeric-ids", 0, 0, OPT_NUMERIC_IDS},
{"exclude", 1, 0, OPT_EXCLUDE},
{"exclude-from",1, 0, OPT_EXCLUDE_FROM},
{"include", 1, 0, OPT_INCLUDE},
{"include-from",1, 0, OPT_INCLUDE_FROM},
{"rsync-path", 1, 0, OPT_RSYNC_PATH},
{"password-file", 1, 0, OPT_PASSWORD_FILE},
{"one-file-system",0, 0, 'x'},
{"ignore-times",0, 0, 'I'},
{"size-only", 0, 0, OPT_SIZE_ONLY},
{"help", 0, 0, 'h'},
{"dry-run", 0, 0, 'n'},
{"sparse", 0, 0, 'S'},
{"cvs-exclude", 0, 0, 'C'},
{"archive", 0, 0, 'a'},
{"checksum", 0, 0, 'c'},
{"backup", 0, 0, 'b'},
{"update", 0, 0, 'u'},
{"verbose", 0, 0, 'v'},
{"quiet", 0, 0, 'q'},
{"recursive", 0, 0, 'r'},
{"relative", 0, 0, 'R'},
{"devices", 0, 0, 'D'},
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"copy-links", 0, 0, 'L'},
{"copy-unsafe-links", 0, 0, OPT_COPY_UNSAFE_LINKS},
{"safe-links", 0, 0, OPT_SAFE_LINKS},
{"whole-file", 0, 0, 'W'},
{"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
{"group", 0, 0, 'g'},
{"times", 0, 0, 't'},
{"rsh", 1, 0, 'e'},
{"suffix", 1, 0, OPT_SUFFIX},
{"block-size", 1, 0, 'B'},
{"timeout", 1, 0, OPT_TIMEOUT},
{"temp-dir", 1, 0, 'T'},
{"compare-dest", 1, 0, OPT_COMPARE_DEST},
{"compress", 0, 0, 'z'},
{"daemon", 0, 0, OPT_DAEMON},
{"stats", 0, 0, OPT_STATS},
{"progress", 0, 0, OPT_PROGRESS},
{"partial", 0, 0, OPT_PARTIAL},
{"delete-after",0, 0, OPT_DELETE_AFTER},
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{"log-format", 1, 0, OPT_LOG_FORMAT},
{"address", 1, 0, OPT_ADDRESS},
{"max-delete", 1, 0, OPT_MAX_DELETE},
{"backup-dir", 1, 0, OPT_BACKUP_DIR},
{0,0,0,0}};
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"version", 0, POPT_ARG_NONE, 0, OPT_VERSION},
{"suffix", 0, POPT_ARG_STRING, &backup_suffix},
{"rsync-path", 0, POPT_ARG_STRING, &rsync_path},
{"password-file", 0, POPT_ARG_STRING, &password_file},
{"ignore-times", 'I', POPT_ARG_NONE, &ignore_times},
{"size-only", 0, POPT_ARG_NONE, &size_only},
{"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW},
{"one-file-system", 'x', POPT_ARG_NONE, &one_file_system},
{"delete", 0, POPT_ARG_NONE, &delete_mode},
{"existing", 0, POPT_ARG_NONE, &only_existing},
{"delete-after", 0, POPT_ARG_NONE, &delete_after},
{"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED},
{"force", 0, POPT_ARG_NONE, &force_delete},
{"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids},
{"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE},
{"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE},
{"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM},
{"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM},
{"safe-links", 0, POPT_ARG_NONE, &safe_symlinks},
{"help", 'h', POPT_ARG_NONE, 0, 'h'},
{"backup", 'b', POPT_ARG_NONE, &make_backups},
{"dry-run", 'n', POPT_ARG_NONE, &dry_run},
{"sparse", 'S', POPT_ARG_NONE, &sparse_files},
{"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude},
{"update", 'u', POPT_ARG_NONE, &update_only},
{"links", 'l', POPT_ARG_NONE, &preserve_links},
{"copy-links", 'L', POPT_ARG_NONE, &copy_links},
{"whole", 'W', POPT_ARG_NONE, &whole_file},
{"copy-unsafe-links", 0, POPT_ARG_NONE, &copy_unsafe_links},
{"perms", 'p', POPT_ARG_NONE, &preserve_perms},
{"owner", 'o', POPT_ARG_NONE, &preserve_uid},
{"group", 'g', POPT_ARG_NONE, &preserve_gid},
{"devices", 'D', POPT_ARG_NONE, &preserve_devices},
{"times", 't', POPT_ARG_NONE, &preserve_times},
{"checksum", 'c', POPT_ARG_NONE, &always_checksum},
{"verbose", 'v', POPT_ARG_NONE, 0, 'v'},
{"quiet", 'q', POPT_ARG_NONE, 0, 'q'},
{"archive", 'a', POPT_ARG_NONE, 0, 'a'},
{"server", 0, POPT_ARG_NONE, &am_server},
{"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER},
{"recursive", 'r', POPT_ARG_NONE, &recurse},
{"relative", 'R', POPT_ARG_NONE, &relative_paths},
{"rsh", 'e', POPT_ARG_STRING, &shell_cmd},
{"block-size", 'B', POPT_ARG_INT, &block_size},
{"max-delete", 0, POPT_ARG_INT, &max_delete},
{"timeout", 0, POPT_ARG_INT, &io_timeout},
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir},
{"compare-dest", 0, POPT_ARG_STRING, &compare_dest},
/* TODO: Should this take an optional int giving the compression level? */
{"compress", 'z', POPT_ARG_NONE, &do_compression},
{"daemon", 0, POPT_ARG_NONE, &am_daemon},
{"no-detach", 0, POPT_ARG_NONE, &global_opts.no_detach},
{"stats", 0, POPT_ARG_NONE, &do_stats},
{"progress", 0, POPT_ARG_NONE, &do_progress},
{"partial", 0, POPT_ARG_NONE, &keep_partial},
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors},
{"blocking-io", 0, POPT_ARG_NONE, &blocking_io},
{0, 'P', POPT_ARG_NONE, 0, 'P'},
{"config", 0, POPT_ARG_STRING, &config_file},
{"port", 0, POPT_ARG_INT, &rsync_port},
{"log-format", 0, POPT_ARG_STRING, &log_format},
{"bwlimit", 0, POPT_ARG_INT, &bwlimit},
{"address", 0, POPT_ARG_STRING, &bind_address, 0},
{"backup-dir", 0, POPT_ARG_STRING, &backup_dir},
{"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links},
{"read-batch", 'f', POPT_ARG_STRING, &batch_ext, 'f'},
{"write-batch", 'F', POPT_ARG_NONE, &write_batch, 0},
#ifdef INET6
{0, '4', POPT_ARG_VAL, &global_opts.af_hint, AF_INET },
{0, '6', POPT_ARG_VAL, &global_opts.af_hint, AF_INET6 },
#endif
{0,0,0,0}
};
static char err_buf[100];
/* We store the option error message, if any, so that we can log the
connection attempt (which requires parsing the options), and then
show the error later on. */
void option_error(void)
{
if (err_buf[0]) {
rprintf(FLOG,"%s", err_buf);
rprintf(FERROR,"%s", err_buf);
rprintf(FLOG, "%s", err_buf);
rprintf(FERROR, "%s: %s", RSYNC_NAME, err_buf);
} else {
rprintf(FLOG,"Error parsing options - unsupported option?\n");
rprintf(FERROR,"Error parsing options - unsupported option?\n");
rprintf (FERROR, "Error parsing options: "
"option may be supported on client but not on server?\n");
rprintf (FERROR, RSYNC_NAME ": Error parsing options: "
"option may be supported on client but not on server?\n");
}
exit_cleanup(RERR_UNSUPPORTED);
}
/* check to see if we should refuse this option */
@@ -258,19 +349,19 @@ static int check_refuse_options(char *ref, int opt)
char *p;
const char *name;
for (i=0; long_options[i].name; i++) {
for (i=0; long_options[i].longName; i++) {
if (long_options[i].val == opt) break;
}
if (!long_options[i].name) return 0;
if (!long_options[i].longName) return 0;
name = long_options[i].name;
name = long_options[i].longName;
len = strlen(name);
while ((p = strstr(ref,name))) {
if ((p==ref || p[-1]==' ') &&
(p[len] == ' ' || p[len] == 0)) {
slprintf(err_buf,sizeof(err_buf),
snprintf(err_buf,sizeof(err_buf),
"The '%s' option is not supported by this server\n", name);
return 1;
}
@@ -280,168 +371,93 @@ static int check_refuse_options(char *ref, int opt)
}
int parse_arguments(int argc, char *argv[], int frommain)
static int count_args(char const **argv)
{
int i = 0;
while (argv[i] != NULL)
i++;
return i;
}
/* Process command line arguments. Called on both local and remote.
* Returns if all options are OK, otherwise fills in err_buf and
* returns 0. */
int parse_arguments(int *argc, const char ***argv, int frommain)
{
int opt;
int option_index;
char *ref = lp_refuse_options(module_id);
poptContext pc;
while ((opt = getopt_long(argc, argv,
short_options, long_options, &option_index))
!= -1) {
/* 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);
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. */
switch (opt) {
case OPT_VERSION:
rprintf(FINFO,"rsync version %s protocol version %d\n\n",
VERSION,PROTOCOL_VERSION);
rprintf(FINFO,"Written by Andrew Tridgell and Paul Mackerras\n");
print_rsync_version(FINFO);
exit_cleanup(0);
case OPT_SUFFIX:
backup_suffix = optarg;
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. */
modify_window_set = 1;
break;
case OPT_RSYNC_PATH:
rsync_path = optarg;
break;
case OPT_PASSWORD_FILE:
password_file =optarg;
break;
case 'I':
ignore_times = 1;
break;
case OPT_SIZE_ONLY:
size_only = 1;
break;
case 'x':
one_file_system=1;
break;
case OPT_DELETE:
delete_mode = 1;
break;
case OPT_EXISTING:
only_existing = 1;
break;
case OPT_DELETE_AFTER:
delete_after = 1;
break;
case OPT_DELETE_EXCLUDED:
delete_excluded = 1;
delete_mode = 1;
break;
case OPT_FORCE:
force_delete = 1;
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_EXCLUDE:
add_exclude(optarg, 0);
add_exclude(poptGetOptArg(pc), 0);
break;
case OPT_INCLUDE:
add_exclude(optarg, 1);
add_exclude(poptGetOptArg(pc), 1);
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(optarg,1, 0);
add_exclude_file(poptGetOptArg(pc), 1, 0);
break;
case OPT_INCLUDE_FROM:
add_exclude_file(optarg,1, 1);
break;
case OPT_COPY_UNSAFE_LINKS:
copy_unsafe_links=1;
break;
case OPT_SAFE_LINKS:
safe_symlinks=1;
add_exclude_file(poptGetOptArg(pc), 1, 1);
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case 'b':
make_backups=1;
break;
case 'n':
dry_run=1;
break;
case 'S':
sparse_files=1;
break;
case 'C':
cvs_exclude=1;
break;
case 'u':
update_only=1;
break;
case 'l':
preserve_links=1;
break;
case 'L':
copy_links=1;
break;
case 'W':
whole_file=1;
break;
case 'H':
#if SUPPORT_HARD_LINKS
preserve_hard_links=1;
#else
slprintf(err_buf,sizeof(err_buf),"hard links are not supported on this server\n");
#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",
am_server ? "server" : "client");
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
return 0;
#endif
break;
case 'p':
preserve_perms=1;
break;
case 'o':
preserve_uid=1;
break;
case 'g':
preserve_gid=1;
break;
case 'D':
preserve_devices=1;
break;
case 't':
preserve_times=1;
break;
case 'c':
always_checksum=1;
#endif /* SUPPORT_HARD_LINKS */
break;
case 'v':
@@ -464,10 +480,6 @@ int parse_arguments(int argc, char *argv[], int frommain)
preserve_devices=1;
break;
case OPT_SERVER:
am_server = 1;
break;
case OPT_SENDER:
if (!am_server) {
usage(FERROR);
@@ -476,99 +488,41 @@ int parse_arguments(int argc, char *argv[], int frommain)
am_sender = 1;
break;
case 'r':
recurse = 1;
break;
case 'R':
relative_paths = 1;
break;
case 'e':
shell_cmd = optarg;
break;
case 'B':
block_size = atoi(optarg);
break;
case OPT_MAX_DELETE:
max_delete = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case 'T':
tmpdir = optarg;
break;
case OPT_COMPARE_DEST:
compare_dest = optarg;
break;
case 'z':
do_compression = 1;
break;
case OPT_DAEMON:
am_daemon = 1;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_PROGRESS:
do_progress = 1;
break;
case OPT_PARTIAL:
keep_partial = 1;
break;
case 'P':
do_progress = 1;
keep_partial = 1;
break;
case OPT_CONFIG:
config_file = optarg;
break;
case OPT_PORT:
rsync_port = atoi(optarg);
break;
case OPT_LOG_FORMAT:
log_format = optarg;
break;
case OPT_ADDRESS:
{
struct in_addr *ia;
if ((ia = ip_address(optarg))) {
socket_address = *ia;
}
}
break;
case OPT_BACKUP_DIR:
backup_dir = optarg;
case 'f':
/* The filename is stored for us by popt */
read_batch = 1;
break;
default:
slprintf(err_buf,sizeof(err_buf),"unrecognised option\n");
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;
}
}
*argv = poptGetArgs(pc);
if (*argv)
*argc = count_args(*argv);
else
*argc = 0;
return 1;
}
/* need to pass all the valid options from the client to the server */
/* Construct a filtered list of options to pass through from the
* client to the server */
void server_options(char **args,int *argc)
{
int ac = *argc;
@@ -576,6 +530,10 @@ void server_options(char **args,int *argc)
static char bsize[30];
static char iotime[30];
static char mdelete[30];
static char mwindow[30];
static char bw[50];
static char fext[20]; /* dw */
int i, x;
args[ac++] = "--server";
@@ -587,6 +545,7 @@ void server_options(char **args,int *argc)
argstr[0] = '-';
for (i=0;i<verbose;i++)
argstr[x++] = 'v';
/* the -q option is intentionally left out */
if (make_backups)
argstr[x++] = 'b';
@@ -628,25 +587,45 @@ void server_options(char **args,int *argc)
argstr[x++] = 'S';
if (do_compression)
argstr[x++] = 'z';
if (write_batch)
argstr[x++] = 'F'; /* dw */
/* 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)
argstr[x++] = 'r';
argstr[x] = 0;
if (x != 1) args[ac++] = argstr;
if (block_size != BLOCK_SIZE) {
slprintf(bsize,sizeof(bsize),"-B%d",block_size);
snprintf(bsize,sizeof(bsize),"-B%d",block_size);
args[ac++] = bsize;
}
if (max_delete && am_sender) {
slprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
snprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
args[ac++] = mdelete;
}
if (batch_ext != NULL) {
sprintf(fext,"-f%s",batch_ext);
args[ac++] = fext;
}
if (io_timeout) {
slprintf(iotime,sizeof(iotime),"--timeout=%d",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;
@@ -661,6 +640,12 @@ void server_options(char **args,int *argc)
if (size_only)
args[ac++] = "--size-only";
if (modify_window_set) {
snprintf(mwindow,sizeof(mwindow),"--modify-window=%d",
modify_window);
args[ac++] = mwindow;
}
if (keep_partial)
args[ac++] = "--partial";
@@ -670,6 +655,9 @@ void server_options(char **args,int *argc)
if (delete_after)
args[ac++] = "--delete-after";
if (ignore_errors)
args[ac++] = "--ignore-errors";
if (copy_unsafe_links)
args[ac++] = "--copy-unsafe-links";

84
packaging/lsb/rsync.spec Normal file
View File

@@ -0,0 +1,84 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.5.0
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.0.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

View File

@@ -0,0 +1,84 @@
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

View File

@@ -1,10 +1,10 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.4.0
Version: 2.5.0
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.4.0.tar.gz
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.0.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync

View File

@@ -0,0 +1,81 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.5.0
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.0.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

View File

@@ -0,0 +1,81 @@
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

9
popt/.cvsignore Normal file
View File

@@ -0,0 +1,9 @@
ID
Makefile
config.cache
config.h
config.log
config.status
dummy
rsync
zlib/dummy

43
popt/CHANGES Normal file
View File

@@ -0,0 +1,43 @@
1.3 ->
- heavy dose of const's
- poptParseArgvString() now NULL terminates the list
1.2.3 -> 1.3
- added support for single -
- misc bug fixes
- portability improvements
1.2.2 -> 1.2.3
- fixed memset() in help message generation (Dale Hawkins)
- added extern "C" stuff to popt.h for C++ compilers (Dale Hawkins)
- const'ified poptParseArgvString (Jeff Garzik)
1.2.1 -> 1.2.2
- fixed bug in chaind alias happens which seems to have only
affected --triggers in rpm
- added POPT_ARG_VAL
- popt.3 installed by default
1.2 -> 1.2.1
- added POPT_ARG_INTL_DOMAIN (Elliot Lee)
- updated Makefile's to be more GNUish (Elliot Lee)
1.1 -> 1.2
- added popt.3 man page (Robert Lynch)
- don't use mmap anymore (its lack of portability isn't worth the
trouble)
- added test script
- added support for exec
- removed support for *_POPT_ALIASES env variable -- it was a bad
idea
- reorganized into multiple source files
- added automatic help generation, POPT_AUTOHELP
- added table callbacks
- added table inclusion
- updated man page for new features
- added test scripts
1.0 -> 1.1
- moved to autoconf (Fred Fish)
- added STRERROR replacement (Norbert Warmuth)
- added const keywords (Bruce Perens)

22
popt/COPYING Normal file
View File

@@ -0,0 +1,22 @@
Copyright (c) 1998 Red Hat Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the X Consortium.

18
popt/README Normal file
View File

@@ -0,0 +1,18 @@
This is the popt command line option parsing library. While it is similiar
to getopt(3), it contains a number of enhancements, including:
1) popt is fully reentrant
2) popt can parse arbitrary argv[] style arrays while
getopt(2) makes this quite difficult
3) popt allows users to alias command line arguments
4) popt provides convience functions for parsting strings
into argv[] style arrays
popt is used by rpm, the Red Hat install program, and many other Red Hat
utilities, all of which provide excellent examples of how to use popt.
Complete documentation on popt is available in popt.ps (included in this
tarball), which is excerpted with permission from the book "Linux
Application Development" by Michael K. Johnson and Erik Troan (availble
from Addison Wesley in May, 1998).
Comments on popt should be addressed to ewt@redhat.com.

104
popt/config.log Normal file
View File

@@ -0,0 +1,104 @@
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

0
popt/dummy.in Normal file
View File

46
popt/findme.c Normal file
View File

@@ -0,0 +1,46 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#include "system.h"
#include "findme.h"
const char * findProgramPath(const char * argv0) {
char * path = getenv("PATH");
char * pathbuf;
char * start, * chptr;
char * buf, *local = NULL;
/* If there is a / in the argv[0], it has to be an absolute
path */
if (strchr(argv0, '/'))
return xstrdup(argv0);
if (!path) return NULL;
local = start = pathbuf = malloc(strlen(path) + 1);
buf = malloc(strlen(path) + strlen(argv0) + 2);
strcpy(pathbuf, path);
chptr = NULL;
do {
if ((chptr = strchr(start, ':')))
*chptr = '\0';
sprintf(buf, "%s/%s", start, argv0);
if (!access(buf, X_OK)) {
if (local) free(local);
return buf;
}
if (chptr)
start = chptr + 1;
else
start = NULL;
} while (start && *start);
free(buf);
if (local) free(local);
return NULL;
}

10
popt/findme.h Normal file
View File

@@ -0,0 +1,10 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#ifndef H_FINDME
#define H_FINDME
const char * findProgramPath(const char * argv0);
#endif

782
popt/popt.c Normal file
View File

@@ -0,0 +1,782 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#include "system.h"
#include "findme.h"
#include "poptint.h"
#ifndef HAVE_STRERROR
static char * strerror(int errno) {
extern int sys_nerr;
extern char * sys_errlist[];
if ((0 <= errno) && (errno < sys_nerr))
return sys_errlist[errno];
else
return POPT_("unknown errno");
}
#endif
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) {
if (con->execPath) xfree(con->execPath);
con->execPath = xstrdup(path);
con->execAbsolute = allowAbsolute;
}
static void invokeCallbacks(poptContext con, const struct poptOption * table,
int post) {
const struct poptOption * opt = table;
poptCallbackType cb;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
invokeCallbacks(con, opt->arg, post);
} else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) &&
((!post && (opt->argInfo & POPT_CBFLAG_PRE)) ||
( post && (opt->argInfo & POPT_CBFLAG_POST)))) {
cb = (poptCallbackType)opt->arg;
cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE,
NULL, NULL, opt->descrip);
}
opt++;
}
}
poptContext poptGetContext(const char * name, int argc, const char ** argv,
const struct poptOption * options, int flags) {
poptContext con = malloc(sizeof(*con));
memset(con, 0, sizeof(*con));
con->os = con->optionStack;
con->os->argc = argc;
con->os->argv = argv;
con->os->argb = NULL;
if (!(flags & POPT_CONTEXT_KEEP_FIRST))
con->os->next = 1; /* skip argv[0] */
con->leftovers = calloc( (argc + 1), sizeof(char *) );
con->options = options;
con->aliases = NULL;
con->numAliases = 0;
con->flags = flags;
con->execs = NULL;
con->numExecs = 0;
con->finalArgvAlloced = argc * 2;
con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
con->execAbsolute = 1;
con->arg_strip = NULL;
if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
con->flags |= POPT_CONTEXT_POSIXMEHARDER;
if (name)
con->appName = strcpy(malloc(strlen(name) + 1), name);
invokeCallbacks(con, con->options, 0);
return con;
}
static void cleanOSE(struct optionStackEntry *os)
{
if (os->nextArg) {
xfree(os->nextArg);
os->nextArg = NULL;
}
if (os->argv) {
xfree(os->argv);
os->argv = NULL;
}
if (os->argb) {
PBM_FREE(os->argb);
os->argb = NULL;
}
}
void poptResetContext(poptContext con) {
int i;
while (con->os > con->optionStack) {
cleanOSE(con->os--);
}
if (con->os->argb) {
PBM_FREE(con->os->argb);
con->os->argb = NULL;
}
con->os->currAlias = NULL;
con->os->nextCharArg = NULL;
con->os->nextArg = NULL;
con->os->next = 1; /* skip argv[0] */
con->numLeftovers = 0;
con->nextLeftover = 0;
con->restLeftover = 0;
con->doExec = NULL;
for (i = 0; i < con->finalArgvCount; i++) {
if (con->finalArgv[i]) {
xfree(con->finalArgv[i]);
con->finalArgv[i] = NULL;
}
}
con->finalArgvCount = 0;
if (con->arg_strip) {
PBM_FREE(con->arg_strip);
con->arg_strip = NULL;
}
}
/* Only one of longName, shortName may be set at a time */
static int handleExec(poptContext con, char * longName, char shortName) {
int i;
i = con->numExecs - 1;
if (longName) {
while (i >= 0 && (!con->execs[i].longName ||
strcmp(con->execs[i].longName, longName))) i--;
} else {
while (i >= 0 &&
con->execs[i].shortName != shortName) i--;
}
if (i < 0) return 0;
if (con->flags & POPT_CONTEXT_NO_EXEC)
return 1;
if (con->doExec == NULL) {
con->doExec = con->execs + i;
return 1;
}
/* We already have an exec to do; remember this option for next
time 'round */
if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
con->finalArgvAlloced += 10;
con->finalArgv = realloc(con->finalArgv,
sizeof(*con->finalArgv) * con->finalArgvAlloced);
}
i = con->finalArgvCount++;
{ char *s = malloc((longName ? strlen(longName) : 0) + 3);
if (longName)
sprintf(s, "--%s", longName);
else
sprintf(s, "-%c", shortName);
con->finalArgv[i] = s;
}
return 1;
}
/* Only one of longName, shortName may be set at a time */
static int handleAlias(poptContext con, const char * longName, char shortName,
/*@keep@*/ const char * nextCharArg) {
int i;
if (con->os->currAlias && con->os->currAlias->longName && longName &&
!strcmp(con->os->currAlias->longName, longName))
return 0;
if (con->os->currAlias && shortName &&
shortName == con->os->currAlias->shortName)
return 0;
i = con->numAliases - 1;
if (longName) {
while (i >= 0 && (!con->aliases[i].longName ||
strcmp(con->aliases[i].longName, longName))) i--;
} else {
while (i >= 0 &&
con->aliases[i].shortName != shortName) i--;
}
if (i < 0) return 0;
if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
if (nextCharArg && *nextCharArg)
con->os->nextCharArg = nextCharArg;
con->os++;
con->os->next = 0;
con->os->stuffed = 0;
con->os->nextArg = NULL;
con->os->nextCharArg = NULL;
con->os->currAlias = con->aliases + i;
poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
&con->os->argc, &con->os->argv);
con->os->argb = NULL;
return 1;
}
static void execCommand(poptContext con) {
const char ** argv;
int pos = 0;
const char * script = con->doExec->script;
argv = malloc(sizeof(*argv) *
(6 + con->numLeftovers + con->finalArgvCount));
if (!con->execAbsolute && strchr(script, '/')) return;
if (!strchr(script, '/') && con->execPath) {
char *s = malloc(strlen(con->execPath) + strlen(script) + 2);
sprintf(s, "%s/%s", con->execPath, script);
argv[pos] = s;
} else {
argv[pos] = script;
}
pos++;
argv[pos] = findProgramPath(con->os->argv[0]);
if (argv[pos]) pos++;
argv[pos++] = ";";
memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount);
pos += con->finalArgvCount;
if (con->numLeftovers) {
argv[pos++] = "--";
memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers);
pos += con->numLeftovers;
}
argv[pos++] = NULL;
#ifdef __hpux
setresuid(getuid(), getuid(),-1);
#else
/*
* XXX " ... on BSD systems setuid() should be preferred over setreuid()"
* XXX sez' Timur Bakeyev <mc@bat.ru>
* XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
*/
#if defined(HAVE_SETUID)
setuid(getuid());
#elif defined (HAVE_SETREUID)
setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
#else
; /* Can't drop privileges */
#endif
#endif
execvp(argv[0], (char *const *)argv);
}
/*@observer@*/ static const struct poptOption *
findOption(const struct poptOption * table, const char * longName,
char shortName,
/*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData,
int singleDash)
{
const struct poptOption * opt = table;
const struct poptOption * opt2;
const struct poptOption * cb = NULL;
/* This happens when a single - is given */
if (singleDash && !shortName && !*longName)
shortName = '-';
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
opt2 = findOption(opt->arg, longName, shortName, callback,
callbackData, singleDash);
if (opt2) {
if (*callback && !*callbackData)
*callbackData = opt->descrip;
return opt2;
}
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
cb = opt;
} else if (longName && opt->longName &&
(!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
!strcmp(longName, opt->longName)) {
break;
} else if (shortName && shortName == opt->shortName) {
break;
}
opt++;
}
if (!opt->longName && !opt->shortName) return NULL;
*callbackData = NULL;
*callback = NULL;
if (cb) {
*callback = (poptCallbackType)cb->arg;
if (!(cb->argInfo & POPT_CBFLAG_INC_DATA))
*callbackData = cb->descrip;
}
return opt;
}
static const char *findNextArg(poptContext con, unsigned argx, int delete)
{
struct optionStackEntry * os = con->os;
const char * arg;
do {
int i;
arg = NULL;
while (os->next == os->argc && os > con->optionStack) os--;
if (os->next == os->argc && os == con->optionStack) break;
for (i = os->next; i < os->argc; i++) {
if (os->argb && PBM_ISSET(i, os->argb)) continue;
if (*os->argv[i] == '-') continue;
if (--argx > 0) continue;
arg = os->argv[i];
if (delete) {
if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
PBM_SET(i, os->argb);
}
break;
}
if (os > con->optionStack) os--;
} while (arg == NULL);
return arg;
}
static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
{
const char *a;
size_t alen;
char *t, *te;
size_t tn = strlen(s) + 1;
char c;
te = t = malloc(tn);;
while ((c = *s++) != '\0') {
switch (c) {
#if 0 /* XXX can't do this */
case '\\': /* escape */
c = *s++;
break;
#endif
case '!':
if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
break;
if ((a = findNextArg(con, 1, 1)) == NULL)
break;
s += 3;
alen = strlen(a);
tn += alen;
*te = '\0';
t = realloc(t, tn);
te = t + strlen(t);
strncpy(te, a, alen); te += alen;
continue;
/*@notreached@*/ break;
default:
break;
}
*te++ = c;
}
*te = '\0';
t = realloc(t, strlen(t)+1); /* XXX memory leak, hard to plug */
return t;
}
static void poptStripArg(poptContext con, int which)
{
if(con->arg_strip == NULL) {
con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
}
PBM_SET(which, con->arg_strip);
}
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con)
{
const struct poptOption * opt = NULL;
int done = 0;
/* looks a bit tricky to get rid of alloca properly in this fn */
#if HAVE_ALLOCA_H
#define ALLOCA(x) alloca(x)
#else
#define ALLOCA(x) malloc(x)
#endif
while (!done) {
const char * origOptString = NULL;
poptCallbackType cb = NULL;
const void * cbData = NULL;
const char * longArg = NULL;
int canstrip = 0;
while (!con->os->nextCharArg && con->os->next == con->os->argc
&& con->os > con->optionStack) {
cleanOSE(con->os--);
}
if (!con->os->nextCharArg && con->os->next == con->os->argc) {
invokeCallbacks(con, con->options, 1);
if (con->doExec) execCommand(con);
return -1;
}
/* Process next long option */
if (!con->os->nextCharArg) {
char * localOptString, * optString;
int thisopt;
if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
con->os->next++;
continue;
}
thisopt=con->os->next;
origOptString = con->os->argv[con->os->next++];
if (con->restLeftover || *origOptString != '-') {
con->leftovers[con->numLeftovers++] = origOptString;
if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
con->restLeftover = 1;
continue;
}
/* Make a copy we can hack at */
localOptString = optString =
strcpy(ALLOCA(strlen(origOptString) + 1),
origOptString);
if (!optString[0])
return POPT_ERROR_BADOPT;
if (optString[1] == '-' && !optString[2]) {
con->restLeftover = 1;
continue;
} else {
char *oe;
int singleDash;
optString++;
if (*optString == '-')
singleDash = 0, optString++;
else
singleDash = 1;
/* XXX aliases with arg substitution need "--alias=arg" */
if (handleAlias(con, optString, '\0', NULL))
continue;
if (handleExec(con, optString, '\0'))
continue;
/* Check for "--long=arg" option. */
for (oe = optString; *oe && *oe != '='; oe++)
;
if (*oe == '=') {
*oe++ = '\0';
/* XXX longArg is mapped back to persistent storage. */
longArg = origOptString + (oe - localOptString);
}
opt = findOption(con->options, optString, '\0', &cb, &cbData,
singleDash);
if (!opt && !singleDash)
return POPT_ERROR_BADOPT;
}
if (!opt) {
con->os->nextCharArg = origOptString + 1;
} else {
if(con->os == con->optionStack &&
opt->argInfo & POPT_ARGFLAG_STRIP) {
canstrip = 1;
poptStripArg(con, thisopt);
}
}
}
/* Process next short option */
if (con->os->nextCharArg) {
origOptString = con->os->nextCharArg;
con->os->nextCharArg = NULL;
if (handleAlias(con, NULL, *origOptString,
origOptString + 1)) {
origOptString++;
continue;
}
if (handleExec(con, NULL, *origOptString))
continue;
opt = findOption(con->options, NULL, *origOptString, &cb,
&cbData, 0);
if (!opt)
return POPT_ERROR_BADOPT;
origOptString++;
if (*origOptString)
con->os->nextCharArg = origOptString;
}
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
*((int *)opt->arg) = 1;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
if (opt->arg)
*((int *) opt->arg) = opt->val;
} else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
if (con->os->nextArg) {
xfree(con->os->nextArg);
con->os->nextArg = NULL;
}
if (longArg) {
con->os->nextArg = expandNextArg(con, longArg);
} else if (con->os->nextCharArg) {
con->os->nextArg = expandNextArg(con, con->os->nextCharArg);
con->os->nextCharArg = NULL;
} else {
while (con->os->next == con->os->argc &&
con->os > con->optionStack) {
cleanOSE(con->os--);
}
if (con->os->next == con->os->argc)
return POPT_ERROR_NOARG;
/* make sure this isn't part of a short arg or the
result of an alias expansion */
if(con->os == con->optionStack &&
opt->argInfo & POPT_ARGFLAG_STRIP &&
canstrip) {
poptStripArg(con, con->os->next);
}
con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]);
}
if (opt->arg) {
long aLong;
char *end;
switch (opt->argInfo & POPT_ARG_MASK) {
case POPT_ARG_STRING:
/* XXX memory leak, hard to plug */
*((const char **) opt->arg) = xstrdup(con->os->nextArg);
break;
case POPT_ARG_INT:
case POPT_ARG_LONG:
aLong = strtol(con->os->nextArg, &end, 0);
if (!(end && *end == '\0'))
return POPT_ERROR_BADNUMBER;
if (aLong == LONG_MIN || aLong == LONG_MAX)
return POPT_ERROR_OVERFLOW;
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
*((long *) opt->arg) = aLong;
} else {
if (aLong > INT_MAX || aLong < INT_MIN)
return POPT_ERROR_OVERFLOW;
*((int *) opt->arg) = aLong;
}
break;
default:
fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"),
opt->argInfo & POPT_ARG_MASK);
exit(EXIT_FAILURE);
}
}
}
if (cb)
cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData);
else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
done = 1;
if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
con->finalArgvAlloced += 10;
con->finalArgv = realloc(con->finalArgv,
sizeof(*con->finalArgv) * con->finalArgvAlloced);
}
{ char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
if (opt->longName)
sprintf(s, "--%s", opt->longName);
else
sprintf(s, "-%c", opt->shortName);
con->finalArgv[con->finalArgvCount++] = s;
}
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE
&& (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL) {
con->finalArgv[con->finalArgvCount++] = xstrdup(con->os->nextArg);
}
}
return opt->val;
}
const char * poptGetOptArg(poptContext con) {
const char * ret = con->os->nextArg;
con->os->nextArg = NULL;
return ret;
}
const char * poptGetArg(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
return con->leftovers[con->nextLeftover++];
}
const char * poptPeekArg(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
return con->leftovers[con->nextLeftover];
}
const char ** poptGetArgs(poptContext con) {
if (con->numLeftovers == con->nextLeftover) return NULL;
/* some apps like [like RPM ;-) ] need this NULL terminated */
con->leftovers[con->numLeftovers] = NULL;
return (con->leftovers + con->nextLeftover);
}
void poptFreeContext(poptContext con) {
int i;
poptResetContext(con);
if (con->os->argb) free(con->os->argb);
for (i = 0; i < con->numAliases; i++) {
if (con->aliases[i].longName) xfree(con->aliases[i].longName);
free(con->aliases[i].argv);
}
for (i = 0; i < con->numExecs; i++) {
if (con->execs[i].longName) xfree(con->execs[i].longName);
xfree(con->execs[i].script);
}
if (con->execs) xfree(con->execs);
free(con->leftovers);
free(con->finalArgv);
if (con->appName) xfree(con->appName);
if (con->aliases) free(con->aliases);
if (con->otherHelp) xfree(con->otherHelp);
if (con->execPath) xfree(con->execPath);
if (con->arg_strip) PBM_FREE(con->arg_strip);
free(con);
}
int poptAddAlias(poptContext con, struct poptAlias newAlias,
/*@unused@*/ int flags)
{
int aliasNum = con->numAliases++;
struct poptAlias * alias;
/* SunOS won't realloc(NULL, ...) */
if (!con->aliases)
con->aliases = malloc(sizeof(newAlias) * con->numAliases);
else
con->aliases = realloc(con->aliases,
sizeof(newAlias) * con->numAliases);
alias = con->aliases + aliasNum;
alias->longName = (newAlias.longName)
? strcpy(malloc(strlen(newAlias.longName) + 1), newAlias.longName)
: NULL;
alias->shortName = newAlias.shortName;
alias->argc = newAlias.argc;
alias->argv = newAlias.argv;
return 0;
}
const char * poptBadOption(poptContext con, int flags) {
struct optionStackEntry * os;
if (flags & POPT_BADOPTION_NOALIAS)
os = con->optionStack;
else
os = con->os;
return os->argv[os->next - 1];
}
#define POPT_ERROR_NOARG -10
#define POPT_ERROR_BADOPT -11
#define POPT_ERROR_OPTSTOODEEP -13
#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
const char *const poptStrerror(const int error) {
switch (error) {
case POPT_ERROR_NOARG:
return POPT_("missing argument");
case POPT_ERROR_BADOPT:
return POPT_("unknown option");
case POPT_ERROR_OPTSTOODEEP:
return POPT_("aliases nested too deeply");
case POPT_ERROR_BADQUOTE:
return POPT_("error in paramter quoting");
case POPT_ERROR_BADNUMBER:
return POPT_("invalid numeric value");
case POPT_ERROR_OVERFLOW:
return POPT_("number too large or too small");
case POPT_ERROR_ERRNO:
return strerror(errno);
default:
return POPT_("unknown error");
}
}
int poptStuffArgs(poptContext con, const char ** argv) {
int argc;
if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
for (argc = 0; argv[argc]; argc++)
;
con->os++;
con->os->next = 0;
con->os->nextArg = NULL;
con->os->nextCharArg = NULL;
con->os->currAlias = NULL;
poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
con->os->argb = NULL;
con->os->stuffed = 1;
return 0;
}
const char * poptGetInvocationName(poptContext con) {
return con->os->argv[0];
}
int poptStrippedArgv(poptContext con, int argc, char **argv)
{
int i,j=1, numargs=argc;
for(i=1; i<argc; i++) {
if(PBM_ISSET(i, con->arg_strip)) {
numargs--;
}
}
for(i=1; i<argc; i++) {
if(PBM_ISSET(i, con->arg_strip)) {
continue;
} else {
if(j<numargs) {
argv[j++]=argv[i];
} else {
argv[j++]='\0';
}
}
}
return(numargs);
}

130
popt/popt.h Normal file
View File

@@ -0,0 +1,130 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#ifndef H_POPT
#define H_POPT
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h> /* for FILE * */
#define POPT_OPTION_DEPTH 10
#define POPT_ARG_NONE 0
#define POPT_ARG_STRING 1
#define POPT_ARG_INT 2
#define POPT_ARG_LONG 3
#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */
#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be
set first in table; arg points
to callback, descrip points to
callback data to pass */
#define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain
for this table and any
included tables; arg points
to the domain string */
#define POPT_ARG_VAL 7 /* arg should take value val */
#define POPT_ARG_MASK 0x0000FFFF
#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */
#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */
#define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */
#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */
#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */
#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line,
not the subtable */
#define POPT_ERROR_NOARG -10
#define POPT_ERROR_BADOPT -11
#define POPT_ERROR_OPTSTOODEEP -13
#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
#define POPT_ERROR_BADNUMBER -17
#define POPT_ERROR_OVERFLOW -18
/* poptBadOption() flags */
#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */
/* poptGetContext() flags */
#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */
#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */
#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */
struct poptOption {
/*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */
char shortName; /* may be '\0' */
int argInfo;
/*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */
int val; /* 0 means don't return, just update flag */
/*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */
/*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */
};
struct poptAlias {
/*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */
char shortName; /* may be '\0' */
int argc;
/*@owned@*/ const char ** argv; /* must be free()able */
};
extern struct poptOption poptHelpOptions[];
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
0, "Help options", NULL },
typedef struct poptContext_s * poptContext;
#ifndef __cplusplus
typedef struct poptOption * poptOption;
#endif
enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
POPT_CALLBACK_REASON_POST,
POPT_CALLBACK_REASON_OPTION };
typedef void (*poptCallbackType)(poptContext con,
enum poptCallbackReason reason,
const struct poptOption * opt,
const char * arg, const void * data);
/*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name,
int argc, /*@keep@*/ const char ** argv,
/*@keep@*/ const struct poptOption * options, int flags);
void poptResetContext(poptContext con);
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con);
/* returns NULL if no argument is available */
/*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con);
/* returns NULL if no more options are available */
/*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con);
/*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con);
/*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con);
/* returns the option which caused the most recent error */
/*@observer@*/ const char * poptBadOption(poptContext con, int flags);
void poptFreeContext( /*@only@*/ poptContext con);
int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv);
int poptAddAlias(poptContext con, struct poptAlias alias, int flags);
int poptReadConfigFile(poptContext con, const char * fn);
/* like above, but reads /etc/popt and $HOME/.popt along with environment
vars */
int poptReadDefaultConfig(poptContext con, int useEnv);
/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated
the same as " and both may include \ quotes */
int poptDupArgv(int argc, const char **argv,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr);
int poptParseArgvString(const char * s,
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr);
/*@observer@*/ const char *const poptStrerror(const int error);
void poptSetExecPath(poptContext con, const char * path, int allowAbsolute);
void poptPrintHelp(poptContext con, FILE * f, int flags);
void poptPrintUsage(poptContext con, FILE * f, int flags);
void poptSetOtherOptionHelp(poptContext con, const char * text);
/*@observer@*/ const char * poptGetInvocationName(poptContext con);
/* shuffles argv pointers to remove stripped args, returns new argc */
int poptStrippedArgv(poptContext con, int argc, char **argv);
#ifdef __cplusplus
}
#endif
#endif

142
popt/poptconfig.c Normal file
View File

@@ -0,0 +1,142 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#include "system.h"
#include "poptint.h"
static void configLine(poptContext con, char * line) {
int nameLength = strlen(con->appName);
char * opt;
struct poptAlias alias;
char * entryType;
char * longName = NULL;
char shortName = '\0';
if (strncmp(line, con->appName, nameLength)) return;
line += nameLength;
if (!*line || !isspace(*line)) return;
while (*line && isspace(*line)) line++;
entryType = line;
while (!*line || !isspace(*line)) line++;
*line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return;
opt = line;
while (!*line || !isspace(*line)) line++;
*line++ = '\0';
while (*line && isspace(*line)) line++;
if (!*line) return;
if (opt[0] == '-' && opt[1] == '-')
longName = opt + 2;
else if (opt[0] == '-' && !opt[2])
shortName = opt[1];
if (!strcmp(entryType, "alias")) {
if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
alias.longName = longName, alias.shortName = shortName;
poptAddAlias(con, alias, 0);
} else if (!strcmp(entryType, "exec")) {
con->execs = realloc(con->execs,
sizeof(*con->execs) * (con->numExecs + 1));
if (longName)
con->execs[con->numExecs].longName = xstrdup(longName);
else
con->execs[con->numExecs].longName = NULL;
con->execs[con->numExecs].shortName = shortName;
con->execs[con->numExecs].script = xstrdup(line);
con->numExecs++;
}
}
int poptReadConfigFile(poptContext con, const char * fn) {
char * file=NULL, * chptr, * end;
char * buf=NULL, * dst;
int fd, rc;
int fileLength;
fd = open(fn, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
return 0;
else
return POPT_ERROR_ERRNO;
}
fileLength = lseek(fd, 0, SEEK_END);
(void) lseek(fd, 0, 0);
file = malloc(fileLength + 1);
if (read(fd, file, fileLength) != fileLength) {
rc = errno;
close(fd);
errno = rc;
if (file) free(file);
return POPT_ERROR_ERRNO;
}
close(fd);
dst = buf = malloc(fileLength + 1);
chptr = file;
end = (file + fileLength);
while (chptr < end) {
switch (*chptr) {
case '\n':
*dst = '\0';
dst = buf;
while (*dst && isspace(*dst)) dst++;
if (*dst && *dst != '#') {
configLine(con, dst);
}
chptr++;
break;
case '\\':
*dst++ = *chptr++;
if (chptr < end) {
if (*chptr == '\n')
dst--, chptr++;
/* \ at the end of a line does not insert a \n */
else
*dst++ = *chptr++;
}
break;
default:
*dst++ = *chptr++;
break;
}
}
free(file);
free(buf);
return 0;
}
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) {
char * fn, * home;
int rc;
if (!con->appName) return 0;
rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc;
if (getuid() != geteuid()) return 0;
if ((home = getenv("HOME"))) {
fn = malloc(strlen(home) + 20);
strcpy(fn, home);
strcat(fn, "/.popt");
rc = poptReadConfigFile(con, fn);
free(fn);
if (rc) return rc;
}
return 0;
}

301
popt/popthelp.c Normal file
View File

@@ -0,0 +1,301 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#include "system.h"
#include "poptint.h"
static void displayArgs(poptContext con,
/*@unused@*/ enum poptCallbackReason foo,
struct poptOption * key,
/*@unused@*/ const char * arg, /*@unused@*/ void * data) {
if (key->shortName== '?')
poptPrintHelp(con, stdout, 0);
else
poptPrintUsage(con, stdout, 0);
exit(0);
}
struct poptOption poptHelpOptions[] = {
{ NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
{ "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
{ "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
} ;
/*@observer@*/ /*@null@*/ static const char *const
getTableTranslationDomain(const struct poptOption *table)
{
const struct poptOption *opt;
for(opt = table;
opt->longName || opt->shortName || opt->arg;
opt++) {
if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
return opt->arg;
}
return NULL;
}
/*@observer@*/ /*@null@*/ static const char *const
getArgDescrip(const struct poptOption * opt, const char *translation_domain)
{
if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
if (opt->argDescrip) return POPT_(opt->argDescrip);
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
return POPT_("ARG");
}
static void singleOptionHelp(FILE * f, int maxLeftCol,
const struct poptOption * opt,
const char *translation_domain) {
int indentLength = maxLeftCol + 5;
int lineLength = 79 - indentLength;
const char * help = D_(translation_domain, opt->descrip);
int helpLength;
const char * ch;
char format[10];
char * left;
const char * argDescrip = getArgDescrip(opt, translation_domain);
left = malloc(maxLeftCol + 1);
*left = '\0';
if (opt->longName && opt->shortName)
sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
else if (opt->shortName)
sprintf(left, "-%c", opt->shortName);
else if (opt->longName)
sprintf(left, "--%s", opt->longName);
if (!*left) return ;
if (argDescrip) {
strcat(left, "=");
strcat(left, argDescrip);
}
if (help)
fprintf(f," %-*s ", maxLeftCol, left);
else {
fprintf(f," %s\n", left);
goto out;
}
helpLength = strlen(help);
while (helpLength > lineLength) {
ch = help + lineLength - 1;
while (ch > help && !isspace(*ch)) ch--;
if (ch == help) break; /* give up */
while (ch > (help + 1) && isspace(*ch)) ch--;
ch++;
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
fprintf(f, format, help, " ");
help = ch;
while (isspace(*help) && *help) help++;
helpLength = strlen(help);
}
if (helpLength) fprintf(f, "%s\n", help);
out:
free(left);
}
static int maxArgWidth(const struct poptOption * opt,
const char * translation_domain) {
int max = 0;
int this;
const char * s;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
this = maxArgWidth(opt->arg, translation_domain);
if (this > max) max = this;
} else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
this = opt->shortName ? 2 : 0;
if (opt->longName) {
if (this) this += 2;
this += strlen(opt->longName) + 2;
}
s = getArgDescrip(opt, translation_domain);
if (s)
this += strlen(s) + 1;
if (this > max) max = this;
}
opt++;
}
return max;
}
static void singleTableHelp(FILE * f, const struct poptOption * table,
int left,
const char *translation_domain) {
const struct poptOption * opt;
const char *sub_transdom;
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
singleOptionHelp(f, left, opt, translation_domain);
opt++;
}
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
sub_transdom = getTableTranslationDomain(opt->arg);
if(!sub_transdom)
sub_transdom = translation_domain;
if (opt->descrip)
fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
singleTableHelp(f, opt->arg, left, sub_transdom);
}
opt++;
}
}
static int showHelpIntro(poptContext con, FILE * f) {
int len = 6;
const char * fn;
fprintf(f, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
fn = con->optionStack->argv[0];
if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
fprintf(f, " %s", fn);
len += strlen(fn) + 1;
}
return len;
}
void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) {
int leftColWidth;
showHelpIntro(con, f);
if (con->otherHelp)
fprintf(f, " %s\n", con->otherHelp);
else
fprintf(f, " %s\n", POPT_("[OPTION...]"));
leftColWidth = maxArgWidth(con->options, NULL);
singleTableHelp(f, con->options, leftColWidth, NULL);
}
static int singleOptionUsage(FILE * f, int cursor,
const struct poptOption * opt,
const char *translation_domain) {
int len = 3;
char shortStr[2] = { '\0', '\0' };
const char * item = shortStr;
const char * argDescrip = getArgDescrip(opt, translation_domain);
if (opt->shortName) {
if (!(opt->argInfo & POPT_ARG_MASK))
return cursor; /* we did these already */
len++;
*shortStr = opt->shortName;
shortStr[1] = '\0';
} else if (opt->longName) {
len += 1 + strlen(opt->longName);
item = opt->longName;
}
if (len == 3) return cursor;
if (argDescrip)
len += strlen(argDescrip) + 1;
if ((cursor + len) > 79) {
fprintf(f, "\n ");
cursor = 7;
}
fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
argDescrip ? (opt->shortName ? " " : "=") : "",
argDescrip ? argDescrip : "");
return cursor + len + 1;
}
static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
const char *translation_domain) {
const struct poptOption * opt;
opt = table;
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
translation_domain = (const char *)opt->arg;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
cursor = singleTableUsage(f, cursor, opt->arg,
translation_domain);
else if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
cursor = singleOptionUsage(f, cursor, opt, translation_domain);
opt++;
}
return cursor;
}
static int showShortOptions(const struct poptOption * opt, FILE * f,
char * str) {
char s[300]; /* this is larger then the ascii set, so
it should do just fine */
s[0] = '\0';
if (str == NULL) {
memset(s, 0, sizeof(s));
str = s;
}
while (opt->longName || opt->shortName || opt->arg) {
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
str[strlen(str)] = opt->shortName;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
showShortOptions(opt->arg, f, str);
opt++;
}
if (s != str || !*s)
return 0;
fprintf(f, " [-%s]", s);
return strlen(s) + 4;
}
void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) {
int cursor;
cursor = showHelpIntro(con, f);
cursor += showShortOptions(con->options, f, NULL);
singleTableUsage(f, cursor, con->options, NULL);
if (con->otherHelp) {
cursor += strlen(con->otherHelp) + 1;
if (cursor > 79) fprintf(f, "\n ");
fprintf(f, " %s", con->otherHelp);
}
fprintf(f, "\n");
}
void poptSetOtherOptionHelp(poptContext con, const char * text) {
if (con->otherHelp) xfree(con->otherHelp);
con->otherHelp = xstrdup(text);
}

87
popt/poptint.h Normal file
View File

@@ -0,0 +1,87 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#ifndef H_POPTINT
#define H_POPTINT
/* Bit mask macros. */
typedef unsigned int __pbm_bits;
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS)
#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS))
typedef struct {
__pbm_bits bits[1];
} pbm_set;
#define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
#define PBM_FREE(s) free(s);
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
struct optionStackEntry {
int argc;
/*@only@*/ const char ** argv;
/*@only@*/ pbm_set * argb;
int next;
/*@only@*/ const char * nextArg;
/*@keep@*/ const char * nextCharArg;
/*@dependent@*/ struct poptAlias * currAlias;
int stuffed;
};
struct execEntry {
const char * longName;
char shortName;
const char * script;
};
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
/*@dependent@*/ struct optionStackEntry * os;
/*@owned@*/ const char ** leftovers;
int numLeftovers;
int nextLeftover;
/*@keep@*/ const struct poptOption * options;
int restLeftover;
/*@only@*/ const char * appName;
/*@only@*/ struct poptAlias * aliases;
int numAliases;
int flags;
struct execEntry * execs;
int numExecs;
/*@only@*/ const char ** finalArgv;
int finalArgvCount;
int finalArgvAlloced;
/*@dependent@*/ struct execEntry * doExec;
/*@only@*/ const char * execPath;
int execAbsolute;
/*@only@*/ const char * otherHelp;
pbm_set * arg_strip;
};
#define xfree(_a) free((void *)_a)
#ifdef HAVE_LIBINTL_H
#include <libintl.h>
#endif
#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
#define _(foo) gettext(foo)
#else
#define _(foo) (foo)
#endif
#if defined(HAVE_DGETTEXT) && !defined(__LCLINT__)
#define D_(dom, str) dgettext(dom, str)
#define POPT_(foo) D_("popt", foo)
#else
#define POPT_(foo) (foo)
#define D_(dom, str) (str)
#endif
#define N_(foo) (foo)
#endif

102
popt/poptparse.c Normal file
View File

@@ -0,0 +1,102 @@
/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
ftp://ftp.redhat.com/pub/code/popt */
#include "system.h"
#define POPT_ARGV_ARRAY_GROW_DELTA 5
int poptDupArgv(int argc, const char **argv,
int * argcPtr, const char *** argvPtr)
{
size_t nb = (argc + 1) * sizeof(*argv);
const char ** argv2;
char * dst;
int i;
for (i = 0; i < argc; i++) {
if (argv[i] == NULL)
return POPT_ERROR_NOARG;
nb += strlen(argv[i]) + 1;
}
dst = malloc(nb);
argv2 = (void *) dst;
dst += (argc + 1) * sizeof(*argv);
for (i = 0; i < argc; i++) {
argv2[i] = dst;
dst += strlen(strcpy(dst, argv[i])) + 1;
}
argv2[argc] = NULL;
*argvPtr = argv2;
*argcPtr = argc;
return 0;
}
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
{
const char * src;
char quote = '\0';
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0;
int buflen = strlen(s) + 1;
char *buf0 = calloc(buflen, 1);
char *buf = buf0;
argv[argc] = buf;
for (src = s; *src; src++) {
if (quote == *src) {
quote = '\0';
} else if (quote) {
if (*src == '\\') {
src++;
if (!*src) {
free(argv);
free(buf0);
return POPT_ERROR_BADQUOTE;
}
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (isspace(*src)) {
if (*argv[argc]) {
buf++, argc++;
if (argc == argvAlloced) {
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
argv = realloc(argv, sizeof(*argv) * argvAlloced);
}
argv[argc] = buf;
}
} else switch (*src) {
case '"':
case '\'':
quote = *src;
break;
case '\\':
src++;
if (!*src) {
free(argv);
free(buf0);
return POPT_ERROR_BADQUOTE;
}
/*@fallthrough@*/
default:
*buf++ = *src;
break;
}
}
if (strlen(argv[argc])) {
argc++, buf++;
}
(void) poptDupArgv(argc, argv, argcPtr, argvPtr);
free(argv);
free(buf0);
return 0;
}

55
popt/system.h Normal file
View File

@@ -0,0 +1,55 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#if HAVE_MCHECK_H
#include <mcheck.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef __NeXT
/* access macros are not declared in non posix mode in unistd.h -
don't try to use posix on NeXTstep 3.3 ! */
#include <libc.h>
#endif
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#elif defined(__GNUC__) && defined(__STRICT_ANSI__)
#define alloca __builtin_alloca
#endif
/*@only@*/ char * xstrdup (const char *str);
#if HAVE_MCHECK_H && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
#define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str)))
#else
#define xstrdup(_str) strdup(_str)
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
#include "popt.h"

View File

@@ -1,5 +1,6 @@
/*
Copyright (C) Andrew Tridgell 1996
/* -*- 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
@@ -82,14 +83,15 @@ static void delete_one(struct file_struct *f)
{
if (!S_ISDIR(f->mode)) {
if (robust_unlink(f_name(f)) != 0) {
rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting %s\n",f_name(f));
}
} else {
if (do_rmdir(f_name(f)) != 0) {
if (errno != ENOTEMPTY && errno != EEXIST)
rprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
rprintf(FERROR,"delete_one: rmdir %s: %s\n",
f_name(f), strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting directory %s\n",f_name(f));
}
@@ -108,13 +110,14 @@ void delete_files(struct file_list *flist)
int i, j;
char *name;
extern int module_id;
extern int ignore_errors;
extern int max_delete;
static int deletion_count;
if (cvs_exclude)
add_cvs_excludes();
if (io_error && !lp_ignore_errors(module_id)) {
if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
return;
}
@@ -176,7 +179,7 @@ static int get_tmpname(char *fnametmp, char *fname)
rprintf(FERROR,"filename too long\n");
return 0;
}
slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
@@ -189,11 +192,11 @@ static int get_tmpname(char *fnametmp, char *fname)
if (f) {
*f = 0;
slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
}
return 1;
@@ -301,6 +304,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
int fd1,fd2;
STRUCT_STAT st;
char *fname;
char template[MAXPATHLEN];
char fnametmp[MAXPATHLEN];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
@@ -368,7 +372,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
if ((fd1 == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
compare_dest,fname);
fnamecmp = fnamecmpbuf;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
@@ -409,17 +413,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
continue;
}
/* mktemp is deliberately used here instead of mkstemp.
because O_EXCL is used on the open, the race condition
is not a problem or a security hole, and we want to
control the access permissions on the created file. */
if (NULL == do_mktemp(fnametmp)) {
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
receive_data(f_in,buf,-1,NULL,file->length);
if (buf) unmap_file(buf);
if (fd1 != -1) close(fd1);
continue;
}
strlcpy(template, fnametmp, sizeof(template));
/* we initially set the perms without the
setuid/setgid bits to ensure that there is no race
@@ -427,16 +421,21 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
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_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & INITACCESSPERMS);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
if (fd2 == -1) {
rprintf(FERROR,"mkstemp %s failed\n",fnametmp);
receive_data(f_in,buf,-1,NULL,file->length);
if (buf) unmap_file(buf);
continue;
}
/* in most cases parent directories will already exist
because their information should have been previously
transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp) == 0) {
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & INITACCESSPERMS);
strlcpy(fnametmp, template, sizeof(fnametmp));
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno));

16
rsync.c
View File

@@ -43,7 +43,7 @@ void free_sums(struct sum_struct *s)
/*
* delete a file or directory. If force_delet is set then delete
* delete a file or directory. If force_delete is set then delete
* recursively
*/
int delete_file(char *fname)
@@ -62,27 +62,26 @@ int delete_file(char *fname)
ret = do_stat(fname, &st);
#endif
if (ret) {
rprintf(FERROR,"stat(%s) : %s\n", fname, strerror(errno));
return -1;
}
if (!S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
rprintf(FERROR,"unlink(%s) : %s\n", fname, strerror(errno));
rprintf(FERROR,"delete_file: unlink(%s) : %s\n", fname, strerror(errno));
return -1;
}
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
if (!force_delete || !recurse ||
(errno != ENOTEMPTY && errno != EEXIST)) {
rprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
return -1;
}
/* now we do a recsursive delete on the directory ... */
d = opendir(fname);
if (!d) {
rprintf(FERROR,"opendir(%s): %s\n",
rprintf(FERROR,"delete_file: opendir(%s): %s\n",
fname,strerror(errno));
return -1;
}
@@ -92,7 +91,7 @@ int delete_file(char *fname)
if (strcmp(dname,".")==0 ||
strcmp(dname,"..")==0)
continue;
slprintf(buf, sizeof(buf), "%s/%s", fname, dname);
snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
if (verbose > 0)
rprintf(FINFO,"deleting %s\n", buf);
if (delete_file(buf) != 0) {
@@ -104,7 +103,7 @@ int delete_file(char *fname)
closedir(d);
if (do_rmdir(fname) != 0) {
rprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
return -1;
}
@@ -163,7 +162,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
}
if (preserve_times && !S_ISLNK(st->st_mode) &&
st->st_mtime != file->modtime) {
cmp_modtime(st->st_mtime, file->modtime) != 0) {
/* don't complain about not setting times on directories
because some filesystems can't do it */
if (set_modtime(fname,file->modtime) != 0 &&
@@ -227,6 +226,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
void sig_int(void)
{
rprintf(FINFO,"\nrsync.c:sig_int() called.\n");
exit_cleanup(RERR_SIGNAL);
}

116
rsync.h
View File

@@ -1,6 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) by Andrew Tridgell 1996, 2000
Copyright (C) Paul Mackerras 1996
Copyright (C) 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
@@ -17,6 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define False 0
#define True 1
@@ -47,7 +49,18 @@
#define SAME_TIME (1<<7)
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 23
#define PROTOCOL_VERSION 25
/* 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
@@ -63,7 +76,10 @@
#define MPLEX_BASE 7
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
/* 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. */
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#include "errcode.h"
@@ -77,12 +93,6 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
#include <sys/types.h>
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
#include "lib/getopt.h"
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -258,9 +268,11 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
#endif
#if HAVE_SHORT_INO_T
#define INO_T uint32
# define INO_T uint32
#elif HAVE_INO_T
# define INO_T ino_t
#else
#define INO_T ino_t
# define INO_T unsigned
#endif
#ifndef MIN
@@ -305,10 +317,20 @@ struct file_struct {
};
#define ARENA_SIZE (32 * 1024)
struct string_area {
char *base;
char *end;
char *current;
struct string_area *next;
};
struct file_list {
int count;
int malloced;
struct file_struct **files;
struct string_area *string_area;
};
struct sum_buf {
@@ -334,7 +356,6 @@ struct map_struct {
};
struct exclude_struct {
char *orig;
char *pattern;
int regular_exp;
int fnmatch_flags;
@@ -366,9 +387,27 @@ static inline int flist_up(struct file_list *flist, int i)
}
#include "byteorder.h"
#include "version.h"
#include "proto.h"
#include "lib/mdfour.h"
#include "lib/permstring.h"
/* We have replacement versions of these if they're missing. */
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...);
#endif
#ifndef HAVE_VASPRINTF
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);
#endif
#if !defined(HAVE_SNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
int snprintf(char *str,size_t count,const char *fmt,...);
#endif
#if !HAVE_STRERROR
extern char *sys_errlist[];
@@ -457,6 +496,22 @@ extern int errno;
#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
#endif
/* work out what fcntl flag to use for non-blocking */
#ifdef O_NONBLOCK
# define NONBLOCK_FLAG O_NONBLOCK
#elif defined(SYSV)
# define NONBLOCK_FLAG O_NDELAY
#else
# define NONBLOCK_FLAG FNDELAY
#endif
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
@@ -478,6 +533,14 @@ extern int errno;
#endif
;
/* This is just like rprintf, but it also tries to print some
* representation of the error code. Normally errcode = errno. */
void rsyserr(enum logcode, int, const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 3, 4)))
#endif
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif
@@ -491,4 +554,31 @@ size_t strlcpy(char *d, const char *s, size_t bufsize);
size_t strlcat(char *d, const char *s, size_t bufsize);
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF))
#endif
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
extern int verbose;
extern struct global_opts {
/** Network address family. **/
int af_hint;
/** Do not go into the background when run as --daemon. Good
* for debugging and required for running as a service on W32,
* or under Unix process-monitors. **/
int no_detach;
} global_opts;
#ifndef HAVE_INET_NTOP
const char *
inet_ntop(int af, const void *src, char *dst, size_t size);
#endif /* !HAVE_INET_NTOP */
#ifndef HAVE_INET_PTON
int isc_net_pton(int af, const char *src, void *dst);
#endif

196
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(1 Mar 1999)()()
manpage(rsync)(1)(29 May 2001)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpagesynopsis()
@@ -223,7 +223,7 @@ verb(
-r, --recursive recurse into directories
-R, --relative use relative path names
-b, --backup make backups (default ~ suffix)
--backup-dir=DIR put backups in the specified directory
--backup-dir make backups into this directory
--suffix=SUFFIX override backup suffix
-u, --update update only (don't overwrite newer files)
-l, --links preserve soft links
@@ -248,6 +248,7 @@ verb(
--delete delete files that don't exist on the sending side
--delete-excluded also delete excluded files on the receiving side
--delete-after delete after transferring, not before
--ignore-errors delete even if there are IO errors
--max-delete=NUM don't delete more than NUM files
--partial keep partially transferred files
--force force deletion of directories even if not empty
@@ -255,6 +256,7 @@ verb(
--timeout=TIME set IO timeout in seconds
-I, --ignore-times don't exclude files that match length and time
--size-only only use file size when determining if a file should be transferred
--modify-window=NUM Timestamp window (seconds) for file match (default=0)
-T --temp-dir=DIR create temporary files in directory DIR
--compare-dest=DIR also compare destination files relative to DIR
-P equivalent to --partial --progress
@@ -265,14 +267,21 @@ verb(
--include-from=FILE don't exclude patterns listed in FILE
--version print version number
--daemon run as a rsync daemon
--address bind to the specified address
--no-detach do not detach from the parent
--address=ADDRESS bind to the specified address
--config=FILE specify alternate rsyncd.conf file
--port=PORT specify alternate rsyncd port number
--blocking-io use blocking IO for the remote shell
--stats give some file transfer stats
--progress show progress during transfer
--log-format=FORMAT log file transfers using specified format
--password-file=FILE get password from FILE
--bwlimit=KBPS limit I/O bandwidth, KBytes per second
-f, --read-batch=FILE read batch file
-F, --write-batch write batch file
-h, --help show this help screen
)
manpageoptions()
@@ -313,14 +322,26 @@ regardless of timestamp. This is useful when starting to use rsync
after using another mirroring system which may not preserve timestamps
exactly.
dit(bf(--modify-window)) When comparing two timestamps rsync treats
the timestamps as being equal if they are within the value of
modify_window. This is normally zero, but you may find it useful to
set this to a larger value in some situations. In particular, when
transferring to/from FAT filesystems which cannot represent times with
a 1 second resolution this option is useful.
dit(bf(-c, --checksum)) This forces the sender to checksum all files using
a 128-bit MD4 checksum before transfer. The checksum is then
explicitly checked on the receiver and any files of the same name
which already exist and have the same checksum and size on the
receiver are skipped. This option can be quite slow.
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick way
of saying you want recursion and want to preserve everything.
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick
way of saying you want recursion and want to preserve almost
everything.
Note however that bf(-a) bf(does not preserve hardlinks), because
finding multiply-linked files is expensive. You must separately
specify bf(-H).
dit(bf(-r, --recursive)) This tells rsync to copy directories
recursively. If you don't specify this then rsync won't copy
@@ -384,8 +405,11 @@ are in the list of files being sent.
This option can be quite slow, so only use it if you need it.
dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
is not used and the whole file is sent as-is instead. This may be
useful when using rsync with a local machine.
is not used and the whole file is sent as-is instead. The transfer may be
faster if this option is used when the bandwidth between the source and
target machines is higher than the bandwidth to disk (especially when the
"disk" is actually a networked file system). This is the default when both
the source and target are on the local machine.
dit(bf(-p, --perms)) This option causes rsync to update the remote
permissions to be the same as the local permissions.
@@ -448,7 +472,7 @@ If the sending side detects any IO errors then the deletion of any
files at the destination will be automatically disabled. This is to
prevent temporary filesystem failures (such as NFS errors) on the
sending side causing a massive deletion of files on the
destination.
destination. You can override this with the --ignore-errors option.
dit(bf(--delete-excluded)) In addition to deleting the files on the
receiving side that are not on the sending side, this tells rsync to also
@@ -459,6 +483,9 @@ transferring files to try to ensure that there is sufficient space on
the receiving filesystem. If you want to delete after transferring
then use the --delete-after switch.
dit(bf(--ignore-errors)) Tells --delete to go ahead and delete files
even when there are IO errors.
dit(bf(--force)) This options tells rsync to delete directories even if
they are not empty. This applies to both the --delete option and to
cases where rsync tries to copy a normal file but the destination
@@ -467,7 +494,7 @@ contains a directory of the same name.
Since this option was added, deletions were reordered to be done depth-first
so it is hardly ever needed anymore except in very obscure cases.
dit(bf(-B , --block_size=BLOCKSIZE)) This controls the block size used in
dit(bf(-B , --block-size=BLOCKSIZE)) This controls the block size used in
the rsync algorithm. See the technical report for details.
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
@@ -478,6 +505,8 @@ like to instead use ssh because of its high security.
You can also choose the remote shell program using the RSYNC_RSH
environment variable.
See also the --blocking-io option which is affected by this option.
dit(bf(--rsync-path=PATH)) Use this to specify the path to the copy of
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
@@ -494,9 +523,9 @@ 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 filenames listed in the file FILE to
the exclude list. Blank lines in FILE and lines starting with ';' or '#'
are ignored.
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.
dit(bf(--include=PATTERN)) This option tells rsync to not exclude the
specified pattern of filenames. This is useful as it allows you to
@@ -549,20 +578,20 @@ scratch directory when creating temporary copies of the files
transferred on the receiving side. The default behavior is to create
the temporary files in the receiving directory.
dit(bf(--compare-dest=DIR)) This option instructs rsync to use DIR as an
additional directory to compare destination files against when doing
transfers. This is useful for doing transfers to a new destination while
leaving existing files intact, and then doing a flash-cutover when all
files have been successfully transferred (for example by moving directories
around and removing the old directory, although this requires also doing
the transfer with -I to avoid skipping files that haven't changed). This
option increases the usefulness of --partial because partially transferred
files will remain in the new temporary destination until they have a chance
to be completed. If DIR is a relative path, it is relative to the
destination directory.
dit(bf(--compare-dest=DIR)) This option instructs rsync to use DIR on
the destination machine as an additional directory to compare destination
files against when doing transfers. This is useful for doing transfers to
a new destination while leaving existing files intact, and then doing a
flash-cutover when all files have been successfully transferred (for
example by moving directories around and removing the old directory,
although this requires also doing the transfer with -I to avoid skipping
files that haven't changed). This option increases the usefulness of
--partial because partially transferred files will remain in the new
temporary destination until they have a chance to be completed. 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 source file(s) which it sends to the destination machine. This
the files that it sends to the destination machine. This
option is useful on slow links. The compression method used is the
same method that gzip uses.
@@ -596,6 +625,15 @@ config file (/etc/rsyncd.conf) on each connect made by a client and
respond to requests accordingly. See the rsyncd.conf(5) man page for more
details.
dit(bf(--no-detach)) When running as a daemon, this option instructs
rsync to not detach itself and become a background process. This
option is required when running as a service on Cygwin, and may also
be useful when rsync is supervised by a program such as
bf(daemontools) or AIX's bf(System Resource Controller).
bf(--no-detach) is also recommended when rsync is run under a
debugger. This option has no effect if rsync is run from inetd or
sshd.
dit(bf(--address)) By default rsync will bind to the wildcard address
when run as a daemon with the --daemon option or when connecting to a
rsync server. The --address option allows you to specify a specific IP
@@ -609,6 +647,12 @@ specified.
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. Ssh prefers blocking IO.
dit(bf(--log-format=FORMAT)) This allows you to specify exactly what the
rsync client logs to stdout on a per-file basis. The log format is
specified using the same format conventions as the log format option in
@@ -642,6 +686,19 @@ transport, not when using a remote shell as the transport. The file
must not be world readable. It should contain just the password as a
single line.
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
transfer rate in kilobytes per second. This option is most effective when
using rsync with large files (several megabytes and up). Due to the nature
of rsync transfers, blocks of data are sent, then if rsync determines the
transfer was too fast, it will wait before sending the next data block. The
result is an average transfer rate equalling the specified limit. A value
of zero specifies no limit.
dit(bf(--read-batch)) Apply a previously generated change batch.
dit(bf(--write-batch)) Generate a set of files that can be transferred
as a batch update.
enddit()
manpagesection(EXCLUDE PATTERNS)
@@ -652,12 +709,16 @@ selection of which files to transfer and which files to skip.
rsync builds a ordered list of include/exclude options as specified on
the command line. When a filename is encountered, rsync checks the
name against each exclude/include pattern in turn. The first matching
pattern is acted on. If it is an exclude pattern than that file is
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.
Note that the --include and --exclude options take one pattern
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.
Note also that the --include and --exclude options take one pattern
each. To add multiple patterns use the --include-from and
--exclude-from options or multiple --include and --exclude options.
@@ -666,9 +727,11 @@ 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 whereas foo would match any file
called foo anywhere in the tree.
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"
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.
it() if the pattern ends with a / then it will only match a
directory, not a file, link or device.
@@ -677,12 +740,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() 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. Furthermore, if
the pattern includes a double asterisk "**" then all wildcards in
the pattern will match slashes, otherwise they will stop at slashes.
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 starts with "+ " (a plus followed by a space)
then it is always considered an include pattern, even if specified as
@@ -699,7 +765,14 @@ itemize(
The +/- rules are most useful in exclude lists, allowing you to have a
single exclude list that contains both include and exclude options.
Here are some examples:
If you end an exclude list with --exclude '*', note that since the
algorithm is applied recursively that unless you explicitly include
parent directories of files you want to include then the algorithm
will stop at the parent directories and never see the files below
them. To include all directories, use --include '*/' before the
--exclude '*'.
Here are some exclude/include examples:
itemize(
it() --exclude "*.o" would exclude all filenames matching *.o
@@ -716,6 +789,29 @@ itemize(
it would be excluded by the "*")
)
manpagesection(BATCH MODE)
The following call generates 4 files that encapsulate the information
for synchronizing the contents of bf(target_dir) with the updates found in
bf(src_dir)
quote(
$ rsync -F [other rsync options here] \nl()
/somewhere/src_dir /somewhere/target_dir
)
The generated files are labeled with a common timestamp:
itemize(
it() bf(rsync_argvs.<timestamp>) command-line arguments
it() bf(rsync_flist.<timestamp>) rsync internal file metadata
it() bf(rsync_csums.<timestamp>) rsync checksums
it() bf(rsync_delta.<timestamp>) data blocks for file update & change
)
See bf(http://www.ils.unc.edu/i2dsi/unc_rsync+.html) for papers and technical
reports.
manpagesection(DIAGNOSTICS)
rsync occasionally produces error messages that may seem a little
@@ -739,6 +835,33 @@ it. The most common cause is incorrectly configured shell startup
scripts (such as .cshrc or .profile) that contain output statements
for non-interactive logins.
If you are having trouble debugging include and exclude patterns, then
try specifying the -vv option. At this level of verbosity rsync will
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
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
enddit()
manpagesection(ENVIRONMENT VARIABLES)
startdit()
@@ -799,7 +922,9 @@ rsync is distributed under the GNU public license. See the file
COPYING for details.
A WEB site is available at
url(http://rsync.samba.org/)(http://rsync.samba.org/)
url(http://rsync.samba.org/)(http://rsync.samba.org/). The site
includes an FAQ-O-Matic which may cover questions unanswered by this
manual page.
The primary ftp site for rsync is
url(ftp://rsync.samba.org/pub/rsync)(ftp://rsync.samba.org/pub/rsync).
@@ -822,3 +947,6 @@ rsync was written by Andrew Tridgell and Paul Mackerras. They may be
contacted via email at tridge@samba.org and
Paul.Mackerras@cs.anu.edu.au
rsync is now also maintained by Martin Pool <mbp@samba.org>

469
rsync3.txt Normal file
View File

@@ -0,0 +1,469 @@
-*- indented-text -*-
Notes towards a new version of rsync
Martin Pool <mbp@samba.org>, September 2001.
Good things about the current implementation:
- Widely known and adopted.
- Fast/efficient, especially for moderately small sets of files over
slow links (transoceanic or modem.)
- Fairly reliable.
- The choice of runnning over a plain TCP socket or tunneling over
ssh.
- rsync operations are idempotent: you can always run the same
command twice to make sure it worked properly without any fear.
(Are there any exceptions?)
- Small changes to files cause small deltas.
- There is a way to evolve the protocol to some extent.
- rdiff and rsync --write-batch allow generation of standalone patch
sets. rsync+ is pretty cheesy, though. xdelta seems cleaner.
- Process triangle is creative, but seems to provoke OS bugs.
- "Morning-after property": you don't need to know anything on the
local machine about the state of the remote machine, or about
transfers that have been done in the past.
- You can easily push or pull simply by switching the order of
files.
- The "modules" system has some neat features compared to
e.g. Apache's per-directory configuration. In particular, because
you can set a userid and chroot directory, there is strong
protection between different modules. I haven't seen any calls
for a more flexible system.
Bad things about the current implementation:
- Persistent and hard-to-diagnose hang bugs remain
- Protocol is sketchily documented, tied to this implementation, and
hard to modify/extend
- Both the program and the protocol assume a single non-interactive
one-way transfer
- A list of all files are held in memory for the entire transfer,
which cripples scalability to large file trees
- Opening a new socket for every operation causes problems,
especially when running over SSH with password authentication.
- Renamed files are not handled: the old file is removed, and the
new file created from scratch.
- The versioning approach assumes that future versions of the
program know about all previous versions, and will do the right
thing.
- People always get confused about ':' vs '::'
- Error messages can be cryptic.
- Default behaviour is not intuitive: in too many cases rsync will
happily do nothing. Perhaps -a should be the default?
- People get confused by trailing slashes, though it's hard to think
of another reasonable way to make this necessary distinction
between a directory and its contents.
Protocol philosophy:
*The* big difference between protocols like HTTP, FTP, and NFS is
that their fundamental operations are "read this file", "delete
this file", and "make this directory", whereas rsync is "make this
directory like this one".
Questionable features:
These are neat, but not necessarily clean or worth preserving.
- The remote rsync can be wrapped by some other program, such as in
tridge's rsync-mail scripts. The general feature of sending and
retrieving mail over rsync is good, but this is perhaps not the
right way to implement it.
Desirable features:
These don't really require architectural changes; they're just
something to keep in mind.
- Synchronize ACLs and extended attributes
- Anonymous servers should be efficient
- Code should be portable to non-UNIX systems
- Should be possible to document the protocol in RFC form
- --dry-run option
- IPv6 support. Pretty straightforward.
- Allow the basis and destination files to be different. For
example, you could use this when you have a CD-ROM and want to
download an updated image onto a hard drive.
- Efficiently interrupt and restart a transfer. We can write a
checkpoint file that says where we're up to in the filesystem.
Alternatively, as long as transfers are idempotent, we can just
restart the whole thing. [NFSv4]
- Scripting support.
- Propagate atimes and do not modify them. This is very ugly on
Unix. It might be better to try to add O_NOATIME to kernels, and
call that.
- Unicode. Probably just use UTF-8 for everything.
- Open authentication system. Can we use PAM? Is SASL an adequate
mapping of PAM to the network, or useful in some other way?
- Resume interrupted transfers without the --partial flag. We need
to leave the temporary file behind, and then know to use it. This
leaves a risk of large temporary files accumulating, which is not
good. Perhaps it should be off by default.
- tcpwrappers support. Should be trivial; can already be done
through tcpd or inetd.
- Socks support built in. It's not clear this is any better than
just linking against the socks library, though.
- When run over SSH, invoke with predictable command-line arguments,
so that people can restrict what commands sshd will run. (Is this
really required?)
- Comparison mode: give a list of which files are new, gone, or
different. Set return code depending on whether anything has
changed.
- Internationalized messages (gettext?)
- Optionally use real regexps rather than globs?
- Show overall progress. Pretty hard to do, especially if we insist
on not scanning the directory tree up front.
Regression testing:
- Support automatic testing.
- Have hard internal timeouts against hangs.
- Be deterministic.
- Measure performance.
Hard links:
At the moment, we can recreate hard links, but it's a bit
inefficient: it depends on holding a list of all files in the tree.
Every time we see a file with a linkcount >1, we need to search for
another known name that has the same (fsid,inum) tuple. We could do
that more efficiently by keeping a list of only files with
linkcount>1, and removing files from that list as all their names
become known.
Command-line options:
We have rather a lot at the moment. We might get more if the tool
becomes more flexible. Do we need a .rc or configuration file?
That wouldn't really fit with its pattern of use: cp and tar don't
have them, though ssh does.
Scripting issues:
- Perhaps support multiple scripting languages: candidates include
Perl, Python, Tcl, Scheme (guile?), sh, ...
- Simply running a subprocess and looking at its stdout/exit code
might be sufficient, though it could also be pretty slow if it's
called often.
- There are security issues about running remote code, at least if
it's not running in the users own account. So we can either
disallow it, or use some kind of sandbox system.
- Python is a good language, but the syntax is not so good for
giving small fragments on the command line.
- Tcl is broken Lisp.
- Lots of sysadmins know Perl, though Perl can give some bizarre or
confusing errors. The built in stat operators and regexps might
be useful.
- Sadly probably not enough people know Scheme.
- sh is hard to embed.
Scripting hooks:
- Whether to transfer a file
- What basis file to use
- Logging
- Whether to allow transfers (for public servers)
- Authentication
- Locking
- Cache
- Generating backup path/name.
- Post-processing of backups, e.g. to do compression.
- After transfer, before replacement: so that we can spit out a diff
of what was changed, or kick off some kind of reconciliation
process.
VFS:
Rather than talking straight to the filesystem, rsyncd talks through
an internal API. Samba has one. Is it useful?
- Could be a tidy way to implement cached signatures.
- Keep files compressed on disk?
Interactive interface:
- Something like ncFTP, or integration into GNOME-vfs. Probably
hold a single socket connection open.
- Can either call us as a separate process, or as a library.
- The standalone process needs to produce output in a form easily
digestible by a calling program, like the --emacs feature some
have. Same goes for output: rpm outputs a series of hash symbols,
which are easier for a GUI to handle than "\r30% complete"
strings.
- Yow! emacs support. (You could probably build that already, of
course.) I'd like to be able to write a simple script on a remote
machine that rsyncs it to my workstation, edits it there, then
pushes it back up.
Pie-in-the-sky features:
These might have a severe impact on the protocol, and are not
clearly in our core requirements. It looks like in many of them
having scripting hooks will allow us
- Transport over UDP multicast. The hard part is handling multiple
destinations which have different basis files. We can look at
multicast-TFTP for inspiration.
- Conflict resolution. Possibly general scripting support will be
sufficient.
- Integrate with locking. It's hard to see a good general solution,
because Unix systems have several locking mechanisms, and grabbing
the lock from programs that don't expect it could cause deadlocks,
timeouts, or other problems. Scripting support might help.
- Replicate in place, rather than to a temporary file. This is
dangerous in the case of interruption, and it also means that the
delta can't refer to blocks that have already been overwritten.
On the other hand we could semi-trivially do this at first by
simply generating a delta with no copy instructions.
- Replicate block devices. Most of the difficulties here are to do
with replication in place, though on some systems we will also
have to do I/O on block boundaries.
- Peer to peer features. Flavour of the year. Can we think about
ways for clients to smoothly and voluntarily become servers for
content they receive?
- Imagine a situation where the destination has a much faster link
to the cloud than the source. In this case, Mojo Nation downloads
interleaved blocks from several slower servers. The general
situation might be a way for a master rsync process to farm out
tasks to several subjobs. In this particular case they'd need
different sockets. This might be related to multicast.
Unlikely features:
- Allow remote source and destination. If this can be cleanly
designed into the protocol, perhaps with the remote machine acting
as a kind of echo, then it's good. It's uncommon enough that we
don't want to shape the whole protocol around it, though.
In fact, in a triangle of machines there are two possibilities:
all traffic passes from remote1 to remote2 through local, or local
just sets up the transfer and then remote1 talks to remote2. FTP
supports the second but it's not clearly good. There are some
security problems with being able to instruct one machine to open
a connection to another.
In favour of evolving the protocol:
- Keeping compatibility with existing rsync servers will help with
adoption and testing.
- We should at the very least be able to fall back to the new
protocol.
- Error handling is not so good.
In favour of using a new protocol:
- Maintaining compatibility might soak up development time that
would better go into improving a new protocol.
- If we start from scratch, it can be documented as we go, and we
can avoid design decisions that make the protocol complex or
implementation-bound.
Error handling:
- Errors should come back reliably, and be clearly associated with
the particular file that caused the problem.
- Some errors ought to cause the whole transfer to abort; some are
just warnings. If any errors have occurred, then rsync ought to
return an error.
Concurrency:
- We want to keep the CPU, filesystem, and network as full as
possible as much of the time as possible.
- We can do nonblocking network IO, but not so for disk.
- It makes sense to on the destination be generating signatures and
applying patches at the same time.
- Can structure this with nonblocking, threads, separate processes,
etc.
Uses:
- Mirroring software distributions:
- Synchronizing laptop and desktop
- NFS filesystem migration/replication. See
http://www.ietf.org/proceedings/00jul/00july-133.htm#P24510_1276764
- Sync with PDA
- Network backup systems
- CVS filemover
Conflict resolution:
- Requires application-specific knowledge. We want to provide
policy, rather than mechanism.
- Possibly allowing two-way migration across a single connection
would be useful.
Moved files: <http://rsync.samba.org/cgi-bin/rsync.fom?file=44>
- There's no trivial way to detect renamed files, especially if they
move between directories.
- If we had a picture of the remote directory from last time on
either machine, then the inode numbers might give us a hint about
files which may have been renamed.
- Files that are renamed and not modified can be detected by
examining the directory listing, looking for files with the same
size/date as the origin.
Filesystem migration:
NFSv4 probably wants to migrate file locks, but that's not really
our problem.
Atomic updates:
The NFSv4 working group wants atomic migration. Most of the
responsibility for this lies on the NFS server or OS.
If migrating a whole tree, then we could do a nearly-atomic rename
at the end. This ties in to having separate basis and destination
files.
There's no way in Unix to replace a whole set of files atomically.
However, if we get them all onto the destination machine and then do
the updates quickly it would greatly reduce the window.
Scalability:
We should aim to work well on machines in use in a year or two.
That probably means transfers of many millions of files in one
batch, and gigabytes or terabytes of data.
For argument's sake: at the low end, we want to sync ten files for a
total of 10kb across a 1kB/s link. At the high end, we want to sync
1e9 files for 1TB of data across a 1GB/s link.
On the whole CPU usage is not normally a limiting factor, if only
because running over SSH burns a lot of cycles on encryption.
Perhaps have resource throttling without relying on rlimit.
Streaming:
A big attraction of rsync is that there are few round-trip delays:
basically only one to get started, and then everything is
pipelined. This is a problem with FTP, and NFS (at least up to
v3). NFSv4 can pipeline operations, but building on that is
probably a bit complicated.
Related work:
- mirror.pl http://freshmeat.net/project/mirror/
- ProFTPd
- Apache
- http://freshmeat.net/search/?site=Freshmeat&q=mirror&section=projects
- BitTorrent -- p2p mirroring
http://bitconjurer.org/BitTorrent/

View File

@@ -44,7 +44,12 @@ in string values.
manpagesection(LAUNCHING THE RSYNC DAEMON)
The rsync daemon is launched by specifying the --daemon option to
rsync. The daemon must run with root privileges.
rsync.
The daemon must run with root privileges if you wish to use chroot, to
bind to a port numbered under 1024 (as is the default 873), or to set
file ownership. Otherwise, it must just have permission to read and
write the appropriate data, log, and lock files.
You can launch it either via inetd or as a stand-alone daemon. If run
as a daemon then just run the command "rsync --daemon" from a suitable
@@ -128,8 +133,11 @@ dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges and
of not being able to follow symbolic links outside of the new root path.
The default is to use chroot.
of not being able to follow symbolic links outside of the new root path
when reading. When "use chroot" is false, for security reasons
symlinks may only be relative paths pointing to other files within the
root path, and leading slashes are removed from absolute paths. The
default for "use chroot" is true.
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow
@@ -156,12 +164,13 @@ for modules to be listable.
dit(bf(uid)) The "uid" option specifies the user name or user id that
file transfers to and from that module should take place as when the daemon
was run as root. In combination with the "gid" option this determines what
file permissions are available. The default is the user "nobody".
file permissions are available. The default is uid -2, which is normally
the user "nobody".
dit(bf(gid)) The "gid" option specifies the group name or group id that
file transfers to and from that module should take place as when the daemon
was run as root. This complements the "uid" option. The default is the
group "nobody".
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
@@ -199,13 +208,14 @@ 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.
dit(bf(auth users)) The "auth users" option specifies a comma
and space separated list of usernames that will be allowed to connect
to this module. The usernames do not need to exist on the local
system. If "auth users" is set then the client will be challenged to
supply a username and password to connect to the module. A challenge
response authentication protocol is used for this exchange. The plain
text usernames are passwords are stored in the file specified by the
dit(bf(auth users)) The "auth users" option specifies a comma and
space separated list of usernames that will be allowed to connect to
this module. The usernames do not need to exist on the local
system. The usernames may also contain shell wildcard characters. If
"auth users" is set then the client will be challenged to supply a
username and password to connect to the module. A challenge response
authentication protocol is used for this exchange. The plain text
usernames are passwords are stored in the file specified by the
"secrets file" option. The default is for all users to be able to
connect without a password (this is called "anonymous rsync").
@@ -220,7 +230,8 @@ limit the length of passwords that can be typed at the client end, so
you may find that passwords longer than 8 characters don't work.
There is no default for the "secrets file" option, you must choose a name
(such as tt(/etc/rsyncd.secrets)).
(such as tt(/etc/rsyncd.secrets)). The file must normally not be readable
by "other"; see "strict modes".
dit(bf(strict modes)) The "strict modes" option determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
@@ -282,6 +293,11 @@ to a temporary resource shortage or other IO error. In some cases this
test is counter productive so you can use this option to turn off this
behaviour.
dit(bf(ignore nonreadable)) This tells the rsync server to completely
ignore files that are not readable by the user. This is useful for
public archives that may have some non-readable files among the
directories, and the sysadmin doesn't want those files to be seen at all.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. If you want to customize the log formats look at
@@ -342,7 +358,7 @@ The "dont compress" option takes a space separated list of
case-insensitive wildcard patterns. Any source filename matching one
of the patterns will not be compressed during transfer.
The default setting is verb(*.gz *.tgz *.zip *.z *.rpm *.deb)
The default setting is verb(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
enddit()
@@ -382,7 +398,7 @@ gid = nobody nl()
use chroot = no nl()
max connections = 4 nl()
syslog facility = local5 nl()
pid file = /etc/rsyncd.pid
pid file = /var/run/rsyncd.pid
verb([ftp]
path = /var/ftp/pub

26
rsyncsh.txt Normal file
View File

@@ -0,0 +1,26 @@
rsyncsh
Copyright (C) 2001 by Martin Pool
This is a quick hack to build an interactive shell around rsync, the
same way we have the ftp, lftp and ncftp programs for the FTP
protocol. The key application for this is connecting to a public
rsync server, such as rsync.kernel.org, change down through and list
directories, and finally pull down the file you want.
rsync is somewhat ill-at-ease as an interactive operation, since every
network connection is used to carry out exactly one operation. rsync
kind of "forks across the network" passing the options and filenames
to operate upon, and the connection is closed when the transfer is
complete. (This might be fixed in the future, either by adapting the
current protocol to allow chained operations over a single socket, or
by writing a new protocol that better supports interactive use.)
So, rsyncsh runs a new rsync command and opens a new socket for every
(network-based) command you type.
This has two consequences. Firstly, there is more command latency
than is really desirable. More seriously, if the connection cannot be
done automatically, because for example it uses SSH with a password,
then you will need to enter the password every time. We might even
fix this in the future, though, by having a way to automatically feed
the password to SSH if it's entered once.

220
runtests.sh Executable file
View File

@@ -0,0 +1,220 @@
#! /bin/sh
# Copyright (C) 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 version
# 2 as published by the Free Software Foundation.
#
# 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# rsync top-level test script -- this invokes all the other more
# detailed tests in order. This script can either be called by `make
# check' or `make installcheck'. `check' runs against the copies of
# the program and other files in the build directory, and
# `installcheck' against the installed copy of the program.
# In either case we need to also be able to find the source directory,
# since we read test scripts and possibly other information from
# there.
# Whenever possible, informational messages are written to stdout and
# error messages to stderr. They're separated out by the build farm
# display scripts.
# According to the GNU autoconf manual, the only valid place to set up
# directory locations is through Make, since users are allowed to (try
# to) change their mind on the Make command line. So, Make has to
# pass in all the values we need.
# For other configured settings we read ./config.sh, which tells us
# about shell commands on this machine and similar things.
# rsync_bin gives the location of the rsync binary. This is either
# builddir/rsync if we're testing an uninstalled copy, or
# install_prefix/bin/rsync if we're testing an installed copy. On the
# build farm rsync will be installed, but into a scratch /usr.
# srcdir gives the location of the source tree, which lets us find the
# build scripts. At the moment we assume we are invoked from the
# source directory.
# This script must be invoked from the build directory.
# A scratch directory, 'testtmp', is created in the build directory to
# hold working files.
# This script also uses the $loglevel environment variable. 1 is the
# default value, and 10 the most verbose. You can set this from the
# Make command line. It's also set by the build farm to give more
# detail for failing builds.
# NOTES FOR TEST CASES:
# Each test case runs in its own shell.
# Exit codes from tests:
# 1 tests failed
# 2 error in starting tests
# 77 this test skipped (random value unlikely to happen by chance, same as
# automake)
# HOWEVER, the overall exit code to the farm is different: we return
# the *number of tests that failed*, so that it will show up nicely in
# the overall summary.
# rsync.fns contains some general setup functions and definitions.
# NOTES ON PORTABILITY:
# Both this script and the Makefile have to be pretty conservative
# about which Unix features they use.
# We cannot count on Make exporting variables to commands, unless
# they're explicitly given on the command line.
# Also, we can't count on 'cp -a' or 'mkdir -p', although they're
# pretty handy.
# I think some of the GNU documentation suggests that we shouldn't
# rely on shell functions. However, the Bash manual seems to say that
# they're in POSIX 1003.2, and since the build farm relies on them
# they're probably working on most machines we really care about.
# You cannot use "function foo {" syntax, but must instead say "foo()
# {", or it breaks on FreeBSD.
# BSD machines tend not to have "head" or "seq".
# You cannot do "export VAR=VALUE" all on one line; the export must be
# separate from the assignment. (SCO SysV)
# STILL TO DO:
# We need a good protection against tests that hang indefinitely.
# Perhaps some combination of starting them in the background, wait,
# and kill?
# Perhaps we need a common way to cleanup tests. At the moment just
# clobbering the directory when we're done should be enough.
# If any of the targets fail, then (GNU?) Make returns 2, instead of
# the return code from the failing command. This is fine, but it
# means that the build farm just shows "2" for failed tests, not the
# number of tests that actually failed. For more details we might
# need to grovel through the log files to find a line saying how many
# failed.
set -e
. "./shconfig"
RUNSHFLAGS='-e'
if [ -n "$loglevel" ] && [ "$loglevel" -gt 8 ]
then
if set -x
then
# If it doesn't work the first time, don't keep trying.
RUNSHFLAGS="$RUNSHFLAGS -x"
fi
fi
echo "============================================================"
echo "$0 running in `pwd`"
echo " rsync_bin=$rsync_bin"
echo " srcdir=$srcdir"
if test ! -f $rsync_bin
then
echo "rsync_bin $rsync_bin is not a file" >&2
exit 2
fi
if test ! -d $srcdir
then
echo "srcdir $srcdir is not a directory" >&2
exit 2
fi
RSYNC="$rsync_bin"
export rsync_bin RSYNC
skipped=0
missing=0
passed=0
failed=0
scratchdir=./testtmp
[ -d "$scratchdir" ] && rm -r "$scratchdir"
mkdir "$scratchdir"
scratchdir=`cd $scratchdir && pwd`
echo " scratchdir=$scratchdir"
suitedir="$srcdir/testsuite"
export scratchdir suitedir
if [ "x$whichtests" = x ]
then
whichtests="*.test"
fi
for testscript in $suitedir/$whichtests
do
testbase=`echo $testscript | sed 's!.*/!!'`
echo "----- $testbase starting"
if sh $RUNSHFLAGS "$testscript"
then
echo "----- $testbase completed successfully"
passed=`expr $passed + 1`
else
case $? in
77)
echo "----- $testbase skipped"
skipped=`expr $skipped + 1`
;;
*)
echo "----- $testbase failed!"
failed=`expr $failed + 1`
if [ "x$nopersist" = "xyes" ]
then
exit 1
fi
esac
fi
done
echo '------------------------------------------------------------'
echo "----- overall results:"
echo " $passed passed"
[ "$failed" -gt 0 ] && echo " $failed failed"
[ "$skipped" -gt 0 ] && echo " $skipped skipped"
[ "$missing" -gt 0 ] && echo " $missing missing"
echo '------------------------------------------------------------'
# OK, so expr exits with 0 if the result is neither null nor zero; and
# 1 if the expression is null or zero. This is the opposite of what
# we want, and if we just call expr then this script will always fail,
# because -e is set.
result=`expr $failed + $missing || true`
echo "overall result is $result"
exit $result

140
sender.c
View File

@@ -83,9 +83,9 @@ static struct sum_struct *receive_sums(int f)
void send_files(struct file_list *flist,int f_out,int f_in)
{
int fd;
int fd = -1;
struct sum_struct *s;
struct map_struct *buf;
struct map_struct *buf = NULL;
STRUCT_STAT st;
char fname[MAXPATHLEN];
int i;
@@ -93,12 +93,17 @@ void send_files(struct file_list *flist,int f_out,int f_in)
int phase = 0;
extern struct stats stats;
struct stats initial_stats;
extern int write_batch; /* dw */
extern int read_batch; /* dw */
int checksums_match; /* dw */
int buff_len; /* dw */
char buff[CHUNK_SIZE]; /* dw */
int j; /* dw */
int done; /* dw */
if (verbose > 2)
rprintf(FINFO,"send_files starting\n");
setup_readbuffer(f_in);
while (1) {
int offset=0;
@@ -154,61 +159,113 @@ void send_files(struct file_list *flist,int f_out,int f_in)
initial_stats = stats;
s = receive_sums(f_in);
if (write_batch) /* dw */
write_batch_csum_info(&i,flist->count,s);
if (!s) {
io_error = 1;
rprintf(FERROR,"receive_sums failed\n");
return;
}
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));
free_sums(s);
continue;
}
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));
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));
free_sums(s);
close(fd);
return;
}
/* map the local file */
if (do_fstat(fd,&st) != 0) {
io_error = 1;
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);
} else {
buf = NULL;
}
if (st.st_size > 0) {
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);
if (verbose > 2)
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);
write_int(f_out,s->count);
write_int(f_out,s->n);
write_int(f_out,s->remainder);
if (write_batch)
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);
}
if (verbose > 2)
rprintf(FINFO,"calling match_sums %s\n",fname);
if (!read_batch)
rprintf(FINFO,"calling match_sums %s\n",fname);
if (!am_server) {
log_transfer(file, fname+offset);
}
set_compression(fname);
match_sums(f_out,s,buf,st.st_size);
log_send(file, &initial_stats);
if (buf) unmap_file(buf);
close(fd);
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);
} /* 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);
}
free_sums(s);
@@ -222,6 +279,11 @@ void send_files(struct file_list *flist,int f_out,int f_in)
match_report();
write_int(f_out,-1);
if (write_batch || read_batch) { /* dw */
close_batch_csums_file();
close_batch_delta_file();
}
}

12
shconfig.in Executable file
View File

@@ -0,0 +1,12 @@
#! /bin/sh
# config.sh.in
# This file is processed by config.status to produce config.status,
# containing autoconf-determined values needed by the test scripts.
ECHO_T="@ECHO_T@"
ECHO_N="@ECHO_N@"
ECHO_C="@ECHO_C@"
export ECHO_T ECHO_N ECHO_C

588
socket.c
View File

@@ -1,5 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1998
/* -*- c-file-style: "linux" -*-
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 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
@@ -16,31 +18,36 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
socket functions used in rsync
*/
/**
* @file socket.c
*
* Socket functions used in rsync.
**/
#include "rsync.h"
#ifndef HAVE_GETADDRINFO
#include "lib/addrinfo.h"
#endif
/* establish a proxy connection on an open socket to a web roxy by using the CONNECT
method */
/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
static int establish_proxy_connection(int fd, char *host, int port)
{
char buffer[1024];
char *cp;
slprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
rprintf(FERROR, "failed to write to proxy - %s\n",
rprintf(FERROR, "failed to write to proxy: %s\n",
strerror(errno));
return -1;
}
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
if (read(fd, cp, 1) != 1) {
rprintf(FERROR, "failed to read from proxy\n");
rprintf(FERROR, "failed to read from proxy: %s\n",
strerror(errno));
return -1;
}
if (*cp == '\n')
@@ -71,7 +78,8 @@ static int establish_proxy_connection(int fd, char *host, int port)
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
cp++) {
if (read(fd, cp, 1) != 1) {
rprintf(FERROR, "failed to read from proxy\n");
rprintf(FERROR, "failed to read from proxy: %s\n",
strerror(errno));
return -1;
}
if (*cp == '\n')
@@ -86,24 +94,44 @@ static int establish_proxy_connection(int fd, char *host, int port)
}
/* open a socket to a tcp remote host with the specified port
based on code from Warren
proxy support by Stephen Rothwell */
int open_socket_out(char *host, int port, struct in_addr *address)
/**
* Open a socket to a tcp remote host with the specified port .
*
* Based on code from Warren. Proxy support by Stephen Rothwell.
* getaddrinfo() rewrite contributed by KAME.net.
*
* Now that we support IPv6 we need to look up the remote machine's
* address first, using @p af_hint to set a preference for the type
* of address. Then depending on whether it has v4 or v6 addresses we
* try to open a connection.
*
* The loop allows for machines with some addresses which may not be
* reachable, perhaps because we can't e.g. route ipv6 to that network
* but we can get ip4 packets through.
*
* @param bind_address Local address to use. Normally NULL to bind
* the wildcard address.
*
* @param af_hint Address family, e.g. AF_INET or AF_INET6.
**/
int open_socket_out(char *host, int port, const char *bind_address,
int af_hint)
{
int type = SOCK_STREAM;
struct sockaddr_in sock_out;
struct sockaddr_in sock;
int res;
struct hostent *hp;
int error;
int s;
int result;
struct addrinfo hints, *res0, *res;
char portbuf[10];
char *h;
unsigned p;
int proxied = 0;
char buffer[1024];
char *cp;
/* if we have a RSYNC_PROXY env variable then redirect our connetcion via a web proxy
at the given address. The format is hostname:port */
/* if we have a RSYNC_PROXY env variable then redirect our
* connetcion via a web proxy at the given address. The format
* is hostname:port */
h = getenv("RSYNC_PROXY");
proxied = (h != NULL) && (*h != '\0');
@@ -111,113 +139,220 @@ int open_socket_out(char *host, int port, struct in_addr *address)
strlcpy(buffer, h, sizeof(buffer));
cp = strchr(buffer, ':');
if (cp == NULL) {
rprintf(FERROR, "invalid proxy specification\n");
rprintf(FERROR,
"invalid proxy specification: should be HOST:PORT\n");
return -1;
}
*cp++ = '\0';
p = atoi(cp);
strcpy(portbuf, cp);
h = buffer;
} else {
snprintf(portbuf, sizeof(portbuf), "%d", port);
h = host;
p = port;
}
res = socket(PF_INET, type, 0);
if (res == -1) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = af_hint;
hints.ai_socktype = type;
error = getaddrinfo(h, portbuf, &hints, &res0);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
h, portbuf, gai_strerror(error));
return -1;
}
hp = gethostbyname(h);
if (!hp) {
rprintf(FERROR,"unknown host: %s\n", h);
close(res);
s = -1;
/* Try to connect to all addresses for this machine until we get
* through. It might e.g. be multi-homed, or have both IPv4 and IPv6
* addresses. We need to create a socket for each record, since the
* address record tells us what protocol to use to try to connect. */
for (res = res0; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0)
continue;
if (bind_address) {
struct addrinfo bhints, *bres;
memset(&bhints, 0, sizeof(bhints));
bhints.ai_family = res->ai_family;
bhints.ai_socktype = type;
bhints.ai_flags = AI_PASSIVE;
error = getaddrinfo(bind_address, NULL, &bhints, &bres);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
"bind address %s <noport>: %s\n",
bind_address, gai_strerror(error));
continue;
}
if (bres->ai_next) {
/* I'm not at all sure that this is the right
* response here... -- mbp */
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: "
"bind address %s resolved to multiple hosts\n",
bind_address);
freeaddrinfo(bres);
continue;
}
bind(s, bres->ai_addr, bres->ai_addrlen);
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
close(s);
s = -1;
continue;
}
if (proxied &&
establish_proxy_connection(s, host, port) != 0) {
close(s);
s = -1;
continue;
} else
break;
}
freeaddrinfo(res0);
if (s < 0) {
rprintf(FERROR, RSYNC_NAME ": failed to connect to %s: %s\n",
h, strerror(errno));
return -1;
}
memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
sock_out.sin_port = htons(p);
sock_out.sin_family = PF_INET;
if (address) {
sock.sin_addr = *address;
sock.sin_port = 0;
sock.sin_family = hp->h_addrtype;
bind(res, (struct sockaddr * ) &sock,sizeof(sock));
}
if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
rprintf(FERROR,"failed to connect to %s - %s\n", h, strerror(errno));
close(res);
return -1;
}
if (proxied && establish_proxy_connection(res, host, port) != 0) {
close(res);
return -1;
}
return res;
return s;
}
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
static int open_socket_in(int type, int port, struct in_addr *address)
/**
* Open an outgoing socket, but allow for it to be intercepted by
* $RSYNC_CONNECT_PROG, which will execute a program across a TCP
* socketpair rather than really opening a socket.
*
* We use this primarily in testing to detect TCP flow bugs, but not
* cause security problems by really opening remote connections.
*
* This is based on the Samba LIBSMB_PROG feature.
*
* @param bind_address Local address to use. Normally NULL to get the stack default.
**/
int open_socket_out_wrapped (char *host,
int port,
const char *bind_address,
int af_hint)
{
char *prog;
if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
return sock_exec (prog);
else
return open_socket_out (host, port, bind_address,
af_hint);
}
/**
* Open a socket of the specified type, port and address for incoming data
*
* Try to be better about handling the results of getaddrinfo(): when
* opening an inbound socket, we might get several address results,
* e.g. for the machine's ipv4 and ipv6 name.
*
* If binding a wildcard, then any one of them should do. If an address
* was specified but it's insufficiently specific then that's not our
* fault.
*
* However, some of the advertized addresses may not work because e.g. we
* don't have IPv6 support in the kernel. In that case go on and try all
* addresses until one succeeds.
*
* @param bind_address Local address to bind, or NULL to allow it to
* default.
**/
static int open_socket_in(int type, int port, const char *bind_address,
int af_hint)
{
struct hostent *hp;
struct sockaddr_in sock;
char host_name[MAXHOSTNAMELEN];
int res;
int one=1;
int s;
struct addrinfo hints, *res, *resp;
char portbuf[10];
int error;
/* get my host name */
if (gethostname(host_name, sizeof(host_name)) == -1) {
rprintf(FERROR,"gethostname failed\n");
return -1;
}
/* get host info */
if ((hp = gethostbyname(host_name)) == 0) {
rprintf(FERROR,"gethostbyname: Unknown host %s\n",host_name);
memset(&hints, 0, sizeof(hints));
hints.ai_family = af_hint;
hints.ai_socktype = type;
hints.ai_flags = AI_PASSIVE;
snprintf(portbuf, sizeof(portbuf), "%d", port);
error = getaddrinfo(bind_address, portbuf, &hints, &res);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
bind_address, gai_strerror(error));
return -1;
}
memset((char *)&sock,0,sizeof(sock));
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
sock.sin_port = htons(port);
sock.sin_family = hp->h_addrtype;
if (address) {
sock.sin_addr = *address;
} else {
sock.sin_addr.s_addr = INADDR_ANY;
}
res = socket(hp->h_addrtype, type, 0);
if (res == -1) {
rprintf(FERROR,"socket failed\n");
return -1;
/* XXX: Do we need to care about getting multiple results
* back? I think probably not; if the user passed
* bind_address == NULL and we set AI_PASSIVE then we ought to
* get a wildcard result. */
resp = res;
while (1) {
s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
if (s >= 0) {
break; /* got a socket */
} else if ((resp = resp->ai_next)) {
switch (errno) {
case EPROTONOSUPPORT:
case EAFNOSUPPORT:
case EPFNOSUPPORT:
/* See if there's another address that will work... */
continue;
}
}
rprintf(FERROR, RSYNC_NAME ": open inbound socket"
"(dom=%d, type=%d, proto=%d) failed: %s\n",
resp->ai_family, resp->ai_socktype, resp->ai_protocol,
strerror(errno));
goto fail;
}
setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
/* now we've got a socket - we need to bind it */
if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) {
rprintf(FERROR,"bind failed on port %d\n", port);
close(res);
return -1;
if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
close(s);
goto fail;
}
return res;
return s;
fail:
freeaddrinfo(res);
return -1;
}
/****************************************************************************
determine if a file descriptor is in fact a socket
****************************************************************************/
/*
* Determine if a file descriptor is in fact a socket
*/
int is_a_socket(int fd)
{
int v,l;
int v;
socklen_t l;
l = sizeof(int);
/* Parameters to getsockopt, setsockopt etc are very
* unstandardized across platforms, so don't be surprised if
* there are compiler warnings on e.g. SCO OpenSwerver or AIX.
* It seems they all eventually get the right idea.
*
* Debian says: ``The fifth argument of getsockopt and
* setsockopt is in reality an int [*] (and this is what BSD
* 4.* and libc4 and libc5 have). Some POSIX confusion
* resulted in the present socklen_t. The draft standard has
* not been adopted yet, but glibc2 already follows it and
* also has socklen_t [*]. See also accept(2).''
*
* We now return to your regularly scheduled programming. */
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
@@ -225,10 +360,11 @@ int is_a_socket(int fd)
void start_accept_loop(int port, int (*fn)(int ))
{
int s;
extern struct in_addr socket_address;
extern char *bind_address;
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port, &socket_address);
s = open_socket_in(SOCK_STREAM, port, bind_address,
global_opts.af_hint);
if (s == -1)
exit_cleanup(RERR_SOCKETIO);
@@ -244,8 +380,13 @@ void start_accept_loop(int port, int (*fn)(int ))
while (1) {
fd_set fds;
int fd;
struct sockaddr addr;
int in_addrlen = sizeof(addr);
struct sockaddr_storage addr;
int addrlen = sizeof(addr);
/* close log file before the potentially very long select so
file can be trimmed by another process instead of growing
forever */
log_close();
FD_ZERO(&fds);
FD_SET(s, &fds);
@@ -256,7 +397,7 @@ void start_accept_loop(int port, int (*fn)(int ))
if(!FD_ISSET(s, &fds)) continue;
fd = accept(s,&addr,&in_addrlen);
fd = accept(s,(struct sockaddr *)&addr,&addrlen);
if (fd == -1) continue;
@@ -271,7 +412,9 @@ void start_accept_loop(int port, int (*fn)(int ))
if (fork()==0) {
close(s);
/* open log file in child before possibly giving
up privileges */
log_open();
_exit(fn(fd));
}
@@ -377,7 +520,8 @@ void set_socket_options(int fd, char *options)
}
if (ret != 0)
rprintf(FERROR,"Failed to set socket option %s\n",tok);
rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
strerror(errno));
}
free(options);
@@ -414,14 +558,13 @@ void become_daemon(void)
}
}
/*******************************************************************
return the IP addr of the client as a string
******************************************************************/
/**
* Return the IP addr of the client as a string
**/
char *client_addr(int fd)
{
struct sockaddr sa;
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
int length = sizeof(sa);
struct sockaddr_storage ss;
int length = sizeof(ss);
static char addr_buf[100];
static int initialised;
@@ -429,28 +572,29 @@ char *client_addr(int fd)
initialised = 1;
if (getpeername(fd, &sa, &length)) {
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
exit_cleanup(RERR_SOCKETIO);
}
strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf));
getnameinfo((struct sockaddr *)&ss, length,
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
return addr_buf;
}
/*******************************************************************
return the DNS name of the client
******************************************************************/
/**
* Return the DNS name of the client
**/
char *client_name(int fd)
{
struct sockaddr sa;
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
int length = sizeof(sa);
struct sockaddr_storage ss;
int length = sizeof(ss);
static char name_buf[100];
struct hostent *hp;
char **p;
static char port_buf[100];
char *def = "UNKNOWN";
static int initialised;
struct addrinfo hints, *res, *res0;
int error;
if (initialised) return name_buf;
@@ -458,70 +602,178 @@ char *client_name(int fd)
strcpy(name_buf,def);
if (getpeername(fd, &sa, &length)) {
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
/* FIXME: Can we really not continue? */
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
fd, strerror(errno));
exit_cleanup(RERR_SOCKETIO);
}
/* Look up the remote host name. */
if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
sizeof(sockin->sin_addr),
AF_INET))) {
strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf));
#ifdef INET6
if (ss.ss_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
struct sockaddr_in6 sin6;
struct sockaddr_in *sin;
memcpy(&sin6, &ss, sizeof(sin6));
sin = (struct sockaddr_in *)&ss;
memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
length = sizeof(struct sockaddr_in);
#ifdef HAVE_SOCKADDR_LEN
sin->sin_len = length;
#endif
sin->sin_port = sin6.sin6_port;
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
sizeof(sin->sin_addr));
}
#endif
/* reverse lookup */
if (getnameinfo((struct sockaddr *)&ss, length,
name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
NI_NAMEREQD | NI_NUMERICSERV) != 0) {
strcpy(name_buf, def);
rprintf(FERROR, "reverse name lookup failed\n");
}
/* do a forward lookup as well to prevent spoofing */
hp = gethostbyname(name_buf);
if (!hp) {
strcpy(name_buf,def);
rprintf(FERROR,"reverse name lookup failed\n");
} else {
for (p=hp->h_addr_list;*p;p++) {
if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) {
break;
}
}
if (!*p) {
strcpy(name_buf,def);
rprintf(FERROR,"reverse name lookup mismatch - spoofed address?\n");
}
/* forward lookup */
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
if (error) {
strcpy(name_buf, def);
rprintf(FERROR,
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
port_buf,
gai_strerror(error));
return name_buf;
}
/* XXX sin6_flowinfo and other fields */
for (res = res0; res; res = res->ai_next) {
if (res->ai_family != ss.ss_family)
continue;
if (res->ai_addrlen != length)
continue;
if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
break;
}
/* TODO: Do a forward lookup as well to prevent spoofing */
if (res == NULL) {
strcpy(name_buf, def);
rprintf(FERROR, RSYNC_NAME ": "
"reverse name lookup mismatch on fd%d - spoofed address?\n",
fd);
}
freeaddrinfo(res0);
return name_buf;
}
/*******************************************************************
convert a string to an IP address. The string can be a name or
dotted decimal number
******************************************************************/
struct in_addr *ip_address(const char *str)
this is like socketpair but uses tcp. It is used by the Samba
regression test code
The function guarantees that nobody else can attach to the socket,
or if they do that this function fails and the socket gets closed
returns 0 on success, -1 on failure
the resulting file descriptors are symmetrical
******************************************************************/
static int socketpair_tcp(int fd[2])
{
static struct in_addr ret;
struct hostent *hp;
int listener;
struct sockaddr_in sock;
struct sockaddr_in sock2;
socklen_t socklen = sizeof(sock);
int connect_done = 0;
fd[0] = fd[1] = listener = -1;
/* try as an IP address */
if (inet_aton(str, &ret) != 0) {
return &ret;
memset(&sock, 0, sizeof(sock));
if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
memset(&sock2, 0, sizeof(sock2));
#ifdef HAVE_SOCK_SIN_LEN
sock2.sin_len = sizeof(sock2);
#endif
sock2.sin_family = PF_INET;
bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
if (listen(listener, 1) != 0) goto failed;
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
set_nonblocking(fd[1]);
sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
if (errno != EINPROGRESS) goto failed;
} else {
connect_done = 1;
}
/* otherwise assume it's a network name of some sort and use
gethostbyname */
if ((hp = gethostbyname(str)) == 0) {
rprintf(FERROR, "gethostbyname: Unknown host. %s\n",str);
return NULL;
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
close(listener);
if (connect_done == 0) {
if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
&& errno != EISCONN) goto failed;
}
if (hp->h_addr == NULL) {
rprintf(FERROR, "gethostbyname: host address is invalid for host %s\n",str);
return NULL;
}
set_blocking (fd[1]);
if (hp->h_length > sizeof(ret)) {
rprintf(FERROR, "gethostbyname: host address is too large\n");
return NULL;
}
/* all OK! */
return 0;
memcpy(&ret.s_addr, hp->h_addr, hp->h_length);
return(&ret);
failed:
if (fd[0] != -1) close(fd[0]);
if (fd[1] != -1) close(fd[1]);
if (listener != -1) close(listener);
return -1;
}
/*******************************************************************
run a program on a local tcp socket, this is used to launch smbd
when regression testing
the return value is a socket which is attached to a subprocess
running "prog". stdin and stdout are attached. stderr is left
attached to the original stderr
******************************************************************/
int sock_exec(const char *prog)
{
int fd[2];
if (socketpair_tcp(fd) != 0) {
rprintf (FERROR, RSYNC_NAME
": socketpair_tcp failed (%s)\n",
strerror(errno));
return -1;
}
if (fork() == 0) {
close(fd[0]);
close(0);
close(1);
dup(fd[1]);
dup(fd[1]);
if (verbose > 3)
fprintf (stderr,
RSYNC_NAME ": execute socket program \"%s\"\n",
prog);
exit (system (prog));
}
close (fd[1]);
return fd[0];
}

View File

@@ -113,11 +113,27 @@ int do_mkdir(char *fname, mode_t mode)
return mkdir(fname, mode);
}
char *do_mktemp(char *template)
/* like mkstemp but forces permissions */
int do_mkstemp(char *template, mode_t perms)
{
if (dry_run) return NULL;
if (read_only) {errno = EROFS; return NULL;}
return mktemp(template);
if (dry_run) return -1;
if (read_only) {errno = EROFS; return -1;}
#if defined(HAVE_SECURE_MKSTEMP) && defined(HAVE_FCHMOD)
{
int fd = mkstemp(template);
if (fd == -1) return -1;
if (fchmod(fd, perms) != 0) {
close(fd);
unlink(template);
return -1;
}
return fd;
}
#else
if (!mktemp(template)) return -1;
return open(template, O_RDWR|O_EXCL|O_CREAT, perms);
#endif
}
int do_stat(const char *fname, STRUCT_STAT *st)

30
test.sh
View File

@@ -24,7 +24,9 @@ not for end users. You may experience failures on some platforms that
do not indicate a problem with rsync.
EOF
export PATH=.:$PATH
RSYNC=`pwd`/rsync
runtest() {
echo -n "Test $1: "
eval "$2"
@@ -52,9 +54,13 @@ mkdir ${FROM}/emptydir
ps ax > ${FROM}/pslist
echo -n "This file has no trailing lf" > ${FROM}/nolf
ln -s nolf ${FROM}/nolf-symlink
cat /etc/inittab /etc/services /etc/resolv.conf > ${FROM}/${F1}
# Gather some random text. We need files that will exist and be
# publicly readable on all platforms: hopefully this will work.
cat /etc/*tab /etc/services /etc/*.conf /etc/*rc > ${FROM}/${F1}
mkdir ${FROM}/dir
cp ${FROM}/${F1} ${FROM}/dir
cp ${FROM}/${F1} ${FROM}/dir/
mkdir ${FROM}/dir/subdir
mkdir ${FROM}/dir/subdir/subsubdir
ls -ltr /etc > ${FROM}/dir/subdir/subsubdir/etc-ltr-list
@@ -123,33 +129,33 @@ EOF
# Main script starts here
runtest "basic operation" 'checkit "rsync -av ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest "basic operation" 'checkit "$RSYNC -av ${FROM}/ ${TO}" ${FROM}/ ${TO}'
ln ${FROM}/pslist ${FROM}/dir
runtest "hard links" 'checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest "hard links" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
rm ${TO}/${F1}
runtest "one file" 'checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest "one file" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
echo "extra line" >> ${TO}/${F1}
runtest "extra data" 'checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
cp ${FROM}/${F1} ${TO}/ThisShouldGo
runtest " --delete" 'checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
LONGDIR=${FROM}/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
mkdir -p ${LONGDIR}
date > ${LONGDIR}/1
ls -la / > ${LONGDIR}/2
runtest "long paths" 'checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
runtest "long paths" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
if type ssh >/dev/null 2>&1; then
if [ "`ssh -o'BatchMode yes' localhost echo yes 2>/dev/null`" = "yes" ]; then
rm -rf ${TO}
runtest "ssh: basic test" 'checkit "rsync -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
mv ${TO}/${F1} ${TO}/ThisShouldGo
runtest "ssh: renamed file" 'checkit "rsync --delete -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
else
printmsg "Skipping SSH tests because ssh conection to localhost not authorised"
fi
@@ -161,7 +167,7 @@ rm -rf ${TO}
mkdir -p ${FROM}2/dir/subdir
cp -a ${FROM}/dir/subdir/subsubdir ${FROM}2/dir/subdir
cp ${FROM}/dir/* ${FROM}2/dir 2>/dev/null
runtest "excludes" 'checkit "rsync -vv -Hlrt --delete --include /dir/ --include /dir/\* --include /dir/\*/subsubdir --include /dir/\*/subsubdir/\*\* --exclude \*\* ${FROM}/dir ${TO}" ${FROM}2/ ${TO}'
runtest "excludes" 'checkit "$RSYNC -vv -Hlrt --delete --include /dir/ --include /dir/\* --include /dir/\*/subsubdir --include /dir/\*/subsubdir/\*\* --exclude \*\* ${FROM}/dir ${TO}" ${FROM}2/ ${TO}'
rm -r ${FROM}2
checkforlogs ${LOG}.?

5
testsuite/00-hello.test Normal file
View File

@@ -0,0 +1,5 @@
#! /bin/sh
echo $0 running
"$rsync_bin" --version || exit 1

7
testsuite/README Normal file
View File

@@ -0,0 +1,7 @@
This directory contains automatic test cases for rsync. You can run
them yourself if you want, preferably by doing "make check" in the
top-level source directory. (Not implemented yet.)
They also run automatically on the build farm, and you can see the
results on http://build.samba.org/. That's controlled by the file
./runlist.

32
testsuite/daemon.test Normal file
View File

@@ -0,0 +1,32 @@
#!/bin/sh
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING)
# We don't really want to start the server listening, because that
# might interfere with the security or operation of the test machine.
# Instead we use the fake-connect feature to dynamically assign a pair
# of ports.
# Having started the server we try some basic operations against it:
# getting a list of module
# listing files in a module
# retrieving a module
# uploading to a module
# checking the log file
# password authentication
# TODO: Put the common framework in a common file, so that we can have
# subtests fail and keep going.
. "$suitedir/rsync.fns"
build_rsyncd_conf
RSYNC_CONNECT_PROG="$rsync_bin --config=$conf --daemon"
export RSYNC_CONNECT_PROG
$rsync_bin -v localhost::

30
testsuite/hands.test Normal file
View File

@@ -0,0 +1,30 @@
#!/bin/sh
# Copyright (C) 1998,1999 Philip Hands <phil@hands.com>
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
#
# This program is distributable under the terms of the GNU GPL (see COPYING)
. "$suitedir/rsync.fns"
hands_setup
# Main script starts here
runtest "basic operation" 'checkit "$RSYNC -av ${FROM}/ ${TO}" ${FROM}/ ${TO}'
ln ${FROM}/filelist ${FROM}/dir
runtest "hard links" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
rm ${TO}/text
runtest "one file" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
echo "extra line" >> ${TO}/text
runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
cp ${FROM}/text ${TO}/ThisShouldGo
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
checkforlogs ${LOG}.?
hands_cleanup

19
testsuite/longdir.test Normal file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
# Copyright (C) 1998,1999 Philip Hands <phil@hands.com>
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
#
# This program is distributable under the terms of the GNU GPL (see COPYING)
. "$suitedir/rsync.fns"
set -x
hands_setup
LONGDIR=${FROM}/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
makepath ${LONGDIR}
date > ${LONGDIR}/1
ls -la / > ${LONGDIR}/2
checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}

214
testsuite/rsync.fns Normal file
View File

@@ -0,0 +1,214 @@
#! /bin/sh
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
# General-purpose test functions for rsync.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version
# 2 as published by the Free Software Foundation.
#
# 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
TMP="$scratchdir"
FROM=${TMP}/from
TO=${TMP}/to
LOG=${TMP}/log
RSYNC="$rsync_bin"
runtest() {
echo $ECHO_N "Test $1: $ECHO_C"
if eval "$2"
then
echo "${ECHO_T} done."
return 0
else
echo "${ECHO_T} failed!"
return 1
fi
}
printmsg() {
echo "$1"
}
rsync_ls_lR() {
find "$@" -print | sort | xargs $TLS
}
####################
# Build test directories TO and FROM, with FROM full of files.
hands_setup() {
# Clean before creation
rm -rf $FROM
rm -rf $TO
[ -d $TMP ] || mkdir $TMP
[ -d $FROM ] || mkdir $FROM
[ -d $TO ] || mkdir $TO
# On some BSD systems, the umask affects the mode of created
# symlinks, even though the mode apparently has no effect on how
# the links behave in the future, and it cannot be changed using
# chmod! rsync always sets its umask to 000 so that it can
# accurately recreate permissions, but this script is probably run
# with a different umask.
# This causes a little problem that "ls -l" of the two will not be
# the same. So, we need to set our umask before doing any creations.
# set up test data
touch ${FROM}/empty
mkdir ${FROM}/emptydir
# a hundred lines of text or so
rsync_ls_lR "${srcdir}" > ${FROM}/filelist
# This might fail on systems that don't have -n
echo $ECHO_N "This file has no trailing lf$ECHO_C" > ${FROM}/nolf
umask 0
ln -s nolf ${FROM}/nolf-symlink
umask 022
cat $srcdir/*.c > ${FROM}/text
mkdir ${FROM}/dir
cp ${FROM}/text ${FROM}/dir
mkdir ${FROM}/dir/subdir
mkdir ${FROM}/dir/subdir/subsubdir
ls -ltr /etc > ${FROM}/dir/subdir/subsubdir/etc-ltr-list
mkdir ${FROM}/dir/subdir/subsubdir2
ls -lt /bin > ${FROM}/dir/subdir/subsubdir2/bin-lt-list
# echo testing head:
# ls -lR ${srcdir} | head -10 || echo failed
}
hands_cleanup() {
rm -r "$TMP"
}
####################
# Many machines do not have "mkdir -p", so we have to build up long paths.
# How boring.
makepath () {
echo " makepath $1"
p="$1"
(
# Absolut Unix.
if echo $p | grep '^/' >/dev/null
then
cd /
fi
# This will break if $1 contains a space.
for c in `echo $p | tr '/' ' '`
do
if [ -d "$c" ] || mkdir "$c"
then
cd "$c" || return $?
else
echo "failed to create $c" >&2; return $?
fi
done
)
}
###########################
# Run a test (in '$1') then compare directories $2 and $3 to see if
# there are any difference. If there are, explain them.
checkit() {
log=${LOG}
failed=
# the log accumulates all output; we only display it if there
# is a problem.
echo "Running: \"$1\"" >${log}
echo "">>${log}
eval "$1" >>${log} 2>&1
status=$?
if [ $status != 0 ]; then
failed="YES";
fi
echo "-------------">>${log}
echo "check how the files compare with diff:">>${log}
echo "">>${log}
diff -cr $2 $3 >>${log} 2>&1 || failed=YES
echo "-------------">>${log}
echo "check how the directory listings compare with diff:">>${log}
echo "">>${log}
( cd "$2" && rsync_ls_lR . ) > ${TMP}/ls-from 2>>${log}
( cd "$3" && rsync_ls_lR . ) > ${TMP}/ls-to 2>>${log}
diff -c ${TMP}/ls-from ${TMP}/ls-to >>${log} 2>&1 || failed=YES
if [ -z "${failed}" ] ; then
rm $log
return 0
else
cat ${log}
rm ${log}
return 1
fi
}
# In fact, we need a more general feature of capturing all stderr/log files,
# and dumping them if something goes wrong.
checkforlogs() {
# skip it if we're under debian-test
if test -n "${Debian}" ; then return 0 ; fi
if [ -f $1 -a -s $1 ] ; then
echo "Failures have occurred. $1 follows:" >&2
cat $1 >&2
exit 1
fi
}
build_rsyncd_conf() {
# Build an appropriate configuration file
conf="$scratchdir/test-rsyncd.conf"
echo "building configuration $conf"
port=2612
pidfile="$scratchdir/rsyncd.pid"
logfile="$scratchdir/rsyncd.log"
cat >$conf <<EOF
# rsyncd configuration file autogenerated by $0
pid file = $pidfile
use chroot = no
hosts allow = localhost, 127.0.0.1
log file = $logfile
[test-from] = $scratchdir/daemon-from/
read only = yes
[test-to] = $scratchdir/daemon-to/
read only = no
EOF
}
# be reproducible
umask 077

33
testsuite/ssh-basic.test Normal file
View File

@@ -0,0 +1,33 @@
#!/bin/sh
# Copyright (C) 1998,1999 Philip Hands <phil@hands.com>
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING)
# This script tests ssh, if possible. It's called by runtests.sh
. "$suitedir/rsync.fns"
if [ "x$rsync_enable_ssh_tests" != xyes ]
then
echo "Skipping SSH tests because \$rsync_enable_ssh_tests is not set"
exit 77
fi
if ! type ssh >/dev/null ; then
echo "Skipping SSH tests because ssh is not in the path"
exit 77
fi
if ! [ "`ssh -o'BatchMode yes' localhost echo yes`" = "yes" ]; then
echo "Skipping SSH tests because ssh conection to localhost not authorised"
exit 77
fi
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
mv ${TO}/${F1} ${TO}/ThisShouldGo
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'

134
tls.c Normal file
View File

@@ -0,0 +1,134 @@
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 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 version
* 2 as published by the Free Software Foundation.
*
* 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.
*/
/**
* \section tls
*
* tls -- Trivial recursive ls, for comparing two directories after
* running an rsync.
*
* The problem with using the system's own ls is that some features
* have little quirks that make directories look different when for
* our purposes they're the same -- for example, the BSD braindamage
* about setting the mode on symlinks based on your current umask.
*
* All the filenames must be given on the command line -- tls does not
* even read directories, let alone recurse. The typical usage is
* "find|sort|xargs tls".
*
* The format is not exactly the same as any particular Unix ls(1).
*
* A key requirement for this program is that the output be "very
* reproducible." So we mask away information that can accidentally
* change.
**/
#include "rsync.h"
#define PROGRAM "tls"
/* These are to make syscall.o shut up. */
int dry_run = 0;
int read_only = 1;
int list_only = 0;
static void failed (char const *what,
char const *where)
{
fprintf (stderr, PROGRAM ": %s %s: %s\n",
what, where, strerror (errno));
exit (1);
}
static void list_file (const char *fname)
{
struct stat buf;
char permbuf[PERMSTRING_SIZE];
struct tm *mt;
char datebuf[50];
char linkbuf[4096];
if (do_lstat(fname, &buf) == -1)
failed ("stat", fname);
/* The size of anything but a regular file is probably not
* worth thinking about. */
if (!S_ISREG(buf.st_mode))
buf.st_size = 0;
/* On some BSD platforms the mode bits of a symlink are
* undefined. Also it tends not to be possible to reset a
* symlink's mtime, so we have to ignore it too. */
if (S_ISLNK(buf.st_mode)) {
buf.st_mode &= ~0777;
buf.st_mtime = (time_t)0;
buf.st_uid = buf.st_gid = 0;
strcpy(linkbuf, " -> ");
/* const-cast required for silly UNICOS headers */
readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
} else {
linkbuf[0] = 0;
}
permstring(permbuf, buf.st_mode);
if (buf.st_mtime) {
mt = gmtime(&buf.st_mtime);
sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
mt->tm_year + 1900,
mt->tm_mon + 1,
mt->tm_mday,
mt->tm_hour,
mt->tm_min,
mt->tm_sec);
} else {
strcpy(datebuf, " ");
}
/* TODO: Perhaps escape special characters in fname? */
/* NB: need to pass size as a double because it might be be
* too large for a long. */
printf("%s %12.0f %6d.%-6d %s %s%s\n",
permbuf, (double) buf.st_size,
buf.st_uid, buf.st_gid,
datebuf, fname, linkbuf);
}
int main (int argc, char *argv[])
{
if (argc < 2) {
fprintf (stderr, "usage: " PROGRAM " DIR ...\n"
"Trivial file listing program for portably checking rsync\n");
return 1;
}
for (argv++; *argv; argv++) {
list_file (*argv);
}
return 0;
}

33
token.c
View File

@@ -90,18 +90,29 @@ 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 */
if (n > 0) {
int l = 0;
while (l < n) {
int n1 = MIN(CHUNK_SIZE,n-l);
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);
}
l += n1;
}
}
/* a -2 token means to send data only and no 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) );
}
}
}
@@ -134,6 +145,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 */
if (last_token == -1) {
/* initialization */
@@ -166,13 +179,27 @@ 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));
}
} 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 (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));
}
}
last_run_end = last_token;
run_start = token;
@@ -231,6 +258,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);
}
}
} while (nb != 0 || tx_strm.avail_out == 0);
@@ -240,6 +269,10 @@ 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));
}
} else if (token != -2) {
/* add the data in the current block to the compressor's

303
util.c
View File

@@ -1,6 +1,8 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
Copyright (C) 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
@@ -26,24 +28,78 @@
extern int verbose;
/* create a file descriptor - like pipe() but use socketpair if
possible (because of blocking issues on pipes */
int fd_pair(int fd[2])
/****************************************************************************
Set a fd into nonblocking mode
****************************************************************************/
void set_nonblocking(int fd)
{
#if HAVE_SOCKETPAIR
return socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
#else
return pipe(fd);
#endif
int val;
if((val = fcntl(fd, F_GETFL, 0)) == -1)
return;
if (!(val & NONBLOCK_FLAG)) {
val |= NONBLOCK_FLAG;
fcntl(fd, F_SETFL, val);
}
}
/****************************************************************************
Set a fd into blocking mode
****************************************************************************/
void set_blocking(int fd)
{
int val;
if((val = fcntl(fd, F_GETFL, 0)) == -1)
return;
if (val & NONBLOCK_FLAG) {
val &= ~NONBLOCK_FLAG;
fcntl(fd, F_SETFL, val);
}
}
/* this is taken from CVS */
int piped_child(char **command,int *f_in,int *f_out)
/* create a file descriptor pair - like pipe() but use socketpair if
possible (because of blocking issues on pipes)
always set non-blocking
*/
int fd_pair(int fd[2])
{
int pid;
int ret;
#if HAVE_SOCKETPAIR
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
#else
ret = pipe(fd);
#endif
if (ret == 0) {
set_nonblocking(fd[0]);
set_nonblocking(fd[1]);
}
return ret;
}
/* this is derived from CVS code
note that in the child STDIN is set to blocking and STDOUT
is set to non-blocking. This is necessary as rsh relies on stdin being blocking
and ssh relies on stdout being non-blocking
if blocking_io is set then use blocking io on both fds. That can be
used to cope with badly broken rsh implementations like the one on
solaris.
*/
pid_t piped_child(char **command,int *f_in,int *f_out)
{
pid_t pid;
int to_child_pipe[2];
int from_child_pipe[2];
extern int blocking_io;
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {
@@ -53,7 +109,7 @@ int piped_child(char **command,int *f_in,int *f_out)
pid = do_fork();
if (pid < 0) {
if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -71,6 +127,10 @@ int piped_child(char **command,int *f_in,int *f_out)
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
umask(orig_umask);
set_blocking(STDIN_FILENO);
if (blocking_io) {
set_blocking(STDOUT_FILENO);
}
execvp(command[0], command);
rprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
@@ -89,11 +149,12 @@ int piped_child(char **command,int *f_in,int *f_out)
return pid;
}
int local_child(int argc, char **argv,int *f_in,int *f_out)
pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
{
int pid;
pid_t pid;
int to_child_pipe[2];
int from_child_pipe[2];
extern int read_batch; /* dw */
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {
@@ -103,7 +164,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
pid = do_fork();
if (pid < 0) {
if (pid == -1) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -112,7 +173,10 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
extern int am_sender;
extern int am_server;
am_sender = !am_sender;
if (read_batch)
am_sender = 0;
else
am_sender = !am_sender;
am_server = 1;
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
@@ -499,10 +563,7 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs)
s = strdup(s);
if (!s) out_of_memory("glob_expand");
base = (char *)malloc(strlen(base1)+3);
if (!base) out_of_memory("glob_expand");
sprintf(base," %s/", base1);
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
@@ -529,33 +590,6 @@ void strlower(char *s)
}
}
/* this is like vsnprintf but it always null terminates, so you
can fit at most n-1 chars in */
int vslprintf(char *str, int n, const char *format, va_list ap)
{
int ret = vsnprintf(str, n, format, ap);
if (ret >= n || ret < 0) {
str[n-1] = 0;
return -1;
}
str[ret] = 0;
return ret;
}
/* like snprintf but always null terminates */
int slprintf(char *str, int n, char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = vslprintf(str,n,format,ap);
va_end(ap);
return ret;
}
void *Realloc(void *p, int size)
{
if (!p) return (void *)malloc(size);
@@ -777,28 +811,91 @@ int u_strcmp(const char *cs1, const char *cs2)
return (int)*s1 - (int)*s2;
}
static OFF_T last_ofs;
static OFF_T last_ofs;
static struct timeval print_time;
static struct timeval start_time;
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;
}
/**
* @param ofs Current position in file
* @param size Total size of file
* @param is_last True if this is the last time progress will be
* printed for this file, so we should output a newline. (Not
* necessarily the same as all bytes being received.)
**/
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, *rem_units;
double remain = 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";
}
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;
if (do_progress && !am_server) {
rprintf(FINFO,"%.0f (100%%)\n", (double)size);
struct timeval now;
gettimeofday(&now, NULL);
rprint_progress(size, size, &now, True);
}
last_ofs = 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;
if (do_progress && !am_server) {
if (ofs > last_ofs + 1000) {
int pct = (int)((100.0*ofs)/size);
rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
last_ofs = ofs;
}
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;
}
}
@@ -872,14 +969,84 @@ char *timestring(time_t t)
}
/****************************************************************************
like waitpid but does the WEXITSTATUS
****************************************************************************/
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF))
#endif
void wait_process(pid_t pid, int *status)
/**
* Sleep for a specified number of milliseconds.
*
* Always returns TRUE. (In the future it might return FALSE if
* interrupted.)
**/
int msleep(int t)
{
waitpid(pid, status, 0);
*status = WEXITSTATUS(*status);
int tdiff=0;
struct timeval tval,t1,t2;
gettimeofday(&t1, NULL);
gettimeofday(&t2, NULL);
while (tdiff < t) {
tval.tv_sec = (t-tdiff)/1000;
tval.tv_usec = 1000*((t-tdiff)%1000);
errno = 0;
select(0,NULL,NULL, NULL, &tval);
gettimeofday(&t2, NULL);
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
(t2.tv_usec - t1.tv_usec)/1000;
}
return True;
}
/*******************************************************************
Determine if two file modification times are equivalent (either exact
or in the modification timestamp window established by --modify-window)
Returns 0 if the times should be treated as the same, 1 if the
first is later and -1 if the 2nd is later
*******************************************************************/
int cmp_modtime(time_t file1, time_t file2)
{
extern int modify_window;
if (file2 > file1) {
if (file2 - file1 <= modify_window) return 0;
return -1;
}
if (file1 - file2 <= modify_window) return 0;
return 1;
}
#ifdef __INSURE__XX
#include <dlfcn.h>
/*******************************************************************
This routine is a trick to immediately catch errors when debugging
with insure. A xterm with a gdb is popped up when insure catches
a error. It is Linux specific.
********************************************************************/
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
{
static int (*fn)();
int ret;
char *cmd;
asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
getpid(), getpid(), getpid());
if (!fn) {
static void *h;
h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
fn = dlsym(h, "_Insure_trap_error");
}
ret = fn(a1, a2, a3, a4, a5, a6);
system(cmd);
free(cmd);
return ret;
}
#endif

View File

@@ -1 +0,0 @@
#define VERSION "2.4.0"

1
zlib/.cvsignore Normal file
View File

@@ -0,0 +1 @@
dummy