Compare commits

...

91 Commits

Author SHA1 Message Date
Martin Pool
a7641441a7 Bump version to 2.4.8 2002-01-25 23:33:24 +00:00
Martin Pool
d19fa730b9 Should be 2.4.8, because we talked about doing 2.4.7 a while ago. 2002-01-25 01:17:45 +00:00
Martin Pool
5c6e0ee27c Signedness security patch from Sebastian Krahmer <krahmer@suse.de> --
in some cases we were not sufficiently careful about reading integers
from the network.
2002-01-25 00:56:35 +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
32 changed files with 1081 additions and 972 deletions

View File

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

36
NEWS
View File

@@ -1,33 +1,7 @@
rsync 2.5.1 (2002-01-03)
rsync 2.4.8 (26 Jan 2002)
BUG FIXES:
* Fix for segfault in --daemon mode configuration parser. (Paul
Mackerras)
SECURITY FIXES:
* 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.
* Signedness security patch from Sebastian Krahmer
<krahmer@suse.de> -- in some cases we were not sufficiently
careful about reading integers from the network.

34
OLDNEWS
View File

@@ -1,3 +1,37 @@
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

157
TODO
View File

@@ -32,14 +32,138 @@ use chroot
for people who want to generate the file list using a find(1)
command or a script.
Performance
Traverse just one directory at a time. Tridge says it's possible.
Can possibly also be smarter about memory use while looking for hard
links by reducing the refcount as we find alternative names. In
fact at the moment the code seems to make a whole second copy of the
file list, which seems unnecessary.
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
@@ -100,10 +224,26 @@ logging
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
@@ -137,10 +277,6 @@ Add machines
NICE -----------------------------------------------------------------
SIGHUP
Re-read config file (just exec() ourselves) rather than exiting.
--no-detach and --no-fork options
Very useful for debugging. Also good when running under a
@@ -149,8 +285,6 @@ SIGHUP
hang/timeout friendliness
On
verbose output
Indicate whether files are new, updated, or deleted
@@ -172,3 +306,4 @@ rsyncsh
current host, directory and so on. We can probably even do
completion of remote filenames.
%K%

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);

64
batch.c
View File

