Compare commits

...

67 Commits

Author SHA1 Message Date
rsync-bugs
cf0d1d819a preparing for release of 1.7.3 1998-04-13 07:00:55 +00:00
Andrew Tridgell
0a25de67e9 fixed a bug in the handling of -R with --delete
I introduced this bug in the last version as a side effect of fixing
the permissions on intermediate directories with -R. drat.
1998-04-13 06:39:33 +00:00
Andrew Tridgell
317302412e not quite so many decimal places in "speedup" :-) 1998-04-13 04:44:49 +00:00
Andrew Tridgell
1250f24ed2 fixed a bug in handling the -c option and non-regular files. It hadn't
turned up before because Linux had a bug in the handling of NULL
pointers to read()/write() on pipes, so I never noticed the bug in my
testing.

I've also sent a patch to Linus.
1998-04-09 00:38:40 +00:00
rsync-bugs
945eba8c1f preparing for release of 1.7.2 1998-04-05 06:46:11 +00:00
Andrew Tridgell
d867229ba0 handle sparse files more efficiently 1998-04-05 06:43:38 +00:00
Andrew Tridgell
1b2d733af2 a couple more system calls wrapped in syscall.c 1998-04-05 06:26:24 +00:00
Andrew Tridgell
366345fe05 in local->local mode don't use exec to start the "remote" rsync,
instead just fork()
1998-04-05 06:07:37 +00:00
Andrew Tridgell
dd04a03440 fixed a bug in the hlink code - it wasn't taking account of the new
pointer list code for flist.
1998-04-05 04:34:52 +00:00
Andrew Tridgell
575f2fca9a fixed a string termination bug in the uidlist handling code. I've also
added a read_sbuf() routine that fixes this kind of bug generically to
avoid similar problems in future.
1998-04-01 05:20:19 +00:00
Andrew Tridgell
fc4e8d51ff don't need to test for SETPGRP any more as it is no longer used 1998-03-27 03:38:06 +00:00
Andrew Tridgell
98ae8c3e38 Solaris uses EEXIST instead of ENOTEMPTY. 1998-03-27 03:04:34 +00:00
rsync-bugs
49f4b973a1 preparing for release of 1.7.1 1998-03-26 06:11:18 +00:00
Andrew Tridgell
a070c37b7e fixed a bug I introduced in the last big commit 1998-03-26 06:09:04 +00:00
Andrew Tridgell
17faa41c7d added some debugging code 1998-03-26 05:48:37 +00:00
rsync-bugs
a90da9985a preparing for release of 1.7.0 1998-03-26 04:53:37 +00:00
Andrew Tridgell
8a24eece38 updated README and man page ready for the new release 1998-03-26 04:43:10 +00:00
Andrew Tridgell
6ba9279fb2 - added an internal io_error flag. Whenever an io error occurs (such
as not being able to open a directory) this flag is set and propogated
to the other end. When this flag is set the --delete code is
disabled. This prevents the problem that io or permission errors could
cause files to be incorrectly deleted on the destination.

- added a --timeout option. This allows you to set an IO timeout in
seconds. If no io occurs in that time then rsync exits with a timeout
error.

- changed some FERROR fds to FINFO
1998-03-26 04:18:47 +00:00
Andrew Tridgell
5fb543d587 if rsync fails to update the group of a file but nothing else then
don't report a problem. On most OSes non-root users can't change the
group of a file.
1998-03-26 00:32:51 +00:00
Andrew Tridgell
0c5f37d9db when using -x to stop at filesystem boundaries, include the mount
points but not their contents.

I did this by calling stat() on the directory above the current
directory and checking to see if it has the correct st_dev. Hopefully
this will work for most systems.

Note that the permissions and ownership on the mount point cannot be
copied correctly as they are unavailable while the filesystem is
mounted. Instead rsync will set the permissions and ownership to those
of the root directory of the mounted filesystem (ie. the apparent
permissions/ownership of the directory)
1998-03-26 00:11:50 +00:00
Andrew Tridgell
42849e9202 add the dummy file to .cvsignore 1998-03-25 11:28:35 +00:00
Andrew Tridgell
a746eb9de0 - fixed a bug in the utimbuf test
- rebuilt prototypes
1998-03-25 11:26:20 +00:00
Andrew Tridgell
71c4617611 - on systems (such as intel linux) where off_t is 32 bits but "long long"
is 64 bits use long long to get the totals right when transferring
  more than 2^32 bytes of data.

- use inline on flist_up if the compiler supports it
1998-03-25 11:08:32 +00:00
Andrew Tridgell
3cb6f5d6cb added a --force option.
This options tells rsync to delete directories even if they are not
empty. This applies to both the --delete option and to cases where
rsync tries to copy a normal file but the destination contains a
directory of the same name. Normally rsync will refuse to do a
recursive directory deletion in such cases, by using --force the
recursive deletion will be done.
1998-03-25 06:05:47 +00:00
Andrew Tridgell
366bd9056c changes to make VPATH work correctly, thanks to patl@cag.lcs.mit.edu 1998-03-25 04:14:18 +00:00
Andrew Tridgell
ac71984aae added this so the lib directory gets created when using VPATH 1998-03-25 04:13:17 +00:00
Andrew Tridgell
649d65edf3 - fixed a bug wth the handling of duplicate names with the new fist
structures

- send intermediate directories when using --relative to ensure the
  permissions are set correctly
1998-03-25 03:34:52 +00:00
Andrew Tridgell
7796395a0a don't show basedir in printed path (a aesthetic change only) 1998-03-25 01:59:23 +00:00
Andrew Tridgell
76076c4bbd fixed the problem where you couldn't specify multiple remote
filenames. The fix will need some testing.
1998-03-25 00:40:47 +00:00
Andrew Tridgell
f92ef572b9 check a few HAVE_* macros 1998-03-24 06:42:11 +00:00
Andrew Tridgell
7308bd66e0 added chmod() and chown() to syscall.c 1998-03-24 06:39:16 +00:00
Andrew Tridgell
0d0e2e93e8 test for "long long" and %lld in configure. 1998-03-23 14:46:03 +00:00
Andrew Tridgell
31e125226d added wrappers around all the system calls that can change what is on
disk. The wrappers check for dry_run.
1998-03-23 13:25:30 +00:00
Andrew Tridgell
3a6a366fc5 finished 64 bit file offset support. Hopefully rsync can now transfer
files up to 2^64 bytes in size. Now I just need to find enough disk
space to test this :-)

The 64 bit offset code only works if off_t is 64 bits (or bigger!) on
both ends of the link. If one end tries to send a file greater than
2^31 in size and the other end doesn't support it then rsync will
abort.

This commit also cleans up some static declarations so they are in a
unitinitialised segment to save load time.
1998-03-23 12:52:57 +00:00
Andrew Tridgell
0b91056090 started to add some 64 bit file offset support - not complete yet 1998-03-23 08:49:48 +00:00
Andrew Tridgell
a76a0039fc label this version 1.7.0alpha 1998-03-23 07:26:14 +00:00
Andrew Tridgell
2d0bb8eb0f save some more memory by only allocating the checksum when needed 1998-03-23 07:25:21 +00:00
Andrew Tridgell
e7ebc36c70 if the file changes during transfer then don't loop forever trying to
update it
1998-03-23 07:11:51 +00:00
Andrew Tridgell
1aa71c8d57 don't adapt the block size to above half the chunk size 1998-03-23 06:26:08 +00:00
Andrew Tridgell
bd39e9d263 prototype update 1998-03-23 04:47:40 +00:00
Andrew Tridgell
3ba62a8308 - keep a list of pids and send them a SIGUSR1 for cleanup rather than
using setpgrp()

- adapt the block size for really large files to reduce the checksum
  size and memory overheads
1998-03-23 04:44:44 +00:00
Andrew Tridgell
feaa89c410 for systems with a broken select use u_sleep() to ensure the write
process doesn't chew too much cpu time.
1998-03-23 04:14:21 +00:00
Andrew Tridgell
3ec4dd9781 a large change to make rsync much more memory efficient. This is done
in 3 ways:

1) the realloc is done on a list of pointers, not a list of structures
2) only the basename of the file is now kept in the file struct an a
   util function f_name() is now used to access the full name when
   required.
3) pointers to directory names are re-used

hopefully I haven't broken anything. This will need lots of testing.
1998-03-23 03:45:02 +00:00
Andrew Tridgell
ec0e5ac001 compatibility functions now split into their own file 1998-02-24 11:54:10 +00:00
Andrew Tridgell
1e9f155ade *** empty log message *** 1998-01-27 17:51:37 +00:00
Andrew Tridgell
6bbbc08b83 *** empty log message *** 1998-01-13 19:25:59 +00:00
Andrew Tridgell
13dc412d76 *** empty log message *** 1998-01-13 19:19:48 +00:00
Andrew Tridgell
950ab32d38 *** empty log message *** 1998-01-13 18:35:10 +00:00
Andrew Tridgell
d0390cd384 *** empty log message *** 1998-01-13 17:16:14 +00:00
Andrew Tridgell
f6c347425a *** empty log message *** 1998-01-13 15:57:26 +00:00
Andrew Tridgell
3b3a2fbcf0 *** empty log message *** 1998-01-06 16:53:52 +00:00
Andrew Tridgell
95a38e8684 cosmetic changes only
- minor correction to --update docs
- don't print "building file list" stuff when building a local file
list for use in the --delete code.
- remove some spaces at the end of lines in Makefile.in
1998-01-05 23:30:44 +00:00
Andrew Tridgell
c778aaa048 *** empty log message *** 1998-01-01 15:53:05 +00:00
Andrew Tridgell
3fac9b6e93 removed the read_write() call, it's not used anywhere 1997-12-31 16:48:11 +00:00
Andrew Tridgell
964ca2eca5 simplified the logic of whether to skip a file or not. The -c
(always_checksum) option is probably now more useful.
1997-12-31 16:39:34 +00:00
Andrew Tridgell
684b4e3113 buffer overflow patches from mhpower@mit.edu (Matt Power) 1997-12-30 17:36:58 +00:00
Andrew Tridgell
dc7a947853 fixed the --suffix option. It wasn't being propogated to the remote
end in the server_options() function.
1997-12-30 10:54:47 +00:00
rsync-bugs
b73c59a2c4 preparing for release of 1.6.8 1997-12-28 22:28:21 +00:00
Andrew Tridgell
f3644f1f2d - added a debug message
- rebuilt prototypes
1997-12-28 22:26:51 +00:00
Andrew Tridgell
e3cd198f8e - fixed spelling errors in man page
- fixed bug in hard link handling that could lead to spurious hard
links.
- fixed bug in the string handling in flist.c
1997-12-28 22:13:40 +00:00
Andrew Tridgell
5c36219d40 following a report of problems with Linux/alpha I've changed zlib.c to
use uint32 instead of "long" in several places. Apparently this fixes
things on the alpha. The strange thing is that my own tests on a
OSF/alpha box and a 64 bit IRIX box showed no problems. I wonder what
was actually going wrong? I'll email the zlib maintainers and let them
know.
1997-12-18 11:18:32 +00:00
Andrew Tridgell
f0e5517fb8 added a new mirror site to the README 1997-12-18 11:13:27 +00:00
rsync-bugs
18463a5a5a preparing for release of 1.6.7 1997-12-17 11:19:01 +00:00
Andrew Tridgell
82306bf6d6 *** empty log message *** 1997-12-17 11:07:17 +00:00
Andrew Tridgell
cbbe489208 handle things more grecefully when one machine supports hard links and
the other doesn't or one machine supports soft links and the other
doesn't.
1997-12-16 23:09:22 +00:00
Andrew Tridgell
6dd1782c42 - check for setlinebuf() in autoconf. Apparently HPUX doesn't have it
- use @exec_prefix@ and @prefix@ in more useful ways in Makefile.in
1997-12-16 22:39:55 +00:00
Andrew Tridgell
fee64929a3 fixed a bug in the handling of the new --relative option. The file was
being opened twice but closed once. The process eventually died with
an out of file descriptors error.
1997-12-16 20:29:35 +00:00
24 changed files with 2615 additions and 1432 deletions

