mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 23:35:27 -04:00
Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf0d1d819a | ||
|
|
0a25de67e9 | ||
|
|
317302412e | ||
|
|
1250f24ed2 | ||
|
|
945eba8c1f | ||
|
|
d867229ba0 | ||
|
|
1b2d733af2 | ||
|
|
366345fe05 | ||
|
|
dd04a03440 | ||
|
|
575f2fca9a | ||
|
|
fc4e8d51ff | ||
|
|
98ae8c3e38 | ||
|
|
49f4b973a1 | ||
|
|
a070c37b7e | ||
|
|
17faa41c7d | ||
|
|
a90da9985a | ||
|
|
8a24eece38 | ||
|
|
6ba9279fb2 | ||
|
|
5fb543d587 | ||
|
|
0c5f37d9db | ||
|
|
42849e9202 | ||
|
|
a746eb9de0 | ||
|
|
71c4617611 | ||
|
|
3cb6f5d6cb | ||
|
|
366bd9056c | ||
|
|
ac71984aae | ||
|
|
649d65edf3 | ||
|
|
7796395a0a | ||
|
|
76076c4bbd | ||
|
|
f92ef572b9 | ||
|
|
7308bd66e0 | ||
|
|
0d0e2e93e8 | ||
|
|
31e125226d | ||
|
|
3a6a366fc5 | ||
|
|
0b91056090 | ||
|
|
a76a0039fc | ||
|
|
2d0bb8eb0f | ||
|
|
e7ebc36c70 | ||
|
|
1aa71c8d57 | ||
|
|
bd39e9d263 | ||
|
|
3ba62a8308 | ||
|
|
feaa89c410 | ||
|
|
3ec4dd9781 | ||
|
|
ec0e5ac001 | ||
|
|
1e9f155ade | ||
|
|
6bbbc08b83 | ||
|
|
13dc412d76 | ||
|
|
950ab32d38 | ||
|
|
d0390cd384 | ||
|
|
f6c347425a | ||
|
|
3b3a2fbcf0 | ||
|
|
95a38e8684 | ||
|
|
c778aaa048 | ||
|
|
3fac9b6e93 | ||
|
|
964ca2eca5 | ||
|
|
684b4e3113 | ||
|
|
dc7a947853 | ||
|
|
b73c59a2c4 | ||
|
|
f3644f1f2d | ||
|
|
e3cd198f8e | ||
|
|
5c36219d40 | ||
|
|
f0e5517fb8 | ||
|
|
18463a5a5a | ||
|
|
82306bf6d6 | ||
|
|
cbbe489208 | ||
|
|
6dd1782c42 | ||
|
|
fee64929a3 |
30
Makefile.in
30
Makefile.in
@@ -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
14
README
@@ -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/
|
||||
|
||||
@@ -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
157
compat.c
@@ -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) {
|
||||
|
||||
17
configure.in
17
configure.in
@@ -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)
|
||||
|
||||
13
exclude.c
13
exclude.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
73
hlink.c
73
hlink.c
@@ -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
263
io.c
@@ -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;
|
||||
|
||||
@@ -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
52
lib/compat.c
Normal 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
2
lib/dummy.in
Normal 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.
|
||||
14
lib/zlib.c
14
lib/zlib.c
@@ -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;
|
||||
|
||||
@@ -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
354
main.c
@@ -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
316
match.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
88
rsync.h
88
rsync.h
@@ -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
97
syscall.c
Normal 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
10
token.c
@@ -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
310
uidlist.c
Normal 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
258
util.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user