@@ -35,6 +35,7 @@ void create_batch_file_ext()
timeptr->tm_year + 1900, timeptr->tm_mon + 1,
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min,
timeptr->tm_sec);
rprintf(FINFO,"batch file extension: %s\n", batch_file_ext);
}
void set_batch_file_ext(char *ext)
@@ -84,12 +85,16 @@ void write_batch_flist_info(int flist_count, struct file_struct **fptr)
/* Write flist info to batch file */
bytes_to_write = sizeof(unsigned) +
bytes_to_write =
sizeof(unsigned) +
sizeof(time_t) +
sizeof(OFF_T) +
sizeof(mode_t) +
sizeof(INO_T) +
(2 * sizeof(dev_t)) + sizeof(uid_t) + sizeof(gid_t);
sizeof(INO64_T) +
sizeof(DEV64_T) +
sizeof(DEV64_T) +
sizeof(uid_t) +
sizeof(gid_t);
fdb_open = 1;
fdb_close = 0;
@@ -128,7 +133,7 @@ void write_char_bufs(char *buf)
}
}
void write_batch_argvs_file(int orig_argc, int argc, char **argv)
void write_batch_argvs_file(int argc, char *argv[])
{
int fdb;
int i;
@@ -149,23 +154,27 @@ void write_batch_argvs_file(int orig_argc, int argc, char **argv)
buff[0] = '\0';
/* Write argvs info to batch file */
for (i = argc - orig_argc; i < argc; i++) {
/* FIXME: This apparently crashes if rsync is run with
* just "rsync -F". I think directly manipulating
* argv[] is probably bogus -- what if -F is part of a
* run of several short options? */
if (!strcmp(argv[i], "-F")) { /* safer to change it here than script */
strncat(buff, "-f ", 3); /* chg to -f + ext to get ready for remote */
strncat(buff, batch_file_ext,
strlen(batch_file_ext));
for (i = 0; i < argc; ++i) {
if (i == argc - 2)
continue;
/*
* FIXME:
* I think directly manipulating argv[] is probably bogus
*/
if (!strcmp(argv[i], "--write-batch")) {
/* Safer to change it here than script */
/* Change to --read-batch + ext * to get ready for remote */
strlcat(buff, "--read-batch ", sizeof(buff));
strlcat(buff, batch_file_ext, sizeof(buff));
} else {
strncat(buff, argv[i], strlen(argv[i]));
strlcat(buff, argv[i], sizeof(buff));
}
if (i < (argc - 1)) {
strncat(buff, " ", 1);
strlcat(buff, " ", sizeof(buff));
}
}
strlcat(buff, "\n", sizeof(buff));
if (!write(fdb, buff, strlen(buff))) {
rprintf(FERROR, "Batch file %s write error: %s\n",
rsync_argvs_file, strerror(errno));
@@ -289,9 +298,9 @@ void read_batch_flist_info(struct file_struct **fptr)
read_batch_flist_file((char *) &file->modtime, sizeof(time_t));
read_batch_flist_file((char *) &file->length, sizeof(OFF_T));
read_batch_flist_file((char *) &file->mode, sizeof(mode_t));
read_batch_flist_file((char *) &file->inode, sizeof(INO_T));
read_batch_flist_file((char *) &file->dev, sizeof(dev_t));
read_batch_flist_file((char *) &file->rdev, sizeof(dev_t));
read_batch_flist_file((char *) &file->inode, sizeof(INO64_T));
read_batch_flist_file((char *) &file->dev, sizeof(DEV64_T));
read_batch_flist_file((char *) &file->rdev, sizeof(DEV64_T));
read_batch_flist_file((char *) &file->uid, sizeof(uid_t));
read_batch_flist_file((char *) &file->gid, sizeof(gid_t));
read_batch_flist_file(char_str_len, sizeof(char_str_len));
@@ -345,7 +354,7 @@ void read_batch_flist_info(struct file_struct **fptr)
}
}
void write_batch_csums_file(char *buff, int bytes_to_write)
void write_batch_csums_file(void *buff, int bytes_to_write)
{
static int fdb_open = 1;
@@ -386,21 +395,24 @@ void close_batch_csums_file()
void write_batch_csum_info(int *flist_entry, int flist_count,
struct sum_struct *s)
{
int i;
int int_zero = 0;
size_t i;
unsigned int int_zero = 0;
extern int csum_length;
fdb_open = 1;
/* Write csum info to batch file */
write_batch_csums_file((char *) flist_entry, sizeof(int));
write_batch_csums_file((char *) (s ? &s->count : &int_zero),
sizeof(int));
/* FIXME: This will break if s->count is ever not exactly an int. */
write_batch_csums_file(flist_entry, sizeof(int));
if (s)
write_batch_csums_file(&s->count, sizeof(int));
else
write_batch_csums_file(&int_zero, sizeof (int));
if (s) {
for (i = 0; i < s->count; i++) {
write_batch_csums_file((char *) &s->sums[i].sum1,
sizeof(uint32));
write_batch_csums_file(&s->sums[i].sum1, sizeof(uint32));
if ((*flist_entry == flist_count - 1)
&& (i == s->count - 1)) {
fdb_close = 1;

View File

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

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.52)
RSYNC_VERSION=2.5.1
RSYNC_VERSION=2.5.2pre3
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -22,13 +22,18 @@ AC_PROG_INSTALL
AC_PROG_CC_STDC
AC_SUBST(SHELL)
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
if test "$xac_cv_prog_cc_stdc" = xno
then
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
fi
# compile with optimisation and without debugging by default, unless
# --debug is given. We must decide this before testing the compiler.
# 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,
@@ -47,8 +52,29 @@ else
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])
@@ -204,6 +230,7 @@ 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 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)
@@ -268,7 +295,7 @@ fi
AC_CHECK_LIB(resolv, inet_ntop)
AC_MSG_NOTICE([Looking in libraries: $LIBS])
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))
@@ -309,7 +336,7 @@ 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([
@@ -525,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()

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;
@@ -31,7 +28,7 @@ extern int delete_mode;
static struct exclude_struct **exclude_list;
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(const char *pattern, int include)
static struct exclude_struct *make_exclude(char *pattern, int include)
{
struct exclude_struct *ret;
@@ -87,8 +84,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;
@@ -124,62 +121,32 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
}
static void report_exclude_result(char const *name,
struct exclude_struct const *ent,
STRUCT_STAT const *st)
{
/* 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)
@@ -207,12 +174,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 +188,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 +210,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;
@@ -299,7 +263,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 +363,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;

83
flist.c
View File

@@ -1,7 +1,6 @@
/*
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
@@ -48,9 +47,6 @@ 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;
@@ -112,14 +108,24 @@ static char *string_area_strdup(struct string_area **ap, const char *src)
static void list_file_entry(struct file_struct *f)
{
char perms[11];
char perms[11] = "----------";
char *perm_map = "rwxrwxrwx";
int i;
if (!f->basename)
/* this can happen if duplicate names were removed */
return;
permstring(perms, f->mode);
for (i=0;i<9;i++) {
if (f->mode & (1<<i)) perms[9-i] = perm_map[8-i];
}
if (S_ISLNK(f->mode)) perms[0] = 'l';
if (S_ISDIR(f->mode)) perms[0] = 'd';
if (S_ISBLK(f->mode)) perms[0] = 'b';
if (S_ISCHR(f->mode)) perms[0] = 'c';
if (S_ISSOCK(f->mode)) perms[0] = 's';
if (S_ISFIFO(f->mode)) perms[0] = 'p';
if (preserve_links && S_ISLNK(f->mode)) {
rprintf(FINFO,"%s %11.0f %s %s -> %s\n",
perms,
@@ -144,7 +150,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;
@@ -176,18 +182,14 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer)
This function is used to check if a file should be included/excluded
from the list of files based on its name and type etc
*/
static int check_exclude_file(int f,char *fname,STRUCT_STAT *st)
static int match_file_name(char *fname,STRUCT_STAT *st)
{
extern int delete_excluded;
/* f is set to -1 when calculating deletion file list */
if ((f == -1) && delete_excluded) {
return 0;
}
if (check_exclude(fname,local_exclude_list,st)) {
return 1;
}
return 0;
if (check_exclude(fname,local_exclude_list,st)) {
if (verbose > 2)
rprintf(FINFO,"excluding file %s\n",fname);
return 0;
}
return 1;
}
/* used by the one_file_system code */
@@ -203,7 +205,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;
@@ -211,8 +213,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;
}
@@ -332,7 +334,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;
@@ -399,6 +401,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);
@@ -464,8 +470,7 @@ static int skip_filesystem(char *fname, STRUCT_STAT *st)
}
#define STRDUP(ap, p) (ap ? string_area_strdup(ap, p) : strdup(p))
/* IRIX cc cares that the operands to the ternary have the same type. */
#define MALLOC(ap, i) (ap ? (void*) string_area_malloc(ap, i) : malloc(i))
#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,
@@ -477,6 +482,7 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
char *p;
char cleaned_name[MAXPATHLEN];
char linkbuf[MAXPATHLEN];
extern int delete_excluded;
extern int module_id;
strlcpy(cleaned_name, fname, MAXPATHLEN);
@@ -490,18 +496,9 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
memset(sum,0,SUM_LENGTH);
if (readlink_stat(fname,&st,linkbuf) != 0) {
int save_errno = errno;
if ((errno == ENOENT) && copy_links && !noexcludes) {
/* symlink pointing nowhere, see if excluded */
memset((char *)&st, 0, sizeof(st));
if (check_exclude_file(f,fname,&st)) {
/* file is excluded anyway, ignore silently */
return NULL;
}
}
io_error = 1;
rprintf(FERROR,"readlink %s: %s\n",
fname,strerror(save_errno));
fname,strerror(errno));
return NULL;
}
@@ -518,7 +515,8 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
return NULL;
}
if (check_exclude_file(f,fname,&st))
/* f is set to -1 when calculating deletion file list */
if (((f != -1) || !delete_excluded) && !match_file_name(fname,&st))
return NULL;
@@ -621,9 +619,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);
@@ -709,8 +704,6 @@ 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);
}
@@ -852,8 +845,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)
@@ -931,7 +922,7 @@ 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) {
@@ -1109,10 +1100,10 @@ static void clean_flist(struct file_list *flist, int strip_root)
for (i=0;i<flist->count;i++) {
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n",
(int) getpid(), i,
getpid(), i,
NS(flist->files[i]->dirname),
NS(flist->files[i]->basename),
(int) flist->files[i]->mode,
flist->files[i]->mode,
(double)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

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
}

225
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
@@ -29,34 +27,26 @@
/* if no timeout is specified then use a 60 second select timeout */
#define SELECT_TIMEOUT 60
extern int bwlimit;
static int io_multiplexing_out;
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;
/** 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);
static void read_loop(int fd, char *buf, size_t len);
static void check_timeout(void)
{
extern int am_server, am_daemon;
time_t t;
err_list_push();
if (!io_timeout) return;
@@ -69,7 +59,7 @@ static void check_timeout(void)
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
if (!am_server && !am_daemon) {
rprintf(FERROR,"io timeout after %d seconds - exiting\n",
rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
}
exit_cleanup(RERR_TIMEOUT);
@@ -90,8 +80,6 @@ static void read_error_fd(void)
int fd = io_error_fd;
int tag, len;
/* io_error_fd is temporarily disabled -- is this meant to
* prevent indefinite recursion? */
io_error_fd = -1;
read_loop(fd, buf, 4);
@@ -113,68 +101,21 @@ static void read_error_fd(void)
}
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.
*/
static int no_flush;
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;
io_flush();
while (ret == 0) {
/* until we manage to read *something* */
fd_set fds;
struct timeval tv;
int fd_count = fd+1;
int count;
FD_ZERO(&fds);
FD_SET(fd, &fds);
@@ -188,16 +129,11 @@ static int read_timeout (int fd, char *buf, int len)
errno = 0;
count = select(fd_count, &fds, NULL, NULL, &tv);
if (count == 0) {
check_timeout();
}
if (count <= 0) {
if (select(fd_count, &fds, NULL, NULL, &tv) < 1) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
check_timeout();
continue;
}
@@ -216,27 +152,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 == EWOULDBLOCK || errno == EAGAIN)) {
continue;
}
if (n == 0) {
if (eof_error) {
rprintf(FERROR,"unexpected EOF in read_timeout\n");
}
exit_cleanup(RERR_STREAMIO);
}
/* this prevents us trying to write errors on a dead socket */
io_multiplexing_close();
rprintf(FERROR,"read error: %s\n", strerror(errno));
exit_cleanup(RERR_STREAMIO);
}
return ret;
}
/*! Continue trying to read len bytes - don't return until len has
been read. */
static void read_loop (int fd, char *buf, int len)
/* continue trying to read len bytes - don't return until len
has been read */
static void read_loop(int fd, char *buf, size_t len)
{
while (len) {
int n = read_timeout(fd, buf, len);
@@ -246,20 +193,16 @@ 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;
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,7 +214,7 @@ static int read_unbuffered(int fd, char *buf, int len)
continue;
}
read_loop (fd, line, 4);
read_loop(fd, line, 4);
tag = IVAL(line, 0);
remaining = tag & 0xFFFFFF;
@@ -305,7 +248,7 @@ static int read_unbuffered(int fd, char *buf, int len)
/* do a buffered read from fd. don't return until all N bytes
have been read. If all N can't be read then exit with an error */
static void readfd (int fd, char *buffer, int N)
static void readfd(int fd,char *buffer,size_t N)
{
int ret;
int total=0;
@@ -313,7 +256,7 @@ static void readfd (int fd, char *buffer, int N)
while (total < N) {
io_flush();
ret = read_unbuffered (fd, buffer + total, N-total);
ret = read_unbuffered(fd,buffer + total,N-total);
total += ret;
}
@@ -356,34 +299,32 @@ 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)
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();
no_flush++;
while (total < len) {
@@ -408,14 +349,11 @@ static void writefd_unbuffered(int fd,char *buf,int len)
&w_fds,NULL,
&tv);
if (count == 0) {
check_timeout();
}
if (count <= 0) {
if (errno == EBADF) {
exit_cleanup(RERR_SOCKETIO);
}
check_timeout();
continue;
}
@@ -425,6 +363,7 @@ static void writefd_unbuffered(int fd,char *buf,int len)
if (FD_ISSET(fd, &w_fds)) {
int ret, n = len-total;
ret = write(fd,buf+total,n);
if (ret == -1 && errno == EINTR) {
@@ -438,10 +377,7 @@ static void writefd_unbuffered(int fd,char *buf,int len)
}
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);
}
@@ -483,7 +419,7 @@ void io_start_buffering(int fd)
/* 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)
static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
{
char buffer[4096];
int n = len;
@@ -509,9 +445,6 @@ static void mplex_write(int fd, enum logcode code, char *buf, int len)
void io_flush(void)
{
int fd = multiplex_out_fd;
err_list_push();
if (!io_buffer_count || no_flush) return;
if (io_multiplexing_out) {
@@ -522,8 +455,6 @@ void io_flush(void)
io_buffer_count = 0;
}
/* XXX: fd is ignored, which seems a little strange. */
void io_end_buffering(int fd)
{
io_flush();
@@ -533,12 +464,21 @@ void io_end_buffering(int fd)
}
}
static void writefd(int fd,char *buf,int len)
/* some OSes have a bug where an exit causes the pending writes on
a socket to be flushed. Do an explicit shutdown to try to prevent this */
void io_shutdown(void)
{
if (multiplex_out_fd != -1) close(multiplex_out_fd);
if (io_error_fd != -1) close(io_error_fd);
multiplex_out_fd = -1;
io_error_fd = -1;
}
static void writefd(int fd,char *buf,size_t len)
{
stats.total_written += len;
err_list_push();
if (!io_buffer || fd != multiplex_out_fd) {
writefd_unbuffered(fd, buf, len);
return;
@@ -565,11 +505,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 +522,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 +539,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 +561,8 @@ int read_line(int f, char *buf, int maxlen)
return 0;
}
eof_error = 1;
return 1;
}
@@ -637,7 +574,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);
@@ -664,7 +601,7 @@ void io_start_multiplex_in(int fd)
}
/* write an message to the multiplexed error stream */
int io_multiplex_write(enum logcode code, char *buf, int len)
int io_multiplex_write(enum logcode code, char *buf, size_t len)
{
if (!io_multiplexing_out) return 0;
@@ -674,6 +611,14 @@ int io_multiplex_write(enum logcode code, char *buf, int len)
return 1;
}
/* write a message to the special error fd */
int io_error_write(int f, enum logcode code, char *buf, size_t len)
{
if (f == -1) return 0;
mplex_write(f, code, buf, len);
return 1;
}
/* stop output multiplexing */
void io_multiplexing_close(void)
{

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);

