Compare commits

...

64 Commits

Author SHA1 Message Date
rsync-bugs
c239825783 preparing for release of 2.2.0 1998-11-03 22:00:59 +00:00
David Dykstra
33e817e37e Document the fact that you can use [USER@] in an rsync URL.
Note: the same thing works for ftp and http URLs in netscape.
1998-11-03 21:58:08 +00:00
David Dykstra
1b8e662a24 Call clean_fname() in sanitize_path() to catch some more strange but
legal file name syntaxes.
1998-11-03 21:49:38 +00:00
David Dykstra
2acf81eb00 Add support for optional ":PORT" in rsync URL. 1998-11-03 21:17:40 +00:00
Andrew Tridgell
654175798b patch from Alberto Accomazzi <aaccomazzi@cfa.harvard.edu> to add
different exit codes for different conditions.
1998-11-03 07:08:27 +00:00
Andrew Tridgell
3e578a1909 documented --delete disabling on IO errors 1998-11-03 05:14:41 +00:00
Andrew Tridgell
b606265491 added the --log-format option to allow users to request arbitrary
per-file logging of interactive rsync sessions.
1998-11-03 03:48:47 +00:00
Andrew Tridgell
263cf2ed55 remove double / from filenames in display 1998-11-02 07:26:36 +00:00
Andrew Tridgell
ab7104da8f the logging wasn't showing the full prefix for filenames 1998-11-02 06:40:11 +00:00
Andrew Tridgell
1b7c47cb55 Jason told me that's its very important for his site to log exactly
how many bytes were needed to be transferred for each file. I added %b
and %c log format options to cover this. See the man page for details.
1998-11-02 04:17:56 +00:00
Andrew Tridgell
039faa8660 - document the rsync:// URL format 1998-11-02 00:55:21 +00:00
Andrew Tridgell
f7632fc60d if no local destination is provided for the transfer then provide
a "ls -l" style listing of the files that would be transferred
1998-11-02 00:52:01 +00:00
Andrew Tridgell
2f098547ea added copyright notice from Patrick Powell 1998-10-31 04:35:44 +00:00
Andrew Tridgell
c7c056410c get the date comparison the right way around 1998-10-31 00:12:59 +00:00
Andrew Tridgell
e803090538 use the orig_umask when choosing perms for the log file. 1998-10-30 23:50:12 +00:00
Andrew Tridgell
6265551a5a fixed perms on rsyncd log file 1998-10-30 23:03:08 +00:00
Andrew Tridgell
958f373550 move the time init before the logfile opening. 1998-10-30 11:18:38 +00:00
Andrew Tridgell
2c51d5deec added a perl script to summarise the rsyncd log format 1998-10-30 06:12:14 +00:00
Andrew Tridgell
97cb8dc29b added %m, %P and %u options to logging 1998-10-30 05:53:05 +00:00
Andrew Tridgell
cd957c70c4 need BIG_ENDIAN test for inet_ntoa replacement 1998-10-30 02:52:42 +00:00
Andrew Tridgell
7b3d425783 check for a broken inet_ntoa() on IRIX 1998-10-30 02:50:02 +00:00
Andrew Tridgell
b24203b323 get null termination right in logging 1998-10-30 02:43:10 +00:00
Andrew Tridgell
3472009789 get null termination right in logging 1998-10-30 02:36:05 +00:00
Andrew Tridgell
f27b53f5b5 hopefuly fix logging of "transfer interrupted" messages 1998-10-30 02:32:29 +00:00
Andrew Tridgell
e08bfe1248 added "log format" option to allow admins to choose the format for
rsyncd log file entries
1998-10-30 02:24:47 +00:00
Andrew Tridgell
74e708d85a hanle null strings in -vvv output 1998-10-30 02:23:01 +00:00
Andrew Tridgell
7597e1a96a fixed cacheing of some values (using code from Samba) 1998-10-29 23:44:30 +00:00
David Dykstra
692da0b555 Fix for systems such as Unixware that have a cc that does not support -o
with -c.
1998-10-29 22:28:56 +00:00
Andrew Tridgell
67ea0d4844 put the pid on each line of the log file to facilitate
auto-parsing. Requested by Jarkko Hietaniemi (jhi@iki.fi)
1998-10-29 11:16:51 +00:00
Andrew Tridgell
9b73d1c0e9 put the pid on each line of the log file to facilitate
auto-parsing. Requested by Jarkko Hietaniemi (jhi@iki.fi)
1998-10-29 11:11:38 +00:00
Andrew Tridgell
f3737e0648 some minor optimisations 1998-10-29 06:39:43 +00:00
Andrew Tridgell
19a013837e a change I made yesterday corrupted the displayed filename in some
cases. cosmetic fix.
1998-10-29 06:10:31 +00:00
Andrew Tridgell
d730b113f4 final change needed to get rsync working on a CRAY J90 1998-10-29 05:48:11 +00:00
Andrew Tridgell
7ae359c331 kfixed char* casts 1998-10-29 05:06:51 +00:00
Andrew Tridgell
8de330a387 changes to get rsync working on a CRAY J90. This machine doesn't have
a 4 byte integer type (short is 8 bytes). I needed to use a new md4
implementation (I used the portable one I wrote for Samba).
1998-10-29 05:01:47 +00:00
Andrew Tridgell
27d3cdbc94 syslog support in rsync daemon has been broken since I added the "log
file" option. I wonder why noone reported it? Or did everyone just use
"log file" ?
1998-10-28 10:43:31 +00:00
Andrew Tridgell
106005004e fixed handling of %.0f in replacement snprintf.c 1998-10-28 04:06:43 +00:00
Andrew Tridgell
92ad2c90c4 fixed a typo 1998-10-28 03:37:53 +00:00
Andrew Tridgell
11a5a3c704 and I thought I wasn't going to do any rsync coding for a while ...
Jason Andrade convinced me to add ftpd style logging of transfers,
enabled with a "transfer logging" option in rsyncd.conf

you can customise the format in log.c
1998-10-28 03:28:30 +00:00
David Dykstra
8bb5aa8fe8 Document the fact that --numeric-ids is implied if the source system is
a daemon using chroot.
1998-10-27 17:30:28 +00:00
David Dykstra
4040be4d60 - Define bindir and mandir as per gnu makefile standards
- Add install-strip target as per gnu makefile standards
Contributed by Fred Sanchez <wsanchez@apple.com>
1998-10-27 16:07:51 +00:00
Andrew Tridgell
a9685611e2 fixed a typecast 1998-10-27 14:19:35 +00:00
Andrew Tridgell
b280a1f47e handle OSes (such as Unicos) which use a different value for S_IFLNK 1998-10-27 14:09:28 +00:00
Andrew Tridgell
f8be5ef4cb added a vsnprintf() implementation from cvslock. See the notes on the
license at the top of lib/snprintf.c
1998-10-26 23:23:45 +00:00
David Dykstra
587cb08dc4 Fix bug in --include and --include-from which didn't work as advertised;
could only include files before if "+ " was explicitly prefixed on files
from any exclude or include option.  Also simplified the code by removing
the "orig" exclude_struct element, and reduced the number of bytes
transferred from client to server by never including "- " prefixes in the
transmitted exclude list because exclusion is the default.
1998-10-26 22:03:18 +00:00
David Dykstra
8638dd48f7 Add "use chroot" and "pid file" rsyncd.conf options. The former allows one
to disable the use of chroot so rsync --daemon can be run as a non-root
user (if a non-privileged --port is used).  The latter allows one to
specify a file in which to write the process id of the daemon, which is
useful when rsync --daemon is not run from inetd.
1998-10-26 21:51:47 +00:00
David Dykstra
2bca43f627 Optimize server for special case of a long list of includes ("+") followed
by a match-all exclude "- *".
1998-10-26 21:45:23 +00:00
David Dykstra
375a4556c7 Add --compare-dest option which enables specifying an additional destination
for comparisons when syncing.  Useful for syncing into a scratch area and
doing a flash-cutover when it is completed.
1998-10-26 21:42:38 +00:00
rsync-bugs
b41c3f9273 preparing for release of 2.1.1 1998-09-09 07:07:11 +00:00
Andrew Tridgell
35bdd146e4 fixed timestring() bug 1998-09-09 07:06:44 +00:00
Andrew Tridgell
8d249b635c don't complain about not setting times on directories
because some filesystems can't do it
1998-09-09 06:37:13 +00:00
Andrew Tridgell
932be9aa52 handle sstem (sco 3) with glob but not glob.h 1998-09-09 06:31:13 +00:00
Andrew Tridgell
c6b81a9865 handle OSes where you can't rename a open file in the cleanup code. 1998-09-09 06:23:27 +00:00
Andrew Tridgell
e0414f4202 put the time in when using log file. 1998-09-09 06:06:08 +00:00
Andrew Tridgell
6e4fb64e61 added finddead target, removed dead code and made some functions
static
1998-09-09 05:57:34 +00:00
Andrew Tridgell
37863201ad doc updates 1998-09-09 05:52:25 +00:00
Andrew Tridgell
4f6325c362 added "log file" option for those systems with broken syslog (like
AIX)
1998-09-09 05:51:42 +00:00
Andrew Tridgell
f98df1d9b7 wanr people who use path names to rsync :: 1998-09-09 05:51:08 +00:00
Andrew Tridgell
3d913675a1 fixed a small memory leak when using -C
thanks to kalt@research.bell-labs.com for this fix.
1998-08-27 05:17:21 +00:00
Andrew Tridgell
2f9af90118 removed the limit on the read buffer size until I fully understand the
interactions with ssh. The old ssh freezes have shown up again and
some debugging (with help from James Welborn) showed that the cause
was the read buffer hitting maximum size. I think this means that ssh
must be misbehaving about blocking IO.

This change gets rid of the freezes at the expense of memory
usage. Where it would have frozen it uses more memory instead.
1998-08-27 05:07:52 +00:00
Andrew Tridgell
3eb388185b a couple of changes to where the nonblocking settings are called. 1998-08-27 05:05:14 +00:00
Andrew Tridgell
858fb9ebad fix PATTERN/FILE in --help output 1998-07-25 09:20:33 +00:00
Andrew Tridgell
2f03f956f4 rsync.c was getting a bit unwieldy so I split the code into 3 modules,
for the 3 logical stages of rsync; generator, sender and receiver.
1998-07-25 02:25:22 +00:00
Andrew Tridgell
0199b05f25 fixed the relative paths bug pointed out by Alberto Accomazzi 1998-07-23 03:09:14 +00:00
38 changed files with 5520 additions and 1459 deletions

View File

@@ -3,8 +3,8 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
INSTALL_BIN=$(exec_prefix)/bin
INSTALL_MAN=$(prefix)/man
bindir=@bindir@
mandir=@mandir@
LIBS=@LIBS@
CC=@CC@
@@ -12,38 +12,43 @@ CFLAGS=@CFLAGS@
INSTALLCMD=@INSTALL@
VPATH=@srcdir@
srcdir=@srcdir@
VPATH=$(srcdir)
SHELL=/bin/sh
.SUFFIXES:
.SUFFIXES: .c .o
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
zlib/zutil.o zlib/adler32.o
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
zlib/zutil.o zlib/adler32.o
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ)
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@
@OBJ_SAVE@
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: rsync
man: rsync.1 rsyncd.conf.5
install: all
-mkdir -p ${INSTALL_BIN}
${INSTALLCMD} -m 755 rsync ${INSTALL_BIN}
-mkdir -p ${INSTALL_MAN}/man1
-mkdir -p ${INSTALL_MAN}/man5
${INSTALLCMD} -m 644 $(srcdir)/rsync.1 ${INSTALL_MAN}/man1
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${INSTALL_MAN}/man5
-mkdir -p ${bindir}
${INSTALLCMD} -m 755 rsync ${bindir}
-mkdir -p ${mandir}/man1
-mkdir -p ${mandir}/man5
${INSTALLCMD} -m 644 $(srcdir)/rsync.1 ${mandir}/man1
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${mandir}/man5
install-strip:
$(MAKE) INSTALLCMD='$(INSTALLCMD) -s' install
rsync: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
@@ -58,5 +63,13 @@ proto:
cat *.c | awk -f mkproto.awk > proto.h
clean:
rm -f *~ $(OBJS) rsync config.cache config.log config.status
rm -f *~ $(OBJS) rsync
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
# dead (ie. unused) functions in the code. (tridge)
finddead:
nm *.o */*.o |grep 'U ' | awk '{print $$2}' | sort -u > nmused.txt
nm *.o */*.o |grep 'T ' | awk '{print $$3}' | sort -u > nmfns.txt
comm -13 nmused.txt nmfns.txt

View File

@@ -8,3 +8,4 @@
#undef ino_t
#undef HAVE_CONNECT
#undef HAVE_SHORT_INO_T
#undef REPLACE_INET_NTOA

23
aclocal.m4 vendored Normal file
View File

@@ -0,0 +1,23 @@
dnl AC_VALIDATE_CACHE_SYSTEM_TYPE[(cmd)]
dnl if the cache file is inconsistent with the current host,
dnl target and build system types, execute CMD or print a default
dnl error message.
AC_DEFUN(AC_VALIDATE_CACHE_SYSTEM_TYPE, [
AC_REQUIRE([AC_CANONICAL_SYSTEM])
AC_MSG_CHECKING([config.cache system type])
if { test x"${ac_cv_host_system_type+set}" = x"set" &&
test x"$ac_cv_host_system_type" != x"$host"; } ||
{ test x"${ac_cv_build_system_type+set}" = x"set" &&
test x"$ac_cv_build_system_type" != x"$build"; } ||
{ test x"${ac_cv_target_system_type+set}" = x"set" &&
test x"$ac_cv_target_system_type" != x"$target"; }; then
AC_MSG_RESULT([different])
ifelse($#, 1, [$1],
[AC_MSG_ERROR(["you must remove config.cache and restart configure"])])
else
AC_MSG_RESULT([same])
fi
ac_cv_host_system_type="$host"
ac_cv_build_system_type="$build"
ac_cv_target_system_type="$target"
])

View File

