Compare commits

...

228 Commits

Author SHA1 Message Date
Martin Pool
461c6de1a8 Bump version to 2.3.3. 2002-01-25 23:31:06 +00:00
Martin Pool
9c380e07ef Bump version to 2.3.3pre1. 2002-01-25 07:06:33 +00:00
Martin Pool
61ea0c9d9b Merge signedness security patch from Sebastian Krahmer
<krahmer@suse.de> -- in some cases we were not sufficiently careful
about reading integers from the network.

Possibly some other changes are required.
2002-01-25 03:13:35 +00:00
Martin Pool
2e1d43deb2 Ignore autoconf fluff. 2002-01-25 02:53:48 +00:00
Martin Pool
6780f72000 Add code to compare sin6_addrs. 2002-01-25 02:45:09 +00:00
Martin Pool
39e01d2d4b Back out last change -- to see whether an address is spoofed, we don't
want to look at the whole sockaddr, but rather just at the sin_addr
that it contains.

Also fix silly bug where ai_flags was set incorrectly for getaddrinfo.
2002-01-25 02:43:35 +00:00
Martin Pool
f75502950b compare_addrinfo_sockaddr: Add code to compare AF_INET6 addresses. 2002-01-25 02:37:20 +00:00
Martin Pool
974f27e7e9 Split out code to compare addrinfo and sockaddr into it's own
function.  The comparison cannot be done just byte-by-byte, because
different parts of the sockaddr will be meaningful depending on the
protocol.  It looks like on some systems the library sets the unused
parts to 0, but this is not reliable.  IPv6 not implemented yet.
2002-01-25 02:29:53 +00:00
Martin Pool
af32f69eb0 Doc. 2002-01-25 02:15:58 +00:00
Martin Pool
0cd2f40764 The name resolution stuff is getting complicated -- split it out into
its own file.
2002-01-25 02:13:04 +00:00
Martin Pool
0d95824995 Verbose messages for spoof check... doesn't work on old linux libc? 2002-01-24 09:42:52 +00:00
Martin Pool
bbc09ffba9 When doing a name->addr translation to check for spoofing, give the
resolver the address family of the original address as a hint, so that
we're more likely to find the correct A or AAAA record.,
2002-01-24 08:52:28 +00:00
Martin Pool
a4677968cf Message on successful configuration. 2002-01-24 08:50:35 +00:00
Martin Pool
03b1cddc31 Fix comment.
Bump version to 2.5.2pre3
2002-01-24 08:42:21 +00:00
Martin Pool
9c2dd04993 Name resolution on machines supporting IPv6 is improved. 2002-01-24 08:20:51 +00:00
Martin Pool
a84a93fafe ignore gmon.out 2002-01-24 08:19:28 +00:00
Martin Pool
5fdcc397b1 Fix getpeername call. 2002-01-24 08:16:27 +00:00
Martin Pool
5664871e5f size_t fix. 2002-01-24 08:09:46 +00:00
Martin Pool
55d9e0fada write_batch_csums_file: Opaque IO buffers should be void*. 2002-01-24 08:08:56 +00:00
Martin Pool
929e3011c6 Fix cast that was breaking HP/UX. 2002-01-24 08:07:35 +00:00
Martin Pool
07d70ff560 Move both calls to getpeername into a common wrapper function that
handles IPV4_MAPPED addresses.
2002-01-24 08:05:22 +00:00
Martin Pool
58c2960960 Must get declarations from addrinfo.h before prototypes. 2002-01-24 07:22:38 +00:00
Martin Pool
00d943d513 Another size_t warning 2002-01-24 05:57:49 +00:00
Martin Pool
71c780da06 check_name: Print out name *before* clobbering it. 2002-01-24 05:57:22 +00:00
Martin Pool
3b18cba889 Try to fix error on Solaris:
+ [ -f /export/home/build/build_farm/rsync/testtmp.symlink-ignore/to/referent ]
+ [ -d /export/home/build/build_farm/rsync/testtmp.symlink-ignore/to/from ]
+ [ -L /export/home/build/build_farm/rsync/testtmp.symlink-ignore/to/dangling ]
./testsuite/symlink-ignore.test: test: argument expected

Solaris says it supports -L, so I'm not sure what's happening...
2002-01-24 05:54:47 +00:00
Martin Pool
2974e20550 If name lookup fails, then show the relevant IP address in the error message. 2002-01-24 05:41:46 +00:00
Martin Pool
430d841a2c At the connections that just get a list of modules are not logged,
but they should be.
2002-01-24 04:49:07 +00:00
Martin Pool
31ec50d7da rsync_module: If host-based access fails, show the exact name/address
used for the check in the error message.  (Just in case...)
2002-01-24 04:41:09 +00:00
Martin Pool
5ad0e46f08 Show command used to start connection child. 2002-01-24 04:36:00 +00:00
Martin Pool
1b5814e338 indent -kr -i8 2002-01-24 04:26:55 +00:00
Martin Pool
255810c0d6 Doc.
Oops, connection program message was in the wrong place.
2002-01-24 04:24:12 +00:00
Martin Pool
5d2640376e Show helper program with -v when opening connection.
Doc.
2002-01-24 04:21:42 +00:00
Martin Pool
d02984bbb7 Doc. 2002-01-24 04:19:41 +00:00
Martin Pool
0f9555207a Fix const 2002-01-24 04:07:07 +00:00
Martin Pool
885448d74c Unbreak the old behavior of using UNKNOWN as a hostname if any of the
addr->name->addr translations fail, because people might count on this
in "hosts deny" lines.
2002-01-24 04:03:06 +00:00
Martin Pool
b14545b3ff Fix inverted sense of error check. 2002-01-24 03:31:28 +00:00
Martin Pool
9a5a86734f Refactor client_name() into smaller functions.
Better messages for DNS failure.

If we can get a reverse name for an IP address, but not confirm that
it is correct using a forward lookup then we still proceed to use the
name, but also emit a warning.
2002-01-24 03:28:20 +00:00
Martin Pool
d1d1505045 Doc. 2002-01-24 03:03:20 +00:00
Martin Pool
144ce1dc21 Bump version to 2.5.2pre2. 2002-01-24 03:01:42 +00:00
Martin Pool
aa126974ba log_formatted: Fill the log buffer with nuls to make sure we cannot
accidentally leave the string unterminated.
2002-01-24 02:41:38 +00:00
Martin Pool
707de53457 Another harmless size_t warning. 2002-01-24 02:33:45 +00:00
Martin Pool
10f83cf43d Doc. 2002-01-23 08:08:48 +00:00
Martin Pool
59ee743c5f More size_t fixes. 2002-01-23 08:04:54 +00:00
Martin Pool
d54765c442 Just for variety we have some socklen_t fixes too. 2002-01-23 07:57:43 +00:00
Martin Pool
91262d5d3e Refactor code in send_sums to remove repeated ternaries. 2002-01-23 07:54:13 +00:00
Martin Pool
1c09c743b1 indent -kr -i8 2002-01-23 07:52:52 +00:00
Martin Pool
06ce139fcc Fix more ints that ought to be size_t's. 2002-01-23 07:48:35 +00:00
Martin Pool
fae5bb3183 Doc.
do_hard_links() actually only looks at the global hardlink table, so
it can be a (void) fn.  (Another gcc warning...)
2002-01-23 07:42:30 +00:00
Martin Pool
6fe25398d6 Fix another int that ought to be a size_t. 2002-01-23 07:36:23 +00:00
Martin Pool
909ce14fc4 indent -kr -i8 2002-01-23 07:34:26 +00:00
Martin Pool
935b920120 Another signedness fix to quieten Sun cc warning. 2002-01-23 07:32:29 +00:00
Martin Pool
b31427cd4a Skip this for now; it's a known bug 2002-01-23 07:28:38 +00:00
Martin Pool
e2e3379d79 Bump version to 2.5.2pre1. 2002-01-23 07:22:03 +00:00
Martin Pool
6b1ef85dd8 Note batch-mode changes. 2002-01-23 07:18:58 +00:00
Martin Pool
92325ada0c Note about proxy authentication and SOCKS. 2002-01-23 07:12:57 +00:00
Martin Pool
1707e0f9e2 Indent. 2002-01-23 06:48:13 +00:00
Martin Pool
7ff701e816 Update thankyou list.
Clarify email addresses.
2002-01-23 05:59:10 +00:00
Martin Pool
2e3c141795 Note that batch mode is currently experimental. 2002-01-23 05:53:58 +00:00
Martin Pool
76f79ba748 Patch from Jos Backus -- Fix breakage from dev_t to DEV64_T in batch
mode.

Also, drop -f and -F for batch mode: these should be reserved for
options that are more commonly used.

It also appends a newline to the argvs file and skips adding the
source directory to the command line.
2002-01-23 05:51:06 +00:00
Martin Pool
9dd891bb28 Signedness security patch from Sebastian Krahmer <krahmer@suse.de> --
in some cases we were not sufficiently careful about reading integers
from the network.

Also, make sure log messages are always nul-terminated.
2002-01-23 04:57:18 +00:00
Martin Pool
99f106d1cf If using gcc, then also turn on -W to get even more warnings.
Remove obsolete message.
2002-01-23 03:52:06 +00:00
Martin Pool
3816cae745 Don't need to reread configuration on SIGHUP because we always do that
on new connections.
2002-01-21 01:57:13 +00:00
David Dykstra
759c0627e1 Aack! Since released version 2.5.0, the --whole-file option was accidentally
changed to --whole.  Change it back.  Anybody who wants to use this option
with any version of rsync will have to switch to using -W.
2002-01-15 21:25:55 +00:00
Martin Pool
e03dfae507 Change gratuituous strlcat's into strlcpy, since we already know the
length of the existing string.
2002-01-15 11:50:32 +00:00
Martin Pool
c7677b892a Clearer doc. 2002-01-15 11:32:30 +00:00
Martin Pool
da7b63972d Add --enable-profile to turn on gprof. This is not perfect, because
it seems to only write to ./gmon.out, and that causes trouble when
there are several rsync processes in the same directory.  But you can
make it work.
2002-01-15 11:20:26 +00:00
Martin Pool
499957d9ba Update 2002-01-15 10:47:59 +00:00
Martin Pool
582250008b The Ted T'so school of program optimization: make progress visible and
people will think it's faster.

