mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
24
Makefile.in
24
Makefile.in
@@ -7,32 +7,36 @@ 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:
|
||||
@@ -41,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)
|
||||
|
||||
10
README
10
README
@@ -47,7 +47,11 @@ Options:
|
||||
--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
|
||||
@@ -89,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
|
||||
@@ -119,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
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
15
configure.in
15
configure.in
@@ -52,4 +52,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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
35
hlink.c
35
hlink.c
@@ -31,17 +31,17 @@ 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)
|
||||
@@ -80,7 +80,10 @@ int check_hard_link(struct file_struct *file)
|
||||
while (low != high) {
|
||||
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
|
||||
@@ -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 (link_stat(hlink_list[i-1].name,&st1) != 0) continue;
|
||||
if (link_stat(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
|
||||
|
||||
183
io.c
183
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,70 @@ 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;
|
||||
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 +177,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;
|
||||
@@ -165,8 +225,8 @@ 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)
|
||||
{
|
||||
@@ -211,27 +271,6 @@ int write_sparse(int f,char *buf,int len)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int writefd(int fd,char *buf,int len)
|
||||
{
|
||||
@@ -255,6 +294,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 +327,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 +340,9 @@ static int writefd(int fd,char *buf,int len)
|
||||
}
|
||||
}
|
||||
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -315,6 +361,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.
|
||||
194
main.c
194
main.c
@@ -22,10 +22,11 @@
|
||||
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;
|
||||
|
||||
@@ -52,26 +53,30 @@ 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;
|
||||
static int 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);
|
||||
write_longint(f,read_total());
|
||||
write_longint(f,write_total());
|
||||
write_longint(f,total_size);
|
||||
write_flush(f);
|
||||
return;
|
||||
}
|
||||
@@ -79,17 +84,24 @@ static void report(int f)
|
||||
if (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 %g bytes/sec\n",
|
||||
(long long)out,(long long)in,(in+out)/(0.5 + (t-starttime)));
|
||||
printf("total size is %lld speedup is %g\n",
|
||||
(long long)tsize,(1.0*tsize)/(in+out));
|
||||
#else
|
||||
printf("wrote %ld bytes read %ld bytes %g bytes/sec\n",
|
||||
(long)out,(long)in,(in+out)/(0.5 + (t-starttime)));
|
||||
printf("total size is %ld speedup is %g\n",
|
||||
(long)tsize,(1.0*tsize)/(in+out));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +110,7 @@ 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";
|
||||
@@ -158,9 +171,30 @@ 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;
|
||||
}
|
||||
|
||||
@@ -170,7 +204,7 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f
|
||||
{
|
||||
char *args[100];
|
||||
int i,argc=0, ret;
|
||||
char *tok,*p,*dir=NULL;
|
||||
char *tok,*dir=NULL;
|
||||
|
||||
if (!local_server) {
|
||||
if (!cmd)
|
||||
@@ -205,31 +239,18 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f
|
||||
|
||||
server_options(args,&argc);
|
||||
|
||||
if (path && *path) {
|
||||
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++] = ".";
|
||||
|
||||
if (path && *path)
|
||||
args[argc++] = path;
|
||||
|
||||
args[argc] = NULL;
|
||||
|
||||
if (verbose > 3) {
|
||||
fprintf(FERROR,"cmd=");
|
||||
fprintf(FINFO,"cmd=");
|
||||
for (i=0;i<argc;i++)
|
||||
fprintf(FERROR,"%s ",args[i]);
|
||||
fprintf(FERROR,"\n");
|
||||
fprintf(FINFO,"%s ",args[i]);
|
||||
fprintf(FINFO,"\n");
|
||||
}
|
||||
|
||||
ret = piped_child(args,f_in,f_out);
|
||||
@@ -291,31 +312,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] = ".";
|
||||
}
|
||||
|
||||
|
||||
@@ -341,10 +362,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);
|
||||
}
|
||||
|
||||
@@ -359,21 +380,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)
|
||||
@@ -386,11 +408,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);
|
||||
@@ -429,7 +451,11 @@ static void usage(FILE *f)
|
||||
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");
|
||||
@@ -442,15 +468,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 = "oblLWHpguDCtcahvrRIxnSe: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},
|
||||
@@ -479,6 +508,8 @@ 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}};
|
||||
|
||||
@@ -500,11 +531,6 @@ int main(int argc,char *argv[])
|
||||
struct file_list *flist;
|
||||
char *local_name = NULL;
|
||||
|
||||
#ifdef SETPGRP_VOID
|
||||
setpgrp();
|
||||
#else
|
||||
setpgrp(0,0);
|
||||
#endif
|
||||
signal(SIGUSR1, sigusr1_handler);
|
||||
|
||||
starttime = time(NULL);
|
||||
@@ -512,7 +538,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
/* 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))
|
||||
@@ -544,6 +570,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;
|
||||
@@ -667,6 +701,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;
|
||||
@@ -754,7 +796,7 @@ 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:"",
|
||||
@@ -776,7 +818,7 @@ int main(int argc,char *argv[])
|
||||
#endif
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"parent=%d child=%d sender=%d recurse=%d\n",
|
||||
fprintf(FINFO,"parent=%d child=%d sender=%d recurse=%d\n",
|
||||
(int)getpid(),pid,sender,recurse);
|
||||
|
||||
if (sender) {
|
||||
@@ -786,10 +828,10 @@ int main(int argc,char *argv[])
|
||||
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);
|
||||
@@ -799,7 +841,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);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
604
rsync.c
604
rsync.c
@@ -29,6 +29,7 @@ extern time_t starttime;
|
||||
extern int remote_version;
|
||||
|
||||
extern char *backup_suffix;
|
||||
extern char *tmpdir;
|
||||
|
||||
extern int whole_file;
|
||||
extern int block_size;
|
||||
@@ -48,6 +49,8 @@ extern int delete_mode;
|
||||
extern int cvs_exclude;
|
||||
extern int am_root;
|
||||
extern int relative_paths;
|
||||
extern int io_timeout;
|
||||
extern int io_error;
|
||||
|
||||
/*
|
||||
free a sums struct
|
||||
@@ -59,6 +62,75 @@ static void free_sums(struct sum_struct *s)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* delete a file or directory. If force_delet is set then delete
|
||||
* recursively
|
||||
*/
|
||||
static int delete_file(char *fname)
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *di;
|
||||
char buf[MAXPATHLEN];
|
||||
extern int force_delete;
|
||||
struct stat st;
|
||||
int ret;
|
||||
|
||||
if (do_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
ret = lstat(fname, &st);
|
||||
#else
|
||||
ret = stat(fname, &st);
|
||||
#endif
|
||||
if (ret) {
|
||||
fprintf(FERROR,"stat(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
fprintf(FERROR,"unlink(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
|
||||
if (!force_delete || errno != ENOTEMPTY) {
|
||||
fprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now we do a recsursive delete on the directory ... */
|
||||
d = opendir(fname);
|
||||
if (!d) {
|
||||
fprintf(FERROR,"opendir(%s): %s\n",
|
||||
fname,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (di=readdir(d); di; di=readdir(d)) {
|
||||
if (strcmp(di->d_name,".")==0 ||
|
||||
strcmp(di->d_name,"..")==0)
|
||||
continue;
|
||||
strncpy(buf, fname, (MAXPATHLEN-strlen(di->d_name))-2);
|
||||
strcat(buf, "/");
|
||||
strcat(buf, di->d_name);
|
||||
buf[MAXPATHLEN-1] = 0;
|
||||
if (verbose > 0)
|
||||
fprintf(FINFO,"deleting %s\n", buf);
|
||||
if (delete_file(buf) != 0) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (do_rmdir(fname) != 0) {
|
||||
fprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
send a sums struct down a fd
|
||||
@@ -111,7 +183,7 @@ static struct sum_struct *generate_sums(struct map_struct *buf,off_t len,int n)
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"count=%d rem=%d n=%d flength=%d\n",
|
||||
fprintf(FINFO,"count=%d rem=%d n=%d flength=%d\n",
|
||||
s->count,s->remainder,s->n,(int)s->flength);
|
||||
|
||||
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
|
||||
@@ -129,7 +201,7 @@ static struct sum_struct *generate_sums(struct map_struct *buf,off_t len,int n)
|
||||
s->sums[i].i = i;
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"chunk[%d] offset=%d len=%d sum1=%08x\n",
|
||||
fprintf(FINFO,"chunk[%d] offset=%d len=%d sum1=%08x\n",
|
||||
i,(int)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
|
||||
|
||||
len -= n1;
|
||||
@@ -158,7 +230,7 @@ static struct sum_struct *receive_sums(int f)
|
||||
s->sums = NULL;
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"count=%d n=%d rem=%d\n",
|
||||
fprintf(FINFO,"count=%d n=%d rem=%d\n",
|
||||
s->count,s->n,s->remainder);
|
||||
|
||||
if (s->count == 0)
|
||||
@@ -182,7 +254,7 @@ static struct sum_struct *receive_sums(int f)
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"chunk[%d] len=%d offset=%d sum1=%08x\n",
|
||||
fprintf(FINFO,"chunk[%d] len=%d offset=%d sum1=%08x\n",
|
||||
i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
|
||||
}
|
||||
|
||||
@@ -222,7 +294,7 @@ static int set_perms(char *fname,struct file_struct *file,struct stat *st,
|
||||
if (preserve_perms && !S_ISLNK(st->st_mode) &&
|
||||
st->st_mode != file->mode) {
|
||||
updated = 1;
|
||||
if (chmod(fname,file->mode) != 0) {
|
||||
if (do_chmod(fname,file->mode) != 0) {
|
||||
fprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
@@ -232,45 +304,81 @@ static int set_perms(char *fname,struct file_struct *file,struct stat *st,
|
||||
|
||||
if ((am_root && preserve_uid && st->st_uid != file->uid) ||
|
||||
(preserve_gid && st->st_gid != file->gid)) {
|
||||
updated = 1;
|
||||
if (lchown(fname,
|
||||
(am_root&&preserve_uid)?file->uid:-1,
|
||||
preserve_gid?file->gid:-1) != 0) {
|
||||
if (verbose>1 || preserve_uid)
|
||||
fprintf(FERROR,"chown %s : %s\n",fname,strerror(errno));
|
||||
return updated;
|
||||
}
|
||||
if (do_lchown(fname,
|
||||
(am_root&&preserve_uid)?file->uid:-1,
|
||||
preserve_gid?file->gid:-1) != 0) {
|
||||
if (preserve_uid && st->st_uid != file->uid)
|
||||
updated = 1;
|
||||
if (verbose>1 || preserve_uid)
|
||||
fprintf(FERROR,"chown %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return updated;
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
if (verbose > 1 && report) {
|
||||
if (updated)
|
||||
fprintf(FINFO,"%s\n",fname);
|
||||
else
|
||||
fprintf(FINFO,"%s is uptodate\n",fname);
|
||||
if (updated)
|
||||
fprintf(FINFO,"%s\n",fname);
|
||||
else
|
||||
fprintf(FINFO,"%s is uptodate\n",fname);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
/* choose whether to skip a particular file */
|
||||
static int skip_file(char *fname,
|
||||
struct file_struct *file, struct stat *st)
|
||||
{
|
||||
if (st->st_size != file->length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if always checksum is set then we use the checksum instead
|
||||
of the file time to determine whether to sync */
|
||||
if (always_checksum && S_ISREG(st->st_mode)) {
|
||||
char sum[MD4_SUM_LENGTH];
|
||||
file_checksum(fname,sum,st->st_size);
|
||||
return (memcmp(sum,file->sum,csum_length) == 0);
|
||||
}
|
||||
|
||||
if (ignore_times) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (st->st_mtime == file->modtime);
|
||||
}
|
||||
|
||||
|
||||
/* use a larger block size for really big files */
|
||||
int adapt_block_size(struct file_struct *file, int bsize)
|
||||
{
|
||||
int ret = file->length / (10000); /* rough heuristic */
|
||||
ret = ret & ~15; /* multiple of 16 */
|
||||
if (ret < bsize) ret = bsize;
|
||||
if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
struct map_struct *buf;
|
||||
struct sum_struct *s;
|
||||
char sum[MD4_SUM_LENGTH];
|
||||
int statret;
|
||||
struct file_struct *file = &flist->files[i];
|
||||
struct file_struct *file = flist->files[i];
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"recv_generator(%s,%d)\n",fname,i);
|
||||
fprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
|
||||
|
||||
statret = link_stat(fname,&st);
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
if (dry_run) return;
|
||||
if (statret == 0 && !S_ISDIR(st.st_mode)) {
|
||||
if (unlink(fname) != 0) {
|
||||
if (do_unlink(fname) != 0) {
|
||||
fprintf(FERROR,"unlink %s : %s\n",fname,strerror(errno));
|
||||
return;
|
||||
}
|
||||
@@ -303,8 +411,8 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!dry_run) unlink(fname);
|
||||
if (!dry_run && symlink(file->link,fname) != 0) {
|
||||
delete_file(fname);
|
||||
if (do_symlink(file->link,fname) != 0) {
|
||||
fprintf(FERROR,"link %s -> %s : %s\n",
|
||||
fname,file->link,strerror(errno));
|
||||
} else {
|
||||
@@ -322,12 +430,11 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
if (statret != 0 ||
|
||||
st.st_mode != file->mode ||
|
||||
st.st_rdev != file->rdev) {
|
||||
if (!dry_run) unlink(fname);
|
||||
delete_file(fname);
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"mknod(%s,0%o,0x%x)\n",
|
||||
fprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
|
||||
fname,(int)file->mode,(int)file->rdev);
|
||||
if (!dry_run &&
|
||||
mknod(fname,file->mode,file->rdev) != 0) {
|
||||
if (do_mknod(fname,file->mode,file->rdev) != 0) {
|
||||
fprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
@@ -343,12 +450,12 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
|
||||
if (preserve_hard_links && check_hard_link(file)) {
|
||||
if (verbose > 1)
|
||||
fprintf(FINFO,"%s is a hard link\n",file->name);
|
||||
fprintf(FINFO,"%s is a hard link\n",f_name(file));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(file->mode)) {
|
||||
fprintf(FERROR,"skipping non-regular file %s\n",fname);
|
||||
fprintf(FINFO,"skipping non-regular file %s\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -364,15 +471,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
/* its not a regular file on the receiving end, but it is on the
|
||||
sending end. If its a directory then skip it (too dangerous to
|
||||
do a recursive deletion??) otherwise try to unlink it */
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
fprintf(FERROR,"ERROR: %s is a directory\n",fname);
|
||||
return;
|
||||
}
|
||||
if (unlink(fname) != 0) {
|
||||
fprintf(FERROR,"%s : not a regular file (generator)\n",fname);
|
||||
if (delete_file(fname) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -382,20 +481,13 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
return;
|
||||
}
|
||||
|
||||
if (update_only && st.st_mtime >= file->modtime) {
|
||||
if (update_only && st.st_mtime > file->modtime) {
|
||||
if (verbose > 1)
|
||||
fprintf(FERROR,"%s is newer\n",fname);
|
||||
fprintf(FINFO,"%s is newer\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (always_checksum && S_ISREG(st.st_mode)) {
|
||||
file_checksum(fname,sum,st.st_size);
|
||||
}
|
||||
|
||||
if (st.st_size == file->length &&
|
||||
((!ignore_times && st.st_mtime == file->modtime) ||
|
||||
(always_checksum && S_ISREG(st.st_mode) &&
|
||||
memcmp(sum,file->sum,csum_length) == 0))) {
|
||||
if (skip_file(fname, file, &st)) {
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
@@ -427,12 +519,12 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"gen mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
fprintf(FINFO,"gen mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
|
||||
s = generate_sums(buf,st.st_size,block_size);
|
||||
s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"sending sums for %d\n",i);
|
||||
fprintf(FINFO,"sending sums for %d\n",i);
|
||||
|
||||
write_int(f_out,i);
|
||||
send_sums(s,f_out);
|
||||
@@ -465,7 +557,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
|
||||
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
|
||||
if (i > 0) {
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"data recv %d at %d\n",i,(int)offset);
|
||||
fprintf(FINFO,"data recv %d at %d\n",i,(int)offset);
|
||||
|
||||
sum_update(data,i);
|
||||
|
||||
@@ -482,7 +574,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
|
||||
len = remainder;
|
||||
|
||||
if (verbose > 3)
|
||||
fprintf(FERROR,"chunk[%d] of size %d at %d offset=%d\n",
|
||||
fprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
|
||||
i,len,(int)offset2,(int)offset);
|
||||
|
||||
map = map_ptr(buf,offset2,len);
|
||||
@@ -508,7 +600,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
|
||||
if (remote_version >= 14) {
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"got file_sum\n");
|
||||
fprintf(FINFO,"got file_sum\n");
|
||||
if (fd != -1 && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0)
|
||||
return 0;
|
||||
}
|
||||
@@ -519,22 +611,77 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
|
||||
static void delete_one(struct file_struct *f)
|
||||
{
|
||||
if (!S_ISDIR(f->mode)) {
|
||||
if (!dry_run && unlink(f->name) != 0) {
|
||||
fprintf(FERROR,"unlink %s : %s\n",f->name,strerror(errno));
|
||||
if (do_unlink(f_name(f)) != 0) {
|
||||
fprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
fprintf(FERROR,"deleting %s\n",f->name);
|
||||
fprintf(FINFO,"deleting %s\n",f_name(f));
|
||||
}
|
||||
} else {
|
||||
if (!dry_run && rmdir(f->name) != 0) {
|
||||
if (do_rmdir(f_name(f)) != 0) {
|
||||
if (errno != ENOTEMPTY)
|
||||
fprintf(FERROR,"rmdir %s : %s\n",f->name,strerror(errno));
|
||||
fprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
fprintf(FERROR,"deleting directory %s\n",f->name);
|
||||
fprintf(FINFO,"deleting directory %s\n",f_name(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* yuck! This function wouldn't have been necessary if I had the sorting
|
||||
algorithm right. Unfortunately fixing the sorting algorithm would introduce
|
||||
a backward incompatibility as file list indexes are sent over the link.
|
||||
|
||||
The aim is to see if a directory has already had the deletion algorithm applied
|
||||
to it (due to recursion), and if so to skip it. The bisection is to
|
||||
prevent this being an n^2 algorithm */
|
||||
static int delete_already_done(struct file_list *flist,int j)
|
||||
{
|
||||
int low=0,high=j-1;
|
||||
char *name;
|
||||
char *p;
|
||||
|
||||
if (j == 0) return 0;
|
||||
|
||||
name = strdup(f_name(flist->files[j]));
|
||||
|
||||
if (!name) {
|
||||
fprintf(FERROR,"out of memory in delete_already_done");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
p = strrchr(name,'/');
|
||||
if (!p) {
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
while (low != high) {
|
||||
int mid = (low+high)/2;
|
||||
int ret = strcmp(f_name(flist->files[flist_up(flist, mid)]),name);
|
||||
if (ret == 0) {
|
||||
free(name);
|
||||
return 1;
|
||||
}
|
||||
if (ret > 0) {
|
||||
high=mid;
|
||||
} else {
|
||||
low=mid+1;
|
||||
}
|
||||
}
|
||||
|
||||
low = flist_up(flist, low);
|
||||
|
||||
if (strcmp(f_name(flist->files[low]),name) == 0) {
|
||||
free(name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* this deletes any files on the receiving side that are not present
|
||||
on the sending side. For version 1.6.4 I have changed the behaviour
|
||||
to match more closely what most people seem to expect of this option */
|
||||
@@ -542,46 +689,47 @@ static void delete_files(struct file_list *flist)
|
||||
{
|
||||
struct file_list *local_file_list;
|
||||
int i, j;
|
||||
char *last_name=NULL;
|
||||
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
|
||||
if (io_error) {
|
||||
fprintf(FINFO,"IO error encountered - skipping file deletion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (j=0;j<flist->count;j++) {
|
||||
if (!S_ISDIR(flist->files[j].mode)) continue;
|
||||
if (strcmp(flist->files[j].name,".")==0) continue;
|
||||
if (last_name &&
|
||||
flist->files[j].name[strlen(last_name)] == '/' &&
|
||||
strncmp(flist->files[j].name,last_name, strlen(last_name))==0)
|
||||
continue;
|
||||
last_name = flist->files[j].name;
|
||||
if (!(local_file_list = send_file_list(-1,1,&last_name)))
|
||||
char *name = f_name(flist->files[j]);
|
||||
|
||||
if (!S_ISDIR(flist->files[j]->mode)) continue;
|
||||
|
||||
if (delete_already_done(flist, j)) continue;
|
||||
|
||||
if (!(local_file_list = send_file_list(-1,1,&name)))
|
||||
continue;
|
||||
|
||||
if (verbose > 1)
|
||||
fprintf(FINFO,"deleting in %s\n", last_name);
|
||||
fprintf(FINFO,"deleting in %s\n", name);
|
||||
|
||||
for (i=local_file_list->count-1;i>=0;i--) {
|
||||
if (!local_file_list->files[i].name) continue;
|
||||
if (-1 == flist_find(flist,&local_file_list->files[i])) {
|
||||
delete_one(&local_file_list->files[i]);
|
||||
if (!local_file_list->files[i]->basename) continue;
|
||||
if (-1 == flist_find(flist,local_file_list->files[i])) {
|
||||
delete_one(local_file_list->files[i]);
|
||||
}
|
||||
}
|
||||
flist_free(local_file_list);
|
||||
}
|
||||
}
|
||||
|
||||
static char *cleanup_fname = NULL;
|
||||
static char *cleanup_fname;
|
||||
|
||||
void exit_cleanup(int code)
|
||||
{
|
||||
if (cleanup_fname)
|
||||
unlink(cleanup_fname);
|
||||
do_unlink(cleanup_fname);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
if (code) {
|
||||
#ifdef GETPGRP_VOID
|
||||
kill(-getpgrp(), SIGUSR1);
|
||||
#else
|
||||
kill(-getpgrp(getpid()), SIGUSR1);
|
||||
#endif
|
||||
kill_all(SIGUSR1);
|
||||
}
|
||||
exit(code);
|
||||
}
|
||||
@@ -605,7 +753,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
int recv_ok;
|
||||
|
||||
if (verbose > 2) {
|
||||
fprintf(FERROR,"recv_files(%d) starting\n",flist->count);
|
||||
fprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
@@ -620,7 +768,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"recv_files phase=%d\n",phase);
|
||||
fprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
write_int(f_gen,-1);
|
||||
write_flush(f_gen);
|
||||
continue;
|
||||
@@ -628,8 +776,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
break;
|
||||
}
|
||||
|
||||
file = &flist->files[i];
|
||||
fname = file->name;
|
||||
file = flist->files[i];
|
||||
fname = f_name(file);
|
||||
|
||||
if (local_name)
|
||||
fname = local_name;
|
||||
@@ -641,7 +789,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"recv_files(%s)\n",fname);
|
||||
fprintf(FINFO,"recv_files(%s)\n",fname);
|
||||
|
||||
/* open the file */
|
||||
fd1 = open(fname,O_RDONLY);
|
||||
@@ -663,7 +811,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
if (fd1 != -1 && st.st_size > 0) {
|
||||
buf = map_file(fd1,st.st_size);
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"recv mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
fprintf(FINFO,"recv mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
@@ -671,10 +819,21 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
/* open tmp file */
|
||||
if (strlen(fname) > (MAXPATHLEN-8)) {
|
||||
fprintf(FERROR,"filename too long\n");
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
sprintf(fnametmp,"%s.XXXXXX",fname);
|
||||
if (tmpdir) {
|
||||
char *f;
|
||||
f = strrchr(fname,'/');
|
||||
if (f == NULL)
|
||||
f = fname;
|
||||
else
|
||||
f++;
|
||||
sprintf(fnametmp,"%s/%s.XXXXXX",tmpdir,f);
|
||||
} else {
|
||||
sprintf(fnametmp,"%s.XXXXXX",fname);
|
||||
}
|
||||
if (NULL == mktemp(fnametmp)) {
|
||||
fprintf(FERROR,"mktemp %s failed\n",fnametmp);
|
||||
receive_data(f_in,buf,-1,NULL);
|
||||
@@ -682,10 +841,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
fd2 = open(fnametmp,O_WRONLY|O_CREAT,file->mode);
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp) == 0) {
|
||||
fd2 = open(fnametmp,O_WRONLY|O_CREAT,file->mode);
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
fprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
|
||||
@@ -703,14 +862,14 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,buf,fd2,fname);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) {
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
}
|
||||
close(fd2);
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"renaming %s to %s\n",fnametmp,fname);
|
||||
fprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
if (make_backups) {
|
||||
char fnamebak[MAXPATHLEN];
|
||||
@@ -727,21 +886,37 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
|
||||
/* move tmp file over real file */
|
||||
if (rename(fnametmp,fname) != 0) {
|
||||
fprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
unlink(fnametmp);
|
||||
if (errno == EXDEV) {
|
||||
/* rename failed on cross-filesystem link.
|
||||
Copy the file instead. */
|
||||
if (copy_file(fnametmp,fname, file->mode)) {
|
||||
fprintf(FERROR,"copy %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
do_unlink(fnametmp);
|
||||
} else {
|
||||
fprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
do_unlink(fnametmp);
|
||||
}
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
|
||||
cleanup_fname = NULL;
|
||||
|
||||
set_perms(fname,file,NULL,0);
|
||||
|
||||
if (!recv_ok) {
|
||||
if (verbose > 1)
|
||||
fprintf(FERROR,"redoing %s(%d)\n",fname,i);
|
||||
if (csum_length == SUM_LENGTH)
|
||||
fprintf(FERROR,"ERROR: file corruption in %s\n",fname);
|
||||
write_int(f_gen,i);
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
fprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
fname);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
fprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
write_int(f_gen,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,137 +926,144 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
/* now we need to fix any directory permissions that were
|
||||
modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = &flist->files[i];
|
||||
if (!file->name || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(file->name,flist,i,-1);
|
||||
struct file_struct *file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(f_name(file),flist,i,-1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"recv_files finished\n");
|
||||
fprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
off_t send_files(struct file_list *flist,int f_out,int f_in)
|
||||
void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
{
|
||||
int fd;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *buf;
|
||||
struct stat st;
|
||||
char fname[MAXPATHLEN];
|
||||
off_t total=0;
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
int offset=0;
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"send_files starting\n");
|
||||
fprintf(FINFO,"send_files starting\n");
|
||||
|
||||
setup_nonblocking(f_in,f_out);
|
||||
|
||||
while (1)
|
||||
{
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out,-1);
|
||||
write_flush(f_out);
|
||||
while (1) {
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out,-1);
|
||||
write_flush(f_out);
|
||||
if (verbose > 2)
|
||||
fprintf(FINFO,"send_files phase=%d\n",phase);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->basedir) {
|
||||
strncpy(fname,file->basedir,MAXPATHLEN-1);
|
||||
fname[MAXPATHLEN-1] = 0;
|
||||
if (strlen(fname) == MAXPATHLEN-1) {
|
||||
io_error = 1;
|
||||
fprintf(FERROR, "send_files failed on long-named directory %s\n",
|
||||
fname);
|
||||
return;
|
||||
}
|
||||
strcat(fname,"/");
|
||||
offset = strlen(file->basedir)+1;
|
||||
}
|
||||
strncat(fname,f_name(file),MAXPATHLEN-strlen(fname));
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FINFO,"send_files(%d,%s)\n",i,fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
write_int(f_out,i);
|
||||
continue;
|
||||
}
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
io_error = 1;
|
||||
fprintf(FERROR,"receive_sums failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) {
|
||||
io_error = 1;
|
||||
fprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
free_sums(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* map the local file */
|
||||
if (fstat(fd,&st) != 0) {
|
||||
io_error = 1;
|
||||
fprintf(FERROR,"fstat failed : %s\n",strerror(errno));
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"send_files phase=%d\n",phase);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
file = &flist->files[i];
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->dir) {
|
||||
strncpy(fname,file->dir,MAXPATHLEN-1);
|
||||
fname[MAXPATHLEN-1] = 0;
|
||||
strcat(fname,"/");
|
||||
}
|
||||
strncat(fname,file->name,MAXPATHLEN-strlen(fname));
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"send_files(%d,%s)\n",i,fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
write_int(f_out,i);
|
||||
continue;
|
||||
}
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
fprintf(FERROR,"receive_sums failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* map the local file */
|
||||
if (fstat(fd,&st) != 0) {
|
||||
fprintf(FERROR,"fstat failed : %s\n",strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"send_files mapped %s of size %d\n",
|
||||
fname,(int)st.st_size);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"calling match_sums %s\n",fname);
|
||||
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
write_flush(f_out);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd);
|
||||
|
||||
free_sums(s);
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"sender finished %s\n",fname);
|
||||
|
||||
total += st.st_size;
|
||||
}
|
||||
fprintf(FINFO,"send_files mapped %s of size %d\n",
|
||||
fname,(int)st.st_size);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FINFO,"calling match_sums %s\n",fname);
|
||||
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname+offset);
|
||||
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
write_flush(f_out);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd);
|
||||
|
||||
free_sums(s);
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FINFO,"sender finished %s\n",fname);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"send files finished\n");
|
||||
fprintf(FINFO,"send files finished\n");
|
||||
|
||||
match_report();
|
||||
|
||||
write_int(f_out,-1);
|
||||
write_flush(f_out);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
@@ -892,13 +1074,13 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
int phase=0;
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"generator starting pid=%d count=%d\n",
|
||||
fprintf(FINFO,"generator starting pid=%d count=%d\n",
|
||||
(int)getpid(),flist->count);
|
||||
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = &flist->files[i];
|
||||
struct file_struct *file = flist->files[i];
|
||||
mode_t saved_mode = file->mode;
|
||||
if (!file->name) continue;
|
||||
if (!file->basename) continue;
|
||||
|
||||
/* we need to ensure that any directories we create have writeable
|
||||
permissions initially so that we can create the files within
|
||||
@@ -907,7 +1089,7 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
file->mode |= S_IWUSR; /* user write */
|
||||
}
|
||||
|
||||
recv_generator(local_name?local_name:file->name,
|
||||
recv_generator(local_name?local_name:f_name(file),
|
||||
flist,i,f);
|
||||
|
||||
file->mode = saved_mode;
|
||||
@@ -918,23 +1100,27 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
ignore_times=1;
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"generate_files phase=%d\n",phase);
|
||||
fprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
write_flush(f);
|
||||
|
||||
/* we expect to just sit around now, so don't exit on a timeout. If we
|
||||
really get a timeout then the other process should exit */
|
||||
io_timeout = 0;
|
||||
|
||||
if (remote_version >= 13) {
|
||||
/* in newer versions of the protocol the files can cycle through
|
||||
the system more than once to catch initial checksum errors */
|
||||
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
|
||||
struct file_struct *file = &flist->files[i];
|
||||
recv_generator(local_name?local_name:file->name,
|
||||
struct file_struct *file = flist->files[i];
|
||||
recv_generator(local_name?local_name:f_name(file),
|
||||
flist,i,f);
|
||||
}
|
||||
|
||||
phase++;
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"generate_files phase=%d\n",phase);
|
||||
fprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
write_flush(f);
|
||||
@@ -942,7 +1128,7 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
fprintf(FERROR,"generator wrote %d\n",write_total());
|
||||
fprintf(FINFO,"generator wrote %ld\n",(long)write_total());
|
||||
}
|
||||
|
||||
|
||||
|
||||
73
rsync.h
73
rsync.h
@@ -39,9 +39,9 @@
|
||||
#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 WRITE_SIZE (32*1024)
|
||||
@@ -163,6 +163,10 @@
|
||||
#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
|
||||
@@ -189,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))
|
||||
@@ -207,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 {
|
||||
@@ -244,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"
|
||||
@@ -319,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))
|
||||
|
||||
|
||||
79
syscall.c
Normal file
79
syscall.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
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
|
||||
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);
|
||||
if (!name) out_of_memory("recv_uid_list");
|
||||
read_buf(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);
|
||||
if (!name) out_of_memory("recv_uid_list");
|
||||
read_buf(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
197
util.c
197
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);
|
||||
@@ -164,38 +167,31 @@ void out_of_memory(char *str)
|
||||
}
|
||||
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -251,3 +247,140 @@ int create_directory_path(char *fname)
|
||||
}
|
||||
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