View File

@@ -1,36 +1,42 @@
# Makefile for rsync. This is processed by configure to produce the final
# Makefile
INSTALL_BIN=@prefix@/bin
INSTALL_MAN=@prefix@/man
prefix=@prefix@
exec_prefix=@exec_prefix@
INSTALL_BIN=$(exec_prefix)/bin
INSTALL_MAN=$(prefix)/man
LIBS=@LIBS@
CC=@CC@
CC=@CC@
CFLAGS=@CFLAGS@
INSTALLCMD=@INSTALL@
SRC=@srcdir@
VPATH=@srcdir@
srcdir=@srcdir@
SHELL=/bin/sh
.SUFFIXES:
.SUFFIXES: .c .o
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o
OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o $(LIBOBJ)
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o lib/compat.o
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o
OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o uidlist.o $(LIBOBJ)
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
$(CC) $(CFLAGS) -c $*.c -o $*.o
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@
all: rsync
install: all
-mkdir -p ${INSTALL_BIN}
${INSTALLCMD} -m 755 rsync ${INSTALL_BIN}
${INSTALLCMD} -m 644 rsync.1 ${INSTALL_MAN}/man1
-mkdir -p ${INSTALL_MAN}/man1
${INSTALLCMD} -m 644 $(srcdir)/rsync.1 ${INSTALL_MAN}/man1
rsync: $(OBJS)
rsync: $(OBJS)
$(CC) $(CFLAGS) -o rsync $(OBJS) $(LIBS)
proto:
@@ -39,7 +45,7 @@ proto:
clean:
rm -f *~ $(OBJS) rsync config.cache config.log config.status
dist:
dist:
tar --exclude-from .ignore -czf dist.tar.gz .
-mkdir rsync-$(VERSION)
(cd rsync-$(VERSION) ; tar xzf ../dist.tar.gz)

14
README
View File