@@ -112,7 +112,7 @@ static int get_secret(int module, char *user, char *secret, int len)
}
/* generate a 16 byte hash from a password and challenge */
void generate_hash(char *in, char *challenge, char *out)
static void generate_hash(char *in, char *challenge, char *out)
{
char buf[16];

View File

@@ -49,82 +49,71 @@ uint32 get_checksum1(char *buf1,int len)
}
static void sum_put(MDstruct *md,char *sum)
{
SIVAL(sum,0,md->buffer[0]);
if (csum_length <= 4) return;
SIVAL(sum,4,md->buffer[1]);
if (csum_length <= 8) return;
SIVAL(sum,8,md->buffer[2]);
if (csum_length <= 12) return;
SIVAL(sum,12,md->buffer[3]);
}
void get_checksum2(char *buf,int len,char *sum)
{
int i;
MDstruct MD;
static char *buf1;
static int len1;
int i;
static char *buf1;
static int len1;
struct mdfour m;
if (len > len1) {
if (buf1) free(buf1);
buf1 = (char *)malloc(len+4);
len1 = len;
if (!buf1) out_of_memory("get_checksum2");
}
MDbegin(&MD);
memcpy(buf1,buf,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
MDupdate(&MD, buf1+i, CSUM_CHUNK*8);
}
if (len - i > 0)
MDupdate(&MD, buf1+i, (len-i)*8);
sum_put(&MD,sum);
if (len > len1) {
if (buf1) free(buf1);
buf1 = (char *)malloc(len+4);
len1 = len;
if (!buf1) out_of_memory("get_checksum2");
}
mdfour_begin(&m);
memcpy(buf1,buf,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
}
if (len - i > 0) {
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
}
mdfour_result(&m, (uchar *)sum);
}
void file_checksum(char *fname,char *sum,OFF_T size)
{
OFF_T i;
MDstruct MD;
struct map_struct *buf;
int fd;
OFF_T len = size;
char tmpchunk[CSUM_CHUNK];
OFF_T i;
struct map_struct *buf;
int fd;
OFF_T len = size;
char tmpchunk[CSUM_CHUNK];
struct mdfour m;
memset(sum,0,csum_length);
fd = open(fname,O_RDONLY);
if (fd == -1) return;
buf = map_file(fd,size);
mdfour_begin(&m);
memset(sum,0,csum_length);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
}
fd = open(fname,O_RDONLY);
if (fd == -1) return;
if (len - i > 0) {
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
}
buf = map_file(fd,size);
mdfour_result(&m, (uchar *)sum);
MDbegin(&MD);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
MDupdate(&MD, tmpchunk, CSUM_CHUNK*8);
}
if (len - i > 0) {
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
MDupdate(&MD, tmpchunk, (len-i)*8);
}
sum_put(&MD,sum);
close(fd);
unmap_file(buf);
close(fd);
unmap_file(buf);
}
@@ -138,58 +127,54 @@ void checksum_init(void)
static MDstruct sumMD;
static int sumresidue;
static char sumrbuf[CSUM_CHUNK];
static struct mdfour md;
void sum_init(void)
{
char s[4];
MDbegin(&sumMD);
sumresidue=0;
SIVAL(s,0,checksum_seed);
sum_update(s,4);
char s[4];
mdfour_begin(&md);
sumresidue=0;
SIVAL(s,0,checksum_seed);
sum_update(s,4);
}
void sum_update(char *p,int len)
{
int i;
if (len + sumresidue < CSUM_CHUNK) {
memcpy(sumrbuf+sumresidue, p, len);
sumresidue += len;
return;
}
int i;
if (len + sumresidue < CSUM_CHUNK) {
memcpy(sumrbuf+sumresidue, p, len);
sumresidue += len;
return;
}
if (sumresidue) {
i = MIN(CSUM_CHUNK-sumresidue,len);
memcpy(sumrbuf+sumresidue,p,i);
MDupdate(&sumMD, sumrbuf, (i+sumresidue)*8);
len -= i;
p += i;
}
if (sumresidue) {
i = MIN(CSUM_CHUNK-sumresidue,len);
memcpy(sumrbuf+sumresidue,p,i);
mdfour_update(&md, (uchar *)sumrbuf, (i+sumresidue));
len -= i;
p += i;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(sumrbuf,p+i,CSUM_CHUNK);
MDupdate(&sumMD, sumrbuf, CSUM_CHUNK*8);
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(sumrbuf,p+i,CSUM_CHUNK);
mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
}
if (len - i > 0) {
sumresidue = len-i;
memcpy(sumrbuf,p+i,sumresidue);
} else {
sumresidue = 0;
}
if (len - i > 0) {
sumresidue = len-i;
memcpy(sumrbuf,p+i,sumresidue);
} else {
sumresidue = 0;
}
}
void sum_end(char *sum)
{
if (sumresidue)
MDupdate(&sumMD, sumrbuf, sumresidue*8);
if (sumresidue) {
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
}
SIVAL(sum,0,sumMD.buffer[0]);
SIVAL(sum,4,sumMD.buffer[1]);
SIVAL(sum,8,sumMD.buffer[2]);
SIVAL(sum,12,sumMD.buffer[3]);
mdfour_result(&md, (uchar *)sum);
}

87
cleanup.c Normal file
View File

@@ -0,0 +1,87 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/* handling the cleanup when a transfer is interrupted is tricky when
--partial is selected. We need to ensure that the partial file is
kept if any real data has been transferred */
int cleanup_got_literal=0;
static char *cleanup_fname;
static char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd1, cleanup_fd2;
static struct map_struct *cleanup_buf;
static int cleanup_pid = 0;
void exit_cleanup(int code)
{
extern int keep_partial;
signal(SIGUSR1, SIG_IGN);
if (cleanup_got_literal && cleanup_fname && keep_partial) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_buf) unmap_file(cleanup_buf);
if (cleanup_fd1 != -1) close(cleanup_fd1);
if (cleanup_fd2 != -1) close(cleanup_fd2);
finish_transfer(cleanup_new_fname, fname, cleanup_file);
}
io_flush();
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code) {
kill_all(SIGUSR1);
}
if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid())) {
char *pidf = lp_pid_file();
if (pidf && *pidf) {
unlink(lp_pid_file());
}
}
if (code) log_exit(code);
exit(code);
}
void cleanup_disable(void)
{
cleanup_fname = NULL;
cleanup_got_literal = 0;
}
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
struct map_struct *buf, int fd1, int fd2)
{
cleanup_fname = fnametmp;
cleanup_new_fname = fname;
cleanup_file = file;
cleanup_buf = buf;
cleanup_fd1 = fd1;
cleanup_fd2 = fd2;
}
void cleanup_set_pid(int pid)
{
cleanup_pid = pid;
}

View File

