Compare commits

...

10 Commits

Author SHA1 Message Date
rsync-bugs
143384f367 preparing for release of 2.0.16 1998-06-01 13:49:12 +00:00
Andrew Tridgell
8c3b04730b added some notes to test.sh 1998-06-01 13:44:06 +00:00
Andrew Tridgell
aa9b77a56c replace calls to strcmp() with a u_strcmp() function that uses only
unsigned comparisons. Transferring files between two machines that
treated strcmp() differently led to the files being given the wrong
name at the destination if the filenames had characters > 128 (such as
Kanji characters) and the source and destination machines treated
strcmp() differently (ie. one treated strings as signed and the other
as unsigned).

We now treat all string comparisons for file list sorting as unsigned.
1998-06-01 13:39:54 +00:00
Andrew Tridgell
b72f24c719 updated the usage info 1998-06-01 10:38:24 +00:00
Andrew Tridgell
a800434a82 added --stats option for verbose stats on the file transfer 1998-06-01 03:42:14 +00:00
rsync-bugs
3b3c3d4390 preparing for release of 2.0.15 1998-05-30 02:10:18 +00:00
Andrew Tridgell
d846b09874 replace BAD with zBAD so it compiles on AIX 1998-05-30 02:07:36 +00:00
Andrew Tridgell
1d3754aede cosmetic fix.
reset offset to 0 at the start of each loop so the filenames get
printed correctly when sending directories followed by local names.
1998-05-30 02:03:29 +00:00
Andrew Tridgell
e44f9a12c4 make sure that io_flush() doesn't call writefd_unbuffered from within
a writefd_unbuffered call!

this should fix the "decompressor lost sync" bug
1998-05-30 02:02:23 +00:00
Andrew Tridgell
5243c216d6 replaced chdir and getcwd calls with push_dir/pop_dir functions. These
are faster and don't cause problems in a chrooted environment on any
systems.
1998-05-29 14:36:39 +00:00
16 changed files with 503 additions and 334 deletions

View File