So now with --progress rsync will show you how many files it has seen
as it builds the file_list.
2002-01-15 10:43:51 +00:00
Martin Pool
a9b31409d5 Remove unused variable. 2002-01-15 10:04:48 +00:00
Martin Pool
98355b8086 Oops, getaddrinfo returns an error code (not -1) for error. -Wall is
good.
2002-01-15 10:04:11 +00:00
Martin Pool
70ed474b38 Define _GNU_SOURCE so that we get all necessary prototypes. 2002-01-15 09:53:27 +00:00
Martin Pool
4775934364 If using GCC, try to turn on -Wall. I want to be clean with respect
to -Wall.
2002-01-15 09:43:21 +00:00
Martin Pool
25f2cb3d6b Fix for <http://rsync.samba.org/cgi-bin/rsync/incoming?id=3750>
temp files must be opened through do_open so that binary modes is used
on cygwin.  (Chris Boucher)
2002-01-14 00:16:51 +00:00
Martin Pool
154f9a3aca Ignore testtmp directories. 2002-01-13 23:57:13 +00:00
Martin Pool
b9df3bf20c DOc. 2002-01-11 08:37:42 +00:00
Martin Pool
6abd193fe3 Always use 64-bit ino_t and dev_t internally, so that we can detect
hardlinks if coming from a larger platform.  Add heaps of comments
explaining why this is so.
2002-01-11 08:25:32 +00:00
Martin Pool
362099a512 More comments about IPv6 stuff.
If a reverse name lookup fails, show the name that we were trying to
look up.
2002-01-11 08:24:34 +00:00
Martin Pool
fdfc3dc9f3 When checking what was copied, use specific -d -f -L flags to test
rather than -e.  (Perhaps Solaris doesn't have test -e?)
2002-01-11 08:08:34 +00:00
Martin Pool
4937459225 The current version of rsync is expected to fail to eliminate all
duplicates from list.
2002-01-11 08:02:43 +00:00
Martin Pool
be2f866b4c Add concept of expected-failure. 2002-01-11 08:01:05 +00:00
Martin Pool
f08aacf7d6 Give cleaner output from "make check" 2002-01-11 07:41:50 +00:00
Martin Pool
4fa6112efe Bump version number.
Now finished merging across work from experimental BK repository.
2002-01-11 07:30:50 +00:00
Martin Pool
1623ba6889 Improved duplicates test: check that each file is
copied once and exactly once.
2002-01-11 07:29:53 +00:00
Martin Pool
766526c791 Check whether code to eliminate duplicate filenames works
(hint: it does not.)
2002-01-11 07:29:02 +00:00
Martin Pool
5c15e29f2b Better mallinfo() output in --stats 2002-01-11 07:26:39 +00:00
Martin Pool
0413e1605f Update copyright 2002-01-11 07:25:54 +00:00
Martin Pool
0e5a1f8352 Doc 2002-01-11 07:24:31 +00:00
Martin Pool
e5a2b8544d Look for mallinfo() and use it to display
heap usage information in --stats
2002-01-11 07:16:11 +00:00
Martin Pool
736a6a291c In protocol version 26, always
send 64-bit ino_t and dev_t.  We also need to try to use 64-bit
ino_t internally *even if* this platform does not have 64-bit
inums itself, because we need to find duplicate inums when
coming from a larger platform with --hardlinks.
2002-01-11 07:15:16 +00:00
Martin Pool
6e69cff118 Autoindent
Add copyright
2002-01-11 07:11:43 +00:00
Martin Pool
cf72f20426 Improved test framework and test for hardlink handling 2002-01-11 07:11:23 +00:00
Martin Pool
d479210cee Bump version 2002-01-11 07:10:25 +00:00
Martin Pool
b781537597 Merge ChangeSet@1.12: Add test case for -H 2002-01-11 07:09:53 +00:00
Martin Pool
ea1438dad8 Merge ChangeSet@1.12: tls now shows number of links to a file to aid in testing -H 2002-01-11 07:09:22 +00:00
Martin Pool
d2e9d069b4 Merge ChangeSet@1.10: Documentation about flist scalabilityTODO 2002-01-11 07:07:49 +00:00
Martin Pool
58379559cc Merge ChangeSet@1.9: Documentation about flist scalability 2002-01-11 07:07:30 +00:00
Martin Pool
b3e6c81565 Merge ChangeSet@1.4: Documentation about flist scalability 2002-01-11 07:05:30 +00:00
Martin Pool
a6a3c3df45 Merge ChangeSet@1.4: Documentation about future development. 2002-01-11 07:04:37 +00:00
Martin Pool
6e3d4c4045 Oops, fix date. 2002-01-03 07:18:17 +00:00
rsync-bugs
ca60b701ee preparing for release of 2.5.1 2002-01-03 07:11:10 +00:00
Martin Pool
e24c0b98d7 Cleanup. 2002-01-03 07:08:35 +00:00
David Dykstra
f389ac80a9 Removed debugging statement that was added to sig_int() by the rsync+ patch
integration.  It was causing the format of the daemon log to be messed up
because of the leading \n.
2001-12-20 15:33:13 +00:00
Martin Pool
50f2f002d9 Suggestion from David Stein
verbose output

  Indicate whether files are new, updated, or deleted
2001-12-20 01:23:28 +00:00
Martin Pool
9ec7528475 Typo 2001-12-18 06:48:56 +00:00
Martin Pool
a8e2a43a09 Get rid of global_opts struct as suggested by Dave -- too many
problems with initialization.
2001-12-18 06:47:40 +00:00
Martin Pool
eb06fa95e4 Documentation fixes based on mail from Edward Welbourne, and an
attempted explanation of rsync's symbolic-link handling.
2001-12-18 06:45:28 +00:00
Martin Pool
1db8b61de7 Add an "unsafe" symlink to the symlink test case so we can see what happens. 2001-12-18 06:26:26 +00:00
Martin Pool
38c66db8d6 Note about hardlink performance. 2001-12-18 06:25:31 +00:00
Martin Pool
f8be7d4219 Refactor code for setting local address on outgoing connections. If a
local address is specified, then try all addrinfo records for it.
2001-12-18 06:21:33 +00:00
Martin Pool
13e29995f5 Get rid of global_opts struct as suggested by Dave -- too many
problems with initialization.

Change the algorithm from trying to open an inbound socket with
getaddrinfo: keep trying suggested addresses until we find one on
which we can both get a socket and bind.  Not convinced this is the
best, but it's probably better.
2001-12-18 05:54:57 +00:00
Martin Pool
7c583c7316 Note rsyncd-over-ssh and documentation TODOs. 2001-12-18 01:33:56 +00:00
Martin Pool
9fecec5e85 Fix from Jeff Garzik for inet_ntop prototype errors on some Linux
distributions: we were failing to define HAVE_INET_NTOP, so our
prototype in rsync.h came through.

Also rerun autoheader, and have comment for HAVE_SOCKADDR_STORAGE.
2001-12-18 01:32:27 +00:00
Martin Pool
9e696bd468 Update README so that Paulus doesn't get bug reports anymore :-)
I think this document needs to be reworked to better explain how to
use rsync, but not right now.
2001-12-18 01:07:20 +00:00
David Dykstra
6ab6d4bfc1 When INET6 is not defined, meaning that IPv6 is not supported, need to
initalize the global_opts.af_hint to AF_INET or systems such as Linux that
have a native getaddrinfo() because they support IPv6 will attempt to
create IPv6 sockets.  This brings up a problem with the new global_opts
structure; in order to initialize them to a value other than 0, we need to
explicitly initialize them all in an order that matches the order in
rsync.h.  I think that's more inconvenient & error prone than keeping
global variables.
2001-12-14 18:25:51 +00:00
David Dykstra
cb1bcc7ebb open_socket_in was attempting to try all the protocols returned from
getaddrinfo(), but only if a corresponding call to socket() returned one of
three *NOSUPPORT errno codes.  A Redhat 6.2 system was observed returning
EINVAL instead so it never went on to try IPv4.  This update adds EINVAL to
the list.  Question: why not always continue through the list regardless of
what errno is?
2001-12-14 18:00:54 +00:00
Martin Pool
19ba7d6318 Verbose. 2001-12-14 05:55:21 +00:00
Martin Pool
7753ca1f49 Only show test output if it failed. 2001-12-14 05:54:24 +00:00
Martin Pool
d52a796c39 Be less verbose. 2001-12-14 05:52:25 +00:00
Martin Pool
60514d457c Fix quoting. 2001-12-14 05:44:04 +00:00
Martin Pool
5bc00efe42 Perhaps Solaris sh wants us to explicitly exit 0, rather than just
using the last return code?
2001-12-14 05:27:42 +00:00
Martin Pool
c45f3133bc More error messages. 2001-12-14 05:19:15 +00:00
Martin Pool
fb47591de0 Typo. 2001-12-14 05:17:52 +00:00
Martin Pool
514d129c49 Make scratch directory properly. 2001-12-14 05:01:48 +00:00
Martin Pool
db843fc12d Doc. 2001-12-14 02:18:31 +00:00
Martin Pool
63787382d8 Clearer error messages. 2001-12-14 02:16:20 +00:00
Martin Pool
85d4d142d8 Clearer error messages. 2001-12-14 02:14:58 +00:00
Martin Pool
3cd2af41e4 Add a test that when none of -l, -L, -a are specified symlinks are not
copied at all.
2001-12-14 02:01:46 +00:00
Martin Pool
b214eda4f0 Clean scratch directory between each test run. 2001-12-14 01:52:43 +00:00
Martin Pool
0771727d41 Readlink(2) does not nul-terminate the output buffer, so we were
getting corrupt output when listing more than one symlink.
2001-12-14 01:48:48 +00:00
Martin Pool
a5d74a1876 Fix contact details. 2001-12-14 01:09:23 +00:00
Martin Pool
23bf32f767 Don't define DEBUG with --enable-debug, because that makes zlib emit strange messages 2001-12-09 21:48:13 +00:00
Martin Pool
87a819edee IRIX cc cares that the operands to the ternary have the same type. 2001-12-05 13:48:41 +00:00
Martin Pool
27a1234874 Be more strict about 'enum logcode' rather than int. IRIX compiler
picked this up -- quite neat.
2001-12-05 13:45:51 +00:00
Martin Pool
51f289d1e6 Some platforms don't have sa_family_t. 2001-12-05 13:44:37 +00:00
Martin Pool
d0d6dc61e8 Bump version 2001-12-05 13:41:38 +00:00
Martin Pool
d91c8c50d2 RFC2553 just says that sockaddr_storage has to have initial fields
isomorphic to sa_family etc from a struct sockaddr, not what they're
called.  On some platforms they seem not to be called ss_family.
Rather than guess, we will try casting to a sockaddr and looking
through that -- I think this is what the RFC intends.
2001-12-05 13:25:29 +00:00
Martin Pool
e20a4f84d6 Some platforms may have getaddrinfo() but not sockaddr_storage. 2001-12-05 13:19:16 +00:00
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
49 changed files with 3259 additions and 2291 deletions

View File

@@ -4,10 +4,15 @@ config.cache
config.h
config.log
config.status
gmon.out
rsync
shconfig
testdir
tests-dont-exist
testtmp
testtmp.*
tls
zlib/dummy
confdefs.h
conftest.c
conftest.log

27
INSTALL
View File

@@ -13,3 +13,30 @@ 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

@@ -23,18 +23,20 @@ VERSION=@VERSION@
.SUFFIXES: .c .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 batch.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o batch.o \
clientname.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
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
tls_OBJ = tls.o syscall.o lib/permstring.o
# Programs we must have to run the test cases
CHECK_PROGS = rsync tls
@@ -61,8 +63,11 @@ 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): config.h
tls: $(tls_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(tls_OBJ) $(LIBS)
@@ -83,17 +88,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
# missing functions
getaddrinfo.o: lib/getaddrinfo.c
$(CC) -I. -I$(srcdir) -I$(srcdir)/lib $(CFLAGS) -c lib/getaddrinfo.c
getnameinfo.o: lib/getnameinfo.c
$(CC) -I. -I$(srcdir) -I$(srcdir)/lib $(CFLAGS) -c lib/getnameinfo.c
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
@@ -123,13 +123,13 @@ test: check
# might lose in the future where POSIX diverges from old sh.
check: all $(CHECK_PROGS)
POSIXLY_CORRECT=1 rsync_bin=`pwd`/rsync srcdir="$(srcdir)" $(srcdir)/runtests.sh
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 rsync_bin="$(bindir)/rsync" srcdir="$(srcdir)" $(srcdir)/runtests.sh
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

80
NEWS
View File

@@ -1,77 +1,7 @@
rsync 2.4.7 (sometime in 2001, maybe :)
rsync 2.3.3 (26 Jan 2002)
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>
* Merged IPv6 patch from KAME.net.
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.
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.
SECURITY FIXES:
* Signedness security patch from Sebastian Krahmer
<krahmer@suse.de> -- in some cases we were not sufficiently
careful about reading integers from the network.

148
OLDNEWS Normal file
View File

@@ -0,0 +1,148 @@
rsync 2.5.1 (2002-01-03)
BUG FIXES:
* Fix for segfault in --daemon mode configuration parser. (Paul
Mackerras)
* Correct string<->address parsing for both IPv4 and 6.
(YOSHIFUJI Hideaki, SUMIKAWA Munechika and Jun-ichiro "itojun"
Hagino)
* Various fixes for IPv6 support. (Dave Dykstra)
* rsync.1 typo fix. (Matt Kraai)
* Test suite typo fixes. (Tom Schmidt)
* rsync.1 grammar and clarity improvements. (Edward
Welbourne)
* Correction to ./configure tests for inet_ntop. (Jeff Garzik)
ENHANCEMENTS:
* --progress and -P now show estimated data transfer rate (in a
multiple of bytes/s) and estimated time to completion. (Rik
Faith)
* --no-detach option, required to run as a W32 service and also
useful when running on Unix under daemontools, AIX's SRC, or a
debugger. (Max Bowsher, Jos Backus)
* Clearer error messages for some conditions.
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.

13
README
View File

@@ -143,9 +143,7 @@ This will give you access to the bug tracking system used by the
developers of rsync and will allow you to look at other bug reports or
submit a new bug report.
If you don't have web access then mail bug reports to
rsync-bugs@samba.org or (if you think it will be of interest to lots
of people) send it to rsync@samba.org
If you don't have web access then mail bug reports to rsync@samba.org.
CVS TREE
@@ -167,11 +165,12 @@ details.
COPYRIGHT
---------
Rsync was written by Andrew Tridgell and Paul Mackerras, and is
available under the GNU General Public License.
rsync was originally written by Andrew Tridgell and has been improved
by many developers around the world. rsync may be used, modified and
redistributed only under the terms of the GNU General Public License,
found in the file COPYING in this distribution, or at
tridge@samba.org
paulus@cs.anu.edu.au
http://www.fsf.org/licenses/gpl.html
AVAILABILITY

283
TODO
View File

@@ -16,21 +16,287 @@ Cross-test versions
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.
At the moment rsync reads the whole file list into memory at the
start, which makes us use a lot of memory and also not pipeline
network access as much as we could.
Handling duplicate names
We need to be careful of duplicate names getting into the file list.
See clean_flist(). This could happen if multiple arguments include
the same file. Bad.
I think duplicates are only a problem if they're both flowing
through the pipeline at the same time. For example we might have
updated the first occurrence after reading the checksums for the
second. So possibly we just need to make sure that we don't have
both in the pipeline at the same time.
Possibly if we did one directory at a time that would be sufficient.
Alternatively we could pre-process the arguments to make sure no
duplicates will ever be inserted. There could be some bad cases
when we're collapsing symlinks.
We could have a hash table.
The root of the problem is that we do not want more than one file
list entry referring to the same file. At first glance there are
several ways this could happen: symlinks, hardlinks, and repeated
names on the command line.
If names are repeated on the command line, they may be present in
different forms, perhaps by traversing directory paths in different
ways, traversing paths including symlinks. Also we need to allow
for expansion of globs by rsync.
At the moment, clean_flist() requires having the entire file list in
memory. Duplicate names are detected just by a string comparison.
We don't need to worry about hard links causing duplicates because
files are never updated in place. Similarly for symlinks.
I think even if we're using a different symlink mode we don't need
to worry.
Unless we're really clever this will introduce a protocol
incompatibility, so we need to be able to accept the old format as
well.
Memory accounting
At exit, show how much memory was used for the file list, etc.
Also we do a wierd exponential-growth allocation in flist.c. I'm
not sure this makes sense with modern mallocs. At any rate it will
make us allocate a huge amount of memory for large file lists.
We can try using the GNU/SVID/XPG mallinfo() function to get some
heap statistics.
Hard-link handling
At the moment hardlink handling is very expensive, so it's off by
default. It does not need to be so.
Since most of the solutions are rather intertwined with the file
list it is probably better to fix that first, although fixing
hardlinks is possibly simpler.
We can rule out hardlinked directories since they will probably
screw us up in all kinds of ways. They simply should not be used.
At the moment rsync only cares about hardlinks to regular files. I
guess you could also use them for sockets, devices and other beasts,
but I have not seen them.
When trying to reproduce hard links, we only need to worry about
files that have more than one name (nlinks>1 && !S_ISDIR).
The basic point of this is to discover alternate names that refer to
the same file. All operations, including creating the file and
writing modifications to it need only to be done for the first name.
For all later names, we just create the link and then leave it
alone.
If hard links are to be preserved:
Before the generator/receiver fork, the list of files is received
from the sender (recv_file_list), and a table for detecting hard
links is built.
The generator looks for hard links within the file list and does
not send checksums for them, though it does send other metadata.
The sender sends the device number and inode with file entries, so
that files are uniquely identified.
The receiver goes through and creates hard links (do_hard_links)
after all data has been written, but before directory permissions
are set.
At the moment device and inum are sent as 4-byte integers, which
will probably cause problems on large filesystems. On Linux the
kernel uses 64-bit ino_t's internally, and people will soon have
filesystems big enough to use them. We ought to follow NFS4 in
using 64-bit device and inode identification, perhaps with a
protocol version bump.
Once we've seen all the names for a particular file, we no longer
need to think about it and we can deallocate the memory.
We can also have the case where there are links to a file that are
not in the tree being transferred. There's nothing we can do about
that. Because we rename the destination into place after writing,
any hardlinks to the old file are always going to be orphaned. In
fact that is almost necessary because otherwise we'd get really
confused if we were generating checksums for one name of a file and
modifying another.
At the moment the code seems to make a whole second copy of the file
list, which seems unnecessary.
We should have a test case that exercises hard links. Since it
might be hard to compare ./tls output where the inodes change we
might need a little program to check whether several names refer to
the same file.
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
At the connections that just get a list of modules are not logged,
but they should be.
rsyncd over ssh
There are already some patches to do this.
proxy authentication
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
HTTP Basic Proxy-Authentication.
Multiple schemes are possible, up to and including the insanity that
is NTLM, but Basic probably covers most cases.
SOCKS
Add --with-socks, and then perhaps a command-line option to put them
on or off. This might be more reliable than LD_PRELOAD hacks.
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.
DOCUMENTATION --------------------------------------------------------
Update README
BUILD FARM -----------------------------------------------------------
Add machines
AMDAHL UTS (Dave Dykstra)
Cygwin (on different versions of Win32?)
HP-UX variants (via HP?)
SCO
NICE -----------------------------------------------------------------
Merge IPv6 support ***
--no-detach and --no-fork options
A patch is available at
Very useful for debugging. Also good when running under a
daemon-monitoring process that tries to restart the service when the
parent exits.
ftp://ftp.kame.net/pub/kame/misc/rsync-244-v6-20000802.diff.gz
hang/timeout friendliness
but tridge reckons it needs to be cleaned up before it can be
accepted.
verbose output
Indicate whether files are new, updated, or deleted
This is now on the track-kameipv6 branch and can be moved across any
time. The KAME people say that it should work on machines without
IPv6 stacks.
internationalization
Change to using gettext(). Probably need to ship this for platforms
that don't have it.
Solicit translations.
Does anyone care?
rsyncsh
@@ -40,3 +306,4 @@ rsyncsh
current host, directory and so on. We can probably even do
completion of remote filenames.
%K%

4
aclocal.m4 vendored
View File

@@ -43,8 +43,8 @@ AC_DEFUN([TYPE_SOCKLEN_T],
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>
#include <sys/types.h>
#include <sys/socket.h>
int getpeername (int, $arg2 *, $t *);
],[

View File

@@ -105,8 +105,8 @@ static int get_secret(int module, char *user, char *secret, int len)
while (!found) {
int i = 0;
memset(line, 0, sizeof(line));
while (i<(sizeof(line)-1)) {
memset(line, 0, sizeof line);
while ((size_t) i < (sizeof(line)-1)) {
if (read(fd, &line[i], 1) != 1) {
memset(line, 0, sizeof(line));
close(fd);

860
batch.c
View File

File diff suppressed because it is too large Load Diff

283
clientname.c Normal file
View File

@@ -0,0 +1,283 @@
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file clientname.c
*
* Functions for looking up the remote name or addr of a socket.
*
* This file is now converted to use the new-style getaddrinfo()
* interface, which supports IPv6 but is also supported on recent
* IPv4-only machines. On systems that don't have that interface, we
* emulate it using the KAME implementation.
**/
#include "rsync.h"
static const char default_name[] = "UNKNOWN";
/**
* Return the IP addr of the client as a string
**/
char *client_addr(int fd)
{
struct sockaddr_storage ss;
socklen_t length = sizeof ss;
static char addr_buf[100];
static int initialised;
if (initialised) return addr_buf;
initialised = 1;
client_sockaddr(fd, &ss, &length);
getnameinfo((struct sockaddr *)&ss, length,
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
return addr_buf;
}
static int get_sockaddr_family(const struct sockaddr_storage *ss)
{
return ((struct sockaddr *) ss)->sa_family;
}
/**
* Return the DNS name of the client.
*
* The name is statically cached so that repeated lookups are quick,
* so there is a limit of one lookup per customer.
*
* If anything goes wrong, including the name->addr->name check, then
* we just use "UNKNOWN", so you can use that value in hosts allow
* lines.
**/
char *client_name(int fd)
{
struct sockaddr_storage ss;
socklen_t ss_len = sizeof ss;
static char name_buf[100];
static char port_buf[100];
static int initialised;
if (initialised) return name_buf;
strcpy(name_buf, default_name);
initialised = 1;
client_sockaddr(fd, &ss, &ss_len);
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf, port_buf, sizeof port_buf))
check_name(fd, &ss, ss_len, name_buf, port_buf);
return name_buf;
}
/**
* Get the sockaddr for the client.
*
* If it comes in as an ipv4 address mapped into IPv6 format then we
* convert it back to a regular IPv4.
**/
void client_sockaddr(int fd,
struct sockaddr_storage *ss,
socklen_t *ss_len)
{
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
/* FIXME: Can we really not continue? */
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
fd, strerror(errno));
exit_cleanup(RERR_SOCKETIO);
}
#ifdef INET6
if (get_sockaddr_family(ss) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
/* OK, so ss is in the IPv6 family, but it is really
* an IPv4 address: something like
* "::ffff:10.130.1.2". If we use it as-is, then the
* reverse lookup might fail or perhaps something else
* bad might happen. So instead we convert it to an
* equivalent address in the IPv4 address family. */
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;
*ss_len = sizeof(struct sockaddr_in);
#ifdef HAVE_SOCKADDR_LEN
sin->sin_len = *ss_len;
#endif
sin->sin_port = sin6.sin6_port;
/* There is a macro to extract the mapped part
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
* to be present in the Linux headers. */
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
sizeof(sin->sin_addr));
}
#endif
}
/**
* Look up a name from @p ss into @p name_buf.
**/
int lookup_name(int fd, const struct sockaddr_storage *ss,
socklen_t ss_len,
char *name_buf, size_t name_buf_len,
char *port_buf, size_t port_buf_len)
{
int name_err;
/* reverse lookup */
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
name_buf, name_buf_len,
port_buf, port_buf_len,
NI_NAMEREQD | NI_NUMERICSERV);
if (name_err != 0) {
strcpy(name_buf, default_name);
rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
client_addr(fd),
gai_strerror(name_err));
return name_err;
}
return 0;
}
/**
* Compare an addrinfo from the resolver to a sockinfo.
*
* Like strcmp, returns 0 for identical.
**/
int compare_addrinfo_sockaddr(const struct addrinfo *ai,
const struct sockaddr_storage *ss)
{
int ss_family = get_sockaddr_family(ss);
const char fn[] = "compare_addrinfo_sockaddr";
if (ai->ai_family != ss_family) {
rprintf(FERROR,
"%s: response family %d != %d\n",
fn, ai->ai_family, ss_family);
return 1;
}
/* The comparison method depends on the particular AF. */
if (ss_family == AF_INET) {
const struct sockaddr_in *sin1, *sin2;
sin1 = (const struct sockaddr_in *) ss;
sin2 = (const struct sockaddr_in *) ai->ai_addr;
return memcmp(&sin1->sin_addr, &sin2->sin_addr,
sizeof sin1->sin_addr);
}
#ifdef INET6
else if (ss_family == AF_INET6) {
const struct sockaddr_in6 *sin1, *sin2;
sin1 = (const struct sockaddr_in6 *) ss;
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
return memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
sizeof sin1->sin6_addr);
}
#endif /* INET6 */
else {
/* don't know */
return 1;
}
}
/**
* Do a forward lookup on @p name_buf and make sure it corresponds to
* @p ss -- otherwise we may be being spoofed. If we suspect we are,
* then we don't abort the connection but just emit a warning, and
* change @p name_buf to be "UNKNOWN".
**/
int check_name(int fd,
const struct sockaddr_storage *ss,
socklen_t ss_len,
char *name_buf,
const char *port_buf)
{
struct addrinfo hints, *res, *res0;
int error;
int ss_family = get_sockaddr_family(ss);
memset(&hints, 0, sizeof(hints));
hints.ai_family = ss_family;
hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
if (error) {
rprintf(FERROR,
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
name_buf, gai_strerror(error));
strcpy(name_buf, default_name);
return error;
}
/* Given all these results, we expect that one of them will be
* the same as ss. The comparison is a bit complicated. */
for (res = res0; res; res = res->ai_next) {
if (!compare_addrinfo_sockaddr(res, ss))
break; /* OK, identical */
}
if (!res0) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FERROR, RSYNC_NAME
": no known address for \"%s\": "
"spoofed address?\n",
name_buf);
strcpy(name_buf, default_name);
} else if (res == NULL) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FERROR, RSYNC_NAME
": %s is not a known address for \"%s\": "
"spoofed address?\n",
client_addr(fd),
name_buf);
strcpy(name_buf, default_name);
}
freeaddrinfo(res0);
return 0;
}