@@ -24,6 +24,7 @@ extern int module_id;
extern int read_only;
extern int verbose;
extern int rsync_port;
char *auth_user;
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
@@ -36,6 +37,11 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
extern int am_client;
extern int am_sender;
if (*path == '/') {
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
return -1;
}
p = strchr(host, '@');
if (p) {
user = host;
@@ -50,7 +56,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
fd = open_socket_out(host, rsync_port);
if (fd == -1) {
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
server_options(sargs,&sargc);
@@ -116,7 +122,7 @@ static int rsync_module(int fd, int i)
char *addr = client_addr(fd);
char *host = client_name(fd);
char *name = lp_name(i);
char *user;
int use_chroot = lp_use_chroot(i);
int start_glob=0;
int ret;
char *request=NULL;
@@ -147,9 +153,9 @@ static int rsync_module(int fd, int i)
}
user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");
auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");
if (!user) {
if (!auth_user) {
rprintf(FERROR,"auth failed on module %s from %s (%s)\n",
name, client_name(fd), client_addr(fd));
io_printf(fd,"@ERROR: auth failed on module %s\n",name);
@@ -189,28 +195,37 @@ static int rsync_module(int fd, int i)
log_open();
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (use_chroot) {
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
}
am_root = (getuid() == 0);
@@ -252,13 +267,28 @@ static int rsync_module(int fd, int i)
}
}
if (!use_chroot) {
/*
* Note that this is applied to all parameters, whether or not
* they are filenames, but no other legal parameters contain
* the forms that need to be sanitized so it doesn't hurt;
* it is not known at this point which parameters are files
* and which aren't.
*/
for (i = 1; i < argc; i++) {
char *copy = sanitize_path(argv[i]);
free((void *)argv[i]);
argv[i] = copy;
}
}
ret = parse_arguments(argc, argv);
if (request) {
if (*user) {
if (*auth_user) {
rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n",
am_sender?"on":"to",
request, user, host, addr);
request, auth_user, host, addr);
} else {
rprintf(FINFO,"rsync %s %s from %s (%s)\n",
am_sender?"on":"to",
@@ -267,8 +297,10 @@ static int rsync_module(int fd, int i)
free(request);
}
#if !TRIDGE
/* don't allow the logs to be flooded too fast */
if (verbose > 1) verbose = 1;
#endif
argc -= optind;
argp = argv + optind;
@@ -279,7 +311,7 @@ static int rsync_module(int fd, int i)
if (!ret) {
rprintf(FERROR,"Error parsing options (unsupported option?) - aborting\n");
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
start_server(fd, fd, argc, argp);
@@ -311,7 +343,7 @@ static int start_daemon(int fd)
extern int remote_version;
if (!lp_load(config_file, 0)) {
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
set_socket_options(fd,"SO_KEEPALIVE");
@@ -321,7 +353,7 @@ static int start_daemon(int fd)
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
motd = lp_motd_file();
if (*motd) {
if (motd && *motd) {
FILE *f = fopen(motd,"r");
while (f && !feof(f)) {
int len = fread(line, 1, sizeof(line)-1, f);
@@ -374,6 +406,7 @@ static int start_daemon(int fd)
int daemon_main(void)
{
extern char *config_file;
char *pid_file;
/* this ensures that we don't call getcwd after the chroot,
which doesn't work on platforms that use popen("pwd","r")
@@ -390,6 +423,9 @@ int daemon_main(void)
close(i);
open("/dev/null", O_RDWR);
}
set_nonblocking(STDIN_FILENO);
return start_daemon(STDIN_FILENO);
}
@@ -397,13 +433,26 @@ int daemon_main(void)
if (!lp_load(config_file, 1)) {
fprintf(stderr,"failed to load config file %s\n", config_file);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
log_open();
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
FILE *f;
int pid = (int) getpid();
cleanup_set_pid(pid);
if ((f = fopen(lp_pid_file(), "w")) == NULL) {
cleanup_set_pid(0);
fprintf(stderr,"failed to create pid file %s\n", pid_file);
exit_cleanup(RERR_FILEIO);
}
fprintf(f, "%d\n", pid);
fclose(f);
}
start_accept_loop(rsync_port, start_daemon);
return -1;
}

View File

@@ -54,7 +54,7 @@ void setup_protocol(int f_out,int f_in)
remote_version > MAX_PROTOCOL_VERSION) {
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
exit_cleanup(1);
exit_cleanup(RERR_PROTOCOL);
}
if (verbose > 2)

627
config.guess vendored Executable file
View File

@@ -0,0 +1,627 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit system type (host/target name).
#
# Only a few systems have been added to this list; please add others
# (but try to keep the structure clean).
#
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
news*:NEWS-OS:6.*:*)
echo mips-sony-newsos6
exit 0 ;;
alpha:OSF1:*:*)
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit 0 ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-cbm-sysv4
exit 0;;
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
echo m68k-cbm-openbsd${UNAME_RELEASE}
exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
Pyramid*:OSx*:*:*)
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit 0 ;;
sun4*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
i86pc:SunOS:5.*:*)
echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit 0 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
atari*:NetBSD:*:*)
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*)
echo m68k-atari-openbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:OpenBSD:*:*)
echo m68k-sun-openbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:OpenBSD:*:*)
echo m68k-apple-openbsd${UNAME_RELEASE}
exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
mips:*:4*:UMIPS)
echo mips-mips-riscos4sysv
exit 0 ;;
mips:*:5*:RISCos)
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit 0 ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit 0 ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit 0 ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else echo i586-dg-dgux${UNAME_RELEASE}
fi
exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit 0 ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit 0 ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit 0 ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit 0 ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i[34]86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
sed 's/^ //' << EOF >dummy.c
#include <sys/systemcfg.h>
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit 0 ;;
*:AIX:*:4)
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=4.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit 0 ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit 0 ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit 0 ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit 0 ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit 0 ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
9000/[3478]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit 0 ;;
3050*:HI-UX:*:*)
sed 's/^ //' << EOF >dummy.c
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit 0 ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit 0 ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit 0 ;;
CRAY*T3E:*:*:*)
echo t3e-cray-unicos_mk
exit 0 ;;
CRAY*X-MP:*:*:*)
echo xmp-cray-unicos
exit 0 ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*C90:*:*:*)
echo c90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
hp3[0-9][05]:OpenBSD:*:*)
echo m68k-hp-openbsd${UNAME_RELEASE}
exit 0 ;;
i[34]86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
*:NetBSD:*:*)
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
i*:CYGWIN*:*)
echo i386-unknown-cygwin32
exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin32
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then
echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then
echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
elif test "${UNAME_MACHINE}" = "alpha" ; then
echo alpha-unknown-linux ; exit 0
else
# Either a pre-BFD a.out linker (linuxoldld) or one that does not give us
# useful --help. Gcc wants to distinguish between linuxoldld and linuxaout.
test ! -d /usr/lib/ldscripts/. \
&& echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0
# Determine whether the default compiler is a.out or elf
cat >dummy.c <<EOF
main(argc, argv)
int argc;
char *argv[];
{
#ifdef __ELF__
printf ("%s-unknown-linux\n", argv[1]);
#else
printf ("%s-unknown-linuxaout\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
i[34]86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
i[34]86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-unknown-sysv32
fi
exit 0 ;;
Intel:Mach:3*:*)
echo i386-unknown-mach3
exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
exit 0 ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit 0 ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit 0 ;;
M680[234]0:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4.3 && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
m680[234]0:LynxOS:2.[23]*:*)
echo m68k-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
i[34]86:LynxOS:2.[23]*:*)
echo i386-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
TSUNAMI:LynxOS:2.[23]*:*)
echo sparc-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
rs6000:LynxOS:2.[23]*:*)
echo rs6000-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
R3000:*System_V*:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
cat >dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3");
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-unknown-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
printf ("vax-dec-bsd\n"); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit 0 ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
c34*)
echo c34-convex-bsd
exit 0 ;;
c38*)
echo c38-convex-bsd
exit 0 ;;
c4*)
echo c4-convex-bsd
exit 0 ;;
esac
fi
#echo '(Unable to guess system type)' 1>&2
exit 1

1099
config.sub vendored Executable file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,9 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(byteorder.h)
AC_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_VALIDATE_CACHE_SYSTEM_TYPE
dnl Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
@@ -10,12 +13,14 @@ AC_SUBST(SHELL)
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH)
AC_C_BIGENDIAN
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h)
AC_CHECK_HEADERS(glob.h)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -32,16 +37,18 @@ AC_TYPE_PID_T
AC_STRUCT_ST_RDEV
AC_CHECK_TYPE(ino_t,unsigned)
echo $ac_n "checking for errno in errno.h... $ac_c"
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
echo yes; AC_DEFINE(HAVE_ERRNO_DECL),
echo no)
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
rsync_cv_errno=yes,rsync_cv_have_errno_decl=no)])
if test x"$rsync_cv_errno" = x"yes"; then
AC_DEFINE(HAVE_ERRNO_DECL)
fi
AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(mmap munmap waitpid getcwd strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes)
AC_CHECK_FUNCS(memmove getopt_long lchown vsnprintf setsid glob strpbrk)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
AC_CHECK_FUNCS(memmove getopt_long lchown vsnprintf snprintf setsid glob strpbrk)
echo $ac_n "checking for working fnmatch... $ac_c"
AC_TRY_RUN([#include <fnmatch.h>
@@ -49,18 +56,22 @@ main() { exit(fnmatch("*.o", "x.o", 0) == 0? 0: 1); }],
echo yes;AC_DEFINE(HAVE_FNMATCH),
echo no)
echo $ac_n "checking for long long ... $ac_c"
AC_CACHE_CHECK([for long long],rsync_cv_have_longlong,[
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
echo yes;AC_DEFINE(HAVE_LONGLONG),
echo no)
rsync_cv_have_longlong=yes,rsync_cv_have_longlong=no,rsync_cv_have_longlong=cross)])
if test x"$rsync_cv_have_longlong" = x"yes"; then
AC_DEFINE(HAVE_LONGLONG)
fi
echo $ac_n "checking for off64_t ... $ac_c"
AC_CACHE_CHECK([for off64_t],rsync_cv_HAVE_OFF64_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/stat.h>
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) return 1; exit((lstat64("/dev/null", &st)==0)?0:1); }],
echo yes;AC_DEFINE(HAVE_OFF64_T),
echo no)
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }],
rsync_cv_HAVE_OFF64_T=yes,rsync_cv_HAVE_OFF64_T=no,rsync_cv_HAVE_OFF64_T=cross)])
if test x"$rsync_cv_HAVE_OFF64_T" = x"yes"; then
AC_DEFINE(HAVE_OFF64_T)
fi
echo $ac_n "checking for short ino_t ... $ac_c"
AC_TRY_RUN([#include <stdio.h>
@@ -70,27 +81,48 @@ main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
echo yes;AC_DEFINE(HAVE_SHORT_INO_T),
echo no)
echo $ac_n "checking for unsigned char ... $ac_c"
AC_CACHE_CHECK([for unsigned char],rsync_cv_HAVE_UNSIGNED_CHAR,[
AC_TRY_RUN([#include <stdio.h>
main() { char c; c=250; exit((c > 0)?0:1); }],
echo yes;AC_DEFINE(HAVE_UNSIGNED_CHAR),
echo no)
rsync_cv_HAVE_UNSIGNED_CHAR=yes,rsync_cv_HAVE_UNSIGNED_CHAR=no,rsync_cv_HAVE_UNSIGNED_CHAR=cross)])
if test x"$rsync_cv_HAVE_UNSIGNED_CHAR" = x"yes"; then
AC_DEFINE(HAVE_UNSIGNED_CHAR)
fi
echo $ac_n "checking for broken readdir ... $ac_c"
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
AC_TRY_RUN([#include <sys/types.h>
#include <dirent.h>
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) return 0; return 1;} ],
echo yes - you are using the broken /usr/ucb/cc;AC_DEFINE(HAVE_BROKEN_READDIR),
echo no)
di->d_name[0] == 0) exit(0); exit(1);} ],
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR)
fi
echo $ac_n "checking for utimbuf ... $ac_c"
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; return utime("foo.c",&tbuf);],
echo yes;AC_DEFINE(HAVE_UTIMBUF),
echo no)
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no,rsync_cv_HAVE_UTIMBUF=cross)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF)
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
exit(1);}],
rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA)
fi
# The following test taken from the cvs sources
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
@@ -98,30 +130,58 @@ echo no)
# libsocket.so which has a bad implementation of gethostbyname (it
# only looks in /etc/hosts), so we only look for -lsocket if we need
# it.
AC_CHECK_FUNC(connect, :,
[case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl_s, printf) ;;
esac
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl, printf) ;;
esac
case "$LIBS" in
*-lsocket*) ;;
*) AC_CHECK_LIB(socket, connect) ;;
esac
case "$LIBS" in
*-linet*) ;;
*) AC_CHECK_LIB(inet, connect) ;;
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test "$ac_cv_lib_socket_connect" = "yes" ||
test "$ac_cv_lib_inet_connect" = "yes"; then
ac_cv_func_connect=yes
AC_DEFINE(HAVE_CONNECT)
fi])
AC_CHECK_FUNCS(connect)
if test x"$ac_cv_func_connect" = x"no"; then
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl_s, printf) ;;
esac
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl, printf) ;;
esac
case "$LIBS" in
*-lsocket*) ;;
*) AC_CHECK_LIB(socket, connect) ;;
esac
case "$LIBS" in
*-linet*) ;;
*) AC_CHECK_LIB(inet, connect) ;;
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
AC_DEFINE(HAVE_CONNECT)
fi
fi
#
# The following test was mostly taken from the tcl/tk plus patches
#
echo $ac_n "checking whether -c -o works ... $ac_c"
rm -rf conftest*
cat > conftest.$ac_ext <<EOF
int main() { return 0; }
EOF
${CC-cc} -c -o conftest..o conftest.$ac_ext
if test -f conftest..o; then
OBJ_SAVE="#"
OBJ_RESTORE="#"
CC_SHOBJ_FLAG='-o $@'
echo yes
else
OBJ_SAVE=' @b=`basename $@ .o`;rm -f $$b.o.sav;if test -f $$b.o; then mv $$b.o $$b.o.sav;fi;'
OBJ_RESTORE=' @b=`basename $@ .o`;if test "$$b.o" != "$@"; then mv $$b.o $@; if test -f $$b.o.sav; then mv $$b.o.sav $$b.o; fi; fi'
CC_SHOBJ_FLAG=""
echo no
fi
rm -rf conftest*
AC_SUBST(OBJ_SAVE)
AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_OUTPUT(Makefile lib/dummy zlib/dummy)

18
errcode.h Normal file
View File

@@ -0,0 +1,18 @@
/* error codes returned by rsync */
#define RERR_SYNTAX 1 /* syntax or usage error */
#define RERR_PROTOCOL 2 /* protocol incompatibility */
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
#define RERR_NOSUPPORT 4 /* requested action not supported */
#define RERR_SOCKETIO 10 /* error in socket IO */
#define RERR_FILEIO 11 /* error in file IO */
#define RERR_STREAMIO 12 /* error in rsync protocol data stream */
#define RERR_MESSAGEIO 13 /* errors with program diagnostics */
#define RERR_IPC 14 /* error in IPC code */
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */

View File

@@ -26,6 +26,47 @@ extern int verbose;
static struct exclude_struct **exclude_list;
/*
* Optimization for special case when all included files are explicitly
* listed without wildcards in the "exclude" list followed by a "- *"
* to exclude the rest.
* Contributed by Dave Dykstra <dwd@bell-labs.com>
*/
static int only_included_files = 1;
static struct exclude_struct *exclude_the_rest;
int send_included_file_names(int f,struct file_list *flist)
{
struct exclude_struct *ex, **ex_list;
int n;
char *p;
if (!only_included_files || (exclude_the_rest == NULL))
return 0;
if (verbose > 1) {
rprintf(FINFO,"(using include-only optimization) ");
}
/* set exclude_list to NULL temporarily so check_exclude */
/* will always return true */
ex_list = exclude_list;
exclude_list = NULL;
for (n=0; (ex = ex_list[n]) != NULL; n++) {
if (ex == exclude_the_rest)
break;
p = ex->pattern;
while (*p == '/') {
/* skip the allowed beginning slashes */
p++;
}
send_file_name(f,flist,p,0,0);
}
exclude_list = ex_list;
return 1;
}
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(char *pattern, int include)
{
@@ -36,8 +77,6 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
memset(ret, 0, sizeof(*ret));
ret->orig = strdup(pattern);
if (strncmp(pattern,"- ",2) == 0) {
pattern += 2;
} else if (strncmp(pattern,"+ ",2) == 0) {
@@ -49,9 +88,18 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
ret->pattern = strdup(pattern);
if (!ret->orig || !ret->pattern) out_of_memory("make_exclude");
if (!ret->pattern) out_of_memory("make_exclude");
if (strpbrk(pattern, "*[?")) ret->regular_exp = 1;
if (strpbrk(pattern, "*[?")) {
if (!ret->include && (*pattern == '*') && (*(pattern+1) == '\0')) {
exclude_the_rest = ret;
} else {
only_included_files = 0;
}
ret->regular_exp = 1;
} else if (!ret->include) {
only_included_files = 0;
}
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
ret->pattern[strlen(pattern)-1] = 0;
@@ -67,7 +115,6 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
static void free_exclude(struct exclude_struct *ex)
{
free(ex->orig);
free(ex->pattern);
memset(ex,0,sizeof(*ex));
free(ex);
@@ -143,6 +190,8 @@ void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
}
free((*list));
*list = NULL;
only_included_files = 1;
exclude_the_rest = NULL;
return;
}
@@ -172,7 +221,7 @@ struct exclude_struct **make_exclude_list(char *fname,
if (!f) {
if (fatal) {
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
}
return list;
}
@@ -207,23 +256,21 @@ void send_exclude_list(int f)
}
for (i=0;exclude_list[i];i++) {
char *pattern = exclude_list[i]->orig;
char *pattern = exclude_list[i]->pattern;
int l;
if (remote_version < 19) {
if (strncmp(pattern,"+ ", 2)==0) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
exit_cleanup(1);
}
if (strncmp(pattern,"- ", 2) == 0) {
pattern += 2;
}
}
l = strlen(pattern);
if (l == 0) continue;
write_int(f,l);
if (exclude_list[i]->include) {
if (remote_version < 19) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
exit_cleanup(RERR_NOSUPPORT);
}
write_int(f,l+2);
write_buf(f,"+ ",2);
} else {
write_int(f,l);
}
write_buf(f,pattern,l);
}

View File

@@ -136,7 +136,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
}
if (munmap(map->map, map->p_len) != 0) {
rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_MALLOC);
}
/* align the mmap region on a nice boundary back a bit from
@@ -186,7 +186,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
rprintf(FERROR,"lseek failed in map_ptr\n");
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
}
if ((nread=read(map->fd,map->p,len)) != len) {

147
flist.c
View File

@@ -49,6 +49,38 @@ extern int io_error;
static struct exclude_struct **local_exclude_list;
static void clean_flist(struct file_list *flist, int strip_root);
static void list_file_entry(struct file_struct *f)
{
char perms[11] = "----------";
char *perm_map = "rwxrwxrwx";
int i;
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,
(double)f->length, timestring(f->modtime),
f_name(f), f->link);
} else {
rprintf(FINFO,"%s %11.0f %s %s\n",
perms,
(double)f->length, timestring(f->modtime), f_name(f));
}
}
int link_stat(const char *Path, STRUCT_STAT *Buffer)
{
#if SUPPORT_LINKS
@@ -87,12 +119,29 @@ static void set_filesystem(char *fname)
}
static int to_wire_mode(mode_t mode)
{
if (S_ISLNK(mode) && (S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | 0120000;
}
return (int)mode;
}
static mode_t from_wire_mode(int mode)
{
if ((mode & (_S_IFMT)) == 0120000 && (S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | S_IFLNK;
}
return (mode_t)mode;
}
static void send_directory(int f,struct file_list *flist,char *dir);
static char *flist_dir;
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
static void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
{
unsigned char flags;
static time_t last_time;
@@ -145,7 +194,7 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
if (!(flags & SAME_TIME))
write_int(f,(int)file->modtime);
if (!(flags & SAME_MODE))
write_int(f,(int)file->mode);
write_int(f,to_wire_mode(file->mode));
if (preserve_uid && !(flags & SAME_UID)) {
add_uid(file->uid);
write_int(f,(int)file->uid);
@@ -225,12 +274,6 @@ static void receive_file_entry(struct file_struct **fptr,
clean_fname(thisname);
if (relative_paths && thisname[0] == '/') {
/* strip / off absolute paths in destination */
memmove(thisname, thisname+1, strlen(thisname));
if (!thisname[0]) strcpy(thisname,".");
}
if ((p = strrchr(thisname,'/'))) {
static char *lastdir;
*p = 0;
@@ -252,7 +295,7 @@ static void receive_file_entry(struct file_struct **fptr,
file->flags = flags;
file->length = read_longint(f);
file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : from_wire_mode(read_int(f));
if (preserve_uid)
file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
if (preserve_gid)
@@ -436,7 +479,7 @@ static struct file_struct *make_file(char *fname)
static void send_file_name(int f,struct file_list *flist,char *fname,
void send_file_name(int f,struct file_list *flist,char *fname,
int recursive, unsigned base_flags)
{
struct file_struct *file;
@@ -502,6 +545,8 @@ static void send_directory(int f,struct file_list *flist,char *dir)
}
p = fname + strlen(fname);
local_exclude_list = NULL;
if (cvs_exclude) {
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
strcpy(p,".cvsignore");
@@ -521,6 +566,10 @@ static void send_directory(int f,struct file_list *flist,char *dir)
send_file_name(f,flist,fname,recurse,0);
}
if (local_exclude_list) {
add_exclude_list("!", &local_exclude_list, 0);
}
closedir(d);
}
@@ -530,7 +579,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
{
int i,l;
STRUCT_STAT st;
char *p,*dir;
char *p,*dir,*olddir;
char lastpath[MAXPATHLEN]="";
struct file_list *flist;
int64 start_write;
@@ -578,6 +627,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
dir = NULL;
olddir = NULL;
if (!relative_paths) {
p = strrchr(fname,'/');
@@ -613,7 +663,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
fname = ".";
if (dir && *dir) {
char *olddir = push_dir(dir, 1);
olddir = push_dir(dir, 1);
if (!olddir) {
io_error=1;
@@ -623,21 +673,22 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
flist_dir = dir;
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(1);
}
continue;
}
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
if (!recurse || !send_included_file_names(f,flist))
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
if (olddir != NULL) {
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
}
}
if (f != -1) {
@@ -647,7 +698,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (verbose && recurse && !am_server && f != -1)
rprintf(FINFO,"done\n");
clean_flist(flist);
clean_flist(flist, 0);
/* now send the uid/gid list. This was introduced in protocol
version 15 */
@@ -678,6 +729,7 @@ struct file_list *recv_file_list(int f)
struct file_list *flist;
unsigned char flags;
int64 start_read;
extern int list_only;
if (verbose && recurse && !am_server) {
rprintf(FINFO,"receiving file list ... ");
@@ -728,7 +780,7 @@ struct file_list *recv_file_list(int f)
if (verbose > 2)
rprintf(FINFO,"received %d names\n",flist->count);
clean_flist(flist);
clean_flist(flist, relative_paths);
if (verbose && recurse && !am_server) {
rprintf(FINFO,"done\n");
@@ -744,6 +796,14 @@ struct file_list *recv_file_list(int f)
io_error |= read_int(f);
}
if (list_only) {
int i;
for (i=0;i<flist->count;i++) {
list_file_entry(flist->files[i]);
}
}
if (verbose > 2)
rprintf(FINFO,"recv_file_list done\n");
@@ -826,7 +886,7 @@ void flist_free(struct file_list *flist)
* This routine ensures we don't have any duplicate names in our file list.
* duplicate names can cause corruption because of the pipelining
*/
void clean_flist(struct file_list *flist)
static void clean_flist(struct file_list *flist, int strip_root)
{
int i;
@@ -848,6 +908,37 @@ void clean_flist(struct file_list *flist)
free_file(flist->files[i]);
}
}
if (strip_root) {
/* we need to strip off the root directory in the case
of relative paths, but this must be done _after_
the sorting phase */
for (i=0;i<flist->count;i++) {
if (flist->files[i]->dirname &&
flist->files[i]->dirname[0] == '/') {
memmove(&flist->files[i]->dirname[0],
&flist->files[i]->dirname[1],
strlen(flist->files[i]->dirname));
}
if (flist->files[i]->dirname &&
!flist->files[i]->dirname[0]) {
flist->files[i]->dirname = NULL;
}
}
}
if (verbose <= 3) return;
for (i=0;i<flist->count;i++) {
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n",
getpid(), i,
NS(flist->files[i]->dirname),
NS(flist->files[i]->basename),
flist->files[i]->mode,
(int)flist->files[i]->length);
}
}
@@ -865,7 +956,9 @@ char *f_name(struct file_struct *f)
n = (n+1)%10;
if (f->dirname) {
slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename);
strlcpy(p, f->dirname, MAXPATHLEN-1);
strlcat(p, "/", MAXPATHLEN-1);
strlcat(p, f->basename, MAXPATHLEN-1);
} else {
strlcpy(p, f->basename, MAXPATHLEN-1);
}

420
generator.c Normal file
View File

@@ -0,0 +1,420 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int relative_paths;
extern int preserve_links;
extern int am_root;
extern int preserve_devices;
extern int preserve_hard_links;
extern int update_only;
extern int whole_file;
extern int block_size;
extern int csum_length;
extern int ignore_times;
extern int io_timeout;
extern int remote_version;
extern int always_checksum;
/* choose whether to skip a particular file */
static int skip_file(char *fname,
struct file_struct *file, STRUCT_STAT *st)
{
if (st->st_size != file->length) {
return 0;
}
/* if always checksum is set then we use the checksum instead
of the file time to determine whether to sync */
if (always_checksum && S_ISREG(st->st_mode)) {
char sum[MD4_SUM_LENGTH];
file_checksum(fname,sum,st->st_size);
return (memcmp(sum,file->sum,csum_length) == 0);
}
if (ignore_times) {
return 0;
}
return (st->st_mtime == file->modtime);
}
/* use a larger block size for really big files */
static int adapt_block_size(struct file_struct *file, int bsize)
{
int ret;
if (bsize != BLOCK_SIZE) return bsize;
ret = file->length / (10000); /* rough heuristic */
ret = ret & ~15; /* multiple of 16 */
if (ret < bsize) ret = bsize;
if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
return ret;
}
/*
send a sums struct down a fd
*/
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)
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);
}
}
/*
generate a stream of signatures/checksums that describe a buffer
generate approximately one checksum every n bytes
*/
static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
{
int i;
struct sum_struct *s;
int count;
int block_len = n;
int remainder = (len%block_len);
OFF_T offset = 0;
count = (len+(block_len-1))/block_len;
s = (struct sum_struct *)malloc(sizeof(*s));
if (!s) out_of_memory("generate_sums");
s->count = count;
s->remainder = remainder;
s->n = n;
s->flength = len;
if (count==0) {
s->sums = NULL;
return s;
}
if (verbose > 3)
rprintf(FINFO,"count=%d rem=%d n=%d flength=%d\n",
s->count,s->remainder,s->n,(int)s->flength);
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
if (!s->sums) out_of_memory("generate_sums");
for (i=0;i<count;i++) {
int n1 = MIN(len,n);
char *map = map_ptr(buf,offset,n1);
s->sums[i].sum1 = get_checksum1(map,n1);
get_checksum2(map,n1,s->sums[i].sum2);
s->sums[i].offset = offset;
s->sums[i].len = n1;
s->sums[i].i = i;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] offset=%d len=%d sum1=%08x\n",
i,(int)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
len -= n1;
offset += n1;
}
return s;
}
void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
{
int fd;
STRUCT_STAT st;
struct map_struct *buf;
struct sum_struct *s;
int statret;
struct file_struct *file = flist->files[i];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
extern char *compare_dest;
extern int list_only;
if (list_only) return;
if (verbose > 2)
rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
statret = link_stat(fname,&st);
if (S_ISDIR(file->mode)) {
if (dry_run) return;
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (do_unlink(fname) != 0) {
rprintf(FERROR,"unlink %s : %s\n",fname,strerror(errno));
return;
}
statret = -1;
}
if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
if (!(relative_paths && errno==ENOENT &&
create_directory_path(fname)==0 &&
do_mkdir(fname,file->mode)==0)) {
rprintf(FERROR,"mkdir %s : %s (2)\n",
fname,strerror(errno));
}
}
if (set_perms(fname,file,NULL,0) && verbose)
rprintf(FINFO,"%s/\n",fname);
return;
}
if (preserve_links && S_ISLNK(file->mode)) {
#if SUPPORT_LINKS
char lnk[MAXPATHLEN];
int l;
extern int safe_symlinks;
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
if (verbose) {
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
fname,file->link);
}
return;
}
if (statret == 0) {
l = readlink(fname,lnk,MAXPATHLEN-1);
if (l > 0) {
lnk[l] = 0;
if (strcmp(lnk,file->link) == 0) {
set_perms(fname,file,&st,1);
return;
}
}
}
delete_file(fname);
if (do_symlink(file->link,fname) != 0) {
rprintf(FERROR,"link %s -> %s : %s\n",
fname,file->link,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose) {
rprintf(FINFO,"%s -> %s\n",
fname,file->link);
}
}
#endif
return;
}
#ifdef HAVE_MKNOD
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
if (statret != 0 ||
st.st_mode != file->mode ||
st.st_rdev != file->rdev) {
delete_file(fname);
if (verbose > 2)
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
fname,(int)file->mode,(int)file->rdev);
if (do_mknod(fname,file->mode,file->rdev) != 0) {
rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose)
rprintf(FINFO,"%s\n",fname);
}
} else {
set_perms(fname,file,&st,1);
}
return;
}
#endif
if (preserve_hard_links && check_hard_link(file)) {
if (verbose > 1)
rprintf(FINFO,"%s is a hard link\n",f_name(file));
return;
}
if (!S_ISREG(file->mode)) {
rprintf(FINFO,"skipping non-regular file %s\n",fname);
return;
}
fnamecmp = fname;
if ((statret == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
int saveerrno = errno;
slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s",compare_dest,fname);
statret = link_stat(fnamecmpbuf,&st);
if (!S_ISREG(st.st_mode))
statret = -1;
if (statret == -1)
errno = saveerrno;
else
fnamecmp = fnamecmpbuf;
}
if (statret == -1) {
if (errno == ENOENT) {
write_int(f_out,i);
if (!dry_run) send_sums(NULL,f_out);
} else {
if (verbose > 1)
rprintf(FERROR,"recv_generator failed to open %s\n",fname);
}
return;
}
if (!S_ISREG(st.st_mode)) {
if (delete_file(fname) != 0) {
return;
}
/* now pretend the file didn't exist */
write_int(f_out,i);
if (!dry_run) send_sums(NULL,f_out);
return;
}
if (update_only && st.st_mtime > file->modtime && fnamecmp == fname) {
if (verbose > 1)
rprintf(FINFO,"%s is newer\n",fname);
return;
}
if (skip_file(fname, file, &st)) {
set_perms(fname,file,&st,1);
return;
}
if (dry_run) {
write_int(f_out,i);
return;
}
if (whole_file) {
write_int(f_out,i);
send_sums(NULL,f_out);
return;
}
/* open the file */
fd = open(fnamecmp,O_RDONLY);
if (fd == -1) {
rprintf(FERROR,"failed to open %s : %s\n",fnamecmp,strerror(errno));
rprintf(FERROR,"skipping %s\n",fname);
return;
}
if (st.st_size > 0) {
buf = map_file(fd,st.st_size);
} else {
buf = NULL;
}
if (verbose > 3)
rprintf(FINFO,"gen mapped %s of size %d\n",fnamecmp,(int)st.st_size);
s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
if (verbose > 2)
rprintf(FINFO,"sending sums for %d\n",i);
write_int(f_out,i);
send_sums(s,f_out);
close(fd);
if (buf) unmap_file(buf);
free_sums(s);
}
void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
{
int i;
int phase=0;
if (verbose > 2)
rprintf(FINFO,"generator starting pid=%d count=%d\n",
(int)getpid(),flist->count);
for (i = 0; i < flist->count; i++) {
struct file_struct *file = flist->files[i];
mode_t saved_mode = file->mode;
if (!file->basename) continue;
/* we need to ensure that any directories we create have writeable
permissions initially so that we can create the files within
them. This is then fixed after the files are transferred */
if (!am_root && S_ISDIR(file->mode)) {
file->mode |= S_IWUSR; /* user write */
}
recv_generator(local_name?local_name:f_name(file),
flist,i,f);
file->mode = saved_mode;
}
phase++;
csum_length = SUM_LENGTH;
ignore_times=1;
if (verbose > 2)
rprintf(FINFO,"generate_files phase=%d\n",phase);
write_int(f,-1);
/* we expect to just sit around now, so don't exit on a
timeout. If we really get a timeout then the other process should
exit */
io_timeout = 0;
if (remote_version >= 13) {
/* in newer versions of the protocol the files can cycle through
the system more than once to catch initial checksum errors */
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
struct file_struct *file = flist->files[i];
recv_generator(local_name?local_name:f_name(file),
flist,i,f);
}
phase++;
if (verbose > 2)
rprintf(FINFO,"generate_files phase=%d\n",phase);
write_int(f,-1);
}
}