@@ -22,6 +22,7 @@ Basically you use rsync just like rcp, but rsync has many additional options.
Here is a brief description of available options:
Options:
-v, --verbose increase verbosity
-c, --checksum always checksum
-a, --archive archive mode (same as -rlptDog)
@@ -30,6 +31,7 @@ Here is a brief description of available options:
-b, --backup make backups (default ~ extension)
-u, --update update only (don't overwrite newer files)
-l, --links preserve soft links
-L, --copy-links treat soft links like regular files
-H, --hard-links preserve hard links
-p, --perms preserve permissions
-o, --owner preserve owner (root only)
@@ -38,13 +40,18 @@ Here is a brief description of available options:
-t, --times preserve times
-S, --sparse handle sparse files efficiently
-n, --dry-run show what would have been transferred
-W, --whole-file copy whole files, no incremental checks
-x, --one-file-system don't cross filesystem boundaries
-B, --block-size SIZE checksum blocking size
-e, --rsh COMMAND specify rsh replacement
--rsync-path PATH specify path to rsync on the remote machine
-C, --cvs-exclude auto ignore files in the same way CVS does
--delete delete files that don't exist on the sending side
--force force deletion of directories even if not empty
--numeric-ids don't map uid/gid values by user/group name
--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
-z, --compress compress file data
--exclude FILE exclude file FILE
--exclude-from FILE exclude files listed in FILE
@@ -86,7 +93,7 @@ BUG REPORTS
-----------
If you have web access then please look at
http://samba.anu.edu.au/cgi-bin/rsync
http://samba.anu.edu.au/rsync/
This will give you access to the bug tracking system used by the
developers of rsync and will allow you to look at other bug reports or
@@ -116,9 +123,9 @@ COPYRIGHT
---------
Rsync was written by Andrew Tridgell and Paul Mackerras, and is
available under the GPL.
available under the Gnu Public License.
Andrew.Tridgell@anu.edu.au
tridge@samba.anu.edu.au
paulus@cs.anu.edu.au
@@ -131,3 +138,4 @@ Mirrors are available at:
ftp://sunsite.auc.dk/pub/unix/rsync
ftp://ftp.sunet.se/pub/unix/admin/rsync
ftp://ftp.fu-berlin.de/pub/unix/network/rsync/

View File

@@ -65,8 +65,8 @@ void get_checksum2(char *buf,int len,char *sum)
{
int i;
MDstruct MD;
static char *buf1 = NULL;
static int len1 = 0;
static char *buf1;
static int len1;
if (len > len1) {
if (buf1) free(buf1);
@@ -95,11 +95,11 @@ void get_checksum2(char *buf,int len,char *sum)
void file_checksum(char *fname,char *sum,off_t size)
{
int i;
off_t i;
MDstruct MD;
struct map_struct *buf;
int fd;
int len = size;
off_t len = size;
char tmpchunk[CSUM_CHUNK];
bzero(sum,csum_length);

157
compat.c
View File

@@ -36,152 +36,7 @@ extern int checksum_seed;
extern int remote_version;
void (*send_file_entry)(struct file_struct *file,int f) = NULL;
void (*receive_file_entry)(struct file_struct *file,
unsigned char flags,int f) = NULL;
void send_file_entry_v10(struct file_struct *file,int f)
{
unsigned char flags;
static mode_t last_mode=0;
static dev_t last_rdev=0;
static uid_t last_uid=0;
static gid_t last_gid=0;
static char lastdir[MAXPATHLEN]="";
char *p=NULL;
if (f == -1) return;
if (!file) {
write_byte(f,0);
return;
}
flags = FILE_VALID;
if (file->mode == last_mode) flags |= SAME_MODE;
if (file->rdev == last_rdev) flags |= SAME_RDEV;
if (file->uid == last_uid) flags |= SAME_UID;
if (file->gid == last_gid) flags |= SAME_GID;
if (strncmp(file->name,lastdir,strlen(lastdir)) == 0) {
flags |= SAME_DIR;
p = file->name + strlen(lastdir);
} else {
p = file->name;
}
write_byte(f,flags);
if (flags & SAME_DIR)
write_byte(f,strlen(p));
else
write_int(f,strlen(p));
write_buf(f,p,strlen(p));
write_int(f,(int)file->modtime);
write_int(f,(int)file->length);
if (!(flags & SAME_MODE))
write_int(f,(int)file->mode);
if (preserve_uid && !(flags & SAME_UID))
write_int(f,(int)file->uid);
if (preserve_gid && !(flags & SAME_GID))
write_int(f,(int)file->gid);
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
write_int(f,(int)file->rdev);
#if SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
write_int(f,strlen(file->link));
write_buf(f,file->link,strlen(file->link));
}
#endif
if (always_checksum) {
write_buf(f,file->sum,csum_length);
}
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
p = strrchr(file->name,'/');
if (p) {
int l = (int)(p - file->name) + 1;
strncpy(lastdir,file->name,l);
lastdir[l] = 0;
} else {
strcpy(lastdir,"");
}
}
void receive_file_entry_v10(struct file_struct *file,
unsigned char flags,int f)
{
static mode_t last_mode=0;
static dev_t last_rdev=0;
static uid_t last_uid=0;
static gid_t last_gid=0;
static char lastdir[MAXPATHLEN]="";
char *p=NULL;
int l1,l2;
if (flags & SAME_DIR) {
l1 = read_byte(f);
l2 = strlen(lastdir);
} else {
l1 = read_int(f);
l2 = 0;
}
file->name = (char *)malloc(l1+l2+1);
if (!file->name) out_of_memory("receive_file_entry");
strncpy(file->name,lastdir,l2);
read_buf(f,file->name+l2,l1);
file->name[l1+l2] = 0;
file->modtime = (time_t)read_int(f);
file->length = (off_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
if (preserve_uid)
file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
#if SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry");
read_buf(f,file->link,l);
file->link[l] = 0;
}
#endif
if (always_checksum)
read_buf(f,file->sum,csum_length);
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
p = strrchr(file->name,'/');
if (p) {
int l = (int)(p - file->name) + 1;
strncpy(lastdir,file->name,l);
lastdir[l] = 0;
} else {
strcpy(lastdir,"");
}
}
extern int verbose;
void setup_protocol(int f_out,int f_in)
{
@@ -201,13 +56,9 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(1);
}
if (remote_version == 10) {
send_file_entry = send_file_entry_v10;
receive_file_entry = receive_file_entry_v10;
} else {
send_file_entry = send_file_entry_v11;
receive_file_entry = receive_file_entry_v11;
}
if (verbose > 2)
fprintf(FINFO, "local_version=%d remote_version=%d\n",
PROTOCOL_VERSION, remote_version);
if (remote_version >= 12) {
if (am_server) {

View File

@@ -42,7 +42,7 @@ AC_FUNC_MMAP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(waitpid strtok pipe getcwd mkdir strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
AC_CHECK_FUNCS(memmove getopt_long lchown)
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf)
echo $ac_n "checking for working fnmatch... $ac_c"
AC_TRY_RUN([#include <fnmatch.h>
@@ -50,4 +50,17 @@ main() { exit(fnmatch("*.o", "x.o", 0) == 0? 0: 1); }],
echo yes;AC_DEFINE(HAVE_FNMATCH),
echo no)
AC_OUTPUT(Makefile)
echo $ac_n "checking for long long... $ac_c"
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000000000; char b[20]; sprintf(b,"%lld", x); exit(strcmp("1000000000000", b) == 0? 0: 1); }],
echo yes;AC_DEFINE(HAVE_LONGLONG),
echo no)
echo $ac_n "checking for utimbuf ... $ac_c"
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)
AC_OUTPUT(Makefile lib/dummy)

View File

@@ -24,8 +24,9 @@
#include "rsync.h"
extern int verbose;
extern int am_server;
static char **exclude_list = NULL;
static char **exclude_list;
static int is_regex(char *str)
{
@@ -86,7 +87,7 @@ void add_exclude_list(char *pattern,char ***list)
if (strcmp(pattern,"!") == 0) {
if (verbose > 2)
fprintf(FERROR,"clearing exclude list\n");
fprintf(FINFO,"clearing exclude list\n");
while ((len)--)
free((*list)[len]);
free((*list));
@@ -104,7 +105,7 @@ void add_exclude_list(char *pattern,char ***list)
out_of_memory("add_exclude");
if (verbose > 2)
fprintf(FERROR,"add_exclude(%s)\n",pattern);
fprintf(FINFO,"add_exclude(%s)\n",pattern);
(*list)[len+1] = NULL;
}
@@ -163,9 +164,9 @@ void recv_exclude_list(int f)
char line[MAXPATHLEN];
int l;
while ((l=read_int(f))) {
read_buf(f,line,l);
line[l] = 0;
add_exclude(line);
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
add_exclude(line);
}
}

1302
flist.c
View File

File diff suppressed because it is too large Load Diff

73
hlink.c
View File

@@ -31,39 +31,39 @@ static int hlink_compare(struct file_struct *f1,struct file_struct *f2)
if (!S_ISREG(f2->mode)) return 1;
if (f1->dev != f2->dev)
return (f1->dev - f2->dev);
return (int)(f1->dev - f2->dev);
if (f1->inode != f2->inode)
return (f1->inode - f2->inode);
return file_compare(f1,f2);
return file_compare(&f1,&f2);
}
static struct file_struct *hlink_list = NULL;
static int hlink_count=0;
static struct file_struct *hlink_list;
static int hlink_count;
#endif
void init_hard_links(struct file_list *flist)
{
#if SUPPORT_HARD_LINKS
if (flist->count < 2) return;
int i;
if (flist->count < 2) return;
if (hlink_list) free(hlink_list);
if (hlink_list) free(hlink_list);
if (!(hlink_list =
(struct file_struct *)malloc(sizeof(hlink_list[0])*flist->count)))
out_of_memory("init_hard_links");
if (!(hlink_list =
(struct file_struct *)malloc(sizeof(hlink_list[0])*flist->count)))
out_of_memory("init_hard_links");
bcopy((char *)flist->files,
(char *)hlink_list,
sizeof(hlink_list[0])*flist->count);
for (i = 0; i < flist->count; i++)
bcopy(flist->files[i], &hlink_list[i], sizeof(hlink_list[0]));
qsort(hlink_list,flist->count,
sizeof(hlink_list[0]),
(int (*)())hlink_compare);
qsort(hlink_list,flist->count,
sizeof(hlink_list[0]),
(int (*)())hlink_compare);
hlink_count=flist->count;
hlink_count=flist->count;
#endif
}
@@ -73,26 +73,29 @@ int check_hard_link(struct file_struct *file)
{
#if SUPPORT_HARD_LINKS
int low=0,high=hlink_count-1;
int mid=0,ret=0;
int ret=0;
if (!hlink_list || !S_ISREG(file->mode)) return 0;
while (low != high) {
mid = (low+high)/2;
int mid = (low+high)/2;
ret = hlink_compare(&hlink_list[mid],file);
if (ret == 0) break;
if (ret == 0) {
low = mid;
break;
}
if (ret > 0)
high=mid;
else
low=mid+1;
}
if (hlink_compare(&hlink_list[mid],file) != 0) return 0;
if (hlink_compare(&hlink_list[low],file) != 0) return 0;
if (mid > 0 &&
S_ISREG(hlink_list[mid-1].mode) &&
file->dev == hlink_list[mid-1].dev &&
file->inode == hlink_list[mid-1].inode)
if (low > 0 &&
S_ISREG(hlink_list[low-1].mode) &&
file->dev == hlink_list[low-1].dev &&
file->inode == hlink_list[low-1].inode)
return 1;
#endif
@@ -111,35 +114,35 @@ void do_hard_links(struct file_list *flist)
for (i=1;i<hlink_count;i++) {
if (S_ISREG(hlink_list[i].mode) &&
S_ISREG(hlink_list[i-1].mode) &&
hlink_list[i].name && hlink_list[i-1].name &&
hlink_list[i].basename && hlink_list[i-1].basename &&
hlink_list[i].dev == hlink_list[i-1].dev &&
hlink_list[i].inode == hlink_list[i-1].inode) {
struct stat st1,st2;
if (lstat(hlink_list[i-1].name,&st1) != 0) continue;
if (lstat(hlink_list[i].name,&st2) != 0) {
if (!dry_run && link(hlink_list[i-1].name,hlink_list[i].name) != 0) {
if (link_stat(f_name(&hlink_list[i-1]),&st1) != 0) continue;
if (link_stat(f_name(&hlink_list[i]),&st2) != 0) {
if (do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
fprintf(FINFO,"link %s => %s : %s\n",
hlink_list[i].name,
hlink_list[i-1].name,strerror(errno));
f_name(&hlink_list[i]),
f_name(&hlink_list[i-1]),strerror(errno));
continue;
}
} else {
if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino) continue;
if (!dry_run && (unlink(hlink_list[i].name) != 0 ||
link(hlink_list[i-1].name,hlink_list[i].name) != 0)) {
if (do_unlink(f_name(&hlink_list[i])) != 0 ||
do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
fprintf(FINFO,"link %s => %s : %s\n",
hlink_list[i].name,
hlink_list[i-1].name,strerror(errno));
f_name(&hlink_list[i]),
f_name(&hlink_list[i-1]),strerror(errno));
continue;
}
}
if (verbose > 0)
fprintf(FINFO,"%s => %s\n",
hlink_list[i].name,hlink_list[i-1].name);
f_name(&hlink_list[i]),f_name(&hlink_list[i-1]));
}
}
#endif

263
io.c
View File