View File

@@ -45,6 +45,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
extern char *shell_cmd;
extern int kludge_around_eof;
extern char *bind_address;
extern int default_af_hint;
if (argc == 0 && !am_sender) {
extern int list_only;
@@ -78,7 +79,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_wrapped (host, rsync_port, bind_address);
fd = open_socket_out_wrapped (host, rsync_port, bind_address,
default_af_hint);
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
@@ -166,9 +168,9 @@ static int rsync_module(int fd, int i)
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
name, client_name(fd), client_addr(fd));
name, host, addr);
io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n",
name, client_name(fd), client_addr(fd));
name, host, addr);
return -1;
}
@@ -485,6 +487,7 @@ int daemon_main(void)
extern char *config_file;
extern int orig_umask;
char *pid_file;
extern int no_detach;
if (is_a_socket(STDIN_FILENO)) {
int i;
@@ -500,7 +503,8 @@ int daemon_main(void)
return start_daemon(STDIN_FILENO);
}
become_daemon();
if (!no_detach)
become_daemon();
if (!lp_load(config_file, 1)) {
exit_cleanup(RERR_SYNTAX);
@@ -512,7 +516,8 @@ int daemon_main(void)
RSYNC_VERSION,
rsync_port);
/* TODO: If listening on a particular address, then show that
* address too. */
* 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];

View File

@@ -5,6 +5,12 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.52)
RSYNC_VERSION=2.5.2pre3
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
LDFLAGS=${LDFLAGS-""}
AC_CANONICAL_TARGET([])
@@ -13,14 +19,21 @@ dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_CC_STDC
AC_SUBST(SHELL)
RSYNC_VERSION=2.4.7pre2
AC_SUBST(RSYNC_VERSION)
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
# compile with optimisation and without debugging by default, unless
# --debug is given. We must decide this before testing the compiler.
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
# We must decide this before testing the compiler.
# Please allow this to default to yes, so that your users have more
# chance of getting a useful stack trace if problems occur.
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
@@ -35,12 +48,33 @@ then
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 AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
dnl CFLAGS=${CFLAGS-"-g"}
fi
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],
[turn on CPU profiling (default no)],
[], []))
if test x"$enable_profile" = xyes
then
CFLAGS="$CFLAGS -pg"
fi
# This is needed for our included version of popt. Kind of silly, but
# I don't want our version too far out of sync.
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
# If GCC, turn on warnings.
if test "x$GCC" = "xyes"
then
CFLAGS="$CFLAGS -Wall -W"
fi
AC_ARG_WITH(included-popt,
[ --with-included-popt use bundled popt library, not from system])
@@ -90,29 +124,15 @@ if test x"$rsync_cv_HAVE_BROKEN_LARGEFILE" != x"yes"; then
AC_SYS_LARGEFILE
fi
AC_DEFINE(ss_family, __ss_family, [KAME hack])
AC_DEFINE(ss_len, __ss_len, [KAME hack])
CFLAGS="$CFLAGS"
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6], [do not try to support IPv6]))
AC_MSG_CHECKING([whether IPv6 is explicitly disabled])
if test "$xenable_ipv6" = xyes
then
AC_MSG_RESULT(yes)
ipv6=no
else
AC_MSG_RESULT(no)
ipv6=yes
fi
ipv6type=unknown
ipv6lib=none
ipv6trylibc=no
ipv6trylibc=yes
if test "$ipv6" = "yes"; then
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
@@ -197,152 +217,10 @@ yes
fi
done
AC_MSG_RESULT($ipv6type)
AC_SEARCH_LIBS(getaddrinfo, inet6)
fi
if test "$ipv6" = "yes" -a -f /usr/local/v6/lib/libinet6.a; then
ac_inet6_LDFLAGS="inet6"
ipv6libdir=/usr/local/v6/lib
LDFLAGS="$LDFLAGS -L/usr/local/v6/lib"
AC_CHECK_LIB(inet6, getaddrinfo, , ipv6lib="$ac_inet6_LDFLAGS")
fi
if test "$ipv6" = "yes" -a -f /usr/lib/libinet6.a; then
ac_inet6_LDFLAGS="inet6"
AC_CHECK_LIB(inet6, getaddrinfo, , ipv6lib="$ac_inet6_LDFLAGS")
fi
if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then
if test -d $ipv6libdir -a -f $ipv6libdir/lib$ipv6lib.a; then
LIBS="-L$ipv6libdir -l$ipv6lib $LIBS"
echo "You have $ipv6lib library, using it"
else
if test "$ipv6trylibc" = "yes"; then
echo "You do not have $ipv6lib library, using libc"
else
echo 'Fatal: no $ipv6lib library found. cannot continue.'
echo "You need to fetch lib$ipv6lib.a from appropriate"
echo 'ipv6 kit and compile beforehand.'
exit 1
fi
fi
fi
AC_MSG_CHECKING(getaddrinfo bug)
AC_TRY_RUN([
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
main()
{
int passive, gaierr, inet4 = 0, inet6 = 0;
struct addrinfo hints, *ai, *aitop;
char straddr[INET6_ADDRSTRLEN], strport[16];
for (passive = 0; passive <= 1; passive++) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = passive ? AI_PASSIVE : 0;
hints.ai_socktype = SOCK_STREAM;
if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
(void)gai_strerror(gaierr);
goto bad;
}
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_addr == NULL ||
ai->ai_addrlen == 0 ||
getnameinfo(ai->ai_addr, ai->ai_addrlen,
straddr, sizeof(straddr), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
goto bad;
}
switch (ai->ai_family) {
case AF_INET:
if (strcmp(strport, "54321") != 0) {
goto bad;
}
if (passive) {
if (strcmp(straddr, "0.0.0.0") != 0) {
goto bad;
}
} else {
if (strcmp(straddr, "127.0.0.1") != 0) {
goto bad;
}
}
inet4++;
break;
case AF_INET6:
if (strcmp(strport, "54321") != 0) {
goto bad;
}
if (passive) {
if (strcmp(straddr, "::") != 0) {
goto bad;
}
} else {
if (strcmp(straddr, "::1") != 0) {
goto bad;
}
}
inet6++;
break;
case AF_UNSPEC:
goto bad;
break;
default:
/* another family support? */
break;
}
}
}
if (!(inet4 == 0 || inet4 == 2))
goto bad;
if (!(inet6 == 0 || inet6 == 2))
goto bad;
if (aitop)
freeaddrinfo(aitop);
exit(0);
bad:
if (aitop)
freeaddrinfo(aitop);
exit(1);
}
],
AC_MSG_RESULT(good)
buggygetaddrinfo=no,
AC_MSG_RESULT(buggy)
buggygetaddrinfo=yes,
AC_MSG_RESULT(buggy)
buggygetaddrinfo=yes)
if test "$buggygetaddrinfo" = "yes"; then
if test "$ipv6" = "yes" -a "$ipv6type" != "linux"; then
echo 'Fatal: You must get working getaddrinfo() function.'
echo ' or you can specify "--disable-ipv6"'.
exit 1
elif test "$ipv6type" = "linux"; then
echo 'Warning: getaddrinfo() implementation on your system seems be buggy.'
echo ' Better upgreade your system library to newest version'
echo ' of GNU C library (aka glibc).'
fi
fi
AC_REPLACE_FUNCS(getaddrinfo getnameinfo)
AC_CHECK_MEMBER([struct sockaddr.sa_len],
[ AC_DEFINE(HAVE_SOCKADDR_LEN) ],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
])
AC_C_BIGENDIAN
AC_HEADER_DIRENT
AC_HEADER_TIME
@@ -350,7 +228,9 @@ 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 alloca.h mcheck.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_HEADERS(malloc.h)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -413,7 +293,33 @@ if test x"$ac_cv_func_connect" = x"no"; then
fi
fi
#
AC_CHECK_LIB(resolv, inet_ntop)
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
AC_CHECK_FUNCS(inet_ntop, , AC_LIBOBJ(lib/inet_ntop))
AC_CHECK_FUNCS(inet_pton, , AC_LIBOBJ(lib/inet_pton))
AC_CHECK_FUNCS(getaddrinfo, , AC_LIBOBJ(lib/getaddrinfo))
AC_CHECK_FUNCS(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, 1,
[Define if you have strct sockaddr_storage.] ),
AC_MSG_RESULT(no))
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
#
AC_CHECK_FUNCS(strcasecmp)
@@ -421,20 +327,26 @@ if test x"$ac_cv_func_strcasecmp" = x"no"; then
AC_CHECK_LIB(resolv, strcasecmp)
fi
AC_FUNC_MEMCMP
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_CHECK_FUNCS(strlcat strlcpy mtrace mallinfo)
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);
}],
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, [ ])
@@ -640,3 +552,7 @@ AC_SUBST(BUILD_POPT)
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
AC_OUTPUT
AC_MSG_RESULT()
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
AC_MSG_RESULT()

154
exclude.c
View File