43
io.c
View File

@@ -60,7 +60,7 @@ static void check_timeout(void)
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
exit_cleanup(1);
exit_cleanup(RERR_TIMEOUT);
}
}
@@ -100,7 +100,6 @@ static int read_timeout(int fd, char *buf, int len)
n = read(fd, buf, len);
if (n > 0) {
stats.total_read += n;
buf += n;
len -= n;
ret += n;
@@ -126,11 +125,11 @@ static int read_timeout(int fd, char *buf, int len)
if (eof_error) {
rprintf(FERROR,"unexpected EOF in read_timeout\n");
}
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
rprintf(FERROR,"read error: %s\n", strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
return ret;
@@ -182,13 +181,13 @@ static int read_unbuffered(int fd, char *buf, int len)
if (tag != FERROR && tag != FINFO) {
rprintf(FERROR,"unexpected tag %d\n", tag);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (remaining > sizeof(line)-1) {
rprintf(FERROR,"multiplexing overflow %d\n\n",
remaining);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
@@ -264,14 +263,20 @@ static void readfd(int fd,char *buffer,int N)
ret = read_unbuffered(fd,buffer + total,N-total);
total += ret;
}
stats.total_read += total;
}
int32 read_int(int f)
{
char b[4];
int32 ret;
readfd(f,b,4);
return IVAL(b,0);
ret = IVAL(b,0);
if (ret == (int32)0xffffffff) return -1;
return ret;
}
int64 read_longint(int f)
@@ -281,11 +286,13 @@ int64 read_longint(int f)
char b[8];
ret = read_int(f);
if ((int32)ret != (int32)0xffffffff) return ret;
if ((int32)ret != (int32)0xffffffff) {
return ret;
}
#ifdef NO_INT64
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
exit_cleanup(1);
exit_cleanup(RERR_UNSUPPORTED);
#else
if (remote_version >= 16) {
readfd(f,b,8);
@@ -337,8 +344,7 @@ static void writefd_unbuffered(int fd,char *buf,int len)
fd_count = fd+1;
if (!no_flush_read) {
reading = (buffer_f_in != -1 &&
read_buffer_len < MAX_READ_BUFFER);
reading = (buffer_f_in != -1);
}
if (reading) {
@@ -380,12 +386,11 @@ static void writefd_unbuffered(int fd,char *buf,int len)
if (ret <= 0) {
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
blocked = 0;
total += ret;
stats.total_written += ret;
if (io_timeout)
last_io = time(NULL);
@@ -436,6 +441,8 @@ void io_end_buffering(int fd)
static void writefd(int fd,char *buf,int len)
{
stats.total_written += len;
if (!io_buffer) {
writefd_unbuffered(fd, buf, len);
return;
@@ -472,7 +479,7 @@ void write_longint(int f, int64 x)
return;
}
write_int(f, -1);
write_int(f, (int32)0xFFFFFFFF);
SIVAL(b,0,(x&0xFFFFFFFF));
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
@@ -485,7 +492,7 @@ void write_buf(int f,char *buf,int len)
}
/* write a string to the connection */
void write_sbuf(int f,char *buf)
static void write_sbuf(int f,char *buf)
{
write_buf(f, buf, strlen(buf));
}
@@ -534,7 +541,7 @@ void io_printf(int fd, const char *format, ...)
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);
if (len < 0) exit_cleanup(RERR_STREAMIO);
write_sbuf(fd, buf);
}
@@ -556,7 +563,7 @@ void io_start_multiplex_in(int fd)
io_flush();
if (read_buffer_len) {
fprintf(stderr,"ERROR: data in read buffer at mplx start\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
io_multiplexing_in = 1;
@@ -572,6 +579,8 @@ int io_multiplex_write(int f, char *buf, int len)
SIVAL(io_buffer-4, 0, ((MPLEX_BASE + f)<<24) + len);
memcpy(io_buffer, buf, len);
stats.total_written += (len+4);
writefd_unbuffered(multiplex_out_fd, io_buffer-4, len+4);
return 1;
}

View File

@@ -76,3 +76,19 @@ char *strpbrk(const char *s, const char *accept)
return NULL;
}
#endif
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#if WORDS_BIGENDIAN
slprintf(buf, 17, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
slprintf(buf, 17, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif

278
lib/mdfour.c Normal file
View File

@@ -0,0 +1,278 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/* NOTE: This code makes no attempt to be fast!
It assumes that a int is at least 32 bits long
*/
static struct mdfour *m;
static inline uint32 F(uint32 X, uint32 Y, uint32 Z)
{
return (X&Y) | ((~X)&Z);
}
static inline uint32 G(uint32 X, uint32 Y, uint32 Z)
{
return (X&Y) | (X&Z) | (Y&Z);
}
static inline uint32 H(uint32 X, uint32 Y, uint32 Z)
{
return X^Y^Z;
}
static inline uint32 lshift(uint32 x, int s)
{
#ifdef LARGE_INT32
x &= 0xFFFFFFFF;
return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
#else
return ((x<<s) | (x>>(32-s)));
#endif
}
#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s)
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s)
/* this applies md4 to 64 byte chunks */
static void mdfour64(uint32 *M)
{
int j;
uint32 AA, BB, CC, DD;
uint32 X[16];
uint32 A,B,C,D;
for (j=0;j<16;j++)
X[j] = M[j];
A = m->A; B = m->B; C = m->C; D = m->D;
AA = A; BB = B; CC = C; DD = D;
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
A += AA; B += BB; C += CC; D += DD;
#ifdef LARGE_INT32
A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
#endif
for (j=0;j<16;j++)
X[j] = 0;
m->A = A; m->B = B; m->C = C; m->D = D;
}
static void copy64(uint32 *M, unsigned char *in)
{
int i;
for (i=0;i<16;i++)
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
(in[i*4+1]<<8) | (in[i*4+0]<<0);
}
static void copy4(unsigned char *out,uint32 x)
{
out[0] = x&0xFF;
out[1] = (x>>8)&0xFF;
out[2] = (x>>16)&0xFF;
out[3] = (x>>24)&0xFF;
}
void mdfour_begin(struct mdfour *md)
{
md->A = 0x67452301;
md->B = 0xefcdab89;
md->C = 0x98badcfe;
md->D = 0x10325476;
md->totalN = 0;
}
static void mdfour_tail(unsigned char *in, int n)
{
unsigned char buf[128];
uint32 M[16];
uint32 b;
m->totalN += n;
b = m->totalN * 8;
memset(buf, 0, 128);
if (n) memcpy(buf, in, n);
buf[n] = 0x80;
if (n <= 55) {
copy4(buf+56, b);
copy64(M, buf);
mdfour64(M);
} else {
copy4(buf+120, b);
copy64(M, buf);
mdfour64(M);
copy64(M, buf+64);
mdfour64(M);
}
}
void mdfour_update(struct mdfour *md, unsigned char *in, int n)
{
uint32 M[16];
if (n == 0) mdfour_tail(in, n);
m = md;
while (n >= 64) {
copy64(M, in);
mdfour64(M);
in += 64;
n -= 64;
m->totalN += 64;
}
if (n) mdfour_tail(in, n);
}
void mdfour_result(struct mdfour *md, unsigned char *out)
{
m = md;
copy4(out, m->A);
copy4(out+4, m->B);
copy4(out+8, m->C);
copy4(out+12, m->D);
}
void mdfour(unsigned char *out, unsigned char *in, int n)
{
struct mdfour md;
mdfour_begin(&md);
mdfour_update(&md, in, n);
mdfour_result(&md, out);
}
#ifdef TEST_MDFOUR
static void file_checksum1(char *fname)
{
int fd, i;
struct mdfour md;
unsigned char buf[64], sum[16];
fd = open(fname,O_RDONLY);
if (fd == -1) {
perror("fname");
exit(1);
}
mdfour_begin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
mdfour_update(&md, buf, n);
}
close(fd);
mdfour_result(&md, sum);
for (i=0;i<16;i++)
printf("%02X", sum[i]);
printf("\n");
}
#include "../md4.h"
static void file_checksum2(char *fname)
{
int fd, i;
MDstruct md;
unsigned char buf[64], sum[16];
fd = open(fname,O_RDONLY);
if (fd == -1) {
perror("fname");
exit(1);
}
MDbegin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
MDupdate(&md, buf, n*8);
}
if (!md.done) {
MDupdate(&md, buf, 0);
}
close(fd);
memcpy(sum, md.buffer, 16);
for (i=0;i<16;i++)
printf("%02X", sum[i]);
printf("\n");
}
int main(int argc, char *argv[])
{
file_checksum1(argv[1]);
file_checksum2(argv[1]);
return 0;
}
#endif

34
lib/mdfour.h Normal file
View File

@@ -0,0 +1,34 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct mdfour {
uint32 A, B, C, D;
uint32 totalN;
};
void mdfour_begin(struct mdfour *md);
void mdfour_update(struct mdfour *md, unsigned char *in, int n);
void mdfour_result(struct mdfour *md, unsigned char *out);
void mdfour(unsigned char *out, unsigned char *in, int n);

820
lib/snprintf.c Normal file
View File

@@ -0,0 +1,820 @@
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.anu.edu.au) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
**************************************************************/
#include "config.h"
#include <string.h>
# include <ctype.h>
#include <sys/types.h>
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
/* Define this as a fall through, HAVE_STDARG_H is probably already set */
#define HAVE_VARARGS_H
/* varargs declarations: */
#if defined(HAVE_STDARG_H)
# include <stdarg.h>
# define HAVE_STDARGS /* let's hope that works everywhere (mj) */
# define VA_LOCAL_DECL va_list ap
# define VA_START(f) va_start(ap, f)
# define VA_SHIFT(v,t) ; /* no-op for ANSI */
# define VA_END va_end(ap)
#else
# if defined(HAVE_VARARGS_H)
# include <varargs.h>
# undef HAVE_STDARGS
# define VA_LOCAL_DECL va_list ap
# define VA_START(f) va_start(ap) /* f is ignored! */
# define VA_SHIFT(v,t) v = va_arg(ap,t)
# define VA_END va_end(ap)
# else
/*XX ** NO VARARGS ** XX*/
# endif
#endif
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
/*int snprintf (char *str, size_t count, const char *fmt, ...);*/
/*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
static void dopr (char *buffer, size_t maxlen, const char *format,
va_list args);
static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
#define DP_C_LONG 2
#define DP_C_LDOUBLE 3
#define char_to_int(p) (p - '0')
#define MAX(p,q) ((p >= q) ? p : q)
static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
{
char ch;
long value;
LDOUBLE fvalue;
char *strvalue;
int min;
int max;
int state;
int flags;
int cflags;
size_t currlen;
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
max = -1;
ch = *format++;
while (state != DP_S_DONE)
{
if ((ch == '\0') || (currlen >= maxlen))
state = DP_S_DONE;
switch(state)
{
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
dopr_outch (buffer, &currlen, maxlen, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch)
{
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch))
{
min = 10*min + char_to_int (ch);
ch = *format++;
}
else if (ch == '*')
{
min = va_arg (args, int);
ch = *format++;
state = DP_S_DOT;
}
else
state = DP_S_DOT;
break;
case DP_S_DOT:
if (ch == '.')
{
state = DP_S_MAX;
ch = *format++;
}
else
state = DP_S_MOD;
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch))
{
if (max < 0)
max = 0;
max = 10*max + char_to_int (ch);
ch = *format++;
}
else if (ch == '*')
{
max = va_arg (args, int);
ch = *format++;
state = DP_S_MOD;
}
else
state = DP_S_MOD;
break;
case DP_S_MOD:
/* Currently, we don't support Long Long, bummer */
switch (ch)
{
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch)
{
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
value = va_arg (args, short int);
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else
value = va_arg (args, int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned short int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned short int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
case 'x':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned short int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
/* um, floating point? */
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'E':
flags |= DP_F_UP;
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'G':
flags |= DP_F_UP;
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'c':
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
if (max < 0)
max = maxlen; /* ie, no max */
fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
break;
case 'p':
strvalue = va_arg (args, void *);
fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
break;
case 'n':
if (cflags == DP_C_SHORT)
{
short int *num;
num = va_arg (args, short int *);
*num = currlen;
}
else if (cflags == DP_C_LONG)
{
long int *num;
num = va_arg (args, long int *);
*num = (long int)currlen;
}
else
{
int *num;
num = va_arg (args, int *);
*num = currlen;
}
break;
case '%':
dopr_outch (buffer, &currlen, maxlen, ch);
break;
case 'w':
/* not supported yet, treat as next char */
ch = *format++;
break;
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else
buffer[maxlen - 1] = '\0';
}
static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
if (value == 0)
{
value = "<NULL>";
}
for (strln = 0; value[strln]; ++strln); /* strlen */
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while ((padlen > 0) && (cnt < max))
{
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
++cnt;
}
while (*value && (cnt < max))
{
dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
while ((padlen < 0) && (cnt < max))
{
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
++cnt;
}
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned long uvalue;
char convert[20];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
if (max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED))
{
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
}
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else
if (flags & DP_F_SPACE)
signvalue = ' ';
}
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < 20));
if (place == 20) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0) zpadlen = 0;
if (spadlen < 0) spadlen = 0;
if (flags & DP_F_ZERO)
{
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while (spadlen > 0)
{
dopr_outch (buffer, currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
/* Zeros */
if (zpadlen > 0)
{
while (zpadlen > 0)
{
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while (place > 0)
dopr_outch (buffer, currlen, maxlen, convert[--place]);
/* Left Justified spaces */
while (spadlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++spadlen;
}
}
static LDOUBLE abs_val (LDOUBLE value)
{
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE pow10 (int exp)
{
LDOUBLE result = 1;
while (exp)
{
result *= 10;
exp--;
}
return result;
}
static long round (LDOUBLE value)
{
long intpart;
intpart = (long)value;
value = value - intpart;
if (value >= 0.5)
intpart++;
return intpart;
}
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
{
int signvalue = 0;
LDOUBLE ufvalue;
char iconvert[20];
char fconvert[20];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
long intpart;
long fracpart;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (max < 0)
max = 6;
ufvalue = abs_val (fvalue);
if (fvalue < 0)
signvalue = '-';
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else
if (flags & DP_F_SPACE)
signvalue = ' ';
#if 0
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
intpart = (long)ufvalue;
/*
* Sorry, we only support 9 digits past the decimal because of our
* conversion method
*/
if (max > 9)
max = 9;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
fracpart = round ((pow10 (max)) * (ufvalue - intpart));
if (fracpart >= pow10 (max))
{
intpart++;
fracpart -= pow10 (max);
}
#ifdef DEBUG_SNPRINTF
printf("fmtfp: %g %d.%d min=%d max=%d\n",
(double)fvalue, intpart, fracpart, min, max);
#endif
/* Convert integer part */
do {
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
intpart = (intpart / 10);
} while(intpart && (iplace < 20));
if (iplace == 20) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
do {
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
fracpart = (fracpart / 10);
} while(fracpart && (fplace < 20));
if (fplace == 20) fplace--;
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0)
zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0))
{
if (signvalue)
{
dopr_outch (buffer, currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0)
{
dopr_outch (buffer, currlen, maxlen, '0');
--padlen;
}
}
while (padlen > 0)
{
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
while (iplace > 0)
dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0) {
dopr_outch (buffer, currlen, maxlen, '.');
while (fplace > 0)
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
}
while (zpadlen > 0)
{
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
while (padlen < 0)
{
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
}
}
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
{
if (*currlen < maxlen)
buffer[(*currlen)++] = c;
}
#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
#ifndef HAVE_VSNPRINTF
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
str[0] = 0;
dopr(str, count, fmt, args);
return(strlen(str));
}
#endif /* !HAVE_VSNPRINTF */
#ifndef HAVE_SNPRINTF
/* VARARGS3 */
#ifdef HAVE_STDARGS
int snprintf (char *str,size_t count,const char *fmt,...)
#else
int snprintf (va_alist) va_dcl
#endif
{
#ifndef HAVE_STDARGS
char *str;
size_t count;
char *fmt;
#endif
VA_LOCAL_DECL;
VA_START (fmt);
VA_SHIFT (str, char *);
VA_SHIFT (count, size_t );
VA_SHIFT (fmt, char *);
(void) vsnprintf(str, count, fmt, ap);
VA_END;
return(strlen(str));
}
#else
/* keep compilers happy about empty files */
void dummy_snprintf(void) {}
#endif /* !HAVE_SNPRINTF */
#ifdef TEST_SNPRINTF
#ifndef LONG_STRING
#define LONG_STRING 1024
#endif
int main (void)
{
char buf1[LONG_STRING];
char buf2[LONG_STRING];
char *fp_fmt[] = {
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%.1f",
NULL
};
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
NULL
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
int x, y;
int fail = 0;
int num = 0;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] != NULL ; x++)
for (y = 0; fp_nums[y] != 0 ; y++)
{
snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
fp_fmt[x], buf1, buf2);
fail++;
}
num++;
}
for (x = 0; int_fmt[x] != NULL ; x++)
for (y = 0; int_nums[y] != 0 ; y++)
{
snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
int_fmt[x], buf1, buf2);
fail++;
}
num++;
}
printf ("%d tests failed out of %d.\n", fail, num);
}
#endif /* SNPRINTF_TEST */