269
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
@@ -182,30 +78,11 @@ void log_init(void)
#endif
}
void log_open()
{
if (logfname && !logfile) {
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
}
}
void log_close()
{
if (logfile) {
fclose(logfile);
logfile = NULL;
}
}
/* setup the error file descriptor - used when we are a server
that is receiving files */
void set_error_fd(int fd)
{
log_error_fd = fd;
set_nonblocking(log_error_fd);
}
/* this is the underlying (unformatted) rsync debugging function. Call
@@ -229,14 +106,12 @@ void rwrite(enum logcode code, char *buf, int len)
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();
/* first try to pass it off the our sibling */
if (am_server && io_error_write(log_error_fd, code, buf, len)) {
return;
}
/* if that fails, try to pass it to the other end */
/* then try to pass it to the other end */
if (am_server && io_multiplex_write(code, buf, len)) {
return;
}
@@ -250,7 +125,7 @@ void rwrite(enum logcode code, char *buf, int len)
depth++;
log_init();
log_open();
logit(priority, buf);
depth--;
@@ -258,7 +133,6 @@ void rwrite(enum logcode code, char *buf, int len)
}
if (code == FERROR) {
log_got_error = 1;
f = stderr;
}
@@ -277,86 +151,22 @@ void rwrite(enum logcode code, char *buf, int len)
}
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
void rprintf(enum logcode code, const char *format, ...)
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
va_start(ap, format);
len = 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);
len = vslprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
sysmsg = strerror(errcode);
sys_len = strlen(sysmsg);
if (len + 3 + sys_len > sizeof(buf) - 1)
exit_cleanup(RERR_MESSAGEIO);
strcpy(buf + len, ": ");
len += 2;
strcpy(buf + len, sysmsg);
len += sys_len;
strcpy(buf + len, "\n");
len++;
rwrite(code, buf, len);
}
void rflush(enum logcode code)
{
FILE *f = NULL;
@@ -405,6 +215,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 +228,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 +258,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 +269,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 +278,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);
@@ -511,15 +323,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 +333,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
@@ -122,6 +122,7 @@ static void print_rsync_version(enum logcode f)
char const *hardlinks = "no ";
char const *links = "no ";
char const *ipv6 = "no ";
STRUCT_STAT *dumstat;
#ifdef HAVE_SOCKETPAIR
got_socketpair = "";
@@ -142,13 +143,20 @@ static void print_rsync_version(enum logcode 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
@@ -232,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");
@@ -254,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 */
@@ -285,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},
@@ -323,8 +331,8 @@ 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, &default_af_hint, AF_INET },
{0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6 },
@@ -503,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;
@@ -542,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;
@@ -597,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
@@ -621,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;
}

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
@@ -83,15 +82,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));
}
@@ -179,7 +177,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 +190,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 +204,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;
@@ -304,7 +303,6 @@ 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];
@@ -372,7 +370,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);
@@ -413,7 +411,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 +429,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));