@@ -1,7 +1,6 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 1996 by Paul Mackerras
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,8 +20,6 @@
/* 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;
@@ -30,8 +27,52 @@ extern int delete_mode;
static struct exclude_struct **exclude_list;
/*
* Optimization for special case when all included files are explicitly
* listed without wildcards in the "exclude" list followed by a "- *"
* to exclude the rest.
* Contributed by Dave Dykstra <dwd@bell-labs.com>
*/
static int only_included_files = 1;
static struct exclude_struct *exclude_the_rest;
int send_included_file_names(int f,struct file_list *flist)
{
struct exclude_struct *ex, **ex_list;
int n;
char *p;
if (!only_included_files || (exclude_the_rest == NULL) || delete_mode)
return 0;
if (verbose > 1) {
rprintf(FINFO,"(using include-only optimization) ");
}
/* set exclude_list to NULL temporarily so check_exclude */
/* will always return true */
ex_list = exclude_list;
exclude_list = NULL;
for (n=0; (ex = ex_list[n]) != NULL; n++) {
if (ex == exclude_the_rest)
break;
p = ex->pattern;
while (*p == '/') {
/* skip the allowed beginning slashes */
p++;
}
/* silently skip files that don't exist to
be more like non-optimized case */
if (access(p,0) == 0)
send_file_name(f,flist,p,0,0);
}
exclude_list = ex_list;
return 1;
}
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(const char *pattern, int include)
static struct exclude_struct *make_exclude(char *pattern, int include)
{
struct exclude_struct *ret;
@@ -54,18 +95,15 @@ static struct exclude_struct *make_exclude(const char *pattern, int include)
if (!ret->pattern) out_of_memory("make_exclude");
if (strpbrk(pattern, "*[?")) {
ret->regular_exp = 1;
ret->fnmatch_flags = FNM_PATHNAME;
if (strstr(pattern, "**")) {
static int tested;
if (!tested) {
tested = 1;
if (fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME)==0) {
rprintf(FERROR,"WARNING: fnmatch FNM_PATHNAME is broken on your system\n");
}
}
ret->fnmatch_flags = 0;
if (!ret->include && (*pattern == '*') && (*(pattern+1) == '\0')) {
exclude_the_rest = ret;
} else {
only_included_files = 0;
}
ret->regular_exp = 1;
ret->fnmatch_flags = strstr(pattern, "**") ? 0 : FNM_PATHNAME;
} else if (!ret->include) {
only_included_files = 0;
}
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
@@ -87,8 +125,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;
@@ -107,79 +145,47 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
}
if (ex->regular_exp) {
if (fnmatch(pattern, name, ex->fnmatch_flags) == 0) {
if (fnmatch(pattern, name, ex->fnmatch_flags) == 0)
return 1;
}
} else {
int l1 = strlen(name);
int l2 = strlen(pattern);
if (l2 <= l1 &&
strcmp(name+(l1-l2),pattern) == 0 &&
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/'))) {
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/')))
return 1;
}
}
return 0;
}
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,
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++) {
ent = exclude_list[n];
if (check_one_exclude(name, ent, st)) {
report_exclude_result(name, ent, st);
return !ent->include;
}
}
for (n=0; exclude_list[n]; n++)
if (check_one_exclude(name,exclude_list[n],st))
return !exclude_list[n]->include;
}
if (local_exclude_list) {
for (n=0; local_exclude_list[n]; n++) {
ent = local_exclude_list[n];
if (check_one_exclude(name, ent, st)) {
report_exclude_result(name, ent, st);
return !ent->include;
}
}
for (n=0; local_exclude_list[n]; n++)
if (check_one_exclude(name,local_exclude_list[n],st))
return !local_exclude_list[n]->include;
}
return 0;
}
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
{
int len=0;
if (list && *list)
@@ -193,6 +199,8 @@ void add_exclude_list(const char *pattern, struct exclude_struct ***list, int in
}
free((*list));
*list = NULL;
only_included_files = 1;
exclude_the_rest = NULL;
return;
}
@@ -207,12 +215,12 @@ void add_exclude_list(const char *pattern, struct exclude_struct ***list, int in
(*list)[len+1] = NULL;
}
void add_exclude(const char *pattern, int include)
void add_exclude(char *pattern, int include)
{
add_exclude_list(pattern,&exclude_list, include);
}
struct exclude_struct **make_exclude_list(const char *fname,
struct exclude_struct **make_exclude_list(char *fname,
struct exclude_struct **list1,
int fatal, int include)
{
@@ -221,10 +229,7 @@ struct exclude_struct **make_exclude_list(const char *fname,
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
rsyserr(FERROR, errno,
"failed to open %s file %s",
include ? "include" : "exclude",
fname);
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
return list;
@@ -246,7 +251,7 @@ struct exclude_struct **make_exclude_list(const char *fname,
}
void add_exclude_file(const char *fname, int fatal, int include)
void add_exclude_file(char *fname,int fatal,int include)
{
if (!fname || !*fname) return;
@@ -258,12 +263,6 @@ 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);
@@ -299,7 +298,8 @@ void send_exclude_list(int f)
void recv_exclude_list(int f)
{
char line[MAXPATHLEN];
int l;
unsigned int l;
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
@@ -398,7 +398,7 @@ void add_cvs_excludes(void)
add_exclude(cvs_ignore_list[i], 0);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
slprintf(fname,sizeof(fname), "%s/.cvsignore",p);
add_exclude_file(fname,0,0);
}

View File

@@ -36,7 +36,7 @@ int sparse_end(int f)
}
static int write_sparse(int f,char *buf,int len)
static int write_sparse(int f,char *buf,size_t len)
{
int l1=0,l2=0;
int ret;
@@ -69,7 +69,7 @@ static int write_sparse(int f,char *buf,int len)
int write_file(int f,char *buf,int len)
int write_file(int f,char *buf,size_t len)
{
int ret = 0;

191
flist.c
View File

@@ -47,67 +47,12 @@ 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)
{
@@ -153,7 +98,7 @@ int readlink_stat(const char *Path, STRUCT_STAT *Buffer, char *Linkbuf)
}
if (S_ISLNK(Buffer->st_mode)) {
int l;
if ((l = readlink((char *) Path, Linkbuf, MAXPATHLEN-1))== -1) {
if ((l = readlink(Path,Linkbuf,MAXPATHLEN-1)) == -1) {
return -1;
}
Linkbuf[l] = 0;
@@ -188,6 +133,8 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer)
static int match_file_name(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;
@@ -206,7 +153,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;
@@ -214,8 +161,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;
}
@@ -335,7 +282,7 @@ static void receive_file_entry(struct file_struct **fptr,
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
int l1=0,l2=0;
unsigned int l1=0,l2=0;
char *p;
struct file_struct *file;
@@ -352,11 +299,7 @@ static void receive_file_entry(struct file_struct **fptr,
memset((char *)file, 0, sizeof(*file));
(*fptr) = file;
if (l2 >= MAXPATHLEN-l1) {
rprintf(FERROR,"overflow: flags=0x%x l1=%d l2=%d lastname=%s\n",
flags, l1, l2, lastname);
overflow("receive_file_entry");
}
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
strlcpy(thisname,lastname,l1+1);
read_sbuf(f,&thisname[l1],l2);
@@ -402,6 +345,10 @@ static void receive_file_entry(struct file_struct **fptr,
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
if (l < 0) {
rprintf(FERROR,"overflow: l=%d\n", l);
overflow("receive_file_entry");
}
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
@@ -466,12 +413,7 @@ 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 string_area **ap,
int noexcludes)
static struct file_struct *make_file(int f, char *fname)
{
struct file_struct *file;
STRUCT_STAT st;
@@ -480,7 +422,6 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
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;
@@ -490,23 +431,15 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
}
fname = cleaned_name;
/* f is set to -1 when calculating deletion file list */
if (((f != -1) || !delete_excluded) && !noexcludes && !match_file_name(fname,&st))
return NULL;
memset(sum,0,SUM_LENGTH);
if (readlink_stat(fname,&st,linkbuf) != 0) {
io_error = 1;
rprintf(FERROR,"readlink %s: %s\n",
rprintf(FERROR,"%s: %s\n",
fname,strerror(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;
@@ -517,12 +450,10 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
return NULL;
}
if (lp_ignore_nonreadable(module_id) && access(fname, R_OK) != 0)
/* f is set to -1 when calculating deletion file list */
if (((f != -1) || !delete_excluded) && !match_file_name(fname,&st))
return NULL;
skip_excludes:
if (verbose > 2)
rprintf(FINFO,"make_file(%d,%s)\n",f,fname);
@@ -539,11 +470,11 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
file->dirname = strdup(fname);
lastdir = file->dirname;
}
file->basename = STRDUP(ap, p+1);
file->basename = strdup(p+1);
*p = '/';
} else {
file->dirname = NULL;
file->basename = STRDUP(ap, fname);
file->basename = strdup(fname);
}
file->modtime = st.st_mtime;
@@ -559,12 +490,12 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
#if SUPPORT_LINKS
if (S_ISLNK(st.st_mode)) {
file->link = STRDUP(ap, linkbuf);
file->link = strdup(linkbuf);
}
#endif
if (always_checksum) {
file->sum = (char *)MALLOC(ap, MD4_SUM_LENGTH);
file->sum = (char *)malloc(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
@@ -601,7 +532,7 @@ void send_file_name(int f,struct file_list *flist,char *fname,
{
struct file_struct *file;
file = make_file(f,fname, &flist->string_area, 0);
file = make_file(f,fname);
if (!file) return;
@@ -617,9 +548,6 @@ 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);
@@ -694,6 +622,7 @@ 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;
@@ -705,14 +634,19 @@ 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 = flist_new();
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 (f != -1) {
io_start_buffering(f);
@@ -738,10 +672,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
if (link_stat(fname,&st) != 0) {
if (f != -1) {
io_error=1;
rprintf(FERROR,"link_stat %s : %s\n",fname,strerror(errno));
}
io_error=1;
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
continue;
}
@@ -809,7 +741,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
if (!recurse || !send_included_file_names(f,flist))
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
if (olddir != NULL) {
flist_dir = NULL;
@@ -848,8 +781,6 @@ 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)
@@ -927,10 +858,9 @@ 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 && !read_batch) { /* dw-added readbatch */
if (f != -1 && remote_version >= 17) {
extern int module_id;
extern int ignore_errors;
if (lp_ignore_errors(module_id) || ignore_errors) {
if (lp_ignore_errors(module_id)) {
read_int(f);
} else {
io_error |= read_int(f);
@@ -996,38 +926,16 @@ int flist_find(struct file_list *flist,struct file_struct *f)
/*
* free up one file
*/
void free_file(struct file_struct *file)
static void free_file(struct file_struct *file)
{
if (!file) return;
if (file->basename) free(file->basename);
if (file->link) free(file->link);
if (file->sum) free(file->sum);
*file = null_file;
memset((char *)file, 0, sizeof(*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
*/
@@ -1035,14 +943,11 @@ void flist_free(struct file_list *flist)
{
int i;
for (i=1;i<flist->count;i++) {
if (!flist->string_area)
free_file(flist->files[i]);
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);
}
@@ -1071,13 +976,7 @@ 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);
/* 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]);
free_file(flist->files[i]);
}
}
@@ -1104,12 +1003,12 @@ static void clean_flist(struct file_list *flist, int strip_root)
if (verbose <= 3) return;
for (i=0;i<flist->count;i++) {
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n",
(int) getpid(), i,
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n",
getpid(), i,
NS(flist->files[i]->dirname),
NS(flist->files[i]->basename),
(int) flist->files[i]->mode,
(double)flist->files[i]->length);
flist->files[i]->mode,
(int)flist->files[i]->length);
}
}

View File

@@ -1,7 +1,10 @@
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -99,25 +102,30 @@ static int adapt_block_size(struct file_struct *file, int bsize)
/*
send a sums struct down a fd
*/
static void send_sums(struct sum_struct *s,int f_out)
static void send_sums(struct sum_struct *s, int f_out)
{
int i;
/* tell the other guy how many we are going to be doing and how many
bytes there are in the last chunk */
write_int(f_out,s?s->count:0);
write_int(f_out,s?s->n:block_size);
write_int(f_out,s?s->remainder:0);
if (s) {
size_t i;
if (!s) return;
/* tell the other guy how many we are going to be
doing and how many bytes there are in the last
chunk */
write_int(f_out, s->count);
write_int(f_out, s->n);
write_int(f_out, s->remainder);
for (i=0;i<s->count;i++) {
write_int(f_out,s->sums[i].sum1);
write_buf(f_out,s->sums[i].sum2,csum_length);
for (i = 0; i < s->count; i++) {
write_int(f_out, s->sums[i].sum1);
write_buf(f_out, s->sums[i].sum2, csum_length);
}
} else {
/* we don't have checksums */
write_int(f_out, 0);
write_int(f_out, block_size);
write_int(f_out, 0);
}
}
/*
generate a stream of signatures/checksums that describe a buffer
@@ -210,7 +218,8 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
if (only_existing && statret == -1 && errno == ENOENT) {
/* we only want to update existing files */
if (verbose > 1) rprintf(FINFO,"not creating %s\n",fname);
if (verbose > 1) rprintf(FINFO, RSYNC_NAME
": not creating new file \"%s\"\n",fname);
return;
}
@@ -230,10 +239,11 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
* we need to delete it. If it doesn't exist, then
* recursively create it. */
if (dry_run) return;
if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) != 0) {
rprintf(FERROR,"recv_generator: unlink %s: %s\n",
rprintf(FERROR, RSYNC_NAME
": recv_generator: unlink \"%s\" to make room for directory: %s\n",
fname,strerror(errno));
return;
}
@@ -243,11 +253,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,"recv_generator: mkdir %s: %s (2)\n",
rprintf(FERROR, RSYNC_NAME ": 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;
}
@@ -260,7 +272,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
if (verbose) {
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
rprintf(FINFO,RSYNC_NAME ": ignoring unsafe symlink \"%s\" -> \"%s\"\n",
fname,file->link);
}
return;
@@ -269,20 +281,26 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
l = readlink(fname,lnk,MAXPATHLEN-1);
if (l > 0) {
lnk[l] = 0;
/* A link already pointing to the
* right place -- no further action
* required. */
if (strcmp(lnk,file->link) == 0) {
set_perms(fname,file,&st,1);
return;
}
}
}
/* Not a symlink, so delete whatever's
* already there and put a new symlink
* in place. */
delete_file(fname);
}
if (do_symlink(file->link,fname) != 0) {
rprintf(FERROR,"symlink %s -> %s : %s\n",
rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
fname,file->link,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose) {
rprintf(FINFO,"%s -> %s\n",
rprintf(FINFO,RSYNC_NAME": %s -> %s\n",
fname,file->link);
}
}
@@ -315,12 +333,14 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
if (preserve_hard_links && check_hard_link(file)) {
if (verbose > 1)
rprintf(FINFO,"%s is a hard link\n",f_name(file));
rprintf(FINFO, RSYNC_NAME
": \"%s\" is a hard link\n",f_name(file));
return;
}
if (!S_ISREG(file->mode)) {
rprintf(FINFO,"skipping non-regular file %s\n",fname);
rprintf(FINFO, RSYNC_NAME
": skipping non-regular file \"%s\"\n",fname);
return;
}
@@ -345,7 +365,9 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
if (!dry_run) send_sums(NULL,f_out);
} else {
if (verbose > 1)
rprintf(FERROR,"recv_generator failed to open %s\n",fname);
rprintf(FERROR, RSYNC_NAME
": recv_generator failed to open \"%s\": %s\n",
fname, strerror(errno));
}
return;
}
@@ -388,7 +410,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
fd = do_open(fnamecmp, O_RDONLY, 0);
if (fd == -1) {
rprintf(FERROR,"failed to open %s, continuing : %s\n",fnamecmp,strerror(errno));
rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
/* pretend the file didn't exist */
write_int(f_out,i);
send_sums(NULL,f_out);

151
hlink.c
View File

@@ -1,6 +1,7 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,19 +24,22 @@ extern int dry_run;
extern int verbose;
#if SUPPORT_HARD_LINKS
static int hlink_compare(struct file_struct *f1,struct file_struct *f2)
static int hlink_compare(struct file_struct *f1, struct file_struct *f2)
{
if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode)) return 0;
if (!S_ISREG(f1->mode)) return -1;
if (!S_ISREG(f2->mode)) return 1;
if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode))
return 0;
if (!S_ISREG(f1->mode))
return -1;
if (!S_ISREG(f2->mode))
return 1;
if (f1->dev != f2->dev)
return (int)(f1->dev>f2->dev?1:-1);
if (f1->dev != f2->dev)
return (int) (f1->dev > f2->dev ? 1 : -1);
if (f1->inode != f2->inode)
return (int)(f1->inode>f2->inode?1:-1);
if (f1->inode != f2->inode)
return (int) (f1->inode > f2->inode ? 1 : -1);
return file_compare(&f1,&f2);
return file_compare(&f1, &f2);
}
@@ -47,22 +51,25 @@ void init_hard_links(struct file_list *flist)
{
#if SUPPORT_HARD_LINKS
int i;
if (flist->count < 2) return;
if (flist->count < 2)
return;
if (hlink_list) free(hlink_list);
if (!(hlink_list =
(struct file_struct *)malloc(sizeof(hlink_list[0])*flist->count)))
if (hlink_list)
free(hlink_list);
if (!(hlink_list =
(struct file_struct *) malloc(sizeof(hlink_list[0]) *
flist->count)))
out_of_memory("init_hard_links");
for (i = 0; i < flist->count; i++)
memcpy(&hlink_list[i], flist->files[i], sizeof(hlink_list[0]));
memcpy(&hlink_list[i], flist->files[i],
sizeof(hlink_list[0]));
qsort(hlink_list,flist->count,
sizeof(hlink_list[0]),
(int (*)())hlink_compare);
qsort(hlink_list, flist->count,
sizeof(hlink_list[0]), (int (*)()) hlink_compare);
hlink_count=flist->count;
hlink_count = flist->count;
#endif
}
@@ -71,86 +78,102 @@ void init_hard_links(struct file_list *flist)
int check_hard_link(struct file_struct *file)
{
#if SUPPORT_HARD_LINKS
int low=0,high=hlink_count-1;
int ret=0;
int low = 0, high = hlink_count - 1;
int ret = 0;
if (!hlink_list || !S_ISREG(file->mode)) return 0;
if (!hlink_list || !S_ISREG(file->mode))
return 0;
while (low != high) {
int mid = (low+high)/2;
ret = hlink_compare(&hlink_list[mid],file);
if (ret == 0) {
low = mid;
break;
}
if (ret > 0)
high=mid;
else
low=mid+1;
}
while (low != high) {
int mid = (low + high) / 2;
ret = hlink_compare(&hlink_list[mid], file);
if (ret == 0) {
low = mid;
break;
}
if (ret > 0)
high = mid;
else
low = mid + 1;
}
if (hlink_compare(&hlink_list[low],file) != 0) return 0;
if (hlink_compare(&hlink_list[low], file) != 0)
return 0;
if (low > 0 &&
S_ISREG(hlink_list[low-1].mode) &&
file->dev == hlink_list[low-1].dev &&
file->inode == hlink_list[low-1].inode)
return 1;
if (low > 0 &&
S_ISREG(hlink_list[low - 1].mode) &&
file->dev == hlink_list[low - 1].dev &&
file->inode == hlink_list[low - 1].inode)
return 1;
#endif
return 0;
return 0;
}
#if SUPPORT_HARD_LINKS
static void hard_link_one(int i)
{
STRUCT_STAT st1,st2;
STRUCT_STAT st1, st2;
if (link_stat(f_name(&hlink_list[i-1]),&st1) != 0) return;
if (link_stat(f_name(&hlink_list[i - 1]), &st1) != 0)
return;
if (link_stat(f_name(&hlink_list[i]),&st2) != 0) {
if (do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
if (link_stat(f_name(&hlink_list[i]), &st2) != 0) {
if (do_link
(f_name(&hlink_list[i - 1]),
f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
rprintf(FINFO,"link %s => %s : %s\n",
rprintf(FINFO, "link %s => %s : %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i-1]),strerror(errno));
f_name(&hlink_list[i - 1]),
strerror(errno));
return;
}
} else {
if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino) return;
if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino)
return;
if (robust_unlink(f_name(&hlink_list[i])) != 0 ||
do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
do_link(f_name(&hlink_list[i - 1]),
f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
rprintf(FINFO,"link %s => %s : %s\n",
rprintf(FINFO, "link %s => %s : %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i-1]),strerror(errno));
f_name(&hlink_list[i - 1]),
strerror(errno));
return;
}
}
if (verbose > 0)
rprintf(FINFO,"%s => %s\n",
f_name(&hlink_list[i]),f_name(&hlink_list[i-1]));
rprintf(FINFO, "%s => %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i - 1]));
}
#endif
/* create any hard links in the flist */
void do_hard_links(struct file_list *flist)
/**
* Create any hard links in the global hlink_list. They were put
* there by running init_hard_links on the filelist.
**/
void do_hard_links(void)
{
#if SUPPORT_HARD_LINKS
int i;
if (!hlink_list) return;
for (i=1;i<hlink_count;i++) {
if (!hlink_list)
return;
for (i = 1; i < hlink_count; i++) {
if (S_ISREG(hlink_list[i].mode) &&
S_ISREG(hlink_list[i-1].mode) &&
hlink_list[i].basename && hlink_list[i-1].basename &&
hlink_list[i].dev == hlink_list[i-1].dev &&
hlink_list[i].inode == hlink_list[i-1].inode) {
S_ISREG(hlink_list[i - 1].mode) &&
hlink_list[i].basename && hlink_list[i - 1].basename &&
hlink_list[i].dev == hlink_list[i - 1].dev &&
hlink_list[i].inode == hlink_list[i - 1].inode) {
hard_link_one(i);
}
}
}
#endif
}

439
io.c
View File

@@ -1,8 +1,6 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2001 by Andrew Tridgell
/*
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
@@ -20,7 +18,7 @@
*/
/*
socket and pipe IO utilities used in rsync
Utilities used in rsync
tridge, June 1996
*/
@@ -34,29 +32,21 @@ static int io_multiplexing_in;
static int multiplex_in_fd;
static int multiplex_out_fd;
static time_t last_io;
static int no_flush;
extern int bwlimit;
static int eof_error=1;
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;
@@ -68,145 +58,45 @@ static void check_timeout(void)
t = time(NULL);
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
if (!am_server && !am_daemon) {
rprintf(FERROR,"io timeout after %d seconds - exiting\n",
(int)(t-last_io));
}
rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
exit_cleanup(RERR_TIMEOUT);
}
}
/* setup the fd used to propogate errors */
void io_set_error_fd(int fd)
{
io_error_fd = fd;
}
/* read some data from the error fd and write it to the write log code */
static void read_error_fd(void)
{
char buf[200];
int n;
int fd = io_error_fd;
int tag, len;
static char *read_buffer;
static char *read_buffer_p;
static int read_buffer_len;
static int read_buffer_size;
static int no_flush;
static int no_flush_read;
/* io_error_fd is temporarily disabled -- is this meant to
* prevent indefinite recursion? */
io_error_fd = -1;
read_loop(fd, buf, 4);
tag = IVAL(buf, 0);
len = tag & 0xFFFFFF;
tag = tag >> 24;
tag -= MPLEX_BASE;
while (len) {
n = len;
if (n > (sizeof(buf)-1)) n = sizeof(buf)-1;
read_loop(fd, buf, n);
rwrite((enum logcode)tag, buf, n);
len -= n;
}
io_error_fd = fd;
}
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.
*/
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)
/* 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, size_t len)
{
int n, ret=0;
no_flush_read++;
io_flush();
no_flush_read--;
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);
if (io_error_fd != -1) {
FD_SET(io_error_fd, &fds);
if (io_error_fd > fd) fd_count = io_error_fd+1;
}
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
tv.tv_usec = 0;
errno = 0;
count = select(fd_count, &fds, NULL, NULL, &tv);
if (count == 0) {
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
check_timeout();
}
if (count <= 0) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
continue;
}
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
read_error_fd();
}
if (!FD_ISSET(fd, &fds)) continue;
n = read(fd, buf, len);
if (n > 0) {
@@ -216,27 +106,38 @@ 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 == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK)) {
/* this shouldn't happen, if it does then
sleep for a short time to prevent us
chewing too much CPU */
u_sleep(100);
continue;
}
if (n == 0) {
if (eof_error) {
rprintf(FERROR,"unexpected EOF in read_timeout\n");
}
exit_cleanup(RERR_STREAMIO);
}
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, size_t len)
{
while (len) {
int n = read_timeout(fd, buf, len);
@@ -246,20 +147,17 @@ static void read_loop (int fd, char *buf, int len)
}
}
/**
* 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)
/* read from the file descriptor handling multiplexing -
return number of bytes read
never return <= 0 */
static int read_unbuffered(int fd, char *buf, size_t len)
{
static int remaining;
char ibuf[4];
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) {
@@ -271,8 +169,8 @@ static int read_unbuffered(int fd, char *buf, int len)
continue;
}
read_loop (fd, line, 4);
tag = IVAL(line, 0);
read_loop(fd, ibuf, 4);
tag = IVAL(ibuf, 0);
remaining = tag & 0xFFFFFF;
tag = tag >> 24;
@@ -295,7 +193,7 @@ static int read_unbuffered(int fd, char *buf, int len)
read_loop(fd, line, remaining);
line[remaining] = 0;
rprintf((enum logcode)tag,"%s", line);
rprintf(tag,"%s", line);
remaining = 0;
}
@@ -303,17 +201,66 @@ static int read_unbuffered(int fd, char *buf, int len)
}
/* This function was added to overcome a deadlock problem when using
* ssh. It looks like we can't allow our receive queue to get full or
* ssh will clag up. Uggh. */
static void read_check(int f)
{
int n = 8192;
if (f == -1) return;
if (read_buffer_len == 0) {
read_buffer_p = read_buffer;
}
if (n > MAX_READ_BUFFER/4)
n = MAX_READ_BUFFER/4;
if (read_buffer_p != read_buffer) {
memmove(read_buffer,read_buffer_p,read_buffer_len);
read_buffer_p = read_buffer;
}
if (n > (read_buffer_size - read_buffer_len)) {
read_buffer_size += n;
read_buffer = (char *)Realloc(read_buffer,read_buffer_size);
if (!read_buffer) out_of_memory("read check");
read_buffer_p = read_buffer;
}
n = read_unbuffered(f,read_buffer+read_buffer_len,n);
read_buffer_len += n;
}
/* 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,size_t N)
{
int ret;
int total=0;
if ((read_buffer_len < N) && (N < 1024)) {
read_check(buffer_f_in);
}
while (total < N) {
io_flush();
if (read_buffer_len > 0 && buffer_f_in == fd) {
ret = MIN(read_buffer_len,N-total);
memcpy(buffer+total,read_buffer_p,ret);
read_buffer_p += ret;
read_buffer_len -= ret;
total += ret;
continue;
}
ret = read_unbuffered (fd, buffer + total, N-total);
no_flush_read++;
io_flush();
no_flush_read--;
ret = read_unbuffered(fd,buffer + total,N-total);
total += ret;
}
@@ -356,33 +303,37 @@ int64 read_longint(int f)
return ret;
}
void read_buf(int f,char *buf,int len)
void read_buf(int f,char *buf,size_t len)
{
readfd(f,buf,len);
}
void read_sbuf(int f,char *buf,int len)
void read_sbuf(int f,char *buf,size_t len)
{
read_buf (f,buf,len);
read_buf(f,buf,len);
buf[len] = 0;
}
unsigned char read_byte(int f)
{
unsigned char c;
read_buf (f, (char *)&c, 1);
read_buf(f,(char *)&c,1);
return c;
}
/* write len bytes to fd */
static void writefd_unbuffered(int fd,char *buf,int len)
/* 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 */
static void writefd_unbuffered(int fd,char *buf,size_t len)
{
int total = 0;
fd_set w_fds, r_fds;
int fd_count, count;
struct timeval tv;
err_list_push();
int reading=0;
int blocked=0;
no_flush++;
@@ -390,74 +341,55 @@ static void writefd_unbuffered(int fd,char *buf,int len)
FD_ZERO(&w_fds);
FD_ZERO(&r_fds);
FD_SET(fd,&w_fds);
fd_count = fd;
fd_count = fd+1;
if (io_error_fd != -1) {
FD_SET(io_error_fd,&r_fds);
if (io_error_fd > fd_count)
fd_count = io_error_fd;
if (!no_flush_read) {
reading = (buffer_f_in != -1);
}
if (reading) {
FD_SET(buffer_f_in,&r_fds);
if (buffer_f_in > fd)
fd_count = buffer_f_in+1;
}
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
tv.tv_usec = 0;
errno = 0;
count = select(fd_count+1,
io_error_fd != -1?&r_fds:NULL,
count = select(fd_count,
reading?&r_fds:NULL,
&w_fds,NULL,
&tv);
if (count == 0) {
check_timeout();
}
if (count <= 0) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
check_timeout();
continue;
}
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
read_error_fd();
if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
read_check(buffer_f_in);
}
if (FD_ISSET(fd, &w_fds)) {
int ret, n = len-total;
ret = write(fd,buf+total,n);
int n = (len-total)>>blocked;
int ret = write(fd,buf+total,n?n:1);
if (ret == -1 && errno == EINTR) {
continue;
}
if (ret == -1 &&
(errno == EWOULDBLOCK || errno == EAGAIN)) {
msleep(1);
(errno == EAGAIN || errno == EWOULDBLOCK)) {
blocked++;
continue;
}
if (ret <= 0) {
rprintf(FERROR,
"error writing %d unbuffered bytes"
" - exiting: %s\n", len,
strerror(errno));
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
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);
}
blocked = 0;
total += ret;
if (io_timeout)
@@ -476,70 +408,42 @@ void io_start_buffering(int fd)
{
if (io_buffer) return;
multiplex_out_fd = fd;
io_buffer = (char *)malloc(IO_BUFFER_SIZE);
io_buffer = (char *)malloc(IO_BUFFER_SIZE+4);
if (!io_buffer) out_of_memory("writefd");
io_buffer_count = 0;
/* leave room for the multiplex header in case it's needed */
io_buffer += 4;
}
/* write an message to a multiplexed stream. If this fails then rsync
exits */
static void mplex_write(int fd, enum logcode code, char *buf, int len)
{
char buffer[4096];
int n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
if (n > (sizeof(buffer)-4)) {
n = sizeof(buffer)-4;
}
memcpy(&buffer[4], buf, n);
writefd_unbuffered(fd, buffer, n+4);
len -= n;
buf += n;
if (len) {
writefd_unbuffered(fd, buf, len);
}
}
void io_flush(void)
{
int fd = multiplex_out_fd;
err_list_push();
if (!io_buffer_count || no_flush) return;
if (io_multiplexing_out) {
mplex_write(fd, FNONE, io_buffer, io_buffer_count);
SIVAL(io_buffer-4, 0, (MPLEX_BASE<<24) + io_buffer_count);
writefd_unbuffered(fd, io_buffer-4, io_buffer_count+4);
} else {
writefd_unbuffered(fd, io_buffer, io_buffer_count);
}
io_buffer_count = 0;
}
/* XXX: fd is ignored, which seems a little strange. */
void io_end_buffering(int fd)
{
io_flush();
if (!io_multiplexing_out) {
free(io_buffer);
free(io_buffer-4);
io_buffer = NULL;
}
}
static void writefd(int fd,char *buf,int len)
static void writefd(int fd,char *buf,size_t len)
{
stats.total_written += len;
err_list_push();
if (!io_buffer || fd != multiplex_out_fd) {
if (!io_buffer) {
writefd_unbuffered(fd, buf, len);
return;
}
@@ -565,11 +469,6 @@ 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;
@@ -587,7 +486,7 @@ void write_longint(int f, int64 x)
writefd(f,b,8);
}
void write_buf(int f,char *buf,int len)
void write_buf(int f,char *buf,size_t len)
{
writefd(f,buf,len);
}
@@ -604,10 +503,10 @@ void write_byte(int f,unsigned char c)
write_buf(f,(char *)&c,1);
}
int read_line(int f, char *buf, int maxlen)
int read_line(int f, char *buf, size_t maxlen)
{
eof_error = 0;
while (maxlen) {
buf[0] = 0;
read_buf(f, buf, 1);
@@ -626,6 +525,8 @@ int read_line(int f, char *buf, int maxlen)
return 0;
}
eof_error = 1;
return 1;
}
@@ -637,7 +538,7 @@ void io_printf(int fd, const char *format, ...)
int len;
va_start(ap, format);
len = vsnprintf(buf, sizeof(buf), format, ap);
len = vslprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len < 0) exit_cleanup(RERR_STREAMIO);
@@ -660,23 +561,31 @@ void io_start_multiplex_in(int fd)
{
multiplex_in_fd = fd;
io_flush();
if (read_buffer_len) {
fprintf(stderr,"ERROR: data in read buffer at mplx start\n");
exit_cleanup(RERR_STREAMIO);
}
io_multiplexing_in = 1;
}
/* write an message to the multiplexed error stream */
int io_multiplex_write(enum logcode code, char *buf, int len)
/* write an message to the error stream */
int io_multiplex_write(int f, char *buf, size_t len)
{
if (!io_multiplexing_out) return 0;
io_flush();
SIVAL(io_buffer-4, 0, ((MPLEX_BASE + f)<<24) + len);
memcpy(io_buffer, buf, len);
stats.total_written += (len+4);
mplex_write(multiplex_out_fd, code, buf, len);
writefd_unbuffered(multiplex_out_fd, io_buffer-4, len+4);
return 1;
}
/* stop output multiplexing */
void io_multiplexing_close(void)
void io_close_input(int fd)
{
io_multiplexing_out = 0;
buffer_f_in = -1;
}

View File

@@ -97,8 +97,10 @@
#ifndef HAVE_STRLCPY
/* like strncpy but does not 0 fill the buffer and always null
terminates. bufsize is the size of the destination buffer */
/* Like strncpy but does not 0 fill the buffer and always null
* terminates. bufsize is the size of the destination buffer.
*
* Returns the index of the terminating byte. */
size_t strlcpy(char *d, const char *s, size_t bufsize)
{
size_t len = strlen(s);

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

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

@@ -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
@@ -379,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);
}

334
log.c
View File

@@ -1,7 +1,5 @@
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
/*
Copyright (C) Andrew Tridgell 1998
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
@@ -19,121 +17,18 @@
*/
/*
Logging and utility functions.
tridge, May 1998
logging and utility functions
Mapping to human-readable messages added by Martin Pool
<mbp@samba.org>, Oct 2000.
tridge, May 1998
*/
#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 (logfname) {
if (!logfile)
log_open();
if (logfile) {
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
@@ -142,11 +37,12 @@ static void logit(int priority, char *buf)
}
}
void log_init(void)
void log_open(void)
{
static int initialised;
int options = LOG_PID;
time_t t;
char *logf;
if (initialised) return;
initialised = 1;
@@ -158,13 +54,13 @@ void log_init(void)
localtime(&t);
/* optionally use a log file instead of syslog */
logfname = lp_log_file();
if (logfname) {
if (*logfname) {
log_open();
return;
}
logfname = NULL;
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;
}
#ifdef LOG_NDELAY
@@ -181,88 +77,60 @@ void log_init(void)
logit(LOG_INFO,"rsyncd started\n");
#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
it with FINFO, FERROR or FLOG */
void rwrite(enum logcode code, char *buf, int len)
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
void rprintf(int fd, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
FILE *f=NULL;
extern int am_daemon;
extern int am_server;
extern int quiet;
/* recursion can happen with certain fatal conditions */
if (quiet && code == FINFO) return;
if (quiet != 0 && fd == FINFO) return;
va_start(ap, format);
len = vslprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
buf[len] = 0;
if (code == FLOG) {
if (fd == FLOG) {
if (am_daemon) logit(LOG_INFO, buf);
return;
}
/* 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;
}
/* if that fails, try to pass it to the other end */
if (am_server && io_multiplex_write(code, buf, len)) {
return;
}
if (am_daemon) {
static int depth;
int priority = LOG_INFO;
if (code == FERROR) priority = LOG_WARNING;
if (fd == FERROR) priority = LOG_WARNING;
if (depth) return;
depth++;
log_init();
logit(priority, buf);
log_open();
if (!io_multiplex_write(fd, buf, strlen(buf))) {
logit(priority, buf);
}
depth--;
return;
}
if (code == FERROR) {
log_got_error = 1;
if (fd == FERROR) {
f = stderr;
}
if (code == FINFO) {
if (fd == FINFO) {
extern int am_server;
if (am_server)
f = stderr;
else
@@ -275,89 +143,8 @@ void rwrite(enum logcode code, char *buf, int len)
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
}
/* 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 = 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)
void rflush(int fd)
{
FILE *f = NULL;
extern int am_daemon;
@@ -366,15 +153,15 @@ void rflush(enum logcode code)
return;
}
if (code == FLOG) {
if (fd == FLOG) {
return;
}
if (code == FERROR) {
if (fd == FERROR) {
f = stderr;
}
if (code == FINFO) {
if (fd == FINFO) {
extern int am_server;
if (am_server)
f = stderr;
@@ -390,7 +177,7 @@ void rflush(enum logcode code)
/* a generic logging routine for send/recv, with parameter
substitiution */
static void log_formatted(enum logcode code,
static void log_formatted(int fd,
char *format, char *op, struct file_struct *file,
struct stats *initial_stats)
{
@@ -405,6 +192,8 @@ static void log_formatted(enum logcode code,
extern int am_daemon;
int64 b;
memset(buf,0,sizeof(buf));
strlcpy(buf, format, sizeof(buf));
for (s=&buf[0];
@@ -416,18 +205,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':
snprintf(buf2,sizeof(buf2),"%.0f",
slprintf(buf2,sizeof(buf2),"%.0f",
(double)file->length);
n = buf2;
break;
case 'p':
snprintf(buf2,sizeof(buf2),"%d",
slprintf(buf2,sizeof(buf2),"%d",
(int)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'f':
snprintf(buf2, sizeof(buf2), "%s/%s",
slprintf(buf2, sizeof(buf2), "%s/%s",
file->basedir?file->basedir:"",
f_name(file));
clean_fname(buf2);
@@ -446,7 +235,7 @@ static void log_formatted(enum logcode code,
b = stats.total_read -
initial_stats->total_read;
}
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
n = buf2;
break;
case 'c':
@@ -457,7 +246,7 @@ static void log_formatted(enum logcode code,
b = stats.total_read -
initial_stats->total_read;
}
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
n = buf2;
break;
}
@@ -466,7 +255,7 @@ static void log_formatted(enum logcode code,
l = strlen(n);
if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
if (l + ((int)(s - &buf[0])) > sizeof(buf)) {
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
@@ -480,7 +269,7 @@ static void log_formatted(enum logcode code,
s = p+l;
}
rprintf(code,"%s\n", buf);
rprintf(fd,"%s\n", buf);
}
/* log the outgoing transfer of a file */
@@ -511,15 +300,7 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
}
}
/*
* Called when the transfer is interrupted for some reason.
*
* Code is one of the RERR_* codes from errcode.h, or terminating
* successfully.
*/
/* called when the transfer is interrupted for some reason */
void log_exit(int code, const char *file, int line)
{
if (code == 0) {
@@ -529,20 +310,11 @@ void log_exit(int code, const char *file, int line)
(double)stats.total_read,
(double)stats.total_size);
} else {
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);
rprintf(FLOG,"transfer interrupted (code %d) at %s(%d)\n",
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

44
main.c
View File

@@ -2,7 +2,7 @@
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@ struct stats stats;
extern int verbose;
static void show_malloc_stats(void);
/****************************************************************************
wait for a process to exit, calling io_flush while waiting
@@ -56,6 +57,11 @@ static void report(int f)
extern int remote_version;
int send_stats;
if (do_stats) {
/* These come out from every process */
show_malloc_stats();
}
if (am_daemon) {
log_exit(0, __FILE__, __LINE__);
if (f == -1 || !am_sender) return;
@@ -126,6 +132,38 @@ static void report(int f)
}
/**
* If our C library can get malloc statistics, then show them to FINFO
**/
static void show_malloc_stats(void)
{
#ifdef HAVE_MALLINFO
struct mallinfo mi;
extern int am_server;
extern int am_sender;
extern int am_daemon;
mi = mallinfo();
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
getpid(),
am_server ? "server " : "",
am_daemon ? "daemon " : "",
am_sender ? "sender" : "receiver");
rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
rprintf(FINFO, " smblks: %10d\n", mi.smblks);
rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
#endif /* HAVE_MALLINFO */
}
/* 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)
{
@@ -765,8 +803,10 @@ int main(int argc,char *argv[])
extern int write_batch; /* dw */
extern char *batch_ext; /* dw */
int orig_argc; /* dw */
char **orig_argv;
orig_argc = argc; /* dw */
orig_argv = argv;
signal(SIGUSR1, sigusr1_handler);
signal(SIGUSR2, sigusr2_handler);
@@ -806,7 +846,7 @@ int main(int argc,char *argv[])
if (write_batch) { /* dw */
create_batch_file_ext();
write_batch_argvs_file(orig_argc, argc, argv);
write_batch_argvs_file(orig_argc, orig_argv);
}
if (read_batch) { /* dw */

View File

@@ -1,7 +1,7 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
Copyright (C) 2000, 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -75,10 +75,20 @@ int modify_window=0;
int blocking_io=0;
/** Network address family. **/
int af = AF_INET;
#ifdef INET6
int default_af_hint = 0; /* Any protocol */
#else
int default_af_hint = AF_INET; /* Must use IPv4 */
#endif
int read_batch=0; /* dw */
int write_batch=0; /* dw */
/** 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 = 0;
int read_batch=0;
int write_batch=0;
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
@@ -106,12 +116,13 @@ static int modify_window_set;
char *bind_address;
static void print_rsync_version(int f)
static void print_rsync_version(enum logcode f)
{
char const *got_socketpair = "no ";
char const *hardlinks = "no ";
char const *links = "no ";
char const *ipv6 = "no ";
STRUCT_STAT *dumstat;
#ifdef HAVE_SOCKETPAIR
got_socketpair = "";
@@ -132,13 +143,20 @@ static void print_rsync_version(int f)
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");
"Copyright (C) 1996-2002 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",
"%shard links, %ssymlinks, batchfiles, %sIPv6,\n",
(int) (sizeof(OFF_T) * 8),
got_socketpair, hardlinks, links, ipv6);
/* Note that this field may not have type ino_t. It depends
* on the complicated interaction between largefile feature
* macros. */
rprintf(f, " %d-bit system inums, %d-bit internal inums\n",
(int) (sizeof(dumstat->st_ino) * 8),
(int) (sizeof(INO64_T) * 8));
#ifdef NO_INT64
rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
#endif
@@ -171,8 +189,8 @@ void usage(enum logcode F)
rprintf(F," --backup-dir make backups into this directory\n");
rprintf(F," --suffix=SUFFIX override backup suffix\n");
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
rprintf(F," -l, --links preserve soft links\n");
rprintf(F," -L, --copy-links treat soft links like regular files\n");
rprintf(F," -l, --links copy symlinks as symlinks\n");
rprintf(F," -L, --copy-links copy the referent of symlinks\n");
rprintf(F," --copy-unsafe-links copy links outside the source tree\n");
rprintf(F," --safe-links ignore links outside the destination tree\n");
rprintf(F," -H, --hard-links preserve hard links\n");
@@ -212,7 +230,8 @@ 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");
@@ -221,8 +240,8 @@ void usage(enum logcode F)
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," --read-batch=EXT read batch file\n");
rprintf(F," --write-batch write batch file\n");
rprintf(F," -h, --help show this help screen\n");
#ifdef INET6
rprintf(F," -4 prefer IPv4\n");
@@ -243,7 +262,7 @@ enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
OPT_MODIFY_WINDOW};
OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH};
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
@@ -274,7 +293,7 @@ static struct poptOption long_options[] = {
{"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},
{"whole-file", '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},
@@ -298,6 +317,7 @@ static struct poptOption long_options[] = {
/* 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, &no_detach},
{"stats", 0, POPT_ARG_NONE, &do_stats},
{"progress", 0, POPT_ARG_NONE, &do_progress},
{"partial", 0, POPT_ARG_NONE, &keep_partial},
@@ -311,11 +331,11 @@ static struct poptOption long_options[] = {
{"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},
{"read-batch", 0, POPT_ARG_STRING, &batch_ext, OPT_READ_BATCH},
{"write-batch", 0, POPT_ARG_NONE, &write_batch},
#ifdef INET6
{0, '4', POPT_ARG_VAL, &af, AF_INET },
{0, '6', POPT_ARG_VAL, &af, AF_INET6 },
{0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET },
{0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6 },
#endif
{0,0,0,0}
};
@@ -491,9 +511,8 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
keep_partial = 1;
break;
case 'f':
/* The filename is stored for us by popt */
case OPT_READ_BATCH:
/* The filename is stored in batch_ext for us by popt */
read_batch = 1;
break;
@@ -530,7 +549,8 @@ void server_options(char **args,int *argc)
static char mdelete[30];
static char mwindow[30];
static char bw[50];
static char fext[20]; /* dw */
static char fext[20];
static char wbatch[14];
int i, x;
@@ -585,8 +605,6 @@ 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
@@ -609,8 +627,13 @@ void server_options(char **args,int *argc)
args[ac++] = mdelete;
}
if (write_batch) {
snprintf(wbatch,sizeof(wbatch),"--write-batch");
args[ac++] = wbatch;
}
if (batch_ext != NULL) {
sprintf(fext,"-f%s",batch_ext);
snprintf(fext,sizeof(fext),"--read-batch=%s",batch_ext);
args[ac++] = fext;
}

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.1
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.1.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.6
Version: 2.5.1
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.4.6.tar.gz
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.1.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync

View File

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

View File

@@ -1,6 +1,5 @@
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
@@ -37,12 +36,14 @@ extern char *compare_dest;
extern int make_backups;
extern char *backup_suffix;
static struct delete_list {
dev_t dev;
INO_T inode;
} *delete_list;
static int dlist_len, dlist_alloc_len;
/* yuck! This function wouldn't have been necessary if I had the sorting
algorithm right. Unfortunately fixing the sorting algorithm would introduce
a backward incompatibility as file list indexes are sent over the link.
@@ -83,15 +84,14 @@ static void delete_one(struct file_struct *f)
{
if (!S_ISDIR(f->mode)) {
if (robust_unlink(f_name(f)) != 0) {
rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno));
rprintf(FERROR,"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,"delete_one: rmdir %s: %s\n",
f_name(f), strerror(errno));
rprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting directory %s\n",f_name(f));
}
@@ -104,20 +104,17 @@ static void delete_one(struct file_struct *f)
/* this deletes any files on the receiving side that are not present
on the sending side. For version 1.6.4 I have changed the behaviour
to match more closely what most people seem to expect of this option */
void delete_files(struct file_list *flist)
static void delete_files(struct file_list *flist)
{
struct file_list *local_file_list;
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) || ignore_errors)) {
if (io_error && !lp_ignore_errors(module_id)) {
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
return;
}
@@ -140,7 +137,6 @@ void delete_files(struct file_list *flist)
rprintf(FINFO,"deleting in %s\n", name);
for (i=local_file_list->count-1;i>=0;i--) {
if (max_delete && deletion_count > max_delete) break;
if (!local_file_list->files[i]->basename) continue;
if (remote_version < 19 &&
S_ISDIR(local_file_list->files[i]->mode))
@@ -148,12 +144,10 @@ void delete_files(struct file_list *flist)
if (-1 == flist_find(flist,local_file_list->files[i])) {
char *f = f_name(local_file_list->files[i]);
int k = strlen(f) - strlen(backup_suffix);
/* Hi Andrew, do we really need to play with backup_suffix here? */
if (make_backups && ((k <= 0) ||
(strcmp(f+k,backup_suffix) != 0))) {
(void) make_backup(f);
} else {
deletion_count++;
delete_one(local_file_list->files[i]);
}
}
@@ -179,7 +173,7 @@ static int get_tmpname(char *fnametmp, char *fname)
rprintf(FERROR,"filename too long\n");
return 0;
}
snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
@@ -192,11 +186,11 @@ static int get_tmpname(char *fnametmp, char *fname)
if (f) {
*f = 0;
snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
}
return 1;
@@ -206,7 +200,8 @@ static int get_tmpname(char *fnametmp, char *fname)
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
OFF_T total_size)
{
int i,n,remainder,len,count;
int i;
unsigned int n,remainder,len,count;
OFF_T offset = 0;
OFF_T offset2;
char *data;
@@ -228,8 +223,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
extern int cleanup_got_literal;
if (verbose > 3) {
rprintf(FINFO,"data recv %d at %.0f\n",
i,(double)offset);
rprintf(FINFO,"data recv %d at %d\n",
i,(int)offset);
}
stats.literal_data += i;
@@ -246,7 +241,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
}
i = -(i+1);
offset2 = i*(OFF_T)n;
offset2 = i*n;
len = n;
if (i == count-1 && remainder != 0)
len = remainder;
@@ -254,15 +249,13 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
stats.matched_data += len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
i,len,(double)offset2,(double)offset);
rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
i,len,(int)offset2,(int)offset);
if (buf) {
map = map_ptr(buf,offset2,len);
map = map_ptr(buf,offset2,len);
see_token(map, len);
sum_update(map,len);
}
see_token(map, len);
sum_update(map,len);
if (fd != -1 && write_file(fd,map,len) != len) {
rprintf(FERROR,"write failed on %s : %s\n",
@@ -272,7 +265,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
offset += len;
}
end_progress(total_size);
end_progress();
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
rprintf(FERROR,"write failed on %s : %s\n",
@@ -296,15 +289,12 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
}
/* main routine for receiver process. Receiver process runs on the
same host as the generator process. */
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
{
int fd1,fd2;
STRUCT_STAT st;
char *fname;
char template[MAXPATHLEN];
char fnametmp[MAXPATHLEN];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
@@ -322,6 +312,12 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
if (!delete_after) {
if (recurse && delete_mode && !local_name && flist->count>0) {
delete_files(flist);
}
}
while (1) {
cleanup_disable();
@@ -372,7 +368,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 */
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
compare_dest,fname);
fnamecmp = fnamecmpbuf;
fd1 = do_open(fnamecmp, O_RDONLY, 0);
@@ -402,7 +398,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
if (fd1 != -1 && st.st_size > 0) {
buf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
rprintf(FINFO,"recv mapped %s of size %d\n",fnamecmp,(int)st.st_size);
} else {
buf = NULL;
}
@@ -413,7 +409,17 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
continue;
}
strlcpy(template, fnametmp, sizeof(template));
/* 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;
}
/* we initially set the perms without the
setuid/setgid bits to ensure that there is no race
@@ -421,21 +427,16 @@ 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_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;
}
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & INITACCESSPERMS);
/* in most cases parent directories will already exist
because their information should have been previously
transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp) == 0) {
strlcpy(fnametmp, template, sizeof(fnametmp));
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & INITACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno));
@@ -468,7 +469,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
finish_transfer(fname, fnametmp, file);
cleanup_disable();
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",

View File

@@ -226,7 +226,6 @@ 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);
}

110
rsync.h
View File

@@ -1,7 +1,6 @@
/*
Copyright (C) by Andrew Tridgell 1996, 2000
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
@@ -18,7 +17,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define False 0
#define True 1
@@ -49,19 +47,8 @@
#define SAME_TIME (1<<7)
/* update this if you make incompatible changes */
#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 PROTOCOL_VERSION 21
#define MIN_PROTOCOL_VERSION 11
#define MAX_PROTOCOL_VERSION 30
#define RSYNC_PORT 873
@@ -71,15 +58,14 @@
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (256*1024)
#define IO_BUFFER_SIZE (4092)
#define MAX_READ_BUFFER (1024*1024)
#define MAX_ARGS 1000
#define MPLEX_BASE 7
/* 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 };
#define FERROR 1
#define FINFO 2
#define FLOG 3
#include "errcode.h"
@@ -93,6 +79,12 @@ 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
@@ -268,11 +260,9 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
#endif
#if HAVE_SHORT_INO_T
# define INO_T uint32
#elif HAVE_INO_T
# define INO_T ino_t
#define INO_T uint32
#else
# define INO_T unsigned
#define INO_T ino_t
#endif
#ifndef MIN
@@ -317,20 +307,10 @@ 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 {
@@ -343,9 +323,9 @@ struct sum_buf {
struct sum_struct {
OFF_T flength; /* total file length */
int count; /* how many chunks */
int remainder; /* flength % block_length */
int n; /* block_length */
size_t count; /* how many chunks */
size_t remainder; /* flength % block_length */
size_t n; /* block_length */
struct sum_buf *sums; /* points to info for each chunk */
};
@@ -356,6 +336,7 @@ struct map_struct {
};
struct exclude_struct {
char *orig;
char *pattern;
int regular_exp;
int fnmatch_flags;
@@ -387,28 +368,10 @@ static inline int flist_up(struct file_list *flist, int i)
}
#include "byteorder.h"
#include "version.h"
#include "proto.h"
#include "lib/mdfour.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[];
#define strerror(i) sys_errlist[i]
@@ -496,22 +459,6 @@ 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))
@@ -527,20 +474,12 @@ extern int errno;
#define NS(s) ((s)?(s):"<NULL>")
/* use magic gcc attributes to catch format errors */
void rprintf(enum logcode , const char *, ...)
void rprintf(int , const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
#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
@@ -554,11 +493,4 @@ 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;

155
rsync.yo
View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(29 May 2001)()()
manpage(rsync)(1)(14 Dec 2001)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpagesynopsis()
@@ -19,7 +19,7 @@ manpagedescription()
rsync is a program that behaves in much the same way that rcp does,
but has many more options and uses the rsync remote-update protocol to
greatly speedup file transfers when the destination file already
greatly speed up file transfers when the destination file already
exists.
The rsync remote-update protocol allows rsync to transfer just the
@@ -81,7 +81,7 @@ Once installed you can use rsync to any machine that you can use rsh
to. rsync uses rsh for its communications, unless both the source and
destination are local.
You can also specify an alternative to rsh, by either using the -e
You can also specify an alternative to rsh, either by using the -e
command line option, or by setting the RSYNC_RSH environment variable.
One common substitute is to use ssh, which offers a high degree of
@@ -139,10 +139,10 @@ It is also possible to use rsync without using rsh or ssh as the
transport. In this case you will connect to a remote rsync server
running on TCP port 873.
You may establish the connetcion via a web proxy by setting the
You may establish the connection via a web proxy by setting the
environment variable RSYNC_PROXY to a hostname:port pair pointing to
your web proxy. Note that your web proxy must allow proxying to port
873, this must be configured in your proxy servers ruleset.
your web proxy. Note that your web proxy's configuration must allow
proxying to port 873.
Using rsync in this way is the same as using it with rsh or ssh except
that:
@@ -226,8 +226,8 @@ verb(
--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
-L, --copy-links treat soft links like regular files
-l, --links copy symlinks as symlinks
-L, --copy-links copy the referent of symlinks
--copy-unsafe-links copy links outside the source tree
--safe-links ignore links outside the destination tree
-H, --hard-links preserve hard links
@@ -267,7 +267,8 @@ 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
@@ -276,8 +277,8 @@ verb(
--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
--read-batch=FILE read batch file
--write-batch write batch file
-h, --help show this help screen
@@ -334,8 +335,13 @@ 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
@@ -372,17 +378,16 @@ dit(bf(-u, --update)) This forces rsync to skip any files for which the
destination file already exists and has a date later than the source
file.
dit(bf(-l, --links)) This tells rsync to recreate symbolic links on the
remote system to be the same as the local system. Without this
option, all symbolic links are skipped.
dit(bf(-l, --links)) When symlinks are encountered, recreate the
symlink on the destination.
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
like ordinary files.
dit(bf(-L, --copy-links)) When symlinks are encountered, the file that
they point to is copied, rather than the symlink.
dit(bf(--copy-unsafe-links)) This tells rsync to treat symbolic links that
point outside the source tree like ordinary files. Absolute symlinks are
also treated like ordinary files, and so are any symlinks in the source
path itself when --relative is used.
dit(bf(--copy-unsafe-links)) This tells rsync to copy the referent of
symbolic links that point outside the source tree. Absolute symlinks
are also treated like ordinary files, and so are any symlinks in the
source path itself when --relative is used.
dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
which point outside the destination tree. All absolute symlinks are
@@ -408,16 +413,15 @@ 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.
dit(bf(-o, --owner)) This option causes rsync to update the remote owner
of the file to be the same as the local owner. This is only available
to the super-user. Note that if the source system is a daemon using chroot,
the --numeric-ids option is implied because the source system cannot get
access to the usernames.
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
destination file to be the same as the source file. On most systems,
only the super-user can set file ownership.
dit(bf(-g, --group)) This option causes rsync to update the remote group
of the file to be the same as the local group. If the receving system is
not running as the super-user, only groups that the receiver is a member of
will be preserved (by group name, not group id number).
dit(bf(-g, --group)) This option causes rsync to set the group of the
destination file to be the same as the source file. If the receiving
program is not running as the super-user, only groups that the
receiver is a member of will be preserved (by group name, not group id
number).
dit(bf(-D, --devices)) This option causes rsync to transfer character and
block device information to the remote system to recreate these
@@ -488,7 +492,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
@@ -545,8 +549,9 @@ quote(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
then files listed in a $HOME/.cvsignore are added to the list and any
files listed in the CVSIGNORE environment variable (space delimited).
Finally in each directory any files listed in the .cvsignore file in
that directory are added to the list.
Finally, any file is ignored if it is in the same directory as a
.cvsignore file and matches one of the patterns listed therein. See
the bf(cvs(1)) manual for more information.
dit(bf(--csum-length=LENGTH)) By default the primary checksum used in
rsync is a very strong 16 byte MD4 checksum. In most cases you will
@@ -603,21 +608,33 @@ what ownership to give files. The special uid 0 and the special group
0 are never mapped via user/group names even if the --numeric-ids
option is not specified.
If the source system is a daemon using chroot, or if a user or group name
does not exist on the destination system, then the numeric id from the
source system is used instead.
If the source system is a daemon using chroot, or if a user or group
name does not exist on the destination system, then the numeric id
from the source system is used instead.
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
timeout in seconds. If no data is transferred for the specified time
then rsync will exit. The default is 0, which means no timeout.
dit(bf(--daemon)) This tells rsync that it is to run as a rsync
daemon. If standard input is a socket then rsync will assume that it
is being run via inetd, otherwise it will detach from the current
terminal and become a background daemon. The daemon will read the
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(--daemon)) This tells rsync that it is to run as a daemon. The
daemon may be accessed using the bf(host::module) or
bf(rsync://host/module/) syntax.
If standard input is a socket then rsync will assume that it is being
run via inetd, otherwise it will detach from the current terminal and
become a background daemon. The daemon will read the 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
@@ -691,7 +708,7 @@ manpagesection(EXCLUDE PATTERNS)
The exclude and include patterns specified to rsync allow for flexible
selection of which files to transfer and which files to skip.
rsync builds a ordered list of include/exclude options as specified on
rsync builds an 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, then that file is
@@ -744,7 +761,7 @@ itemize(
part of an include option. The "- " part is discarded before matching.
it() if the pattern is a single exclamation mark ! then the current
exclude list is reset, removing all previous exclude patterns.
include/exclude list is reset, removing all previously defined patterns.
)
The +/- rules are most useful in exclude lists, allowing you to have a
@@ -776,12 +793,15 @@ itemize(
manpagesection(BATCH MODE)
bf(Note:) Batch mode should be considered experimental in this version
of rsync. The interface or behaviour may change before it stabilizes.
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()
$ rsync --write-batch [other rsync options here] \nl()
/somewhere/src_dir /somewhere/target_dir
)
@@ -797,6 +817,29 @@ 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(SYMBOLIC LINKS)
Three basic behaviours are possible when rsync encounters a symbolic
link in the source directory.
By default, symbolic links are not transferred at all. A message
"skipping non-regular" file is emitted for any symlinks that exist.
If bf(--links) is specified, then symlinks are recreated with the same
target on the destination. Note that bf(--archive) implies
bf(--links).
If bf(--copy-links) is specified, then symlinks are "collapsed" by
copying their referent, rather than the symlink.
rsync also distinguishes "safe" and "unsafe" symbolic links. An
example where this might be used is a web site mirror that wishes
ensure the rsync module they copy does not include symbolic links to
bf(/etc/passwd) in the public section of the site. Using
bf(--copy-unsafe-links) will cause any links to be copied as the file
they point to on the destination. Using bf(--safe-links) will cause
unsafe links to be ommitted altogether.
manpagesection(DIAGNOSTICS)
rsync occasionally produces error messages that may seem a little
@@ -922,16 +965,22 @@ Jean-loup Gailly and Mark Adler.
manpagesection(THANKS)
Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
and David Bell for helpful suggestions and testing of rsync. I've
probably missed some people, my apologies if I have.
and David Bell for helpful suggestions, patches and testing of rsync.
I've probably missed some people, my apologies if I have.
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer.
manpageauthor()
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 was written by Andrew Tridgell <tridge@samba.org> and Paul
Mackerras.
rsync is now also maintained by Martin Pool <mbp@samba.org>
rsync is now maintained by Martin Pool <mbp@samba.org>.
Mailing lists for support and development are available at
url(http://lists.samba.org)(lists.samba.org)
If you suspect you have found a security vulnerability in rsync,
please send it directly to Martin Pool and Andrew Tridgell. For other
enquiries, please use the mailing list.

View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version
@@ -160,16 +160,27 @@ missing=0
passed=0
failed=0
scratchdir=./testtmp
[ -d "$scratchdir" ] && rm -r "$scratchdir"
mkdir "$scratchdir"
scratchdir=`cd $scratchdir && pwd`
echo " scratchdir=$scratchdir"
# Prefix for scratch directory. We create separate directories for
# each test case, so that they can be left behind in case of failure
# to aid investigation.
scratchbase="`pwd`"/testtmp
echo " scratchbase=$scratchbase"
suitedir="$srcdir/testsuite"
export scratchdir suitedir
prep_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
mkdir "$scratchdir"
return 0
}
discard_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
return 0
}
if [ "x$whichtests" = x ]
then
whichtests="*.test"
@@ -177,29 +188,45 @@ fi
for testscript in $suitedir/$whichtests
do
testbase=`echo $testscript | sed 's!.*/!!'`
testbase=`echo $testscript | sed 's!.*/!!' | sed -e 's/.test\$//'`
scratchdir="$scratchbase.$testbase"
echo "----- $testbase starting"
prep_scratch
if sh $RUNSHFLAGS "$testscript"
then
echo "----- $testbase completed succesfully"
set +e
sh $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
result=$?
set -e
case $result in
0)
echo "PASS $testbase"
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
discard_scratch
;;
77)
echo "SKIP $testbase"
skipped=`expr $skipped + 1`
discard_scratch
;;
78)
# It failed, but we expected that. don't dump out error logs,
# because most users won't want to see them. But do leave
# the working directory around.
echo "XFAIL $testbase"
failed=`expr $failed + 1`
;;
*)
echo "FAIL $testbase"
echo "----- $testbase failed: log follows"
cat "$scratchdir/test.log"
echo "----- $testbase log ends"
failed=`expr $failed + 1`
if [ "x$nopersist" = "xyes" ]
then
exit 1
fi
esac
done
echo '------------------------------------------------------------'

View File

@@ -159,13 +159,14 @@ 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;
}
if (write_batch)
write_batch_csum_info(&i,flist->count,s);
if (!read_batch) {
fd = do_open(fname, O_RDONLY, 0);

405
socket.c
View File

@@ -1,7 +1,9 @@
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,18 +20,19 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
socket functions used in rsync
*/
/**
* @file socket.c
*
* Socket functions used in rsync.
*
* This file is now converted to use the new-style getaddrinfo()
* interface, which supports IPv6 but is also supported on recent
* IPv4-only machines. On systems that don't have that interface, we
* emulate it using the KAME implementation.
**/
#include "rsync.h"
#ifndef HAVE_GETADDRINFO
#include "lib/addrinfo.h"
#endif
extern int af;
/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
@@ -39,7 +42,7 @@ static int establish_proxy_connection(int fd, char *host, int port)
char *cp;
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
rprintf(FERROR, "failed to write to proxy: %s\n",
strerror(errno));
return -1;
@@ -95,20 +98,66 @@ 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
*
*
* @param bind_address Local address to use. Normally NULL to get the stack default.
/**
* Try to set the local address for a newly-created socket. Return -1
* if this fails.
**/
int open_socket_out(char *host, int port, const char *bind_address)
int try_bind_local(int s,
int ai_family, int ai_socktype,
const char *bind_address)
{
int error;
struct addrinfo bhints, *bres_all, *r;
memset(&bhints, 0, sizeof(bhints));
bhints.ai_family = ai_family;
bhints.ai_socktype = ai_socktype;
bhints.ai_flags = AI_PASSIVE;
if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
bind_address, gai_strerror(error));
return -1;
}
for (r = bres_all; r; r = r->ai_next) {
if (bind(s, r->ai_addr, r->ai_addrlen) == -1)
continue;
return s;
}
/* no error message; there might be some problem that allows
* creation of the socket but not binding, perhaps if the
* machine has no ipv6 address of this name. */
return -1;
}
/**
* 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;
int error;
int s;
int result;
struct addrinfo hints, *res0, *res;
char portbuf[10];
char *h;
@@ -139,41 +188,32 @@ int open_socket_out(char *host, int port, const char *bind_address)
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
hints.ai_family = af_hint;
hints.ai_socktype = type;
error = getaddrinfo(h, portbuf, &hints, &res0);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s: %s\n", portbuf, gai_strerror(error));
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
h, portbuf, gai_strerror(error));
return -1;
}
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: %s\n",
bind_address, gai_strerror(error));
if (bind_address)
if (try_bind_local(s, res->ai_family, type,
bind_address) == -1) {
close(s);
s = -1;
continue;
}
if (bres->ai_next) {
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);
@@ -212,14 +252,16 @@ int open_socket_out(char *host, int port, const char *bind_address)
**/
int open_socket_out_wrapped (char *host,
int port,
const char *bind_address)
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);
return open_socket_out (host, port, bind_address,
af_hint);
}
@@ -227,55 +269,73 @@ int open_socket_out_wrapped (char *host,
/**
* 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)
static int open_socket_in(int type, int port, const char *bind_address,
int af_hint)
{
int one=1;
int s;
struct addrinfo hints, *res;
struct addrinfo hints, *all_ai, *resp;
char portbuf[10];
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
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);
error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
if (error) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
bind_address, gai_strerror(error));
return -1;
}
if (res->ai_next) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: "
"resolved to multiple hosts\n",
bind_address);
freeaddrinfo(res);
return -1;
/* We may not be able to create the socket, if for example the
* machine knows about IPv6 in the C library, but not in the
* kernel. */
for (resp = all_ai; resp; resp = resp->ai_next) {
s = socket(resp->ai_family, resp->ai_socktype,
resp->ai_protocol);
if (s == -1)
/* See if there's another address that will work... */
continue;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&one, sizeof one);
/* now we've got a socket - we need to bind it */
if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
/* Nope, try another */
close(s);
continue;
}
return s;
}
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
rprintf(FERROR, RSYNC_NAME ": open socket in failed: %s\n",
strerror(errno));
freeaddrinfo(res);
return -1;
}
rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
"%s\n",
port,
strerror(errno));
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
/* now we've got a socket - we need to bind it */
if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
freeaddrinfo(res);
close(s);
return -1;
}
return s;
freeaddrinfo(all_ai);
return -1;
}
@@ -309,9 +369,10 @@ void start_accept_loop(int port, int (*fn)(int ))
{
int s;
extern char *bind_address;
extern int default_af_hint;
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port, bind_address);
s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
if (s == -1)
exit_cleanup(RERR_SOCKETIO);
@@ -328,7 +389,7 @@ void start_accept_loop(int port, int (*fn)(int ))
fd_set fds;
int fd;
struct sockaddr_storage addr;
int in_addrlen = sizeof(addr);
socklen_t addrlen = sizeof addr;
/* close log file before the potentially very long select so
file can be trimmed by another process instead of growing
@@ -344,7 +405,7 @@ void start_accept_loop(int port, int (*fn)(int ))
if(!FD_ISSET(s, &fds)) continue;
fd = accept(s,(struct sockaddr *)&addr,&in_addrlen);
fd = accept(s,(struct sockaddr *)&addr,&addrlen);
if (fd == -1) continue;
@@ -505,180 +566,6 @@ void become_daemon(void)
}
}
/*******************************************************************
return the IP addr of the client as a string
******************************************************************/
char *client_addr(int fd)
{
struct sockaddr_storage ss;
int length = sizeof(ss);
static char addr_buf[100];
static int initialised;
if (initialised) return addr_buf;
initialised = 1;
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
exit_cleanup(RERR_SOCKETIO);
}
getnameinfo((struct sockaddr *)&ss, length,
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
return addr_buf;
}
/*******************************************************************
return the DNS name of the client
******************************************************************/
char *client_name(int fd)
{
struct sockaddr_storage ss;
int length = sizeof(ss);
static char name_buf[100];
static char port_buf[100];
char *def = "UNKNOWN";
static int initialised;
struct addrinfo hints, *res, *res0;
int error;
if (initialised) return name_buf;
initialised = 1;
strcpy(name_buf,def);
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
exit_cleanup(RERR_SOCKETIO);
}
#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");
}
/* 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,
"reverse name lookup mismatch - spoofed address?\n");
}
freeaddrinfo(res0);
return name_buf;
}
/**
Convert a string to an IP address. The string can be a name or
dotted decimal number.
Returns a pointer to a static in_addr struct -- if you call this
more than once then you should copy it.
*/
struct in_addr *ip_address(const char *str)
{
static struct in_addr ret;
struct hostent *hp;
if (!str) {
rprintf (FERROR, "ip_address received NULL name\n");
return NULL;
}
/* try as an IP address */
if (inet_aton(str, &ret) != 0) {
return &ret;
}
/* otherwise assume it's a network name of some sort and use
gethostbyname */
if ((hp = gethostbyname (str)) == 0) {
rprintf(FERROR, "gethostbyname failed for \"%s\": unknown host?\n",str);
return NULL;
}
if (hp->h_addr == NULL) {
rprintf(FERROR, "gethostbyname: host address is invalid for host \"%s\"\n",str);
return NULL;
}
if (hp->h_length > sizeof ret) {
rprintf(FERROR, "gethostbyname: host address for \"%s\" is too large\n",
str);
return NULL;
}
if (hp->h_addrtype != AF_INET) {
rprintf (FERROR, "gethostname: host address for \"%s\" is not IPv4\n",
str);
return NULL;
}
/* This is kind of difficult. The only field in ret is
s_addr, which is the IP address as a 32-bit int. On
UNICOS, s_addr is in fact a *bitfield* for reasons best
know to Cray. This means we can't memcpy in to it. On the
other hand, h_addr is a char*, so we can't just assign.
Since there's meant to be only one field inside the in_addr
structure we will try just copying over the top and see how
that goes. */
memcpy (&ret, hp->h_addr, hp->h_length);
return &ret;
}
/*******************************************************************
this is like socketpair but uses tcp. It is used by the Samba
@@ -747,16 +634,20 @@ static int socketpair_tcp(int fd[2])
}
/*******************************************************************
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
******************************************************************/
/**
* Run a program on a local tcp socket, so that we can talk to it's
* stdin and stdout. This is used to fake a connection to a daemon
* for testing -- not for the normal case of running SSH.
*
* @return 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",
@@ -769,10 +660,12 @@ int sock_exec(const char *prog)
close(1);
dup(fd[1]);
dup(fd[1]);
if (verbose > 3)
if (verbose > 3) {
/* Can't use rprintf because we've forked. */
fprintf (stderr,
RSYNC_NAME ": execute socket program \"%s\"\n",
prog);
}
exit (system (prog));
}
close (fd[1]);