View File

@@ -98,6 +98,8 @@ typedef struct
{
char *motd_file;
char *lock_file;
char *log_file;
char *pid_file;
int syslog_facility;
int max_connections;
char *socket_options;
@@ -117,6 +119,8 @@ typedef struct
char *comment;
BOOL read_only;
BOOL list;
BOOL use_chroot;
BOOL transfer_logging;
char *uid;
char *gid;
char *hosts_allow;
@@ -125,6 +129,7 @@ typedef struct
char *secrets_file;
char *exclude;
char *exclude_from;
char *log_format;
} service;
@@ -136,6 +141,8 @@ static service sDefault =
NULL, /* comment */
True, /* read only */
True, /* list */
True, /* use chroot */
False, /* transfer logging */
"nobody",/* uid */
"nobody",/* gid */
NULL, /* hosts allow */
@@ -144,6 +151,7 @@ static service sDefault =
NULL, /* secrets file */
NULL, /* exclude */
NULL, /* exclude from */
"%o %h [%a] %m (%u) %f %l", /* log format */
};
@@ -231,12 +239,15 @@ static struct parm_struct parm_table[] =
{"lock file", P_STRING, P_GLOBAL, &Globals.lock_file, NULL, 0},
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
{"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
@@ -245,6 +256,8 @@ static struct parm_struct parm_table[] =
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
};
@@ -295,6 +308,8 @@ static void init_locals(void)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
@@ -304,6 +319,8 @@ FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
@@ -312,6 +329,7 @@ FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
FN_LOCAL_STRING(lp_log_format, log_format)
/* local prototypes */
static int strwicmp( char *psz1, char *psz2 );
@@ -340,7 +358,7 @@ static void string_set(char **s, char *v)
return;
}
*s = strdup(v);
if (!*s) exit_cleanup(1);
if (!*s) exit_cleanup(RERR_MALLOC);
}

227
log.c
View File

@@ -23,16 +23,46 @@
*/
#include "rsync.h"
static FILE *logfile;
static void logit(int priority, char *buf)
{
if (logfile) {
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
} else {
syslog(priority, "%s", buf);
}
}
void log_open(void)
{
static int initialised;
int options = LOG_PID;
time_t t;
char *logf;
if (initialised) return;
initialised = 1;
/* this looks pointless, but it is needed in order for the
C library on some systems to fetch the timezone info
before the chroot */
t = time(NULL);
localtime(&t);
/* optionally use a log file instead of syslog */
logf = lp_log_file();
if (logf && *logf) {
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logf, "a");
umask(old_umask);
return;
}
#ifdef LOG_NDELAY
options |= LOG_NDELAY;
#endif
@@ -44,19 +74,13 @@ void log_open(void)
#endif
#ifndef LOG_NDELAY
syslog(LOG_INFO,"rsyncd started\n");
logit(LOG_INFO,"rsyncd started\n");
#endif
/* this looks pointless, but it is needed in order for the
C library on some systems to fetch the timezone info
before the chroot */
t = time(NULL);
localtime(&t);
}
/* this is the rsync debugging function. Call it with FINFO or FERROR */
void rprintf(int fd, const char *format, ...)
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
void rprintf(int fd, const char *format, ...)
{
va_list ap;
char buf[1024];
@@ -64,29 +88,34 @@ void rprintf(int fd, const char *format, ...)
FILE *f=NULL;
extern int am_daemon;
/* recursion can happen with certain fatal conditions */
static int depth;
if (depth) return;
depth++;
va_start(ap, format);
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
if (len > sizeof(buf)-1) exit_cleanup(1);
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
buf[len] = 0;
if (fd == FLOG) {
if (am_daemon) logit(LOG_INFO, buf);
return;
}
if (am_daemon) {
static int depth;
int priority = LOG_INFO;
if (fd == FERROR) priority = LOG_WARNING;
if (depth) return;
depth++;
log_open();
if (!io_multiplex_write(fd, buf, strlen(buf))) {
syslog(priority, "%s", buf);
logit(priority, buf);
}
depth--;
@@ -105,13 +134,11 @@ void rprintf(int fd, const char *format, ...)
f = stdout;
}
if (!f) exit_cleanup(1);
if (!f) exit_cleanup(RERR_MESSAGEIO);
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
depth--;
}
void rflush(int fd)
@@ -123,6 +150,10 @@ void rflush(int fd)
return;
}
if (fd == FLOG) {
return;
}
if (fd == FERROR) {
f = stderr;
}
@@ -135,7 +166,159 @@ void rflush(int fd)
f = stdout;
}
if (!f) exit_cleanup(1);
if (!f) exit_cleanup(RERR_MESSAGEIO);
fflush(f);
}
/* a generic logging routine for send/recv, with parameter
substitiution */
static void log_formatted(int fd,
char *format, char *op, struct file_struct *file,
struct stats *initial_stats)
{
extern int module_id;
extern char *auth_user;
char buf[1024];
char buf2[1024];
char *p, *s, *n;
int l;
extern struct stats stats;
extern int am_sender;
int64 b;
strlcpy(buf, format, sizeof(buf)-1);
for (s=&buf[0];
s && (p=strchr(s,'%')); ) {
n = NULL;
s = p + 1;
switch (p[1]) {
case 'h': n = client_name(0); break;
case 'a': n = client_addr(0); break;
case 'l':
slprintf(buf2,sizeof(buf2)-1,"%.0f",
(double)file->length);
n = buf2;
break;
case 'p':
slprintf(buf2,sizeof(buf2)-1,"%d",
(int)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'f':
slprintf(buf2, sizeof(buf2)-1, "%s/%s",
file->basedir?file->basedir:"",
f_name(file));
clean_fname(buf2);
n = buf2;
if (*n == '/') n++;
break;
case 'm': n = lp_name(module_id); break;
case 't': n = timestring(time(NULL)); break;
case 'P': n = lp_path(module_id); break;
case 'u': n = auth_user; break;
case 'b':
if (am_sender) {
b = stats.total_written -
initial_stats->total_written;
} else {
b = stats.total_read -
initial_stats->total_read;
}
slprintf(buf2,sizeof(buf2)-1,"%.0f", (double)b);
n = buf2;
break;
case 'c':
if (!am_sender) {
b = stats.total_written -
initial_stats->total_written;
} else {
b = stats.total_read -
initial_stats->total_read;
}
slprintf(buf2,sizeof(buf2)-1,"%.0f", (double)b);
n = buf2;
break;
}
if (!n) continue;
l = strlen(n);
if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
}
if (l != 2) {
memmove(s+(l-1), s+1, strlen(s+1)+1);
}
memcpy(p, n, l);
s = p+l;
}
rprintf(fd,"%s\n", buf);
}
/* log the outgoing transfer of a file */
void log_send(struct file_struct *file, struct stats *initial_stats)
{
extern int module_id;
extern int am_server;
extern char *log_format;
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, "send", file, initial_stats);
}
}
/* log the incoming transfer of a file */
void log_recv(struct file_struct *file, struct stats *initial_stats)
{
extern int module_id;
extern int am_server;
extern char *log_format;
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, "send", file, initial_stats);
}
}
/* called when the transfer is interrupted for some reason */
void log_exit(int code)
{
if (code == 0) {
extern struct stats stats;
rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
} else {
rprintf(FLOG,"transfer interrupted (code %d)\n", code);
}
}
/* log the incoming transfer of a file for interactive use, this
will be called at the end where the client was run
it i called when a file starts to be transferred
*/
void log_transfer(struct file_struct *file, char *fname)
{
extern int verbose;
if (!verbose) return;
rprintf(FINFO,"%s\n", fname);
}

83
main.c
View File