89
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,18 +47,7 @@
#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 PROTOCOL_VERSION 24
#define MIN_PROTOCOL_VERSION 15
#define MAX_PROTOCOL_VERSION 30
@@ -76,10 +63,7 @@
#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 };
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
#include "errcode.h"
@@ -93,6 +77,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 +258,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
@@ -343,9 +331,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 +344,7 @@ struct map_struct {
};
struct exclude_struct {
char *orig;
char *pattern;
int regular_exp;
int fnmatch_flags;
@@ -387,28 +376,9 @@ static inline int flist_up(struct file_list *flist, int i)
}
#include "byteorder.h"
#include "version.h"
#include "proto.h"
#include "lib/mdfour.h"
#include "lib/permstring.h"
#include "lib/addrinfo.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[];
@@ -506,13 +476,6 @@ extern int errno;
# 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))
@@ -534,14 +497,6 @@ extern int errno;
#endif
;
/* This is just like rprintf, but it also tries to print some
* representation of the error code. Normally errcode = errno. */
void rsyserr(enum logcode, int, const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 3, 4)))
#endif
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif
@@ -560,15 +515,3 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#endif
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
extern int verbose;
#ifndef HAVE_INET_NTOP
const char *
inet_ntop(int af, const void *src, char *dst, size_t size);
#endif /* !HAVE_INET_NTOP */
#ifndef HAVE_INET_PTON
int isc_net_pton(int af, const char *src, void *dst);
#endif