View File

@@ -132,7 +132,7 @@ int do_mkstemp(char *template, mode_t perms)
}
#else
if (!mktemp(template)) return -1;
return open(template, O_RDWR|O_EXCL|O_CREAT, perms);
return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
#endif
}

57
testsuite/duplicates.test Normal file
View File

@@ -0,0 +1,57 @@
#! /bin/sh
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of duplicate filenames.
# It's quite possible that the user might specify the same source file
# more than once on the command line, perhaps through shell variables
# or wildcard expansions. It might cause problems for rsync if the
# same name occurred more than once in the file list, because we might
# be trying to update the first copy and generate checksums for the
# second copy at the same time. See clean_flist() for the implementation.
# We don't need to worry about hardlinks or symlinks. Because we
# always rename-and-replace the new copy, they can't affect us.
# This test is not great, because it is a timing-dependent bug.
. $srcdir/testsuite/rsync.fns
echo "SKIP THIS FOR NOW; It's a known bug"
exit 77
set -x
# Build some hardlinks
fromdir="$scratchdir/from"
todir="$scratchdir/to"
mkdir "$fromdir"
name1="$fromdir/name1"
name2="$fromdir/name2"
echo "This is the file" > "$name1"
ln -s "$name1" "$name2" || fail "can't create symlink"
outfile="$scratchdir/rsync.out"
checkit "rsync -avv \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
| tee "$outfile"
# Make sure each file was only copied once...
if [ `grep -c '^name1$' "$outfile"` != 1 ]
then
test_xfail "name1 was not copied exactly once"
fi
if [ `grep -c '^name2$' "$outfile"` != 1 ]
then
test_xfail "name2 was not copied exactly once"
fi
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -26,3 +26,5 @@ cp ${FROM}/text ${TO}/ThisShouldGo
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
checkforlogs ${LOG}.?
hands_cleanup