@@ -36,10 +36,7 @@ static void report(int f)
extern int do_stats;
if (am_daemon) {
syslog(LOG_INFO,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
log_exit(0);
if (f == -1 || !am_sender) return;
}
@@ -181,13 +178,13 @@ static char *get_local_name(struct file_list *flist,char *name)
if (!push_dir(name, 0)) {
rprintf(FERROR,"push_dir %s : %s (1)\n",
name,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
return NULL;
}
if (flist->count > 1) {
rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
return name;
}
@@ -200,7 +197,7 @@ static char *get_local_name(struct file_list *flist,char *name)
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
} else {
if (verbose > 0)
rprintf(FINFO,"created directory %s\n",name);
@@ -209,7 +206,7 @@ static char *get_local_name(struct file_list *flist,char *name)
if (!push_dir(name, 0)) {
rprintf(FERROR,"push_dir %s : %s (2)\n",
name,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
return NULL;
@@ -231,7 +228,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
if (!relative_paths && !push_dir(dir, 0)) {
rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
argc--;
argv++;
@@ -250,15 +247,15 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
argv[0] = ".";
}
set_nonblocking(f_out);
if (f_in != f_out)
set_nonblocking(f_in);
flist = send_file_list(f_out,argc,argv);
if (!flist || flist->count == 0) {
exit_cleanup(0);
}
set_nonblocking(f_out);
if (f_in != f_out)
set_nonblocking(f_in);
send_files(flist,f_out,f_in);
report(f_out);
io_flush();
@@ -278,7 +275,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
if (pipe(recv_pipe) < 0) {
rprintf(FERROR,"pipe failed in do_recv\n");
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
io_flush();
@@ -288,6 +285,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
if (f_in != f_out) close(f_out);
set_nonblocking(f_in);
set_nonblocking(recv_pipe[1]);
recv_files(f_in,flist,local_name,recv_pipe[1]);
report(f_in);
@@ -301,6 +299,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
if (f_in != f_out) close(f_in);
set_nonblocking(f_out);
set_nonblocking(recv_pipe[0]);
io_start_buffering(f_out);
@@ -331,7 +330,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
if (!am_daemon && !push_dir(dir, 0)) {
rprintf(FERROR,"push_dir %s : %s (4)\n",
dir,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
}
@@ -341,7 +340,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
flist = recv_file_list(f_in);
if (!flist || flist->count == 0) {
rprintf(FERROR,"server_recv: nothing to do\n");
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
if (argc > 0) {
@@ -362,8 +361,12 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
extern int cvs_exclude;
extern int am_sender;
set_nonblocking(f_out);
if (f_in != f_out)
set_nonblocking(f_in);
setup_protocol(f_out, f_in);
if (am_sender) {
recv_exclude_list(f_in);
if (cvs_exclude)
@@ -381,6 +384,7 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
int status = 0, status2 = 0;
char *local_name = NULL;
extern int am_sender;
extern int list_only;
setup_protocol(f_out,f_in);
@@ -409,6 +413,8 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
report(-1);
exit_cleanup(status);
}
if (argc == 0) list_only = 1;
send_exclude_list(f_out);
@@ -458,6 +464,26 @@ static int start_client(int argc, char *argv[])
extern int local_server;
extern int am_sender;
extern char *shell_cmd;
extern int rsync_port;
if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
char *host, *path;
host = argv[0] + strlen(URL_PREFIX);
p = strchr(host,'/');
if (p) {
*p = 0;
path = p+1;
} else {
path="";
}
p = strchr(host,':');
if (p) {
rsync_port = atoi(p+1);
*p = 0;
}
return start_socket_client(host, path, argc-1, argv+1);
}
p = find_colon(argv[0]);
@@ -467,9 +493,9 @@ static int start_client(int argc, char *argv[])
return start_socket_client(argv[0], p+2, argc-1, argv+1);
}
if (argc < 2) {
if (argc < 1) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
am_sender = 0;
@@ -491,7 +517,7 @@ static int start_client(int argc, char *argv[])
if (argc < 2) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
if (local_server) {
@@ -522,9 +548,9 @@ static int start_client(int argc, char *argv[])
shell_path?shell_path:"");
}
if (!am_sender && argc != 1) {
if (!am_sender && argc > 1) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
@@ -538,8 +564,8 @@ static int start_client(int argc, char *argv[])
}
RETSIGTYPE sigusr1_handler(int val) {
exit_cleanup(1);
static RETSIGTYPE sigusr1_handler(int val) {
exit_cleanup(RERR_SIGNAL);
}
int main(int argc,char *argv[])
@@ -559,7 +585,7 @@ int main(int argc,char *argv[])
if (argc < 2) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
/* we set a 0 umask so that correct file permissions can be
@@ -567,7 +593,7 @@ int main(int argc,char *argv[])
orig_umask = (int)umask(0);
if (!parse_arguments(argc, argv)) {
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
argc -= optind;
@@ -578,6 +604,7 @@ int main(int argc,char *argv[])
signal(SIGINT,SIGNAL_CAST sig_int);
signal(SIGPIPE,SIGNAL_CAST sig_int);
signal(SIGHUP,SIGNAL_CAST sig_int);
signal(SIGTERM,SIGNAL_CAST sig_int);
if (am_daemon) {
return daemon_main();
@@ -585,7 +612,7 @@ int main(int argc,char *argv[])
if (argc < 1) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
if (dry_run)
@@ -594,7 +621,7 @@ int main(int argc,char *argv[])
#ifndef SUPPORT_LINKS
if (!am_server && preserve_links) {
rprintf(FERROR,"ERROR: symbolic links not supported\n");
exit_cleanup(1);
exit_cleanup(RERR_UNSUPPORTED);
}
#endif

4
md4.c
View File

@@ -102,7 +102,7 @@
** Assumes X is an array of 16 ints.
** The macro revx reverses the byte-ordering of the next word of X.
*/
void MDreverse(X)
static void MDreverse(X)
unsigned int32 *X;
{ register unsigned int32 t;
register unsigned int i;
@@ -225,7 +225,7 @@
/* Process data */
if (count == 512)
{ /* Full block of data to handle */
MDblock(MDp,(unsigned int *)X);
MDblock(MDp,(unsigned int32 *)X);
}
else if (count > 512) /* Check for count too large */
{ rprintf(FERROR,"\nError: MDupdate called with illegal count value %d."

View File

@@ -64,15 +64,17 @@ int block_size=BLOCK_SIZE;
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
char *compare_dest = NULL;
char *config_file = RSYNCD_CONF;
char *shell_cmd = NULL;
char *log_format = NULL;
char *rsync_path = RSYNC_NAME;
int rsync_port = RSYNC_PORT;
int verbose = 0;
int always_checksum = 0;
int list_only = 0;
void usage(int F)
{
@@ -86,6 +88,7 @@ void usage(int F)
rprintf(F," or rsync [OPTION]... SRC DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC DEST\n");
rprintf(F," or rsync [OPTION]... SRC [USER@]HOST::DEST\n");
rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC DEST\n");
rprintf(F,"\nOptions\n");
rprintf(F," -v, --verbose increase verbosity\n");
rprintf(F," -c, --checksum always checksum\n");
@@ -118,11 +121,12 @@ void usage(int F)
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
rprintf(F," -z, --compress compress file data\n");
rprintf(F," --exclude=PATTERN exclude file FILE\n");
rprintf(F," --exclude-from=PATTERN exclude files listed in FILE\n");
rprintf(F," --include=PATTERN don't exclude file FILE\n");
rprintf(F," --include-from=PATTERN don't exclude files listed in FILE\n");
rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
rprintf(F," --suffix=SUFFIX override backup suffix\n");
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
@@ -130,6 +134,7 @@ void usage(int F)
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
rprintf(F," --stats give some file transfer stats\n");
rprintf(F," --progress show progress during transfer\n");
rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
rprintf(F," -h, --help show this help screen\n");
rprintf(F,"\n");
@@ -144,7 +149,7 @@ enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
OPT_SAFE_LINKS};
OPT_SAFE_LINKS, OPT_COMPARE_DEST, OPT_LOG_FORMAT};
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
@@ -188,6 +193,7 @@ static struct option long_options[] = {
{"block-size", 1, 0, 'B'},
{"timeout", 1, 0, OPT_TIMEOUT},
{"temp-dir", 1, 0, 'T'},
{"compare-dest", 1, 0, OPT_COMPARE_DEST},
{"compress", 0, 0, 'z'},
{"daemon", 0, 0, OPT_DAEMON},
{"stats", 0, 0, OPT_STATS},
@@ -195,6 +201,7 @@ static struct option long_options[] = {
{"partial", 0, 0, OPT_PARTIAL},
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{"log-format", 1, 0, OPT_LOG_FORMAT},
{0,0,0,0}};
@@ -355,7 +362,7 @@ int parse_arguments(int argc, char *argv[])
case OPT_SENDER:
if (!am_server) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
am_sender = 1;
break;
@@ -384,6 +391,10 @@ int parse_arguments(int argc, char *argv[])
tmpdir = optarg;
break;
case OPT_COMPARE_DEST:
compare_dest = optarg;
break;
case 'z':
do_compression = 1;
break;
@@ -412,6 +423,10 @@ int parse_arguments(int argc, char *argv[])
rsync_port = atoi(optarg);
break;
case OPT_LOG_FORMAT:
log_format = optarg;
break;
default:
return 0;
}
@@ -516,6 +531,16 @@ void server_options(char **args,int *argc)
args[ac++] = tmpdir;
}
if (compare_dest && am_sender) {
/* the server only needs this option if it is not the sender,
* and it may be an older version that doesn't know this
* option, so don't send it if client is the sender.
*/
args[ac++] = "--compare-dest";
args[ac++] = compare_dest;
}
*argc = ac;
}

View File

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

471
receiver.c Normal file
View File

@@ -0,0 +1,471 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int recurse;
extern int delete_mode;
extern int remote_version;
extern int csum_length;
extern struct stats stats;
extern int dry_run;
extern int am_server;
extern int relative_paths;
extern int preserve_hard_links;
extern int cvs_exclude;
extern int io_error;
extern char *tmpdir;
extern char *compare_dest;
static struct delete_list {
dev_t dev;
INO_T inode;
} *delete_list;
static int dlist_len, dlist_alloc_len;
/* yuck! This function wouldn't have been necessary if I had the sorting
algorithm right. Unfortunately fixing the sorting algorithm would introduce
a backward incompatibility as file list indexes are sent over the link.
*/
static int delete_already_done(struct file_list *flist,int j)
{
int i;
STRUCT_STAT st;
if (link_stat(f_name(flist->files[j]), &st)) return 1;
for (i=0;i<dlist_len;i++) {
if (st.st_ino == delete_list[i].inode &&
st.st_dev == delete_list[i].dev)
return 1;
}
return 0;
}
static void add_delete_entry(struct file_struct *file)
{
if (dlist_len == dlist_alloc_len) {
dlist_alloc_len += 1024;
delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
if (!delete_list) out_of_memory("add_delete_entry");
}
delete_list[dlist_len].dev = file->dev;
delete_list[dlist_len].inode = file->inode;
dlist_len++;
if (verbose > 3)
rprintf(FINFO,"added %s to delete list\n", f_name(file));
}
static void delete_one(struct file_struct *f)
{
if (!S_ISDIR(f->mode)) {
if (do_unlink(f_name(f)) != 0) {
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,"rmdir %s : %s\n",f_name(f),strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting directory %s\n",f_name(f));
}
}
}
/* this deletes any files on the receiving side that are not present
on the sending side. For version 1.6.4 I have changed the behaviour
to match more closely what most people seem to expect of this option */
static void delete_files(struct file_list *flist)
{
struct file_list *local_file_list;
int i, j;
char *name;
if (cvs_exclude)
add_cvs_excludes();
if (io_error) {
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
return;
}
for (j=0;j<flist->count;j++) {
if (!S_ISDIR(flist->files[j]->mode) ||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
if (remote_version < 19 &&
delete_already_done(flist, j)) continue;
name = strdup(f_name(flist->files[j]));
if (!(local_file_list = send_file_list(-1,1,&name))) {
free(name);
continue;
}
if (verbose > 1)
rprintf(FINFO,"deleting in %s\n", name);
for (i=local_file_list->count-1;i>=0;i--) {
if (!local_file_list->files[i]->basename) continue;
if (remote_version < 19 &&
S_ISDIR(local_file_list->files[i]->mode))
add_delete_entry(local_file_list->files[i]);
if (-1 == flist_find(flist,local_file_list->files[i])) {
delete_one(local_file_list->files[i]);
}
}
flist_free(local_file_list);
free(name);
}
}
static int get_tmpname(char *fnametmp, char *fname)
{
char *f;
/* open tmp file */
if (tmpdir) {
f = strrchr(fname,'/');
if (f == NULL)
f = fname;
else
f++;
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
f = strrchr(fname,'/');
if (strlen(fname)+9 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
if (f) {
*f = 0;
slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname);
}
return 1;
}
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;
OFF_T offset = 0;
OFF_T offset2;
char *data;
static char file_sum1[MD4_SUM_LENGTH];
static char file_sum2[MD4_SUM_LENGTH];
char *map=NULL;
count = read_int(f_in);
n = read_int(f_in);
remainder = read_int(f_in);
sum_init();
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
show_progress(offset, total_size);
if (i > 0) {
extern int cleanup_got_literal;
if (verbose > 3) {
rprintf(FINFO,"data recv %d at %d\n",
i,(int)offset);
}
stats.literal_data += i;
cleanup_got_literal = 1;
sum_update(data,i);
if (fd != -1 && write_file(fd,data,i) != i) {
rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
offset += i;
continue;
}
i = -(i+1);
offset2 = i*n;
len = n;
if (i == count-1 && remainder != 0)
len = remainder;
stats.matched_data += len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
i,len,(int)offset2,(int)offset);
map = map_ptr(buf,offset2,len);
see_token(map, len);
sum_update(map,len);
if (fd != -1 && write_file(fd,map,len) != len) {
rprintf(FERROR,"write failed on %s : %s\n",
fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
offset += len;
}
end_progress();
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
rprintf(FERROR,"write failed on %s : %s\n",
fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
sum_end(file_sum1);
if (remote_version >= 14) {
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
if (verbose > 2) {
rprintf(FINFO,"got file_sum\n");
}
if (fd != -1 &&
memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
return 0;
}
}
return 1;
}
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 fnametmp[MAXPATHLEN];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
struct map_struct *buf;
int i;
struct file_struct *file;
int phase=0;
int recv_ok;
extern struct stats stats;
struct stats initial_stats;
if (verbose > 2) {
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
if (recurse && delete_mode && !local_name && flist->count>0) {
delete_files(flist);
}
while (1) {
cleanup_disable();
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO,"recv_files phase=%d\n",phase);
write_int(f_gen,-1);
continue;
}
break;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
i, flist->count);
exit_cleanup(RERR_PROTOCOL);
}
file = flist->files[i];
fname = f_name(file);
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
if (local_name)
fname = local_name;
if (dry_run) {
if (!am_server) {
log_transfer(file, fname);
}
continue;
}
initial_stats = stats;
if (verbose > 2)
rprintf(FINFO,"recv_files(%s)\n",fname);
fnamecmp = fname;
/* open the file */
fd1 = open(fnamecmp,O_RDONLY);
if ((fd1 == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s",
compare_dest,fname);
fnamecmp = fnamecmpbuf;
fd1 = open(fnamecmp,O_RDONLY);
}
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
receive_data(f_in,NULL,-1,NULL,file->length);
close(fd1);
continue;
}
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
receive_data(f_in,NULL,-1,NULL,file->length);
close(fd1);
continue;
}
if (fd1 != -1 && st.st_size > 0) {
buf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %d\n",fnamecmp,(int)st.st_size);
} else {
buf = NULL;
}
if (!get_tmpname(fnametmp,fname)) {
if (buf) unmap_file(buf);
if (fd1 != -1) close(fd1);
continue;
}
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
condition. They are then correctly updated after
the lchown. Thanks to snabb@epipe.fi for pointing
this out */
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & ACCESSPERMS);
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp) == 0) {
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & ACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL,file->length);
if (buf) unmap_file(buf);
if (fd1 != -1) close(fd1);
continue;
}
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
if (!am_server) {
log_transfer(file, fname);
}
/* recv file data */
recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
log_recv(file, &initial_stats);
if (buf) unmap_file(buf);
if (fd1 != -1) {
close(fd1);
}
close(fd2);
if (verbose > 2)
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
finish_transfer(fname, fnametmp, file);
cleanup_disable();
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
fname);
} else {
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
write_int(f_gen,i);
}
}
}
if (preserve_hard_links)
do_hard_links(flist);
/* now we need to fix any directory permissions that were
modified during the transfer */
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
if (!file->basename || !S_ISDIR(file->mode)) continue;
recv_generator(f_name(file),flist,i,-1);
}
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");
return 0;
}