View File

@@ -277,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
@@ -793,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
)
@@ -962,15 +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.
rsync was written by Andrew Tridgell <tridge@samba.org> and Paul
Mackerras.
rsync is now 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)
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,25 @@ missing=0
passed=0
failed=0
scratchdir="`pwd`"/testtmp
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
clean_scratch() {
prep_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
mkdir "$scratchdir"
return 0
}
discard_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
return 0
}
if [ "x$whichtests" = x ]
@@ -179,32 +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"
clean_scratch
prep_scratch
if sh $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
then
echo "----- $testbase completed successfully"
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: log follows"
cat "$scratchdir/test.log"
echo "----- $testbase log ends"
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);

212
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
@@ -22,10 +24,18 @@
* @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"
static const char default_name[] = "UNKNOWN";
/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
static int establish_proxy_connection(int fd, char *host, int port)
@@ -34,7 +44,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;
@@ -105,7 +115,7 @@ int try_bind_local(int s,
bhints.ai_family = ai_family;
bhints.ai_socktype = ai_socktype;
bhints.ai_flags = AI_PASSIVE;
if (getaddrinfo(bind_address, NULL, &bhints, &bres_all) == -1) {
if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
bind_address, gai_strerror(error));
return -1;
@@ -150,7 +160,6 @@ int open_socket_out(char *host, int port, const char *bind_address,
int type = SOCK_STREAM;
int error;
int s;
int result;
struct addrinfo hints, *res0, *res;
char portbuf[10];
char *h;
@@ -382,7 +391,7 @@ void start_accept_loop(int port, int (*fn)(int ))
fd_set fds;
int fd;
struct sockaddr_storage addr;
int 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
@@ -565,7 +574,7 @@ void become_daemon(void)
char *client_addr(int fd)
{
struct sockaddr_storage ss;
int length = sizeof(ss);
socklen_t length = sizeof ss;
static char addr_buf[100];
static int initialised;
@@ -573,12 +582,11 @@ char *client_addr(int fd)
initialised = 1;
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
exit_cleanup(RERR_SOCKETIO);
}
client_sockaddr(fd, &ss, &length);
getnameinfo((struct sockaddr *)&ss, length,
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
return addr_buf;
}
@@ -590,26 +598,46 @@ static int get_sockaddr_family(const struct sockaddr_storage *ss)
/**
* Return the DNS name of the client
* 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;
int length = sizeof(ss);
socklen_t ss_len = 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;
strcpy(name_buf, default_name);
initialised = 1;
strcpy(name_buf,def);
client_sockaddr(fd, &ss, &ss_len);
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
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.
**/
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));
@@ -617,69 +645,141 @@ char *client_name(int fd)
}
#ifdef INET6
if (get_sockaddr_family(&ss) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
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;
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);
*ss_len = sizeof(struct sockaddr_in);
#ifdef HAVE_SOCKADDR_LEN
sin->sin_len = length;
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 */
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");
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;
}
/* forward lookup */
return 0;
}
/* Do a forward lookup on name_buf and make sure it corresponds to ss
* -- otherwise we may be being spoofed. If we suspect we are, then
* we don't abort the connection but just emit a warning. */
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 = PF_UNSPEC;
hints.ai_flags = AI_CANONNAME;
hints.ai_flags = ss_family;
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,
RSYNC_NAME ": forward name lookup for %s:%s failed: %s\n",
name_buf, port_buf,
gai_strerror(error));
return name_buf;
strcpy(name_buf, default_name);
return error;
}
/* XXX sin6_flowinfo and other fields */
/* We expect that one of the results will be the same as ss. */
for (res = res0; res; res = res->ai_next) {
if (res->ai_family != get_sockaddr_family(&ss))
if (res->ai_family != ss_family) {
rprintf(FERROR,
"check_name: response family %d != %d\n",
res->ai_family, ss_family);
continue;
if (res->ai_addrlen != length)
}
if (res->ai_addrlen != ss_len) {
rprintf(FERROR,
"check_name: addrlen %d != %d\n",
res->ai_addrlen, ss_len);
continue;
if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
}
if (memcmp(res->ai_addr, ss, res->ai_addrlen) == 0) {
rprintf(FERROR,
"check_name: %d bytes of address identical\n",
res->ai_addrlen);
break;
} else{
rprintf(FERROR,
"check_name: %d bytes of address NOT identical\n",
res->ai_addrlen);
}
}
/* TODO: Do a forward lookup as well to prevent spoofing */
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);
}
if (res == NULL) {
strcpy(name_buf, def);
rprintf(FERROR, RSYNC_NAME ": "
"reverse name lookup mismatch on fd%d - spoofed address?\n",
fd);
/* 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 name_buf;
return 0;
}
@@ -750,16 +850,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",
@@ -772,10 +876,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

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

@@ -135,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" && rsync_ls_lR . ) > ${TMP}/ls-from 2>>${log}
( cd "$3" && rsync_ls_lR . ) > ${TMP}/ls-to 2>>${log}
diff -c ${TMP}/ls-from ${TMP}/ls-to >>${log} 2>&1 || failed=YES
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
}
@@ -226,5 +222,13 @@ test_fail() {
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

@@ -18,11 +18,11 @@ build_symlinks || test_fail "failed to build symlinks"
# should be missing.
"$rsync_bin" -r "$fromdir/" "$todir" || test_fail "rsync returned $?"
[ -e "$todir/referent" ] || test_fail "referent was not copied"
[ -e "$todir/from" ] && test_fail "extra level of directories"
[ -e "$todir/dangling" ] && test_fail "dangling symlink was copied"
[ -e "$todir/relative" ] && test_fail "relative symlink was copied"
[ -e "$todir/absolute" ] && test_fail "absolute symlink was copied"
[ -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

5
tls.c
View File

@@ -1,6 +1,6 @@
/* -*- c-file-style: "linux" -*-
*
* 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
@@ -117,9 +117,10 @@ static void list_file (const char *fname)
/* NB: need to pass size as a double because it might be be
* too large for a long. */
printf("%s %12.0f %6d.%-6d %s %s%s\n",
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);
}