@@ -362,6 +362,11 @@ int daemon_main(void)
{
extern char *config_file;
/* this ensures that we don't call getcwd after the chroot,
which doesn't work on platforms that use popen("pwd","r")
for getcwd */
push_dir("/", 0);
if (is_a_socket(STDIN_FILENO)) {
/* we are running via inetd */
return start_daemon(STDIN_FILENO);

83
flist.c
View File

@@ -21,12 +21,13 @@
#include "rsync.h"
extern struct stats stats;
extern int csum_length;
extern int verbose;
extern int am_server;
extern int always_checksum;
extern int64 total_size;
extern int cvs_exclude;
@@ -90,49 +91,6 @@ static void send_directory(int f,struct file_list *flist,char *dir);
static char *flist_dir;
static void clean_fname(char *name)
{
char *p;
int l;
int modified = 1;
if (!name) return;
while (modified) {
modified = 0;
if ((p=strstr(name,"/./"))) {
modified = 1;
while (*p) {
p[0] = p[2];
p++;
}
}
if ((p=strstr(name,"//"))) {
modified = 1;
while (*p) {
p[0] = p[1];
p++;
}
}
if (strncmp(p=name,"./",2) == 0) {
modified = 1;
do {
p[0] = p[2];
} while (*p++);
}
l = strlen(p=name);
if (l > 1 && p[l-1] == '/') {
modified = 1;
p[l-1] = 0;
}
}
}
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
{
@@ -464,7 +422,7 @@ static struct file_struct *make_file(char *fname)
}
if (!S_ISDIR(st.st_mode))
total_size += st.st_size;
stats.total_size += st.st_size;
return file;
}
@@ -566,15 +524,17 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
int i,l;
STRUCT_STAT st;
char *p,*dir;
char dbuf[MAXPATHLEN];
char lastpath[MAXPATHLEN]="";
struct file_list *flist;
int64 start_write;
if (verbose && recurse && !am_server && f != -1) {
rprintf(FINFO,"building file list ... ");
rflush(FINFO);
}
start_write = stats.total_written;
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist) out_of_memory("send_file_list");
@@ -646,24 +606,23 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
fname = ".";
if (dir && *dir) {
if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
rprintf(FERROR,"getwd : %s\n",strerror(errno));
exit_cleanup(1);
}
if (chdir(dir) != 0) {
char *olddir = push_dir(dir, 1);
if (!olddir) {
io_error=1;
rprintf(FERROR,"chdir %s : %s\n",
rprintf(FERROR,"push_dir %s : %s\n",
dir,strerror(errno));
continue;
}
flist_dir = dir;
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
flist_dir = NULL;
if (chdir(dbuf) != 0) {
rprintf(FERROR,"chdir %s : %s\n",
dbuf,strerror(errno));
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(1);
}
continue;
@@ -696,6 +655,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (f != -1) {
io_end_buffering(f);
stats.flist_size = stats.total_written - start_write;
stats.num_files = flist->count;
}
if (verbose > 2)
@@ -709,12 +670,15 @@ struct file_list *recv_file_list(int f)
{
struct file_list *flist;
unsigned char flags;
int64 start_read;
if (verbose && recurse && !am_server) {
rprintf(FINFO,"receiving file list ... ");
rflush(FINFO);
}
start_read = stats.total_read;
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist)
goto oom;
@@ -745,7 +709,7 @@ struct file_list *recv_file_list(int f)
receive_file_entry(&flist->files[i],flags,f);
if (S_ISREG(flist->files[i]->mode))
total_size += flist->files[i]->length;
stats.total_size += flist->files[i]->length;
flist->count++;
@@ -776,6 +740,9 @@ struct file_list *recv_file_list(int f)
if (verbose > 2)
rprintf(FINFO,"recv_file_list done\n");
stats.flist_size = stats.total_read - start_read;
stats.num_files = flist->count;
return flist;
oom:
@@ -790,8 +757,8 @@ int file_compare(struct file_struct **f1,struct file_struct **f2)
if (!(*f1)->basename) return -1;
if (!(*f2)->basename) return 1;
if ((*f1)->dirname == (*f2)->dirname)
return strcmp((*f1)->basename, (*f2)->basename);
return strcmp(f_name(*f1),f_name(*f2));
return u_strcmp((*f1)->basename, (*f2)->basename);
return u_strcmp(f_name(*f1),f_name(*f2));
}

31
io.c
View File

@@ -24,9 +24,6 @@
*/
#include "rsync.h"
static int64 total_written;
static int64 total_read;
static int io_multiplexing_out;
static int io_multiplexing_in;
static int multiplex_in_fd;
@@ -35,17 +32,7 @@ static time_t last_io;
static int eof_error=1;
extern int verbose;
extern int io_timeout;
int64 write_total(void)
{
return total_written;
}
int64 read_total(void)
{
return total_read;
}
extern struct stats stats;
static int buffer_f_in = -1;
@@ -79,6 +66,7 @@ static char *read_buffer;
static char *read_buffer_p;
static int read_buffer_len;
static int read_buffer_size;
static int no_flush;
/* read from a socket with IO timeout. return the number of
bytes read. If no bytes can be read then exit, never return
@@ -107,6 +95,7 @@ static int read_timeout(int fd, char *buf, int len)
n = read(fd, buf, len);
if (n > 0) {
stats.total_read += n;
buf += n;
len -= n;
ret += n;
@@ -266,7 +255,6 @@ int32 read_int(int f)
{
char b[4];
readfd(f,b,4);
total_read += 4;
return IVAL(b,0);
}
@@ -285,7 +273,6 @@ int64 read_longint(int f)
#else
if (remote_version >= 16) {
readfd(f,b,8);
total_read += 8;
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
}
#endif
@@ -296,7 +283,6 @@ int64 read_longint(int f)
void read_buf(int f,char *buf,int len)
{
readfd(f,buf,len);
total_read += len;
}
void read_sbuf(int f,char *buf,int len)
@@ -325,6 +311,8 @@ static void writefd_unbuffered(int fd,char *buf,int len)
struct timeval tv;
int reading;
no_flush++;
reading = (buffer_f_in != -1 && read_buffer_len < MAX_READ_BUFFER);
while (total < len) {
@@ -365,6 +353,8 @@ static void writefd_unbuffered(int fd,char *buf,int len)
}
total += ret;
stats.total_written += ret;
if (io_timeout)
last_io = time(NULL);
continue;
@@ -374,6 +364,8 @@ static void writefd_unbuffered(int fd,char *buf,int len)
read_check(buffer_f_in);
}
}
no_flush--;
}
@@ -395,7 +387,7 @@ void io_start_buffering(int fd)
void io_flush(void)
{
int fd = multiplex_out_fd;
if (!io_buffer_count) return;
if (!io_buffer_count || no_flush) return;
if (io_multiplexing_out) {
SIVAL(io_buffer-4, 0, (MPLEX_BASE<<24) + io_buffer_count);
@@ -441,7 +433,6 @@ void write_int(int f,int32 x)
char b[4];
SIVAL(b,0,x);
writefd(f,b,4);
total_written += 4;
}
void write_longint(int f, int64 x)
@@ -459,13 +450,11 @@ void write_longint(int f, int64 x)
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
writefd(f,b,8);
total_written += 8;
}
void write_buf(int f,char *buf,int len)
{
writefd(f,buf,len);
total_written += len;
}
/* write a string to the connection */

75
main.c
View File

@@ -20,7 +20,8 @@
#include "rsync.h"
time_t starttime = 0;
int64 total_size = 0;
struct stats stats;
extern int csum_length;
@@ -28,16 +29,17 @@ extern int verbose;
static void report(int f)
{
int64 in,out,tsize;
time_t t = time(NULL);
extern int am_server;
extern int am_sender;
extern int am_daemon;
extern int do_stats;
if (am_daemon) {
syslog(LOG_INFO,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
(double)write_total(),(double)read_total(),
(double)total_size);
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
if (f == -1 || !am_sender) return;
}
@@ -46,26 +48,46 @@ static void report(int f)
if (am_server && !am_sender) return;
if (am_server && am_sender) {
write_longint(f,read_total());
write_longint(f,write_total());
write_longint(f,total_size);
write_longint(f,stats.total_read);
write_longint(f,stats.total_written);
write_longint(f,stats.total_size);
return;
}
if (am_sender) {
in = read_total();
out = write_total();
tsize = total_size;
} else {
out = read_longint(f);
in = read_longint(f);
tsize = read_longint(f);
if (!am_sender) {
int64 r;
stats.total_written = read_longint(f);
r = read_longint(f);
stats.total_size = read_longint(f);
stats.total_read = r;
}
if (do_stats) {
printf("\nNumber of files: %d\n", stats.num_files);
printf("Number of files transferred: %d\n",
stats.num_transferred_files);
printf("Total file size: %.0f bytes\n",
(double)stats.total_size);
printf("Total transferred file size: %.0f bytes\n",
(double)stats.total_transferred_size);
printf("Literal data: %.0f bytes\n",
(double)stats.literal_data);
printf("Matched data: %.0f bytes\n",
(double)stats.matched_data);
printf("File list size: %d\n", stats.flist_size);
printf("Total bytes written: %.0f\n",
(double)stats.total_written);
printf("Total bytes read: %.0f\n\n",
(double)stats.total_read);
}
printf("wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
(double)out,(double)in,(in+out)/(0.5 + (t-starttime)));
(double)stats.total_written,
(double)stats.total_read,
(stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
printf("total size is %.0f speedup is %.2f\n",
(double)tsize,(1.0*tsize)/(in+out));
(double)stats.total_size,
(1.0*stats.total_size)/(stats.total_written+stats.total_read));
}
@@ -149,8 +171,8 @@ static char *get_local_name(struct file_list *flist,char *name)
if (do_stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (chdir(name) != 0) {
rprintf(FERROR,"chdir %s : %s (1)\n",
if (!push_dir(name, 0)) {
rprintf(FERROR,"push_dir %s : %s (1)\n",
name,strerror(errno));
exit_cleanup(1);
}
@@ -176,8 +198,9 @@ static char *get_local_name(struct file_list *flist,char *name)
rprintf(FINFO,"created directory %s\n",name);
}
if (chdir(name) != 0) {
rprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
if (!push_dir(name, 0)) {
rprintf(FERROR,"push_dir %s : %s (2)\n",
name,strerror(errno));
exit_cleanup(1);
}
@@ -198,8 +221,8 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
if (verbose > 2)
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
if (!relative_paths && chdir(dir) != 0) {
rprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
if (!relative_paths && !push_dir(dir, 0)) {
rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
}
argc--;
@@ -289,8 +312,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
dir = argv[0];
argc--;
argv++;
if (!am_daemon && chdir(dir) != 0) {
rprintf(FERROR,"chdir %s : %s (4)\n",
if (!am_daemon && !push_dir(dir, 0)) {
rprintf(FERROR,"push_dir %s : %s (4)\n",
dir,strerror(errno));
exit_cleanup(1);
}
@@ -497,6 +520,8 @@ int main(int argc,char *argv[])
starttime = time(NULL);
am_root = (getuid() == 0);
memset(&stats, 0, sizeof(stats));
if (argc < 2) {
usage(FERROR);
exit_cleanup(1);

15
match.c
View File

@@ -34,13 +34,13 @@ typedef unsigned short tag;
static int false_alarms;
static int tag_hits;
static int matches;
static int data_transfer;
static int64 data_transfer;
static int total_false_alarms;
static int total_tag_hits;
static int total_matches;
static int64 total_data_transfer;
extern struct stats stats;
struct target {
tag t;
@@ -103,8 +103,10 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
data_transfer += n;
if (i >= 0)
if (i >= 0) {
stats.matched_data += s->sums[i].len;
n += s->sums[i].len;
}
for (j=0;j<n;j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,n-j);
@@ -273,7 +275,7 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
total_tag_hits += tag_hits;
total_false_alarms += false_alarms;
total_matches += matches;
total_data_transfer += data_transfer;
stats.literal_data += data_transfer;
}
void match_report(void)
@@ -282,7 +284,8 @@ void match_report(void)
return;
rprintf(FINFO,
"total: matches=%d tag_hits=%d false_alarms=%d data=%ld\n",
"total: matches=%d tag_hits=%d false_alarms=%d data=%.0f\n",
total_matches,total_tag_hits,
total_false_alarms,(long)total_data_transfer);
total_false_alarms,
(double)stats.literal_data);
}

View File

@@ -55,6 +55,7 @@ int am_sender=0;
int recurse = 0;
int am_daemon=0;
int am_client=0;
int do_stats=0;
int block_size=BLOCK_SIZE;
@@ -74,12 +75,15 @@ void usage(int F)
{
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
VERSION);
rprintf(F,"Usage:\t%s [options] src user@host:dest\nOR",RSYNC_NAME);
rprintf(F,"\t%s [options] user@host:src dest\n\n",RSYNC_NAME);
rprintf(F,"Options:\n");
rprintf(F,"Usage:\t%s [options] src user@host:dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] user@host:src dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] src dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] user@host::src dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] src user@host::dest\n",RSYNC_NAME);
rprintf(F,"\nOptions:\n");
rprintf(F,"-v, --verbose increase verbosity\n");
rprintf(F,"-c, --checksum always checksum\n");
rprintf(F,"-a, --archive archive mode (same as -rlptDog)\n");
rprintf(F,"-a, --archive archive mode\n");
rprintf(F,"-r, --recursive recurse into directories\n");
rprintf(F,"-R, --relative use relative path names\n");
rprintf(F,"-b, --backup make backups (default ~ extension)\n");
@@ -115,17 +119,21 @@ void usage(int F)
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
rprintf(F," --config FILE specify alternate rsyncd.conf file\n");
rprintf(F," --port PORT specify alternate rsyncd port number\n");
rprintf(F," --port PORT specify alternate rsyncd port number\n");
rprintf(F," --stats give some file transfer stats\n");
rprintf(F,"\n");
rprintf(F,"the backup suffix defaults to %s\n",BACKUP_SUFFIX);
rprintf(F,"the block size defaults to %d\n",BLOCK_SIZE);
rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
rprintf(F,"See http://samba.anu.edu.au/rsync/ for updates and bug reports\n");
}
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
OPT_INCLUDE, OPT_INCLUDE_FROM};
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS};
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
@@ -170,6 +178,7 @@ static struct option long_options[] = {
{"temp-dir", 1, 0, 'T'},
{"compress", 0, 0, 'z'},
{"daemon", 0, 0, OPT_DAEMON},
{"stats", 0, 0, OPT_STATS},
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{0,0,0,0}};
@@ -364,6 +373,10 @@ void parse_arguments(int argc, char *argv[])
am_daemon = 1;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_CONFIG:
config_file = optarg;
break;

View File

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

416
rsync.c
View File

@@ -51,6 +51,7 @@ extern int am_root;
extern int relative_paths;
extern int io_timeout;
extern int io_error;
extern struct stats stats;
/*
free a sums struct
@@ -559,6 +560,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
if (verbose > 3)
rprintf(FINFO,"data recv %d at %d\n",i,(int)offset);
stats.literal_data += i;
sum_update(data,i);
if (fd != -1 && write_file(fd,data,i) != i) {
@@ -573,6 +575,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
if (i == count-1 && remainder != 0)
len = remainder;
stats.matched_data += len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
i,len,(int)offset2,(int)offset);
@@ -739,215 +743,237 @@ void sig_int(void)
}
static int get_tmpname(char *fnametmp, char *fname)
{
char *f;
/* open tmp file */
if (tmpdir) {
f = strrchr(fname,'/');
if (f == NULL)
f = fname;
else
f++;
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
f = strrchr(fname,'/');
if (strlen(fname)+9 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
if (f) {
*f = 0;
slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname);
}
return 1;
}
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
{
int fd1,fd2;
STRUCT_STAT st;
char *fname;
char fnametmp[MAXPATHLEN];
struct map_struct *buf;
int i;
struct file_struct *file;
int phase=0;
int recv_ok;
if (verbose > 2) {
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
if (recurse && delete_mode && !local_name && flist->count>0) {
delete_files(flist);
}
while (1)
{
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO,"recv_files phase=%d\n",phase);
write_int(f_gen,-1);
continue;
int fd1,fd2;
STRUCT_STAT st;
char *fname;
char fnametmp[MAXPATHLEN];
struct map_struct *buf;
int i;
struct file_struct *file;
int phase=0;
int recv_ok;
if (verbose > 2) {
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
break;
}
file = flist->files[i];
fname = f_name(file);
if (recurse && delete_mode && !local_name && flist->count>0) {
delete_files(flist);
}
if (local_name)
fname = local_name;
while (1) {
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO,"recv_files phase=%d\n",phase);
write_int(f_gen,-1);
continue;
}
break;
}
if (dry_run) {
if (!am_server && verbose)
printf("%s\n",fname);
continue;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
i, flist->count);
exit_cleanup(1);
}
if (verbose > 2)
rprintf(FINFO,"recv_files(%s)\n",fname);
file = flist->files[i];
fname = f_name(file);
/* open the file */
fd1 = open(fname,O_RDONLY);
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno));
receive_data(f_in,NULL,-1,NULL);
close(fd1);
continue;
}
if (local_name)
fname = local_name;
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fname);
receive_data(f_in,NULL,-1,NULL);
close(fd1);
continue;
}
if (dry_run) {
if (!am_server && verbose)
printf("%s\n",fname);
continue;
}
if (fd1 != -1 && st.st_size > 0) {
buf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %d\n",fname,(int)st.st_size);
} else {
buf = NULL;
}
if (verbose > 2)
rprintf(FINFO,"recv_files(%s)\n",fname);
/* open tmp file */
if (tmpdir) {
char *f;
f = strrchr(fname,'/');
if (f == NULL)
f = fname;
else
f++;
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
if (buf) unmap_file(buf);
close(fd1);
continue;
}
slprintf(fnametmp,sizeof(fnametmp)-1, "%s/.%s.XXXXXX",tmpdir,f);
} else {
char *f = strrchr(fname,'/');
/* open the file */
fd1 = open(fname,O_RDONLY);
if (strlen(fname)+9 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
if (buf) unmap_file(buf);
close(fd1);
continue;
}
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno));
receive_data(f_in,NULL,-1,NULL);
close(fd1);
continue;
}
if (f) {
*f = 0;
slprintf(fnametmp,sizeof(fnametmp)-1,"%s/.%s.XXXXXX",fname,f+1);
*f = '/';
} else {
slprintf(fnametmp,sizeof(fnametmp)-1,".%s.XXXXXX",fname);
}
}
if (NULL == do_mktemp(fnametmp)) {
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
receive_data(f_in,buf,-1,NULL);
if (buf) unmap_file(buf);
close(fd1);
continue;
}
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 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
}
if (fd2 == -1) {
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL);
if (buf) unmap_file(buf);
close(fd1);
continue;
}
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fname);
receive_data(f_in,NULL,-1,NULL);
close(fd1);
continue;
}
if (fd1 != -1 && st.st_size > 0) {
buf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %d\n",fname,(int)st.st_size);
} else {
buf = NULL;
}
if (!get_tmpname(fnametmp,fname)) {
if (buf) unmap_file(buf);
close(fd1);
continue;
}
if (NULL == do_mktemp(fnametmp)) {
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
receive_data(f_in,buf,-1,NULL);
if (buf) unmap_file(buf);
close(fd1);
continue;
}
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 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
}
if (fd2 == -1) {
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL);
if (buf) unmap_file(buf);
close(fd1);
continue;
}
cleanup_fname = fnametmp;
cleanup_fname = fnametmp;
if (!am_server && verbose)
printf("%s\n",fname);
if (!am_server && verbose)
printf("%s\n",fname);
/* recv file data */
recv_ok = receive_data(f_in,buf,fd2,fname);
if (buf) unmap_file(buf);
if (fd1 != -1) {
close(fd1);
}
close(fd2);
if (verbose > 2)
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
if (make_backups) {
char fnamebak[MAXPATHLEN];
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
rprintf(FERROR,"backup filename too long\n");
continue;
}
slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
continue;
}
}
/* recv file data */
recv_ok = receive_data(f_in,buf,fd2,fname);
/* move tmp file over real file */
if (do_rename(fnametmp,fname) != 0) {
if (errno == EXDEV) {
/* rename failed on cross-filesystem link.
Copy the file instead. */
if (copy_file(fnametmp,fname, file->mode)) {
rprintf(FERROR,"copy %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
}
do_unlink(fnametmp);
} else {
rprintf(FERROR,"rename %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
do_unlink(fnametmp);
}
} else {
set_perms(fname,file,NULL,0);
}
if (buf) unmap_file(buf);
if (fd1 != -1) {
close(fd1);
}
close(fd2);
cleanup_fname = NULL;
if (verbose > 2)
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
if (make_backups) {
char fnamebak[MAXPATHLEN];
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
rprintf(FERROR,"backup filename too long\n");
continue;
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
fname);
} else {
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
write_int(f_gen,i);
}
}
}
slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
continue;
if (preserve_hard_links)
do_hard_links(flist);
/* now we need to fix any directory permissions that were
modified during the transfer */
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
if (!file->basename || !S_ISDIR(file->mode)) continue;
recv_generator(f_name(file),flist,i,-1);
}
}
/* move tmp file over real file */
if (do_rename(fnametmp,fname) != 0) {
if (errno == EXDEV) {
/* rename failed on cross-filesystem link.
Copy the file instead. */
if (copy_file(fnametmp,fname, file->mode)) {
rprintf(FERROR,"copy %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
}
do_unlink(fnametmp);
} else {
rprintf(FERROR,"rename %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
do_unlink(fnametmp);
}
} else {
set_perms(fname,file,NULL,0);
}
cleanup_fname = NULL;
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
fname);
} else {
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
write_int(f_gen,i);
}
}
}
if (preserve_hard_links)
do_hard_links(flist);
/* now we need to fix any directory permissions that were
modified during the transfer */
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
if (!file->basename || !S_ISDIR(file->mode)) continue;
recv_generator(f_name(file),flist,i,-1);
}
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");
return 0;
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");
return 0;
}
@@ -962,7 +988,6 @@ void send_files(struct file_list *flist,int f_out,int f_in)
int i;
struct file_struct *file;
int phase = 0;
int offset=0;
if (verbose > 2)
rprintf(FINFO,"send_files starting\n");
@@ -970,6 +995,8 @@ void send_files(struct file_list *flist,int f_out,int f_in)
setup_readbuffer(f_in);
while (1) {
int offset=0;
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
@@ -983,8 +1010,17 @@ void send_files(struct file_list *flist,int f_out,int f_in)
break;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
i, flist->count);
exit_cleanup(1);
}
file = flist->files[i];
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
fname[0] = 0;
if (file->basedir) {
strlcpy(fname,file->basedir,MAXPATHLEN-1);
@@ -1132,10 +1168,6 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
write_int(f,-1);
}
if (verbose > 2)
rprintf(FINFO,"generator wrote %ld\n",(long)write_total());
}