1051
rsync.c
View File

File diff suppressed because it is too large Load Diff

47
rsync.h
View File

@@ -23,6 +23,8 @@
#define RSYNC_NAME "rsync"
#define RSYNCD_CONF "/etc/rsyncd.conf"
#define URL_PREFIX "rsync://"
#define BACKUP_SUFFIX "~"
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
@@ -59,6 +61,9 @@
#define MPLEX_BASE 7
#define FERROR 1
#define FINFO 2
#define FLOG 3
#include "errcode.h"
#include "config.h"
@@ -169,7 +174,7 @@
#include "lib/fnmatch.h"
#endif
#ifdef HAVE_GLOB
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
@@ -204,14 +209,6 @@
#endif
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
#endif
#define BOOL int
#ifndef uchar
@@ -231,6 +228,10 @@
#define int32 long
#elif (SIZEOF_SHORT == 4)
#define int32 short
#else
/* I hope this works */
#define int32 int
#define LARGE_INT32
#endif
#endif
@@ -364,7 +365,7 @@ static inline int flist_up(struct file_list *flist, int i)
#include "byteorder.h"
#include "version.h"
#include "proto.h"
#include "md4.h"
#include "lib/mdfour.h"
#if !HAVE_STRERROR
extern char *sys_errlist[];
@@ -409,6 +410,18 @@ extern int errno;
#define S_IWUSR 0200
#endif
#ifndef _S_IFMT
#define _S_IFMT 0170000
#endif
#ifndef _S_IFLNK
#define _S_IFLNK 0120000
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (((mode) & (_S_IFMT)) == (_S_IFLNK))
#endif
#ifndef S_ISBLK
#define S_ISBLK(mode) (((mode) & (_S_IFMT)) == (_S_IFBLK))
#endif
@@ -447,3 +460,17 @@ extern int errno;
#ifndef ACCESSPERMS
#define ACCESSPERMS 0777
#endif
/* handler for null strings in printf format */
#define NS(s) ((s)?(s):"<NULL>")
/* use magic gcc attributes to catch format errors */
void rprintf(int , const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
#endif
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif

View File

@@ -9,9 +9,11 @@ rsync [options] path [user@]host:path
rsync [options] path path
rsync [options] [user@]host::path path
rsync [options] [user@]host::module[/path] path
rsync [options] path [user@]host::path
rsync [options] path [user@]host::module[/path]
rsync [options] rsync://[user@]host[:port]/module/path path
manpagedescription()
@@ -40,7 +42,7 @@ itemize(
manpagesection(GENERAL)
There are five different ways of using rsync. They are:
There are six different ways of using rsync. They are:
itemize(
it() for copying local files. This is invoked when neither
@@ -57,11 +59,16 @@ itemize(
it() for copying from a remote rsync server to the local
machine. This is invoked when the source path contains a ::
separator.
separator. You can also use a rsync:// URL if no username
is required.
it() for copying from the local machine to a remote rsync
server. This is invoked when the destination path contains a ::
separator.
it() for listing files on a remote machine. This is done the
same way as rsync transfers except that you leave off the
local destination.
)
Note that in all cases at least one of the source and destination
@@ -140,6 +147,9 @@ itemize(
it() if you specify no path name on the remote server then the
list of accessible paths on the server will be shown.
it() if you specify no local destination then a listing of the
specified files on the remote server is provided
)
Some paths on the remote server may require authentication. If so then
@@ -198,6 +208,7 @@ Usage: rsync [OPTION]... SRC [USER@]HOST:DEST
or rsync [OPTION]... SRC DEST
or rsync [OPTION]... [USER@]HOST::SRC DEST
or rsync [OPTION]... SRC [USER@]HOST::DEST
or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC DEST
Options
-v, --verbose increase verbosity
@@ -231,11 +242,12 @@ Options
--timeout=TIME set IO timeout in seconds
-I, --ignore-times don't exclude files that match length and time
-T --temp-dir=DIR create temporary files in directory DIR
--compare-dest=DIR also compare destination files relative to DIR
-z, --compress compress file data
--exclude=PATTERN exclude file FILE
--exclude-from=PATTERN exclude files listed in FILE
--include=PATTERN don't exclude file FILE
--include-from=PATTERN don't exclude files listed in FILE
--exclude=PATTERN exclude files matching PATTERN
--exclude-from=FILE exclude files listed in FILE
--include=PATTERN don't exclude files matching PATTERN
--include-from=FILE don't exclude files listed in FILE
--suffix=SUFFIX override backup suffix
--version print version number
--daemon run as a rsync daemon
@@ -243,6 +255,7 @@ Options
--port=PORT specify alternate rsyncd port number
--stats give some file transfer stats
--progress show progress during transfer
--log-format=FORMAT log file transfers using specified format
-h, --help show this help screen
)
@@ -344,10 +357,14 @@ permissions to be the same as the local permissions.
dit(bf(-o, --owner)) This option causes rsync to update the remote owner
of the file to be the same as the local owner. This is only available
to the super-user.
to the super-user. Note that if the source system is a daemon using chroot,
the --numeric-ids option is implied because the source system cannot get
access to the user names.
dit(bf(-g, --group)) This option causes rsync to update the remote group
of the file to be the same as the local group.
of the file to be the same as the local group. Note that if the source
system is a daemon using chroot, the --numeric-ids option is implied because
the source system cannot get access to the group names.
dit(bf(-D, --devices)) This option causes rsync to transfer character and
block device information to the remote system to recreate these
@@ -387,9 +404,11 @@ Still, it is probably easy to get burnt with this option. The moral
of the story is to use the -n option until you get used to the
behavior of --delete.
NOTE: It also may delete files on the destination if the sending side
can't open them or stat them. This is a bug that hopefully will be
fixed in a future release.
If the sending side detects any IO errors then the deletion of any
files at the destination will be automatically disabled. This is to
prevent temporary filesystem failures (such as NFS errors) on the
sending side causing a massive deletion of files on the
destination.
dit(bf(--force)) This options tells rsync to delete directories even if
they are not empty. This applies to both the --delete option and to
@@ -477,11 +496,21 @@ checksum length by default, using a 16 byte file checksum to determine
if a 2nd pass is required with a longer block checksum. Only use this
option if you have read the source code and know what you are doing.
dit(bf(-T, --temp-dir DIR)) This options instructs rsync to use DIR as a
scratch directory when creating a temporary copies of the files
dit(bf(-T, --temp-dir DIR)) This option instructs rsync to use DIR as a
scratch directory when creating temporary copies of the files
transferred on the receiving side. The default behavior is to create
the temporary files in the receiving directory.
dit(bf(--compare-dest DIR)) This option instructs rsync to use DIR as an
additional directory to compare destination files against when doing
transfers. This is useful for doing transfers to a new destination while
leaving existing files intact, and then doing a flash-cutover when all
files have been successfully transfered (for example by moving directories
around and removing the old directory). This option increases the
usefulness of --partial because partially transferred files will remain in
the new temporary destination until they have a chance to be completed.
If DIR is a relative path, it is relative to the destination directory.
dit(bf(-z, --compress)) With this option, rsync compresses any data from
the source file(s) which it sends to the destination machine. This
option is useful on slow links. The compression method used is the
@@ -501,8 +530,9 @@ what ownership to give files. The special uid 0 and the special group
0 and never mapped via user/group names even if the --numeric-ids
option is not specified.
If a user or group name does not exist on the destination system then
the numeric id from the source system is used instead.
If the source system is a daemon using chroot, or if a user or group name
does not exist on the destination system, then the numeric id from the
source system is used instead.
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
timeout in seconds. If no data is transferred for the specified time
@@ -523,6 +553,11 @@ specified.
dit(bf(--port PORT)) This specifies an alternate TCP port number to use
rather than the default port 873.
dit(bf(--log-format=FORMAT)) Normally rsync just logs filenames as
they are transferred. This allows you to specify exactly what gets
logged on a per file basis. The log format is specified using the same
format conventions as the log format option in rsyncd.conf.
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
on the file transfer, allowing you to tell how effective the rsync
algorithm is for your data. This option only works in conjunction with

View File

@@ -91,6 +91,14 @@ support the "max connections" option. The rsync server uses record
locking on this file to ensure that the max connections limit is not
exceeded. The default is tt(/var/run/rsyncd.lock).
dit(bf(log file)) The "log file" option tells the rsync daemon to log
messages to that file rather than using syslog. This is particularly
useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs.
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process id to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync server. You may use any standard syslog facility name which is
@@ -99,6 +107,39 @@ ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. If you want to customise the log formats look at
log_send, log_recv and log_transfer in log.c
dit(bf(log format)) The "log format" option allows you to specify the
format used for logging file transfers when transfer logging is
enabled. The format is a text string containing embedded single
character escape sequences prefixed with a percent (%) character.
The prefixes that are understood are:
itemize(
it() %h for the remote host name
it() %a for the remote IP address
it() %l for the length of the file in bytes
it() %p for the process id of this rsync session
it() %o for the operation, which is either "send" or "recv"
it() %f for the filename
it() %P for the module path
it() %m for the module name
it() %t for the current time
it() %u for the authenticated username (or the null string)
it() %b for the number of bytes actually transferred
it() %c when sending files this gives the number of checksum bytes
received for this file
)
The default log format is "%o %h [%a] %m (%u) %f %l"
A perl script called rsyncstats to summarise this format is included
in the rsync source code distribution.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
@@ -123,9 +164,15 @@ that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the servers
filesystem to make available in this module. The rsync server will
chroot to this path before starting the file transfer with the
client. You must specify this option for each module in tt(/etc/rsyncd.conf).
filesystem to make available in this module. You must specify this option
for each module in tt(/etc/rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges and
of not being able to follow symbolic links outside of the new root path.
The default is to use chroot.
dit(bf(read only)) The "read only" option determines whether clients
will be able to upload files or not. If "read only" is true then any
@@ -267,8 +314,10 @@ A more sophisticated example would be:
uid = nobody nl()
gid = nobody nl()
use chroot = no nl()
max connections = 4 nl()
syslog facility = local5 nl()
pid file = /etc/rsyncd.pid
verb([ftp]
path = /var/ftp/pub

228
sender.c Normal file
View File

@@ -0,0 +1,228 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int remote_version;
extern int csum_length;
extern struct stats stats;
extern int io_error;
extern int dry_run;
extern int am_server;
/*
receive the checksums for a buffer
*/
static struct sum_struct *receive_sums(int f)
{
struct sum_struct *s;
int i;
OFF_T offset = 0;
s = (struct sum_struct *)malloc(sizeof(*s));
if (!s) out_of_memory("receive_sums");
s->count = read_int(f);
s->n = read_int(f);
s->remainder = read_int(f);
s->sums = NULL;
if (verbose > 3)
rprintf(FINFO,"count=%d n=%d rem=%d\n",
s->count,s->n,s->remainder);
if (s->count == 0)
return(s);
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
if (!s->sums) out_of_memory("receive_sums");
for (i=0;i<s->count;i++) {
s->sums[i].sum1 = read_int(f);
read_buf(f,s->sums[i].sum2,csum_length);
s->sums[i].offset = offset;
s->sums[i].i = i;
if (i == s->count-1 && s->remainder != 0) {
s->sums[i].len = s->remainder;
} else {
s->sums[i].len = s->n;
}
offset += s->sums[i].len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] len=%d offset=%d sum1=%08x\n",
i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
}
s->flength = offset;
return s;
}
void send_files(struct file_list *flist,int f_out,int f_in)
{
int fd;
struct sum_struct *s;
struct map_struct *buf;
STRUCT_STAT st;
char fname[MAXPATHLEN];
int i;
struct file_struct *file;
int phase = 0;
extern struct stats stats;
struct stats initial_stats;
if (verbose > 2)
rprintf(FINFO,"send_files starting\n");
setup_readbuffer(f_in);
while (1) {
int offset=0;
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
write_int(f_out,-1);
if (verbose > 2)
rprintf(FINFO,"send_files phase=%d\n",phase);
continue;
}
break;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
i, flist->count);
exit_cleanup(RERR_PROTOCOL);
}
file = flist->files[i];
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
fname[0] = 0;
if (file->basedir) {
strlcpy(fname,file->basedir,MAXPATHLEN-1);
if (strlen(fname) == MAXPATHLEN-1) {
io_error = 1;
rprintf(FERROR, "send_files failed on long-named directory %s\n",
fname);
return;
}
strlcat(fname,"/",MAXPATHLEN-1);
offset = strlen(file->basedir)+1;
}
strlcat(fname,f_name(file),MAXPATHLEN-strlen(fname));
if (verbose > 2)
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
if (dry_run) {
if (!am_server) {
log_transfer(file, fname+offset);
}
write_int(f_out,i);
continue;
}
initial_stats = stats;
s = receive_sums(f_in);
if (!s) {
io_error = 1;
rprintf(FERROR,"receive_sums failed\n");
return;
}
fd = open(fname,O_RDONLY);
if (fd == -1) {
io_error = 1;
rprintf(FERROR,"send_files failed to open %s: %s\n",
fname,strerror(errno));
free_sums(s);
continue;
}
/* map the local file */
if (do_fstat(fd,&st) != 0) {
io_error = 1;
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
free_sums(s);
close(fd);
return;
}
if (st.st_size > 0) {
buf = map_file(fd,st.st_size);
} else {
buf = NULL;
}
if (verbose > 2)
rprintf(FINFO,"send_files mapped %s of size %d\n",
fname,(int)st.st_size);
write_int(f_out,i);
write_int(f_out,s->count);
write_int(f_out,s->n);
write_int(f_out,s->remainder);
if (verbose > 2)
rprintf(FINFO,"calling match_sums %s\n",fname);
if (!am_server) {
log_transfer(file, fname+offset);
}
match_sums(f_out,s,buf,st.st_size);
log_send(file, &initial_stats);
if (buf) unmap_file(buf);
close(fd);
free_sums(s);
if (verbose > 2)
rprintf(FINFO,"sender finished %s\n",fname);
}
if (verbose > 2)
rprintf(FINFO,"send files finished\n");
match_report();
write_int(f_out,-1);
}

View File