165
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
@@ -94,9 +92,9 @@ int fd_pair(int fd[2])
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)
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;
@@ -109,7 +107,7 @@ pid_t piped_child(char **command,int *f_in,int *f_out)
pid = do_fork();
if (pid == -1) {
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -149,12 +147,11 @@ pid_t piped_child(char **command,int *f_in,int *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) {
@@ -164,7 +161,7 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
pid = do_fork();
if (pid == -1) {
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(RERR_IPC);
}
@@ -173,10 +170,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 +269,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 +295,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
@@ -563,7 +557,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 +587,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);
@@ -811,91 +835,28 @@ int u_strcmp(const char *cs1, const char *cs2)
return (int)*s1 - (int)*s2;
}
static OFF_T last_ofs;
static struct timeval print_time;
static struct timeval start_time;
static OFF_T start_ofs;
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
{
return (t2->tv_sec - t1->tv_sec) * 1000
+ (t2->tv_usec - t1->tv_usec) / 1000;
}
/**
* @param ofs Current position in file
* @param size Total size of file
* @param is_last True if this is the last time progress will be
* printed for this file, so we should output a newline. (Not
* necessarily the same as all bytes being received.)
**/
static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
int is_last)
{
int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
unsigned long diff = msdiff(&start_time, now);
double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
const char *units, *rem_units;
double remain = rate ? (double) (size-ofs) / rate / 1000.0: 0.0;
int remain_h, remain_m, remain_s;
if (rate > 1024*1024) {
rate /= 1024.0 * 1024.0;
units = "GB/s";
} else if (rate > 1024) {
rate /= 1024.0;
units = "MB/s";
} else {
units = "kB/s";
}
remain_s = (int) remain % 60;
remain_m = (int) (remain / 60.0) % 60;
remain_h = (int) (remain / 3600.0);
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
(double) ofs, pct, rate, units,
remain_h, remain_m, remain_s,
is_last ? "\n" : "\r");
}
static OFF_T last_ofs;
void end_progress(OFF_T size)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
struct timeval now;
gettimeofday(&now, NULL);
rprint_progress(size, size, &now, True);
rprintf(FINFO,"%.0f (100%%)\n", (double)size);
}
last_ofs = 0;
start_ofs = 0;
print_time.tv_sec = print_time.tv_usec = 0;
start_time.tv_sec = start_time.tv_usec = 0;
last_ofs = 0;
}
void show_progress(OFF_T ofs, OFF_T size)
{
extern int do_progress, am_server;
struct timeval now;
gettimeofday(&now, NULL);
if (!start_time.tv_sec && !start_time.tv_usec) {
start_time.tv_sec = now.tv_sec;
start_time.tv_usec = now.tv_usec;
start_ofs = ofs;
}
if (do_progress
&& !am_server
&& ofs > last_ofs + 1000
&& msdiff(&print_time, &now) > 250) {
rprint_progress(ofs, size, &now, False);
last_ofs = ofs;
print_time.tv_sec = now.tv_sec;
print_time.tv_usec = now.tv_usec;
if (do_progress && !am_server) {
if (ofs > last_ofs + 1000) {
int pct = (int)((100.0*ofs)/size);
rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
last_ofs = ofs;
}
}
}
@@ -969,13 +930,10 @@ char *timestring(time_t t)
}
/**
* Sleep for a specified number of milliseconds.
*
* Always returns TRUE. (In the future it might return FALSE if
* interrupted.)
**/
int msleep(int t)
/*******************************************************************
sleep for a specified number of milliseconds
********************************************************************/
void msleep(int t)
{
int tdiff=0;
struct timeval tval,t1,t2;
@@ -994,8 +952,6 @@ int msleep(int t)
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
(t2.tv_usec - t1.tv_usec)/1000;
}
return True;
}
@@ -1007,6 +963,7 @@ int msleep(int t)
*******************************************************************/
int cmp_modtime(time_t file1, time_t file2)
{
time_t diff;
extern int modify_window;
if (file2 > file1) {
@@ -1030,9 +987,9 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
{
static int (*fn)();
int ret;
char *cmd;
char cmd[1024];
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'",
sprintf(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) {
@@ -1045,8 +1002,6 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
system(cmd);
free(cmd);
return ret;
}
#endif

1
version.h Normal file
View File

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