38
testsuite/hardlinks.test Normal file
View File

@@ -0,0 +1,38 @@
#! /bin/sh
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync handling of hardlinks. By default (in 2.5.1) rsync does
# not detect symlinks and they get split into different files. If you
# specify -H, then hard links are detected and recreated as hardlinks
# on the other end.
. $srcdir/testsuite/rsync.fns
set -x
# Build some hardlinks
fromdir="$scratchdir/from"
todir="$scratchdir/to"
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
mkdir "$fromdir"
name1="$fromdir/name1"
name2="$fromdir/name2"
name3="$fromdir/name3"
name4="$fromdir/name4"
echo "This is the file" > "$name1"
ln "$name1" "$name2" || fail "Can't create hardlink"
ln "$name2" "$name3" || fail "Can't create hardlink"
cp "$name2" "$name4" || fail "Can't copy file"
checkit "rsync -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
exit 0
# last [] may have failed but if we get here then we've won

View File

@@ -5,9 +5,10 @@
#
# 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

View File

@@ -41,6 +41,11 @@ printmsg() {
}
rsync_ls_lR() {
find "$@" -print | sort | xargs $TLS
}
####################
# Build test directories TO and FROM, with FROM full of files.
@@ -48,7 +53,8 @@ hands_setup() {
# Clean before creation
rm -rf $FROM
rm -rf $TO
[ -d $TMP ] || mkdir $TMP
[ -d $FROM ] || mkdir $FROM
[ -d $TO ] || mkdir $TO
@@ -67,7 +73,7 @@ hands_setup() {
mkdir ${FROM}/emptydir
# a hundred lines of text or so
ls -lR ${srcdir} > ${FROM}/filelist
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
@@ -89,12 +95,18 @@ hands_setup() {
}
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.
@@ -106,8 +118,12 @@ makepath () {
# This will break if $1 contains a space.
for c in `echo $p | tr '/' ' '`
do
[ -d "$c" ] || mkdir "$c" || return $?
cd "$c" || return $?
if [ -d "$c" ] || mkdir "$c"
then
cd "$c" || return $?
else
echo "failed to create $c" >&2; return $?
fi
done
)
}
@@ -119,35 +135,31 @@ makepath () {
# 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
# We can just write everything to stdout/stderr, because the
# wrapper hides it unless there is a problem.
echo "Running: \"$1\""
eval "$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 ; ls -laR ) > ${TMP}/ls-from 2>>${log}
( cd $3 ; ls -laR ) > ${TMP}/ls-to 2>>${log}
diff -c ${TMP}/ls-from ${TMP}/ls-to >>${log} 2>&1 || failed=YES
echo "-------------"
echo "check how the files compare with diff:"
echo ""
diff -cr $2 $3 || failed=YES
echo "-------------"
echo "check how the directory listings compare with diff:"
echo ""
( cd "$2" && rsync_ls_lR . ) > ${TMP}/ls-from
( cd "$3" && rsync_ls_lR . ) > ${TMP}/ls-to
diff -c ${TMP}/ls-from ${TMP}/ls-to || failed=YES
if [ -z "${failed}" ] ; then
rm $log
return 0
else
cat ${log}
rm ${log}
return 1
fi
}
@@ -194,3 +206,29 @@ EOF
}
build_symlinks() {
fromdir="$scratchdir/from"
todir="$scratchdir/to"
mkdir "$fromdir"
date >"$fromdir/referent"
ln -s referent "$fromdir/relative"
ln -s "$fromdir/referent" "$fromdir/absolute"
ln -s nonexistent "$fromdir/dangling"
ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
}
test_fail() {
echo "$@" >&2
exit 1
}
# It failed, but we expected that. don't dump out error logs,
# because most users won't want to see them. But do leave
# the working directory around.
test_xfail() {
echo "$@" >&2
exit 78
}
# be reproducible
umask 077