@@ -24,18 +24,19 @@
*/
#include "rsync.h"
static int total_written = 0;
static int total_read = 0;
static int64 total_written;
static int64 total_read;
extern int verbose;
extern int sparse_files;
extern int io_timeout;
int write_total(void)
int64 write_total(void)
{
return total_written;
}
int read_total(void)
int64 read_total(void)
{
return total_read;
}
@@ -49,10 +50,10 @@ void setup_nonblocking(int f_in,int f_out)
}
static char *read_buffer = NULL;
static char *read_buffer_p = NULL;
static int read_buffer_len = 0;
static int read_buffer_size = 0;
static char *read_buffer;
static char *read_buffer_p;
static int read_buffer_len;
static int read_buffer_size;
/* This function was added to overcome a deadlock problem when using
@@ -95,39 +96,71 @@ static void read_check(int f)
}
}
static time_t last_io;
static void check_timeout(void)
{
time_t t;
if (!io_timeout) return;
if (!last_io) {
last_io = time(NULL);
return;
}
t = time(NULL);
if (last_io && io_timeout && (t-last_io)>io_timeout) {
fprintf(FERROR,"read timeout after %d second - exiting\n",
(int)(t-last_io));
exit_cleanup(1);
}
}
static int readfd(int fd,char *buffer,int N)
{
int ret;
int total=0;
int ret;
int total=0;
struct timeval tv;
if (read_buffer_len < N)
read_check(buffer_f_in);
while (total < N) {
if (read_buffer_len > 0 && buffer_f_in == fd) {
ret = MIN(read_buffer_len,N-total);
memcpy(buffer+total,read_buffer_p,ret);
read_buffer_p += ret;
read_buffer_len -= ret;
total += ret;
continue;
}
if (read_buffer_len < N)
read_check(buffer_f_in);
while (total < N)
{
if (read_buffer_len > 0 && buffer_f_in == fd) {
ret = MIN(read_buffer_len,N-total);
memcpy(buffer+total,read_buffer_p,ret);
read_buffer_p += ret;
read_buffer_len -= ret;
} else {
while ((ret = read(fd,buffer + total,N - total)) == -1) {
fd_set fds;
while ((ret = read(fd,buffer + total,N-total)) == -1) {
fd_set fds;
if (errno != EAGAIN && errno != EWOULDBLOCK)
return -1;
FD_ZERO(&fds);
FD_SET(fd, &fds);
select(fd+1, &fds, NULL, NULL, NULL);
if (errno != EAGAIN && errno != EWOULDBLOCK)
return -1;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = io_timeout;
tv.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
check_timeout();
}
}
if (ret <= 0)
return total;
total += ret;
}
}
if (ret <= 0)
if (io_timeout)
last_io = time(NULL);
return total;
total += ret;
}
return total;
}
@@ -145,6 +178,34 @@ int read_int(int f)
return IVAL(b,0);
}
int64 read_longint(int f)
{
extern int remote_version;
int64 ret;
char b[8];
ret = read_int(f);
if (ret != -1) return ret;
#ifndef HAVE_LONGLONG
fprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
exit_cleanup(1);
#else
if (remote_version >= 16) {
if ((ret=readfd(f,b,8)) != 8) {
if (verbose > 1)
fprintf(FERROR,"(%d) Error reading %d bytes : %s\n",
getpid(),8,ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_read += 8;
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
}
#endif
return ret;
}
void read_buf(int f,char *buf,int len)
{
int ret;
@@ -157,6 +218,12 @@ void read_buf(int f,char *buf,int len)
total_read += len;
}
void read_sbuf(int f,char *buf,int len)
{
read_buf(f,buf,len);
buf[len] = 0;
}
unsigned char read_byte(int f)
{
unsigned char c;
@@ -165,71 +232,71 @@ unsigned char read_byte(int f)
}
static char last_byte=0;
static int last_sparse = 0;
static char last_byte;
static int last_sparse;
int sparse_end(int f)
{
if (last_sparse) {
lseek(f,-1,SEEK_CUR);
return (write(f,&last_byte,1) == 1 ? 0 : -1);
}
last_sparse = 0;
return 0;
if (last_sparse) {
lseek(f,-1,SEEK_CUR);
return (write(f,&last_byte,1) == 1 ? 0 : -1);
}
last_sparse = 0;
return 0;
}
int write_sparse(int f,char *buf,int len)
static int write_sparse(int f,char *buf,int len)
{
int l1=0,l2=0;
int ret;
int l1=0,l2=0;
int ret;
if (!sparse_files)
return write(f,buf,len);
for (l1=0;l1<len && buf[l1]==0;l1++) ;
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
for (l1=0;l1<len && buf[l1]==0;l1++) ;
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
last_byte = buf[len-1];
last_byte = buf[len-1];
if (l1 == len || l2 > 0)
last_sparse=1;
if (l1 == len || l2 > 0)
last_sparse=1;
if (l1 > 0)
lseek(f,l1,SEEK_CUR);
if (l1 > 0)
lseek(f,l1,SEEK_CUR);
if (l1 == len)
return len;
if (l1 == len)
return len;
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
if (ret == -1 || ret == 0) return ret;
return (l1+ret);
}
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
if (ret == -1 || ret == 0) return ret;
return (l1+ret);
}
if (l2 > 0)
lseek(f,l2,SEEK_CUR);
return len;
if (l2 > 0)
lseek(f,l2,SEEK_CUR);
return len;
}
int read_write(int fd_in,int fd_out,int size)
{
static char *buf=NULL;
int bufsize = sparse_files?SPARSE_WRITE_SIZE:WRITE_SIZE;
int total=0;
if (!buf) {
buf = (char *)malloc(bufsize);
if (!buf) out_of_memory("read_write");
}
while (total < size) {
int n = MIN(size-total,bufsize);
read_buf(fd_in,buf,n);
if (write_sparse(fd_out,buf,n) != n)
return total;
total += n;
}
return total;
int write_file(int f,char *buf,int len)
{
int ret = 0;
if (!sparse_files)
return write(f,buf,len);
while (len>0) {
int len1 = MIN(len, SPARSE_WRITE_SIZE);
int r1 = write_sparse(f, buf, len1);
if (r1 <= 0) {
if (ret > 0) return ret;
return r1;
}
len -= r1;
buf += r1;
ret += r1;
}
return ret;
}
@@ -255,6 +322,7 @@ static int writefd(int fd,char *buf,int len)
/* hmmm, we got a write select on the fd and then failed to write.
Why doesn't that mean that the fd is dead? It doesn't on some
systems it seems (eg. IRIX) */
u_sleep(1000);
#if 0
fprintf(FERROR,"write exception\n");
exit_cleanup(1);
@@ -287,7 +355,10 @@ static int writefd(int fd,char *buf,int len)
exit_cleanup(1);
}
if (count == 0) continue;
if (count == 0) {
check_timeout();
continue;
}
if (FD_ISSET(fd, &w_fds)) {
got_select = 1;
@@ -297,6 +368,9 @@ static int writefd(int fd,char *buf,int len)
}
}
if (io_timeout)
last_io = time(NULL);
return total;
}
@@ -315,6 +389,29 @@ void write_int(int f,int x)
total_written += 4;
}
void write_longint(int f, int64 x)
{
extern int remote_version;
char b[8];
int ret;
if (remote_version < 16 || x <= 0x7FFFFFFF) {
write_int(f, (int)x);
return;
}
write_int(f, -1);
SIVAL(b,0,(x&0xFFFFFFFF));
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
if ((ret=writefd(f,b,8)) != 8) {
fprintf(FERROR,"write_longint failed : %s\n",
ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_written += 8;
}
void write_buf(int f,char *buf,int len)
{
int ret;

View File

@@ -7,6 +7,7 @@ config.h
config.log
config.status
dist.tar.gz
dummy
rsync
rsync-0.1
rsync-0.1
@@ -30,6 +31,13 @@ rsync-0.5
rsync-0.5
rsync-0.5
rsync-0.5.tar.gz
rsync-0.6
rsync-0.7
rsync-0.7
rsync-0.8
rsync-0.8
rsync-0.8
rsync-0.8
rsync-ERSION
rsync.aux
rsync.dvi
@@ -39,10 +47,3 @@ tech_report.dvi
tech_report.log
tech_report.ps
test
rsync-0.6
rsync-0.7
rsync-0.7
rsync-0.8
rsync-0.8
rsync-0.8
rsync-0.8

52
lib/compat.c Normal file
View File

@@ -0,0 +1,52 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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.
*/
/*
compatibility functions - replacing functions for platforms that don't
have them.
*/
#include "rsync.h"
#ifndef HAVE_STRDUP
char *strdup(char *s)
{
int l = strlen(s) + 1;
char *ret = (char *)malloc(l);
if (ret)
strcpy(ret,s);
return ret;
}
#endif
#ifndef HAVE_GETCWD
char *getcwd(char *buf, int size)
{
return getwd(buf);
}
#endif
#ifndef HAVE_WAITPID
pid_t waitpid(pid_t pid, int *statptr, int options)
{
return wait4(pid, statptr, options, NULL);
}
#endif

2
lib/dummy.in Normal file
View File

@@ -0,0 +1,2 @@
This is a dummy file to ensure that the lib directory gets created
by configure when a VPATH is used.

View File

@@ -252,7 +252,7 @@ typedef struct deflate_state {
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
Long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
@@ -1122,7 +1122,7 @@ local void fill_window(s)
s->match_start -= wsize;
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
s->block_start -= (long) wsize;
s->block_start -= (Long) wsize;
/* Slide the hash table (could be avoided with 32 bit values
at the expense of memory usage):
@@ -1187,7 +1187,7 @@ local void fill_window(s)
#define FLUSH_BLOCK_ONLY(s, flush) { \
ct_flush_block(s, (s->block_start >= 0L ? \
(charf *)&s->window[(unsigned)s->block_start] : \
(charf *)Z_NULL), (long)s->strstart - s->block_start, (flush)); \
(charf *)Z_NULL), (Long)s->strstart - s->block_start, (flush)); \
s->block_start = s->strstart; \
flush_pending(s->strm); \
Tracev((stderr,"[FLUSH]")); \
@@ -1907,8 +1907,8 @@ local void gen_bitlen(s, desc)
if (m > max_code) continue;
if (tree[m].Len != (unsigned) bits) {
Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
s->opt_len += ((long)bits - (long)tree[m].Len)
*(long)tree[m].Freq;
s->opt_len += ((Long)bits - (Long)tree[m].Len)
*(Long)tree[m].Freq;
tree[m].Len = (ush)bits;
}
n--;
@@ -4578,8 +4578,8 @@ uLong adler32(adler, buf, len)
Bytef *buf;
uInt len;
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
uLong s1 = adler & 0xffff;
uLong s2 = (adler >> 16) & 0xffff;
int k;
if (buf == Z_NULL) return 1L;

View File

@@ -112,7 +112,8 @@
typedef unsigned char Byte; /* 8 bits */
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
typedef int32 Long; /* 32 bits or more */
typedef uint32 uLong; /* 32 bits or more */
typedef Byte FAR Bytef;
typedef char FAR charf;

354
main.c
View File

@@ -22,14 +22,17 @@
int verbose = 0;
int always_checksum = 0;
time_t starttime;
off_t total_size = 0;
int64 total_size = 0;
int block_size=BLOCK_SIZE;
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
static char *rsync_path = RSYNC_NAME;
int make_backups = 0;
int whole_file = 0;
int copy_links = 0;
int preserve_links = 0;
int preserve_hard_links = 0;
int preserve_perms = 0;
@@ -50,44 +53,55 @@ int do_compression=0;
int am_root=0;
int orig_umask=0;
int relative_paths=0;
int numeric_ids = 0;
int force_delete = 0;
int io_timeout = 0;
int io_error = 0;
extern int csum_length;
int am_server = 0;
static int sender = 0;
int am_sender;
int recurse = 0;
static void usage(FILE *f);
static void report(int f)
{
int in,out,tsize;
int64 in,out,tsize;
time_t t = time(NULL);
if (!verbose) return;
if (am_server && sender) {
write_int(f,read_total());
write_int(f,write_total());
write_int(f,total_size);
if (am_server && am_sender) {
write_longint(f,read_total());
write_longint(f,write_total());
write_longint(f,total_size);
write_flush(f);
return;
}
if (sender) {
if (am_sender) {
in = read_total();
out = write_total();
tsize = (int)total_size;
tsize = total_size;
} else {
in = read_int(f);
out = read_int(f);
tsize = read_int(f);
in = read_longint(f);
out = read_longint(f);
tsize = read_longint(f);
}
printf("wrote %d bytes read %d bytes %g bytes/sec\n",
out,in,(in+out)/(0.5 + (t-starttime)));
printf("total size is %d speedup is %g\n",
tsize,(1.0*tsize)/(in+out));
#if HAVE_LONGLONG
printf("wrote %lld bytes read %lld bytes %.2f bytes/sec\n",
(long long)out,(long long)in,(in+out)/(0.5 + (t-starttime)));
printf("total size is %lld speedup is %.2f\n",
(long long)tsize,(1.0*tsize)/(in+out));
#else
printf("wrote %ld bytes read %ld bytes %.2f bytes/sec\n",
(long)out,(long)in,(in+out)/(0.5 + (t-starttime)));
printf("total size is %ld speedup is %.2f\n",
(long)tsize,(1.0*tsize)/(in+out));
#endif
}
@@ -96,11 +110,12 @@ static void server_options(char **args,int *argc)
int ac = *argc;
static char argstr[50];
static char bsize[30];
static char iotime[30];
int i, x;
args[ac++] = "--server";
if (!sender)
if (!am_sender)
args[ac++] = "--sender";
x = 1;
@@ -115,6 +130,10 @@ static void server_options(char **args,int *argc)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if (copy_links)
argstr[x++] = 'L';
if (whole_file)
argstr[x++] = 'W';
if (preserve_hard_links)
argstr[x++] = 'H';
if (preserve_uid)
@@ -152,85 +171,101 @@ static void server_options(char **args,int *argc)
args[ac++] = bsize;
}
if (io_timeout) {
sprintf(iotime,"--timeout=%d",io_timeout);
args[ac++] = iotime;
}
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
args[ac++] = "--suffix";
args[ac++] = backup_suffix;
}
if (delete_mode)
args[ac++] = "--delete";
if (force_delete)
args[ac++] = "--force";
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = tmpdir;
}
*argc = ac;
}
int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
{
char *args[100];
int i,argc=0;
char *tok,*p;
char *args[100];
int i,argc=0, ret;
char *tok,*dir=NULL;
if (!local_server) {
if (!cmd)
cmd = getenv(RSYNC_RSH_ENV);
if (!cmd)
cmd = RSYNC_RSH;
cmd = strdup(cmd);
if (!cmd)
goto oom;
if (!local_server) {
if (!cmd)
cmd = getenv(RSYNC_RSH_ENV);
if (!cmd)
cmd = RSYNC_RSH;
cmd = strdup(cmd);
if (!cmd)
goto oom;
for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
args[argc++] = tok;
}
for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
args[argc++] = tok;
}
#if HAVE_REMSH
/* remsh (on HPUX) takes the arguments the other way around */
args[argc++] = machine;
if (user) {
args[argc++] = "-l";
args[argc++] = user;
}
/* remsh (on HPUX) takes the arguments the other way around */
args[argc++] = machine;
if (user) {
args[argc++] = "-l";
args[argc++] = user;
}
#else
if (user) {
args[argc++] = "-l";
args[argc++] = user;
}
args[argc++] = machine;
if (user) {
args[argc++] = "-l";
args[argc++] = user;
}
args[argc++] = machine;
#endif
}
args[argc++] = rsync_path;
args[argc++] = rsync_path;
server_options(args,&argc);
server_options(args,&argc);
}
if (path && *path) {
char *dir = strdup(path);
p = strrchr(dir,'/');
if (p && !relative_paths) {
*p = 0;
if (!dir[0])
args[argc++] = "/";
else
args[argc++] = dir;
p++;
} else {
args[argc++] = ".";
p = dir;
}
if (p[0])
args[argc++] = path;
}
args[argc++] = ".";
args[argc] = NULL;
if (path && *path)
args[argc++] = path;
if (verbose > 3) {
fprintf(FERROR,"cmd=");
for (i=0;i<argc;i++)
fprintf(FERROR,"%s ",args[i]);
fprintf(FERROR,"\n");
}
args[argc] = NULL;
return piped_child(args,f_in,f_out);
if (verbose > 3) {
fprintf(FINFO,"cmd=");
for (i=0;i<argc;i++)
fprintf(FINFO,"%s ",args[i]);
fprintf(FINFO,"\n");
}
if (local_server) {
ret = local_child(argc, args, f_in, f_out);
} else {
ret = piped_child(args,f_in,f_out);
}
if (dir) free(dir);
return ret;
oom:
out_of_memory("do_cmd");
return 0; /* not reached */
out_of_memory("do_cmd");
return 0; /* not reached */
}
@@ -261,7 +296,7 @@ static char *get_local_name(struct file_list *flist,char *name)
if (!name)
return NULL;
if (mkdir(name,0777 & ~orig_umask) != 0) {
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
fprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
exit_cleanup(1);
} else {
@@ -282,31 +317,31 @@ static char *get_local_name(struct file_list *flist,char *name)
void do_server_sender(int argc,char *argv[])
{
int i;
char *dir = argv[0];
struct file_list *flist;
char *dir = argv[0];
if (verbose > 2)
fprintf(FERROR,"server_sender starting pid=%d\n",(int)getpid());
fprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
if (!relative_paths && chdir(dir) != 0) {
fprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
fprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
}
argc--;
argv++;
if (strcmp(dir,".")) {
int l = strlen(dir);
if (strcmp(dir,"/") == 0)
l = 0;
for (i=0;i<argc;i++)
argv[i] += l+1;
int l = strlen(dir);
if (strcmp(dir,"/") == 0)
l = 0;
for (i=0;i<argc;i++)
argv[i] += l+1;
}
if (argc == 0 && recurse) {
argc=1;
argv--;
argv[0] = ".";
argc=1;
argv--;
argv[0] = ".";
}
@@ -332,10 +367,10 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
}
if ((pid=fork()) == 0) {
if ((pid=do_fork()) == 0) {
recv_files(f_in,flist,local_name,recv_pipe[1]);
if (verbose > 2)
fprintf(FERROR,"receiver read %d\n",read_total());
fprintf(FINFO,"receiver read %ld\n",(long)read_total());
exit_cleanup(0);
}
@@ -350,21 +385,22 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
void do_server_recv(int argc,char *argv[])
{
int status;
char *dir = NULL;
struct file_list *flist;
char *local_name=NULL;
char *dir = NULL;
if (verbose > 2)
fprintf(FERROR,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
fprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
if (argc > 0) {
dir = argv[0];
argc--;
argv++;
if (chdir(dir) != 0) {
fprintf(FERROR,"chdir %s : %s (4)\n",dir,strerror(errno));
exit_cleanup(1);
}
dir = argv[0];
argc--;
argv++;
if (chdir(dir) != 0) {
fprintf(FERROR,"chdir %s : %s (4)\n",
dir,strerror(errno));
exit_cleanup(1);
}
}
if (delete_mode)
@@ -377,11 +413,11 @@ void do_server_recv(int argc,char *argv[])
}
if (argc > 0) {
if (strcmp(dir,".")) {
argv[0] += strlen(dir);
if (argv[0][0] == '/') argv[0]++;
}
local_name = get_local_name(flist,argv[0]);
if (strcmp(dir,".")) {
argv[0] += strlen(dir);
if (argv[0][0] == '/') argv[0]++;
}
local_name = get_local_name(flist,argv[0]);
}
status = do_recv(STDIN_FILENO,STDOUT_FILENO,flist,local_name);
@@ -389,6 +425,22 @@ void do_server_recv(int argc,char *argv[])
}
void start_server(int argc, char *argv[])
{
setup_protocol(STDOUT_FILENO,STDIN_FILENO);
if (am_sender) {
recv_exclude_list(STDIN_FILENO);
if (cvs_exclude)
add_cvs_excludes();
do_server_sender(argc,argv);
} else {
do_server_recv(argc,argv);
}
exit_cleanup(0);
}
static void usage(FILE *f)
{
fprintf(f,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
@@ -404,6 +456,7 @@ static void usage(FILE *f)
fprintf(f,"-b, --backup make backups (default ~ extension)\n");
fprintf(f,"-u, --update update only (don't overwrite newer files)\n");
fprintf(f,"-l, --links preserve soft links\n");
fprintf(f,"-L, --copy-links treat soft links like regular files\n");
fprintf(f,"-H, --hard-links preserve hard links\n");
fprintf(f,"-p, --perms preserve permissions\n");
fprintf(f,"-o, --owner preserve owner (root only)\n");
@@ -412,13 +465,18 @@ static void usage(FILE *f)
fprintf(f,"-t, --times preserve times\n");
fprintf(f,"-S, --sparse handle sparse files efficiently\n");
fprintf(f,"-n, --dry-run show what would have been transferred\n");
fprintf(f,"-W, --whole-file copy whole files, no incremental checks\n");
fprintf(f,"-x, --one-file-system don't cross filesystem boundaries\n");
fprintf(f,"-B, --block-size SIZE checksum blocking size\n");
fprintf(f,"-e, --rsh COMMAND specify rsh replacement\n");
fprintf(f," --rsync-path PATH specify path to rsync on the remote machine\n");
fprintf(f,"-C, --cvs-exclude auto ignore files in the same way CVS does\n");
fprintf(f," --delete delete files that don't exist on the sending side\n");
fprintf(f," --force force deletion of directories even if not empty\n");
fprintf(f," --numeric-ids don't map uid/gid values by user/group name\n");
fprintf(f," --timeout TIME set IO timeout in seconds\n");
fprintf(f,"-I, --ignore-times don't exclude files that match length and time\n");
fprintf(f,"-T --temp-dir DIR create temporary files in directory DIR\n");
fprintf(f,"-z, --compress compress file data\n");
fprintf(f," --exclude FILE exclude file FILE\n");
fprintf(f," --exclude-from FILE exclude files listed in FILE\n");
@@ -431,15 +489,18 @@ static void usage(FILE *f)
}
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_RSYNC_PATH};
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
OPT_FORCE,OPT_TIMEOUT};
static char *short_options = "oblHpguDCtcahvrRIxnSe:B:z";
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
static struct option long_options[] = {
{"version", 0, 0, OPT_VERSION},
{"server", 0, 0, OPT_SERVER},
{"sender", 0, 0, OPT_SENDER},
{"delete", 0, 0, OPT_DELETE},
{"force", 0, 0, OPT_FORCE},
{"numeric-ids", 0, 0, OPT_NUMERIC_IDS},
{"exclude", 1, 0, OPT_EXCLUDE},
{"exclude-from",1, 0, OPT_EXCLUDE_FROM},
{"rsync-path", 1, 0, OPT_RSYNC_PATH},
@@ -459,6 +520,8 @@ static struct option long_options[] = {
{"devices", 0, 0, 'D'},
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"copy-links", 0, 0, 'L'},
{"whole-file", 0, 0, 'W'},
{"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
{"group", 0, 0, 'g'},
@@ -466,9 +529,15 @@ static struct option long_options[] = {
{"rsh", 1, 0, 'e'},
{"suffix", 1, 0, OPT_SUFFIX},
{"block-size", 1, 0, 'B'},
{"timeout", 1, 0, OPT_TIMEOUT},
{"temp-dir", 1, 0, 'T'},
{"compress", 0, 0, 'z'},
{0,0,0,0}};
RETSIGTYPE sigusr1_handler(int val) {
exit_cleanup(1);
}
int main(int argc,char *argv[])
{
int pid, status = 0, status2 = 0;
@@ -483,12 +552,14 @@ int main(int argc,char *argv[])
struct file_list *flist;
char *local_name = NULL;
signal(SIGUSR1, sigusr1_handler);
starttime = time(NULL);
am_root = (getuid() == 0);
/* we set a 0 umask so that correct file permissions can be
carried across */
orig_umask = umask(0);
orig_umask = (int)umask(0);
while ((opt = getopt_long(argc, argv,
short_options, long_options, &option_index))
@@ -520,6 +591,14 @@ int main(int argc,char *argv[])
delete_mode = 1;
break;
case OPT_FORCE:
force_delete = 1;
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_EXCLUDE:
add_exclude(optarg);
break;
@@ -553,14 +632,23 @@ int main(int argc,char *argv[])
break;
case 'l':
#if SUPPORT_LINKS
preserve_links=1;
#endif
break;
case 'L':
copy_links=1;
break;
case 'W':
whole_file=1;
break;
case 'H':
#if SUPPORT_HARD_LINKS
preserve_hard_links=1;
#else
fprintf(FERROR,"ERROR: hard links not supported on this platform\n");
exit_cleanup(1);
#endif
break;
@@ -615,7 +703,7 @@ int main(int argc,char *argv[])
usage(FERROR);
exit_cleanup(1);
}
sender = 1;
am_sender = 1;
break;
case 'r':
@@ -634,6 +722,14 @@ int main(int argc,char *argv[])
block_size = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case 'T':
tmpdir = optarg;
break;
case 'z':
do_compression = 1;
break;
@@ -657,18 +753,15 @@ int main(int argc,char *argv[])
if (dry_run)
verbose = MAX(verbose,1);
#ifndef SUPPORT_LINKS
if (!am_server && preserve_links) {
fprintf(FERROR,"ERROR: symbolic links not supported\n");
exit_cleanup(1);
}
#endif
if (am_server) {
setup_protocol(STDOUT_FILENO,STDIN_FILENO);
if (sender) {
recv_exclude_list(STDIN_FILENO);
if (cvs_exclude)
add_cvs_excludes();
do_server_sender(argc,argv);
} else {
do_server_recv(argc,argv);
}
exit_cleanup(0);
start_server(argc, argv);
}
if (argc < 2) {
@@ -679,14 +772,14 @@ int main(int argc,char *argv[])
p = strchr(argv[0],':');
if (p) {
sender = 0;
am_sender = 0;
*p = 0;
shell_machine = argv[0];
shell_path = p+1;
argc--;
argv++;
} else {
sender = 1;
am_sender = 1;
p = strchr(argv[argc-1],':');
if (!p) {
@@ -714,14 +807,14 @@ int main(int argc,char *argv[])
}
if (verbose > 3) {
fprintf(FERROR,"cmd=%s machine=%s user=%s path=%s\n",
fprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
shell_cmd?shell_cmd:"",
shell_machine?shell_machine:"",
shell_user?shell_user:"",
shell_path?shell_path:"");
}
if (!sender && argc != 1) {
if (!am_sender && argc != 1) {
usage(FERROR);
exit_cleanup(1);
}
@@ -730,24 +823,26 @@ int main(int argc,char *argv[])
setup_protocol(f_out,f_in);
#if HAVE_SETLINEBUF
setlinebuf(FINFO);
setlinebuf(FERROR);
#endif
if (verbose > 3)
fprintf(FERROR,"parent=%d child=%d sender=%d recurse=%d\n",
(int)getpid(),pid,sender,recurse);
fprintf(FINFO,"parent=%d child=%d sender=%d recurse=%d\n",
(int)getpid(),pid,am_sender,recurse);
if (sender) {
if (am_sender) {
if (cvs_exclude)
add_cvs_excludes();
if (delete_mode)
send_exclude_list(f_out);
flist = send_file_list(f_out,argc,argv);
if (verbose > 3)
fprintf(FERROR,"file list sent\n");
fprintf(FINFO,"file list sent\n");
send_files(flist,f_out,f_in);
if (verbose > 3)
fprintf(FERROR,"waiting on %d\n",pid);
fprintf(FINFO,"waiting on %d\n",pid);
waitpid(pid, &status, 0);
report(-1);
exit_cleanup(status);
@@ -757,7 +852,7 @@ int main(int argc,char *argv[])
flist = recv_file_list(f_in);
if (!flist || flist->count == 0) {
fprintf(FERROR,"nothing to do\n");
fprintf(FINFO,"nothing to do\n");
exit_cleanup(0);
}
@@ -771,3 +866,4 @@ int main(int argc,char *argv[])
return status | status2;
}

316
match.c
View File

@@ -36,10 +36,10 @@ static int tag_hits;
static int matches;
static int data_transfer;
static int total_false_alarms=0;
static int total_tag_hits=0;
static int total_matches=0;
static int total_data_transfer=0;
static int total_false_alarms;
static int total_tag_hits;
static int total_matches;
static int64 total_data_transfer;
struct target {
@@ -47,9 +47,9 @@ struct target {
int i;
};
static struct target *targets=NULL;
static struct target *targets;
static tag *tag_table = NULL;
static tag *tag_table;
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
@@ -91,187 +91,191 @@ static off_t last_match;
static void matched(int f,struct sum_struct *s,struct map_struct *buf,
int offset,int i)
off_t offset,int i)
{
int n = offset - last_match;
int j;
off_t n = offset - last_match;
int j;
if (verbose > 2)
if (i != -1)
fprintf(FERROR,"match at %d last_match=%d j=%d len=%d n=%d\n",
(int)offset,(int)last_match,i,(int)s->sums[i].len,n);
if (verbose > 2 && i >= 0)
fprintf(FINFO,"match at %d last_match=%d j=%d len=%d n=%d\n",
(int)offset,(int)last_match,i,(int)s->sums[i].len,(int)n);
send_token(f,i,buf,last_match,n,i==-1?0:s->sums[i].len);
data_transfer += n;
send_token(f,i,buf,last_match,n,i==-1?0:s->sums[i].len);
data_transfer += n;
if (n > 0)
write_flush(f);
if (n > 0)
write_flush(f);
if (i != -1)
n += s->sums[i].len;
if (i >= 0)
n += s->sums[i].len;
for (j=0;j<n;j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,n-j);
sum_update(map_ptr(buf,last_match+j,n1),n1);
}
for (j=0;j<n;j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,n-j);
sum_update(map_ptr(buf,last_match+j,n1),n1);
}
if (i != -1)
last_match = offset + s->sums[i].len;
if (i >= 0)
last_match = offset + s->sums[i].len;
else
last_match = offset;
}
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf,off_t len)
{
int offset,j,k;
int end;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
signed char *map;
off_t offset;
int j,k;
int end;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
signed char *map;
if (verbose > 2)
fprintf(FERROR,"hash search b=%d len=%d\n",s->n,(int)len);
if (verbose > 2)
fprintf(FINFO,"hash search b=%d len=%d\n",s->n,(int)len);
k = MIN(len, s->n);
k = MIN(len, s->n);
map = (signed char *)map_ptr(buf,0,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
fprintf(FINFO, "sum=%.8x k=%d\n", sum, k);
offset = 0;
end = len + 1 - s->sums[s->count-1].len;
if (verbose > 3)
fprintf(FINFO,"hash search s->n=%d len=%d count=%d\n",
s->n,(int)len,s->count);
do {
tag t = gettag2(s1,s2);
int done_csum2 = 0;
j = tag_table[t];
if (verbose > 4)
fprintf(FINFO,"offset=%d sum=%08x\n",(int)offset,sum);
if (j == NULL_TAG) {
goto null_tag;
}
map = (signed char *)map_ptr(buf,0,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
fprintf(FERROR, "sum=%.8x k=%d\n", sum, k);
offset = 0;
end = len + 1 - s->sums[s->count-1].len;
if (verbose > 3)
fprintf(FERROR,"hash search s->n=%d len=%d count=%d\n",
s->n,(int)len,s->count);
do {
tag t = gettag2(s1,s2);
j = tag_table[t];
if (verbose > 4)
fprintf(FERROR,"offset=%d sum=%08x\n",
offset,sum);
if (j != NULL_TAG) {
int done_csum2 = 0;
sum = (s1 & 0xffff) | (s2 << 16);
tag_hits++;
do {
int i = targets[j].i;
if (sum == s->sums[i].sum1) {
if (verbose > 3)
fprintf(FERROR,"potential match at %d target=%d %d sum=%08x\n",
offset,j,i,sum);
if (!done_csum2) {
int l = MIN(s->n,len-offset);
map = (signed char *)map_ptr(buf,offset,l);
get_checksum2((char *)map,l,sum2);
done_csum2 = 1;
}
if (memcmp(sum2,s->sums[i].sum2,csum_length) == 0) {
matched(f,s,buf,offset,i);
offset += s->sums[i].len - 1;
k = MIN((len-offset), s->n);
map = (signed char *)map_ptr(buf,offset,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
++matches;
break;
} else {
false_alarms++;
}
}
j++;
} while (j<s->count && targets[j].t == t);
}
/* Trim off the first byte from the checksum */
map = (signed char *)map_ptr(buf,offset,k+1);
s1 -= map[0] + CHAR_OFFSET;
s2 -= k * (map[0]+CHAR_OFFSET);
/* Add on the next byte (if there is one) to the checksum */
if (k < (len-offset)) {
s1 += (map[k]+CHAR_OFFSET);
s2 += s1;
} else {
--k;
}
} while (++offset < end);
matched(f,s,buf,len,-1);
map_ptr(buf,len-1,1);
sum = (s1 & 0xffff) | (s2 << 16);
tag_hits++;
for (; j<s->count && targets[j].t == t; j++) {
int i = targets[j].i;
if (sum != s->sums[i].sum1) continue;
if (verbose > 3)
fprintf(FINFO,"potential match at %d target=%d %d sum=%08x\n",
(int)offset,j,i,sum);
if (!done_csum2) {
int l = MIN(s->n,len-offset);
map = (signed char *)map_ptr(buf,offset,l);
get_checksum2((char *)map,l,sum2);
done_csum2 = 1;
}
if (memcmp(sum2,s->sums[i].sum2,csum_length) != 0) {
false_alarms++;
continue;
}
matched(f,s,buf,offset,i);
offset += s->sums[i].len - 1;
k = MIN((len-offset), s->n);
map = (signed char *)map_ptr(buf,offset,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
matches++;
break;
}
null_tag:
/* Trim off the first byte from the checksum */
map = (signed char *)map_ptr(buf,offset,k+1);
s1 -= map[0] + CHAR_OFFSET;
s2 -= k * (map[0]+CHAR_OFFSET);
/* Add on the next byte (if there is one) to the checksum */
if (k < (len-offset)) {
s1 += (map[k]+CHAR_OFFSET);
s2 += s1;
} else {
--k;
}
} while (++offset < end);
matched(f,s,buf,len,-1);
map_ptr(buf,len-1,1);
}
void match_sums(int f,struct sum_struct *s,struct map_struct *buf,off_t len)
{
char file_sum[MD4_SUM_LENGTH];
char file_sum[MD4_SUM_LENGTH];
last_match = 0;
false_alarms = 0;
tag_hits = 0;
matches=0;
data_transfer=0;
last_match = 0;
false_alarms = 0;
tag_hits = 0;
matches=0;
data_transfer=0;
sum_init();
sum_init();
if (len > 0 && s->count>0) {
build_hash_table(s);
if (len > 0 && s->count>0) {
build_hash_table(s);
if (verbose > 2)
fprintf(FINFO,"built hash table\n");
hash_search(f,s,buf,len);
if (verbose > 2)
fprintf(FINFO,"done hash search\n");
} else {
matched(f,s,buf,len,-1);
}
if (verbose > 2)
fprintf(FERROR,"built hash table\n");
sum_end(file_sum);
hash_search(f,s,buf,len);
if (remote_version >= 14) {
if (verbose > 2)
fprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
}
if (verbose > 2)
fprintf(FERROR,"done hash search\n");
} else {
matched(f,s,buf,len,-1);
}
sum_end(file_sum);
if (remote_version >= 14) {
if (verbose > 2)
fprintf(FERROR,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
}
if (targets) {
free(targets);
targets=NULL;
}
if (verbose > 2)
fprintf(FERROR, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
total_tag_hits += tag_hits;
total_false_alarms += false_alarms;
total_matches += matches;
total_data_transfer += data_transfer;
if (targets) {
free(targets);
targets=NULL;
}
if (verbose > 2)
fprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
total_tag_hits += tag_hits;
total_false_alarms += false_alarms;
total_matches += matches;
total_data_transfer += data_transfer;
}
void match_report(void)
{
if (verbose <= 1)
return;
if (verbose <= 1)
return;
fprintf(FINFO,
"total: matches=%d tag_hits=%d false_alarms=%d data=%d\n",
total_matches,total_tag_hits,
total_false_alarms,total_data_transfer);
fprintf(FINFO,
"total: matches=%d tag_hits=%d false_alarms=%d data=%ld\n",
total_matches,total_tag_hits,
total_false_alarms,(long)total_data_transfer);
}

View File

@@ -23,7 +23,7 @@ BEGIN {
next;
}
!/^off_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
!/^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
next;
}

647
rsync.c
View File

File diff suppressed because it is too large Load Diff

88
rsync.h
View File

@@ -39,11 +39,11 @@
#define SAME_TIME (1<<7)
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 14
#define MIN_PROTOCOL_VERSION 10
#define MAX_PROTOCOL_VERSION 20
#define PROTOCOL_VERSION 17
#define MIN_PROTOCOL_VERSION 11
#define MAX_PROTOCOL_VERSION 30
#define SPARSE_WRITE_SIZE (4*1024)
#define SPARSE_WRITE_SIZE (1024)
#define WRITE_SIZE (32*1024)
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (4*1024*1024)
@@ -163,6 +163,13 @@
#include "lib/getopt.h"
#endif
/* these are needed for the uid/gid mapping code */
#include <pwd.h>
#include <grp.h>
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
@@ -186,6 +193,11 @@
#define uint32 unsigned int32
#endif
#ifdef HAVE_LONGLONG
#define int64 long long
#else
#define int64 off_t
#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
@@ -204,24 +216,25 @@
#endif
struct file_struct {
time_t modtime;
off_t length;
mode_t mode;
ino_t inode;
dev_t dev;
dev_t rdev;
uid_t uid;
gid_t gid;
char *name;
char *dir;
char *link;
char sum[MD4_SUM_LENGTH];
time_t modtime;
off_t length;
mode_t mode;
ino_t inode;
dev_t dev;
dev_t rdev;
uid_t uid;
gid_t gid;
char *basename;
char *dirname;
char *basedir;
char *link;
char *sum;
};
struct file_list {
int count;
int malloced;
struct file_struct *files;
struct file_struct **files;
};
struct sum_buf {
@@ -241,10 +254,21 @@ struct sum_struct {
};
struct map_struct {
char *map,*p;
int fd,size,p_size,p_offset,p_len;
char *map,*p;
int fd,p_size,p_len;
off_t size, p_offset;
};
/* we need this function because of the silly way in which duplicate
entries are handled in the file lists - we can't change this
without breaking existing versions */
static inline int flist_up(struct file_list *flist, int i)
{
while (!flist->files[i]->basename) i++;
return i;
}
#include "byteorder.h"
#include "version.h"
#include "proto.h"
@@ -287,17 +311,9 @@ extern int errno;
#define bzero(buf,n) memset(buf,0,n)
#endif
#define SUPPORT_LINKS (HAVE_READLINK && defined(S_ISLNK))
#define SUPPORT_LINKS HAVE_READLINK
#define SUPPORT_HARD_LINKS HAVE_LINK
#ifndef S_ISLNK
#define S_ISLNK(x) 0
#endif
#if !SUPPORT_LINKS
#define lstat stat
#endif
#ifndef HAVE_LCHOWN
#define lchown chown
#endif
@@ -324,5 +340,21 @@ extern int errno;
#define S_IWUSR 0200
#endif
#ifndef S_ISBLK
#define S_ISBLK(mode) (((mode) & (_S_IFMT)) == (_S_IFBLK))
#endif
#ifndef S_ISCHR
#define S_ISCHR(mode) (((mode) & (_S_IFMT)) == (_S_IFCHR))
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR))
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
#endif
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))

97
syscall.c Normal file
View File

@@ -0,0 +1,97 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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.
*/
/*
syscall wrappers to ensure that nothing gets done in dry_run mode
*/
#include "rsync.h"
extern int dry_run;
int do_unlink(char *fname)
{
if (dry_run) return 0;
return unlink(fname);
}
int do_symlink(char *fname1, char *fname2)
{
if (dry_run) return 0;
return symlink(fname1, fname2);
}
#if HAVE_LINK
int do_link(char *fname1, char *fname2)
{
if (dry_run) return 0;
return link(fname1, fname2);
}
#endif
int do_lchown(const char *path, uid_t owner, gid_t group)
{
if (dry_run) return 0;
return lchown(path, owner, group);
}
#if HAVE_MKNOD
int do_mknod(char *pathname, mode_t mode, dev_t dev)
{
if (dry_run) return 0;
return mknod(pathname, mode, dev);
}
#endif
int do_rmdir(char *pathname)
{
if (dry_run) return 0;
return rmdir(pathname);
}
int do_open(char *pathname, int flags, mode_t mode)
{
if (dry_run) return -1;
return open(pathname, flags, mode);
}
#if HAVE_CHMOD
int do_chmod(const char *path, mode_t mode)
{
if (dry_run) return 0;
return chmod(path, mode);
}
#endif
int do_rename(char *fname1, char *fname2)
{
if (dry_run) return 0;
return rename(fname1, fname2);
}
int do_mkdir(char *fname, mode_t mode)
{
if (dry_run) return 0;
return mkdir(fname, mode);
}
char *do_mktemp(char *template)
{
if (dry_run) return NULL;
return mktemp(template);
}

10
token.c
View File

@@ -26,8 +26,8 @@ extern int do_compression;
/* non-compressing recv token */
static int simple_recv_token(int f,char **data)
{
static int residue = 0;
static char *buf = NULL;
static int residue;
static char *buf;
int n;
if (!buf) {
@@ -99,7 +99,7 @@ static int last_run_end;
static z_stream tx_strm;
/* Output buffer */
static char *obuf = NULL;
static char *obuf;
/* Send a deflated token */
static void
@@ -220,8 +220,8 @@ static int
recv_deflated_token(int f, char **data)
{
int n, r, flag;
static int init_done = 0;
static int saved_flag = 0;
static int init_done;
static int saved_flag;
for (;;) {
switch (recv_state) {

310
uidlist.c Normal file
View File

@@ -0,0 +1,310 @@
/*
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.
*/
/* handle the mapping of uid/gid and user/group names between systems.
If the source username/group does not exist on the target then use
the numeric ids. Never do any mapping for uid=0 or gid=0 as these
are special.
*/
#include "rsync.h"
extern int preserve_uid;
extern int preserve_gid;
extern int numeric_ids;
struct idlist {
struct idlist *next;
int id, id2;
char *name;
};
static struct idlist *uidlist;
static struct idlist *gidlist;
static struct idlist *add_list(int id, char *name)
{
struct idlist *list = (struct idlist *)malloc(sizeof(list[0]));
if (!list) out_of_memory("add_list");
list->next = NULL;
list->name = strdup(name);
if (!list->name) out_of_memory("add_list");
list->id = (int)id;
return list;
}
/* turn a uid into a user name */
static char *uid_to_name(uid_t uid)
{
struct passwd *pass = getpwuid(uid);
if (pass) return(pass->pw_name);
return NULL;
}
/* turn a gid into a group name */
static char *gid_to_name(gid_t gid)
{
struct group *grp = getgrgid(gid);
if (grp) return(grp->gr_name);
return NULL;
}
/* turn a user name into a uid */
static uid_t name_to_uid(char *name)
{
struct passwd *pass;
if (!name || !*name) return 0;
pass = getpwnam(name);
if (pass) return(pass->pw_uid);
return 0;
}
/* turn a group name into a gid */
static gid_t name_to_gid(char *name)
{
struct group *grp;
if (!name || !*name) return 0;
grp = getgrnam(name);
if (grp) return(grp->gr_gid);
return 0;
}
static int map_uid(int id, char *name)
{
uid_t uid = name_to_uid(name);
if (uid != 0) return uid;
return id;
}
static int map_gid(int id, char *name)
{
gid_t gid = name_to_gid(name);
if (gid != 0) return gid;
return id;
}
/* this function is a definate candidate for a faster algorithm */
static uid_t match_uid(uid_t uid)
{
static uid_t last_in, last_out;
struct idlist *list = uidlist;
if (uid == last_in) return last_out;
last_in = uid;
while (list) {
if (list->id == (int)uid) {
last_out = (uid_t)list->id2;
return last_out;
}
list = list->next;
}
last_out = uid;
return last_out;
}
static gid_t match_gid(gid_t gid)
{
static gid_t last_in, last_out;
struct idlist *list = gidlist;
if (gid == last_in) return last_out;
last_in = gid;
while (list) {
if (list->id == (int)gid) {
last_out = (gid_t)list->id2;
return last_out;
}
list = list->next;
}
last_out = gid;
return last_out;
}
/* add a uid to the list of uids */
void add_uid(uid_t uid)
{
struct idlist *list = uidlist;
char *name;
if (numeric_ids) return;
/* don't map root */
if (uid==0) return;
if (!list) {
if (!(name = uid_to_name(uid))) return;
uidlist = add_list((int)uid, name);
return;
}
while (list->next) {
if (list->id == (int)uid) return;
list = list->next;
}
if (list->id == (int)uid) return;
if (!(name = uid_to_name(uid))) return;
list->next = add_list((int)uid, name);
}
/* add a gid to the list of gids */
void add_gid(gid_t gid)
{
struct idlist *list = gidlist;
char *name;
if (numeric_ids) return;
/* don't map root */
if (gid==0) return;
if (!list) {
if (!(name = gid_to_name(gid))) return;
gidlist = add_list((int)gid, name);
return;
}
while (list->next) {
if (list->id == (int)gid) return;
list = list->next;
}
if (list->id == (int)gid) return;
if (!(name = gid_to_name(gid))) return;
list->next = add_list((int)gid, name);
}
/* send a complete uid/gid mapping to the peer */
void send_uid_list(int f)
{
struct idlist *list;
if (numeric_ids) return;
if (preserve_uid) {
/* we send sequences of uid/byte-length/name */
list = uidlist;
while (list) {
int len = strlen(list->name);
write_int(f, list->id);
write_byte(f, len);
write_buf(f, list->name, len);
list = list->next;
}
/* terminate the uid list with a 0 uid. We explicitly exclude
0 from the list */
write_int(f, 0);
}
if (preserve_gid) {
list = gidlist;
while (list) {
int len = strlen(list->name);
write_int(f, list->id);
write_byte(f, len);
write_buf(f, list->name, len);
list = list->next;
}
write_int(f, 0);
}
}
/* recv a complete uid/gid mapping from the peer and map the uid/gid
in the file list to local names */
void recv_uid_list(int f, struct file_list *flist)
{
int id, i;
char *name;
struct idlist *list;
if (numeric_ids) return;
if (preserve_uid) {
/* read the uid list */
list = uidlist;
id = read_int(f);
while (id != 0) {
int len = read_byte(f);
name = (char *)malloc(len+1);
if (!name) out_of_memory("recv_uid_list");
read_sbuf(f, name, len);
if (!list) {
uidlist = add_list(id, name);
list = uidlist;
} else {
list->next = add_list(id, name);
list = list->next;
}
list->id2 = map_uid(id, name);
free(name);
id = read_int(f);
}
}
if (preserve_gid) {
/* and the gid list */
list = gidlist;
id = read_int(f);
while (id != 0) {
int len = read_byte(f);
name = (char *)malloc(len+1);
if (!name) out_of_memory("recv_uid_list");
read_sbuf(f, name, len);
if (!list) {
gidlist = add_list(id, name);
list = gidlist;
} else {
list->next = add_list(id, name);
list = list->next;
}
list->id2 = map_gid(id, name);
free(name);
id = read_int(f);
}
}
if (!uidlist && !gidlist) return;
/* now convert the uid/gid of all files in the list to the mapped
uid/gid */
for (i=0;i<flist->count;i++) {
if (preserve_uid && flist->files[i]->uid != 0) {
flist->files[i]->uid = match_uid(flist->files[i]->uid);
}
if (preserve_gid && flist->files[i]->gid != 0) {
flist->files[i]->gid = match_gid(flist->files[i]->gid);
}
}
}

258
util.c
View File

@@ -53,6 +53,7 @@ struct map_struct *map_file(int fd,off_t len)
return ret;
}
char *map_ptr(struct map_struct *map,off_t offset,int len)
{
int nread = -2;
@@ -63,7 +64,8 @@ char *map_ptr(struct map_struct *map,off_t offset,int len)
if (len == 0)
return NULL;
len = MIN(len,map->size-offset);
if (len > (map->size-offset))
len = map->size-offset;
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
@@ -71,7 +73,8 @@ char *map_ptr(struct map_struct *map,off_t offset,int len)
}
len = MAX(len,CHUNK_SIZE);
len = MIN(len,map->size - offset);
if (len > (map->size-offset))
len = map->size-offset;
if (len > map->p_size) {
if (map->p) free(map->p);
@@ -82,9 +85,9 @@ char *map_ptr(struct map_struct *map,off_t offset,int len)
if (lseek(map->fd,offset,SEEK_SET) != offset ||
(nread=read(map->fd,map->p,len)) != len) {
fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
(int)offset, len, nread, errno);
exit_cleanup(1);
fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
(int)offset, len, nread, errno);
exit_cleanup(1);
}
map->p_offset = offset;
@@ -119,7 +122,7 @@ int piped_child(char **command,int *f_in,int *f_out)
}
pid = fork();
pid = do_fork();
if (pid < 0) {
fprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
@@ -156,46 +159,96 @@ int piped_child(char **command,int *f_in,int *f_out)
return pid;
}
int local_child(int argc, char **argv,int *f_in,int *f_out)
{
int pid;
int to_child_pipe[2];
int from_child_pipe[2];
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
fprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
}
pid = do_fork();
if (pid < 0) {
fprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
}
if (pid == 0) {
extern int am_sender;
extern int am_server;
am_sender = !am_sender;
am_server = 1;
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
start_server(argc, argv);
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
}
*f_in = from_child_pipe[0];
*f_out = to_child_pipe[1];
return pid;
}
void out_of_memory(char *str)
{
fprintf(FERROR,"out of memory in %s\n",str);
fprintf(FERROR,"ERROR: out of memory in %s\n",str);
exit_cleanup(1);
}
void overflow(char *str)
{
fprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
exit_cleanup(1);
}
#ifndef HAVE_STRDUP
char *strdup(char *s)
{
int l = strlen(s) + 1;
char *ret = (char *)malloc(l);
if (ret)
strcpy(ret,s);
return ret;
}
#endif
int set_modtime(char *fname,time_t modtime)
{
#ifdef HAVE_UTIME_H
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
return utime(fname,&tbuf);
extern int dry_run;
if (dry_run) return 0;
{
#ifdef HAVE_UTIMBUF
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
return utime(fname,&tbuf);
#elif defined(HAVE_UTIME)
time_t t[2];
t[0] = time(NULL);
t[1] = modtime;
return utime(fname,t);
time_t t[2];
t[0] = time(NULL);
t[1] = modtime;
return utime(fname,t);
#else
struct timeval t[2];
t[0].tv_sec = time(NULL);
t[0].tv_usec = 0;
t[1].tv_sec = modtime;
t[1].tv_usec = 0;
return utimes(fname,t);
struct timeval t[2];
t[0].tv_sec = time(NULL);
t[0].tv_usec = 0;
t[1].tv_sec = modtime;
t[1].tv_usec = 0;
return utimes(fname,t);
#endif
}
}
@@ -245,9 +298,146 @@ int create_directory_path(char *fname)
p = fname;
while ((p=strchr(p,'/'))) {
*p = 0;
mkdir(fname,0777 & ~orig_umask);
do_mkdir(fname,0777 & ~orig_umask);
*p = '/';
p++;
}
return 0;
}
/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
Return LEN upon success, write's (negative) error code otherwise.
derived from GNU C's cccp.c.
*/
int full_write(int desc, char *ptr, int len)
{
int total_written;
total_written = 0;
while (len > 0) {
int written = write (desc, ptr, len);
if (written < 0) {
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
return written;
}
total_written += written;
ptr += written;
len -= written;
}
return total_written;
}
/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
Return the actual number of bytes read, zero for EOF, or negative
for an error.
derived from GNU C's cccp.c. */
int safe_read(int desc, char *ptr, int len)
{
int n_chars;
if (len <= 0)
return len;
#ifdef EINTR
do {
n_chars = read(desc, ptr, len);
} while (n_chars < 0 && errno == EINTR);
#else
n_chars = read(desc, ptr, len);
#endif
return n_chars;
}
/* copy a file - this is used in conjunction with the --temp-dir option */
int copy_file(char *source, char *dest, mode_t mode)
{
int ifd;
int ofd;
char buf[1024 * 8];
int len; /* Number of bytes read into `buf'. */
ifd = open(source, O_RDONLY);
if (ifd == -1) {
fprintf(FERROR,"open %s: %s\n",
source,strerror(errno));
return -1;
}
if (do_unlink(dest) && errno != ENOENT) {
fprintf(FERROR,"unlink %s: %s\n",
dest,strerror(errno));
return -1;
}
ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
if (ofd < 0) {
fprintf(FERROR,"open %s: %s\n",
dest,strerror(errno));
close(ifd);
return -1;
}
while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
if (full_write(ofd, buf, len) < 0) {
fprintf(FERROR,"write %s: %s\n",
dest,strerror(errno));
close(ifd);
close(ofd);
return -1;
}
}
close(ifd);
close(ofd);
if (len < 0) {
fprintf(FERROR,"read %s: %s\n",
source,strerror(errno));
return -1;
}
return 0;
}
/* sleep for a while via select */
void u_sleep(int usec)
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = usec;
select(0, NULL, NULL, NULL, &tv);
}
static pid_t all_pids[10];
static int num_pids;
/* fork and record the pid of the child */
pid_t do_fork(void)
{
pid_t newpid = fork();
if (newpid) {
all_pids[num_pids++] = newpid;
}
return newpid;
}
/* kill all children */
void kill_all(int sig)
{
int i;
for (i=0;i<num_pids;i++) {
if (all_pids[i] != getpid())
kill(all_pids[i], sig);
}
}

View File

@@ -1 +1 @@
#define VERSION "1.6.6"
#define VERSION "1.7.3"