@@ -54,6 +54,8 @@ int open_socket_out(char *host, int port)
return -1;
}
set_nonblocking(res);
return res;
}
@@ -110,9 +112,9 @@ determine if a file descriptor is in fact a socket
****************************************************************************/
int is_a_socket(int fd)
{
int v,l;
l = sizeof(int);
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
int v,l;
l = sizeof(int);
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
@@ -123,12 +125,12 @@ void start_accept_loop(int port, int (*fn)(int ))
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port);
if (s == -1)
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
/* ready to listen */
if (listen(s, 5) == -1) {
close(s);
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
@@ -165,6 +167,8 @@ void start_accept_loop(int port, int (*fn)(int ))
if (fork()==0) {
close(s);
set_nonblocking(fd);
_exit(fn(fd));
}
@@ -316,13 +320,17 @@ char *client_addr(int fd)
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
int length = sizeof(sa);
static char addr_buf[100];
static int initialised;
if (initialised) return addr_buf;
initialised = 1;
if (getpeername(fd, &sa, &length)) {
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf)-1);
return addr_buf;
}
@@ -339,11 +347,16 @@ char *client_name(int fd)
struct hostent *hp;
char **p;
char *def = "UNKNOWN";
static int initialised;
if (initialised) return name_buf;
initialised = 1;
strcpy(name_buf,def);
if (getpeername(fd, &sa, &length)) {
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
/* Look up the remote host name. */

286
support/rsyncstats Executable file
View File

@@ -0,0 +1,286 @@
#! /usr/bin/perl
# ---------------------------------------------------------------------------
#
# USAGE: rsyncstats <options>
#
# OPTIONS:
# -f <filename> Use <filename> for the log file
# -h include report on hourly traffic
# -d include report on domain traffic
# -t report on total traffic by section
# -D <domain> report only on traffic from <domain>
# -l <depth> Depth of path detail for sections
# -s <section> Section to report on, For example: -s /pub will report
# only on paths under /pub
#
# This script parses the default logfile format produced by rsync when running
# as a daemon with transfer logging enabled. It is derived from the xferstats
# script that comes with wuftpd
#
# Andrew Tridgell, October 1998
# rsync-bugs@samba.anu.edu.au
#
# ---------------------------------------------------------------------------
# edit the next line to customize for your default log file
$usage_file = "/var/adm/rsyncd.log";
# Edit the following lines for default report settings.
# Entries defined here will be over-ridden by the command line.
$opt_h = 1;
$opt_d = 0;
$opt_t = 1;
$opt_l = 2;
require 'getopts.pl';
&Getopts('f:rahdD:l:s:');
if ($opt_r) { $real = 1;}
if ($opt_a) { $anon = 1;}
if ($real == 0 && $anon == 0) { $anon = 1; }
if ($opt_f) {$usage_file = $opt_f;}
open (LOG,$usage_file) || die "Error opening usage log file: $usage_file\n";
if ($opt_D) {print "Transfer Totals include the '$opt_D' domain only.\n";
print "All other domains are filtered out for this report.\n\n";}
if ($opt_s) {print "Transfer Totals include the '$opt_s' section only.\n";
print "All other sections are filtered out for this report.\n\n";}
line: while (<LOG>) {
@line = split;
$day = $line[0];
$time = $line[1];
$pid = $line[2];
$op = $line[3];
$host = $line[4];
$ip = $line[5];
$module = $line[6];
$user = $line[7];
$file = $line[8];
$bytes = $line[9];
next if ($#line != 9);
next if ($op != "send" && $op != "recv");
$daytime = $day;
$hour = substr($time,0,2);
$file = $module . "/" . $file;
$file =~ s|//|/|mg;
@path = split(/\//, $file);
$pathkey = "";
for ($i=0; $i <= $#path && $i <= $opt_l;$i++) {
$pathkey = $pathkey . "/" . $path[$i];
}
next if (substr($pathkey,0,length("$opt_s")) ne "$opt_s");
$host =~ tr/A-Z/a-z/;
@address = split(/\./, $host);
$domain = $address[$#address];
if ( int($address[0]) > 0 || $#address < 2 )
{ $domain = "unresolved"; }
if ($opt_D) {
next unless (substr($domain,0,length("$opt_D")) eq "$opt_D");
}
# printf ("c=%d day=%s bytes=%d file=%s path=%s\n",
# $#line, $daytime, $bytes, $file, $pathkey);
$xferfiles++; # total files sent
$xfertfiles++; # total files sent
$xferfiles{$daytime}++; # files per day
$groupfiles{$pathkey}++; # per-group accesses
$domainfiles{$domain}++;
$xferbytes{$daytime} += $bytes; # bytes per day
$domainbytes{$domain} += $bytes; # xmit bytes to domain
$xferbytes += $bytes; # total bytes sent
$groupbytes{$pathkey} += $bytes; # per-group bytes sent
$xfertfiles{$hour}++; # files per hour
$xfertbytes{$hour} += $bytes; # bytes per hour
$xfertbytes += $bytes; # total bytes sent
}
close LOG;
@syslist = keys(systemfiles);
@dates = sort datecompare keys(xferbytes);
if ($xferfiles == 0) {die "There was no data to process.\n";}
print "TOTALS FOR SUMMARY PERIOD ", $dates[0], " TO ", $dates[$#dates], "\n\n";
printf ("Files Transmitted During Summary Period %12.0f\n", $xferfiles);
printf ("Bytes Transmitted During Summary Period %12.0f\n", $xferbytes);
printf ("Systems Using Archives %12.0f\n\n", $#syslist+1);
printf ("Average Files Transmitted Daily %12.0f\n",
$xferfiles / ($#dates + 1));
printf ("Average Bytes Transmitted Daily %12.0f\n",
$xferbytes / ($#dates + 1));
format top1 =
Daily Transmission Statistics
Number Of Number of Percent Of Percent Of
Date Files Sent MB Sent Files Sent Bytes Sent
--------------- ---------- ----------- ---------- ----------
.
format line1 =
@<<<<<<<<<<<<<< @>>>>>>>>> @>>>>>>>>>> @>>>>>>> @>>>>>>>
$date, $nfiles, $nbytes/(1024*1024), $pctfiles, $pctbytes
.
$^ = top1;
$~ = line1;
foreach $date ( sort datecompare keys(xferbytes) ) {
$nfiles = $xferfiles{$date};
$nbytes = $xferbytes{$date};
$pctfiles = sprintf("%8.2f", 100*$xferfiles{$date} / $xferfiles);
$pctbytes = sprintf("%8.2f", 100*$xferbytes{$date} / $xferbytes);
write;
}
if ($opt_t) {
format top2 =
Total Transfers from each Archive Section (By bytes)
- Percent -
Archive Section NFiles MB Files Bytes
------------------------------------- ------- ----------- ----- -------
.
format line2 =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>> @>>>>>>>>>> @>>>> @>>>>
$section, $files, $bytes/(1024*1024), $pctfiles, $pctbytes
.
$| = 1;
$- = 0;
$^ = top2;
$~ = line2;
foreach $section ( sort bytecompare keys(groupfiles) ) {
$files = $groupfiles{$section};
$bytes = $groupbytes{$section};
$pctbytes = sprintf("%8.2f", 100 * $groupbytes{$section} / $xferbytes);
$pctfiles = sprintf("%8.2f", 100 * $groupfiles{$section} / $xferfiles);
write;
}
if ( $xferfiles < 1 ) { $xferfiles = 1; }
if ( $xferbytes < 1 ) { $xferbytes = 1; }
}
if ($opt_d) {
format top3 =
Total Transfer Amount By Domain
Number Of Number of Percent Of Percent Of
Domain Name Files Sent MB Sent Files Sent Bytes Sent
----------- ---------- ------------ ---------- ----------
.
format line3 =
@<<<<<<<<<< @>>>>>>>>> @>>>>>>>>>>> @>>>>>>> @>>>>>>>
$domain, $files, $bytes/(1024*1024), $pctfiles, $pctbytes
.
$- = 0;
$^ = top3;
$~ = line3;
foreach $domain ( sort domnamcompare keys(domainfiles) ) {
if ( $domainsecs{$domain} < 1 ) { $domainsecs{$domain} = 1; }
$files = $domainfiles{$domain};
$bytes = $domainbytes{$domain};
$pctfiles = sprintf("%8.2f", 100 * $domainfiles{$domain} / $xferfiles);
$pctbytes = sprintf("%8.2f", 100 * $domainbytes{$domain} / $xferbytes);
write;
}
}
if ($opt_h) {
format top8 =
Hourly Transmission Statistics
Number Of Number of Percent Of Percent Of
Time Files Sent MB Sent Files Sent Bytes Sent
--------------- ---------- ----------- ---------- ----------
.
format line8 =
@<<<<<<<<<<<<<< @>>>>>>>>> @>>>>>>>>>> @>>>>>>> @>>>>>>>
$hour, $nfiles, $nbytes/(1024*1024), $pctfiles, $pctbytes
.
$| = 1;
$- = 0;
$^ = top8;
$~ = line8;
foreach $hour ( sort keys(xfertbytes) ) {
$nfiles = $xfertfiles{$hour};
$nbytes = $xfertbytes{$hour};
$pctfiles = sprintf("%8.2f", 100*$xfertfiles{$hour} / $xferfiles);
$pctbytes = sprintf("%8.2f", 100*$xfertbytes{$hour} / $xferbytes);
write;
}
}
exit(0);
sub datecompare {
$a gt $b;
}
sub domnamcompare {
$sdiff = length($a) - length($b);
($sdiff < 0) ? -1 : ($sdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
}
sub bytecompare {
$bdiff = $groupbytes{$b} - $groupbytes{$a};
($bdiff < 0) ? -1 : ($bdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
}
sub faccompare {
$fdiff = $fac{$b} - $fac{$a};
($fdiff < 0) ? -1 : ($fdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
}

19
token.c
View File

@@ -108,7 +108,7 @@ send_deflated_token(int f, int token,
Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
rprintf(FERROR, "compression init failed\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
out_of_memory("send_deflated_token");
@@ -178,7 +178,7 @@ send_deflated_token(int f, int token,
r = deflate(&tx_strm, flush);
if (r != Z_OK) {
rprintf(FERROR, "deflate returned %d\n", r);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (nb == 0 || tx_strm.avail_out == 0) {
n = MAX_DATA_COUNT - tx_strm.avail_out;
@@ -215,7 +215,7 @@ send_deflated_token(int f, int token,
if (r != Z_OK || tx_strm.avail_in != 0) {
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
r, tx_strm.avail_in);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
}
}
@@ -250,7 +250,7 @@ recv_deflated_token(int f, char **data)
rx_strm.zfree = NULL;
if (inflateInit2(&rx_strm, -15) != Z_OK) {
rprintf(FERROR, "inflate init failed\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
@@ -293,7 +293,7 @@ recv_deflated_token(int f, char **data)
if (r != Z_OK && r != Z_BUF_ERROR) {
rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
r, n);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (n != 0 && r != Z_BUF_ERROR) {
/* have to return some more data and
@@ -308,7 +308,7 @@ recv_deflated_token(int f, char **data)
*/
if (!inflateSyncPoint(&rx_strm)) {
rprintf(FERROR, "decompressor lost sync!\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
rx_strm.avail_in = 4;
rx_strm.next_in = (Bytef *)cbuf;
@@ -343,7 +343,7 @@ recv_deflated_token(int f, char **data)
n = CHUNK_SIZE - rx_strm.avail_out;
if (r != Z_OK) {
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (rx_strm.avail_in == 0)
recv_state = r_inflated;
@@ -366,8 +366,7 @@ recv_deflated_token(int f, char **data)
* put the data corresponding to a token that we've just returned
* from recv_deflated_token into the decompressor's history buffer.
*/
void
see_deflate_token(char *buf, int len)
static void see_deflate_token(char *buf, int len)
{
int r, blklen;
unsigned char hdr[5];
@@ -400,7 +399,7 @@ see_deflate_token(char *buf, int len)
r = inflate(&rx_strm, Z_SYNC_FLUSH);
if (r != Z_OK) {
rprintf(FERROR, "inflate (token) returned %d\n", r);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
} while (len || rx_strm.avail_out == 0);
}

146
util.c
View File

@@ -61,14 +61,14 @@ int piped_child(char **command,int *f_in,int *f_out)
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (pid == 0)
@@ -79,7 +79,7 @@ int piped_child(char **command,int *f_in,int *f_out)
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
@@ -87,17 +87,20 @@ int piped_child(char **command,int *f_in,int *f_out)
execvp(command[0], command);
rprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
*f_in = from_child_pipe[0];
*f_out = to_child_pipe[1];
set_nonblocking(*f_in);
set_nonblocking(*f_out);
return pid;
}
@@ -111,14 +114,14 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (pid == 0) {
@@ -133,7 +136,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
@@ -143,7 +146,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
*f_in = from_child_pipe[0];
@@ -157,13 +160,13 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
void out_of_memory(char *str)
{
rprintf(FERROR,"ERROR: out of memory in %s\n",str);
exit_cleanup(1);
exit_cleanup(RERR_MALLOC);
}
void overflow(char *str)
{
rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
exit_cleanup(1);
exit_cleanup(RERR_MALLOC);
}
@@ -250,7 +253,7 @@ static int full_write(int desc, char *ptr, int len)
for an error.
derived from GNU C's cccp.c. */
int safe_read(int desc, char *ptr, int len)
static int safe_read(int desc, char *ptr, int len)
{
int n_chars;
@@ -407,14 +410,6 @@ int name_to_gid(char *name, gid_t *gid)
}
/****************************************************************************
check if a process exists.
****************************************************************************/
int process_exists(int pid)
{
return(kill(pid,0) == 0 || errno != ESRCH);
}
/* lock a byte range in a open file */
int lock_range(int fd, int offset, int len)
{
@@ -432,7 +427,7 @@ int lock_range(int fd, int offset, int len)
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
{
#ifndef HAVE_GLOB
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
if (!*s) s = ".";
argv[*argc] = strdup(s);
(*argc)++;
@@ -512,7 +507,6 @@ void strlower(char *s)
pass 1023 for n */
int vslprintf(char *str, int n, const char *format, va_list ap)
{
#ifdef HAVE_VSNPRINTF
int ret = vsnprintf(str, n, format, ap);
if (ret > n || ret < 0) {
str[n] = 0;
@@ -520,42 +514,6 @@ int vslprintf(char *str, int n, const char *format, va_list ap)
}
str[ret] = 0;
return ret;
#else
static char *buf;
static int len=MAXPATHLEN*8;
int ret;
/* this code is NOT a proper vsnprintf() implementation. It
relies on the fact that all calls to slprintf() in rsync
pass strings which have already been checked to be less
than MAXPATHLEN in length and never more than 2 strings are
concatenated. This means the above buffer is absolutely
ample and can never be overflowed.
In the future we would like to replace this with a proper
vsnprintf() implementation but right now we need a solution
that is secure and portable. This is it. */
if (!buf) {
buf = malloc(len);
if (!buf) {
/* can't call debug or we would recurse */
exit_cleanup(1);
}
}
vsprintf(buf, format, ap);
ret = strlen(buf);
if (ret > n) {
/* yikes! */
exit_cleanup(1);
}
buf[ret] = 0;
memcpy(str, buf, ret+1);
return ret;
#endif
}
@@ -621,6 +579,55 @@ void clean_fname(char *name)
}
}
/*
* Make path appear as if a chroot had occurred:
* 0. call clean_fname on it.
* 1. remove leading "/" (or replace with "." if at end)
* 2. remove leading ".." components
* 3. delete any other "<dir>/.." (recursively)
* Return a malloc'ed copy.
* Contributed by Dave Dykstra <dwd@bell-labs.com>
*/
char *sanitize_path(char *p)
{
char *copy, *copyp;
clean_fname(p);
copy = (char *) malloc(strlen(p)+1);
copyp = copy;
while (*p != '\0') {
if ((*p == '/') && (copyp == copy)) {
/* remove leading slash */
p++;
}
else if ((*p == '.') && (*(p+1) == '.') &&
((*(p+2) == '/') || (*(p+2) == '\0'))) {
/* remove .. followed by slash or end */
p += 2;
if (copyp != copy) {
/* backup the copy one level */
while ((--copyp != copy) && (*copyp == '/'))
/* skip trailing slashes */
;
while ((copyp != copy) && (*copyp != '/'))
/* skip back through slash */
copyp--;
}
} else {
/* copy one component */
while (1) {
*copyp++ = *p++;
if ((*p == '\0') || (*(p-1) == '/'))
break;
}
}
}
*copyp = '\0';
return(copy);
}
static char curr_dir[MAXPATHLEN];
@@ -757,3 +764,26 @@ int unsafe_symlink(char *dest, char *src)
free(dest);
return (depth < 0);
}
/****************************************************************************
return the date and time as a string
****************************************************************************/
char *timestring(time_t t)
{
static char TimeBuf[200];
struct tm *tm = localtime(&t);
#ifdef HAVE_STRFTIME
strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
#else
strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)-1);
#endif
if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
TimeBuf[strlen(TimeBuf)-1] = 0;
}
return(TimeBuf);
}

View File

@@ -1 +1 @@
#define VERSION "2.1.0"
#define VERSION "2.2.0"