18
rsync.h
View File

@@ -280,9 +280,9 @@ struct file_struct {
};
struct file_list {
int count;
int malloced;
struct file_struct **files;
int count;
int malloced;
struct file_struct **files;
};
struct sum_buf {
@@ -316,6 +316,18 @@ struct exclude_struct {
int local;
};
struct stats {
int64 total_size;
int64 total_transferred_size;
int64 total_written;
int64 total_read;
int64 literal_data;
int64 matched_data;
int flist_size;
int num_files;
int num_transferred_files;
};
/* we need this function because of the silly way in which duplicate
entries are handled in the file lists - we can't change this

View File

@@ -217,9 +217,12 @@ explicitly checked on the receiver and any files of the same name
which already exist and have the same checksum and size on the
receiver are skipped. This option can be quite slow.
dit(bf(-a, --archive)) This is equivalent to -rlptDog. It is a quick way
dit(bf(-a, --archive)) This is equivalent to -rlptDg. It is a quick way
of saying I want recursion and want to preserve everything.
Note: if the user launching rsync is root then the -o option (preserve
uid) is also implied.
dit(bf(-r, --recursive)) This tells rsync to copy directories recursively
dit(bf(-R, --relative)) Use relative paths. This means that the full path
@@ -441,6 +444,10 @@ specified.
dit(bf(--port PORT)) This specifies an alternate TCP port number to use
rather than the default port 873.
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
on the file transfer, allowing you to tell how effective the rsync
algorithm is for your data.
enddit()
manpagesection(EXCLUDE PATTERNS)

View File

@@ -10,6 +10,14 @@
#
#
cat <<EOF
This set of tests is not completely portable. It is intended for developers
not for end users. You may experience failures on some platforms that
do not indicate a problem with rsync.
EOF
export PATH=.:$PATH
TMP=/tmp/rsync-test.$$
FROM=${TMP}/from

108
util.c
View File

@@ -559,3 +559,111 @@ void *Realloc(void *p, int size)
if (!p) return (void *)malloc(size);
return (void *)realloc(p, size);
}
void clean_fname(char *name)
{
char *p;
int l;
int modified = 1;
if (!name) return;
while (modified) {
modified = 0;
if ((p=strstr(name,"/./"))) {
modified = 1;
while (*p) {
p[0] = p[2];
p++;
}
}
if ((p=strstr(name,"//"))) {
modified = 1;
while (*p) {
p[0] = p[1];
p++;
}
}
if (strncmp(p=name,"./",2) == 0) {
modified = 1;
do {
p[0] = p[2];
} while (*p++);
}
l = strlen(p=name);
if (l > 1 && p[l-1] == '/') {
modified = 1;
p[l-1] = 0;
}
}
}
static char curr_dir[MAXPATHLEN];
/* like chdir() but can be reversed with pop_dir() if save is set. It
is also much faster as it remembers where we have been */
char *push_dir(char *dir, int save)
{
char *ret = curr_dir;
static int initialised;
if (!initialised) {
initialised = 1;
getcwd(curr_dir, sizeof(curr_dir)-1);
}
if (chdir(dir)) return NULL;
if (save) {
ret = strdup(curr_dir);
}
if (*dir == '/') {
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
} else {
strlcat(curr_dir,"/", sizeof(curr_dir)-1);
strlcat(curr_dir,dir, sizeof(curr_dir)-1);
}
clean_fname(curr_dir);
return ret;
}
/* reverse a push_dir call */
int pop_dir(char *dir)
{
int ret;
ret = chdir(dir);
if (ret) {
free(dir);
return ret;
}
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
free(dir);
return 0;
}
/* we need to supply our own strcmp function for file list comparisons
to ensure that signed/unsigned usage is consistent between machines. */
int u_strcmp(const char *cs1, const char *cs2)
{
const uchar *s1 = (uchar *)cs1;
const uchar *s2 = (uchar *)cs2;
while (*s1 && *s2 && (*s1 == *s2)) {
s1++; s2++;
}
return (int)*s1 - (int)*s2;
}

View File

@@ -1 +1 @@
#define VERSION "2.0.14"
#define VERSION "2.0.16"

View File

@@ -176,7 +176,7 @@ int r;
break;
case 3: /* illegal */
DUMPBITS(3)
s->mode = BAD;
s->mode = zBAD;
z->msg = (char*)"invalid block type";
r = Z_DATA_ERROR;
LEAVE
@@ -186,7 +186,7 @@ int r;
NEEDBITS(32)
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
{
s->mode = BAD;
s->mode = zBAD;
z->msg = (char*)"invalid stored block lengths";
r = Z_DATA_ERROR;
LEAVE
@@ -219,7 +219,7 @@ int r;
#ifndef PKZIP_BUG_WORKAROUND
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
{
s->mode = BAD;
s->mode = zBAD;
z->msg = (char*)"too many length or distance symbols";
r = Z_DATA_ERROR;
LEAVE
@@ -252,7 +252,7 @@ int r;
ZFREE(z, s->sub.trees.blens);
r = t;
if (r == Z_DATA_ERROR)
s->mode = BAD;
s->mode = zBAD;
LEAVE
}
s->sub.trees.index = 0;
@@ -289,7 +289,7 @@ int r;
(c == 16 && i < 1))
{
ZFREE(z, s->sub.trees.blens);
s->mode = BAD;
s->mode = zBAD;
z->msg = (char*)"invalid bit length repeat";
r = Z_DATA_ERROR;
LEAVE
@@ -317,7 +317,7 @@ int r;
if (t != Z_OK)
{
if (t == (uInt)Z_DATA_ERROR)
s->mode = BAD;
s->mode = zBAD;
r = t;
LEAVE
}
@@ -361,7 +361,7 @@ int r;
case DONE:
r = Z_STREAM_END;
LEAVE
case BAD:
case zBAD:
r = Z_DATA_ERROR;
LEAVE
default:

View File

@@ -22,7 +22,7 @@ typedef enum {
CHECK2, /* two check bytes to go */
CHECK1, /* one check byte to go */
DONE, /* finished check, done */
BAD} /* got an error--stay here */
zBAD} /* got an error--stay here */
inflate_mode;
/* inflate private state */
@@ -38,7 +38,7 @@ struct internal_state {
uLong was; /* computed check value */
uLong need; /* stream check value */
} check; /* if CHECK, check values to compare */
uInt marker; /* if BAD, inflateSync's marker bytes count */
uInt marker; /* if zBAD, inflateSync's marker bytes count */
} sub; /* submode */
/* mode independent information */
@@ -164,14 +164,14 @@ int f;
NEEDBYTE
if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
{
z->state->mode = BAD;
z->state->mode = zBAD;
z->msg = (char*)"unknown compression method";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
{
z->state->mode = BAD;
z->state->mode = zBAD;
z->msg = (char*)"invalid window size";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
@@ -182,7 +182,7 @@ int f;
b = NEXTBYTE;
if (((z->state->sub.method << 8) + b) % 31)
{
z->state->mode = BAD;
z->state->mode = zBAD;
z->msg = (char*)"incorrect header check";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
@@ -213,7 +213,7 @@ int f;
z->state->mode = DICT0;
return Z_NEED_DICT;
case DICT0:
z->state->mode = BAD;
z->state->mode = zBAD;
z->msg = (char*)"need dictionary";
z->state->sub.marker = 0; /* can try inflateSync */
return Z_STREAM_ERROR;
@@ -221,7 +221,7 @@ int f;
r = inflate_blocks(z->state->blocks, z, r);
if (r == Z_DATA_ERROR)
{
z->state->mode = BAD;
z->state->mode = zBAD;
z->state->sub.marker = 0; /* can try inflateSync */
break;
}
@@ -255,7 +255,7 @@ int f;
if (z->state->sub.check.was != z->state->sub.check.need)
{
z->state->mode = BAD;
z->state->mode = zBAD;
z->msg = (char*)"incorrect data check";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
@@ -264,7 +264,7 @@ int f;
z->state->mode = DONE;
case DONE:
return Z_STREAM_END;
case BAD:
case zBAD:
return Z_DATA_ERROR;
default:
return Z_STREAM_ERROR;
@@ -310,9 +310,9 @@ z_streamp z;
/* set up */
if (z == Z_NULL || z->state == Z_NULL)
return Z_STREAM_ERROR;
if (z->state->mode != BAD)
if (z->state->mode != zBAD)
{
z->state->mode = BAD;
z->state->mode = zBAD;
z->state->sub.marker = 0;
}
if ((n = z->avail_in) == 0)

View File

@@ -21,7 +21,7 @@ typedef enum {
CODES, /* processing fixed or dynamic block */
DRY, /* output remaining window bytes */
DONE, /* finished last block, done */
BAD} /* got a data error--stuck here */
zBAD} /* got a data error--stuck here */
inflate_block_mode;
/* inflate blocks semi-private state */