View File

@@ -0,0 +1,29 @@
#! /bin/sh
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test rsync's somewhat over-featured symlink control: the default
# behaviour is that symlinks should not be copied at all.
. $srcdir/testsuite/rsync.fns
set -x
build_symlinks || test_fail "failed to build symlinks"
# Copy recursively, but without -l or -L or -a, and all the symlinks
# should be missing.
"$rsync_bin" -r "$fromdir/" "$todir" || test_fail "rsync returned $?"
[ -f "${todir}/referent" ] || test_fail "referent was not copied"
[ -d "${todir}/from" ] && test_fail "extra level of directories"
[ -L "${todir}/dangling" ] && test_fail "dangling symlink was copied"
[ -L "${todir}/relative" ] && test_fail "relative symlink was copied"
[ -L "${todir}/absolute" ] && test_fail "absolute symlink was copied"
exit 0
# last [] may have failed but if we get here then we've one

91
tls.c
View File

@@ -1,6 +1,6 @@
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 2001 by Martin Pool
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
@@ -27,18 +27,16 @@
* our purposes they're the same -- for example, the BSD braindamage
* about setting the mode on symlinks based on your current umask.
*
* There are some restrictions compared to regular ls: all the names
* on the command line must be directories rather than files; you
* can't give wildcards either.
* 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".
*
* We need to recurse downwards and show all the interesting
* information and no more.
* The format is not exactly the same as any particular Unix ls(1).
*
* \todo Use readdir64 if available?
*
* \todo Sort directory entries. Either that, or output file listing
* in such a format that we can just pipe the whole lot through sort.
*/
* A key requirement for this program is that the output be "very
* reproducible." So we mask away information that can accidentally
* change.
**/
@@ -62,23 +60,68 @@ static void failed (char const *what,
static void list_dir (char const *dn)
static void list_file (const char *fname)
{
DIR *d;
struct dirent *de;
struct stat buf;
char permbuf[PERMSTRING_SIZE];
struct tm *mt;
char datebuf[50];
char linkbuf[4096];
if (!(d = opendir (dn)))
failed ("opendir", dn);
if (do_lstat(fname, &buf) == -1)
failed ("stat", fname);
while ((de = readdir (d))) {
char *dname = d_name (de);
if (!strcmp (dname, ".") || !strcmp (dname, ".."))
continue;
printf ("%s\n", dname);
/* 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)) {
int len;
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 */
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
if (len == -1)
failed("readlink", fname);
else
/* it's not nul-terminated */
linkbuf[4+len] = 0;
} 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, " ");
}
if (closedir (d) == -1)
failed ("closedir", dn);
/* 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 %6d %s %s%s\n",
permbuf, (double) buf.st_size,
buf.st_uid, buf.st_gid,
buf.st_nlink,
datebuf, fname, linkbuf);
}
@@ -91,7 +134,7 @@ int main (int argc, char *argv[])
}
for (argv++; *argv; argv++) {
list_dir (*argv);
list_file (*argv);
}
return 0;

251
util.c
View File

@@ -1,8 +1,6 @@
/* -*- 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>
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,88 +26,49 @@
extern int verbose;
/****************************************************************************
Set a fd into nonblocking mode
Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available,
else
if SYSV use O_NDELAY
if BSD use FNDELAY
****************************************************************************/
void set_nonblocking(int fd)
int set_nonblocking(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);
}
}
/****************************************************************************
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);
}
}
/* 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 ret;
#if HAVE_SOCKETPAIR
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
#ifdef O_NONBLOCK
#define FLAG_TO_SET O_NONBLOCK
#else
ret = pipe(fd);
#ifdef SYSV
#define FLAG_TO_SET O_NDELAY
#else /* BSD */
#define FLAG_TO_SET FNDELAY
#endif
#endif
if (ret == 0) {
set_nonblocking(fd[0]);
set_nonblocking(fd[1]);
}
return ret;
if((val = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
val |= FLAG_TO_SET;
return fcntl( fd, F_SETFL, val);
#undef FLAG_TO_SET
}
/* 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)
/* this is taken from CVS */
int piped_child(char **command,int *f_in,int *f_out)
{
pid_t pid;
int 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) {
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid == -1) {
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -127,10 +86,6 @@ pid_t 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));
@@ -146,25 +101,27 @@ pid_t piped_child(char **command,int *f_in,int *f_out)
*f_in = from_child_pipe[0];
*f_out = to_child_pipe[1];
set_nonblocking(*f_in);
set_nonblocking(*f_out);
return pid;
}
pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
int local_child(int argc, char **argv,int *f_in,int *f_out)
{
pid_t pid;
int 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) {
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid == -1) {
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -173,10 +130,7 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
extern int am_sender;
extern int am_server;
if (read_batch)
am_sender = 0;
else
am_sender = !am_sender;
am_sender = !am_sender;
am_server = 1;
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
@@ -275,7 +229,7 @@ int create_directory_path(char *fname)
derived from GNU C's cccp.c.
*/
static int full_write(int desc, char *ptr, int len)
static int full_write(int desc, char *ptr, size_t len)
{
int total_written;
@@ -301,11 +255,11 @@ static int full_write(int desc, char *ptr, int len)
for an error.
derived from GNU C's cccp.c. */
static int safe_read(int desc, char *ptr, int len)
static int safe_read(int desc, char *ptr, size_t len)
{
int n_chars;
if (len <= 0)
if (len == 0)
return len;
#ifdef EINTR
@@ -443,6 +397,17 @@ int robust_rename(char *from, char *to)
return -1;
return do_rename(from, to);
#endif
}
/* sleep for a while via select */
void u_sleep(int usec)
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = usec;
select(0, NULL, NULL, NULL, &tv);
}
@@ -563,7 +528,10 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs)
s = strdup(s);
if (!s) out_of_memory("glob_expand");
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
base = (char *)malloc(strlen(base1)+3);
if (!base) out_of_memory("glob_expand");
sprintf(base," %s/", base1);
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
@@ -590,6 +558,33 @@ 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);
@@ -813,12 +808,12 @@ int u_strcmp(const char *cs1, const char *cs2)
static OFF_T last_ofs;
void end_progress(OFF_T size)
void end_progress(void)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
rprintf(FINFO,"%.0f (100%%)\n", (double)size);
rprintf(FINFO,"\n");
}
last_ofs = 0;
}
@@ -905,85 +900,3 @@ char *timestring(time_t t)
return(TimeBuf);
}
/**
* Sleep for a specified number of milliseconds.
*
* Always returns TRUE. (In the future it might return FALSE if
* interrupted.)
**/
int msleep(int t)
{
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

1
version.h Normal file
View File

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