LIBOBJ=lib/getopt.o lib/fnmatch.o
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o
-OBJS=$(OBJS1) flist.o io.o compat.o $(LIBOBJ)
+OBJS=$(OBJS1) flist.o io.o compat.o hlink.o $(LIBOBJ)
.c.o:
$(CC) $(CFLAGS) -c $*.c -o $*.o
-b, --backup make backups (default ~ extension)
-u, --update update only (don't overwrite newer files)
-l, --links preserve soft links
+-H, --hard-links preserve hard links
-p, --perms preserve permissions
-o, --owner preserve owner (root only)
-g, --group preserve group
-D, --devices preserve devices (root only)
-t, --times preserve times
+-S, --sparse handle sparse files efficiently
-n, --dry-run show what would have been transferred
-x, --one-file-system don't cross filesystem boundaries
-B, --block-size SIZE checksum blocking size
--exclude FILE exclude file FILE
--exclude-from FILE exclude files listed in FILE
--suffix SUFFIX override backup suffix
+ --csum-length LENGTH set the checksum length
--version print version number
-
SETUP
-----
{
unsigned char flags;
static mode_t last_mode=0;
- static dev_t last_dev=0;
+ static dev_t last_rdev=0;
static uid_t last_uid=0;
static gid_t last_gid=0;
static char lastdir[MAXPATHLEN]="";
flags = FILE_VALID;
if (file->mode == last_mode) flags |= SAME_MODE;
- if (file->dev == last_dev) flags |= SAME_DEV;
+ if (file->rdev == last_rdev) flags |= SAME_RDEV;
if (file->uid == last_uid) flags |= SAME_UID;
if (file->gid == last_gid) flags |= SAME_GID;
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_DEV))
- write_int(f,(int)file->dev);
+ 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)) {
}
last_mode = file->mode;
- last_dev = file->dev;
+ last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
p = strrchr(file->name,'/');
unsigned char flags,int f)
{
static mode_t last_mode=0;
- static dev_t last_dev=0;
+ static dev_t last_rdev=0;
static uid_t last_uid=0;
static gid_t last_gid=0;
static char lastdir[MAXPATHLEN]="";
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
- file->dev = (flags & SAME_DEV) ? last_dev : (dev_t)read_int(f);
+ file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
#if SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
read_buf(f,file->sum,csum_length);
last_mode = file->mode;
- last_dev = file->dev;
+ last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
p = strrchr(file->name,'/');
AC_TYPE_SIZE_T
AC_TYPE_PID_T
AC_STRUCT_ST_RDEV
+AC_CHECK_TYPE(ino_t,unsigned)
echo $ac_n "checking for errno in errno.h... $ac_c"
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
AC_FUNC_MMAP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(waitpid strtok pipe getcwd mkdir strdup strerror chown chmod mknod)
-AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink utime utimes)
+AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
AC_CHECK_FUNCS(memmove getopt_long)
echo $ac_n "checking for working fnmatch... $ac_c"
if (strcmp(pattern,"!") == 0) {
if (verbose > 2)
- fprintf(stderr,"clearing exclude list\n");
+ fprintf(FERROR,"clearing exclude list\n");
while ((len)--)
free((*list)[len]);
free((*list));
out_of_memory("add_exclude");
if (verbose > 2)
- fprintf(stderr,"add_exclude(%s)\n",pattern);
+ fprintf(FERROR,"add_exclude(%s)\n",pattern);
(*list)[len+1] = NULL;
}
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
- fprintf(stderr,"%s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
return list;
extern int one_file_system;
extern int make_backups;
extern int preserve_links;
+extern int preserve_hard_links;
extern int preserve_perms;
extern int preserve_devices;
extern int preserve_uid;
{
if (check_exclude(fname,local_exclude_list)) {
if (verbose > 2)
- fprintf(stderr,"excluding file %s\n",fname);
+ fprintf(FERROR,"excluding file %s\n",fname);
return 0;
}
return 1;
unsigned char flags;
static time_t last_time=0;
static mode_t last_mode=0;
- static dev_t last_dev=0;
+ static dev_t last_rdev=0;
static uid_t last_uid=0;
static gid_t last_gid=0;
static char lastname[MAXPATHLEN]="";
flags = FILE_VALID;
if (file->mode == last_mode) flags |= SAME_MODE;
- if (file->dev == last_dev) flags |= SAME_DEV;
+ 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 (file->modtime == last_time) flags |= SAME_TIME;
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_DEV))
- write_int(f,(int)file->dev);
+ 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)) {
}
#endif
+#if SUPPORT_HARD_LINKS
+ if (preserve_hard_links && S_ISREG(file->mode)) {
+ write_int(f,file->dev);
+ write_int(f,file->inode);
+ }
+#endif
+
if (always_checksum) {
write_buf(f,file->sum,csum_length);
}
last_mode = file->mode;
- last_dev = file->dev;
+ last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
{
static mode_t last_time=0;
static mode_t last_mode=0;
- static dev_t last_dev=0;
+ static dev_t last_rdev=0;
static uid_t last_uid=0;
static gid_t last_gid=0;
static char lastname[MAXPATHLEN]="";
else
l2 = read_byte(f);
+ bzero((char *)file,sizeof(*file));
+
file->name = (char *)malloc(l1+l2+1);
if (!file->name) out_of_memory("receive_file_entry");
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
- file->dev = (flags & SAME_DEV) ? last_dev : (dev_t)read_int(f);
+ file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
#if SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
file->link[l] = 0;
}
#endif
+
+#if SUPPORT_HARD_LINKS
+ if (preserve_hard_links && S_ISREG(file->mode)) {
+ file->dev = read_int(f);
+ file->inode = read_int(f);
+ }
+#endif
if (always_checksum)
read_buf(f,file->sum,csum_length);
last_mode = file->mode;
- last_dev = file->dev;
+ last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
bzero(sum,SUM_LENGTH);
if (lstat(fname,&st) != 0) {
- fprintf(stderr,"%s: %s\n",
+ fprintf(FERROR,"%s: %s\n",
fname,strerror(errno));
return NULL;
}
if (S_ISDIR(st.st_mode) && !recurse) {
- fprintf(stderr,"skipping directory %s\n",fname);
+ fprintf(FERROR,"skipping directory %s\n",fname);
return NULL;
}
return NULL;
if (verbose > 2)
- fprintf(stderr,"make_file(%s)\n",fname);
+ fprintf(FERROR,"make_file(%s)\n",fname);
+
+ bzero((char *)&file,sizeof(file));
file.name = strdup(fname);
file.modtime = st.st_mtime;
file.mode = st.st_mode;
file.uid = st.st_uid;
file.gid = st.st_gid;
+ file.dev = st.st_dev;
+ file.inode = st.st_ino;
#ifdef HAVE_ST_RDEV
- file.dev = st.st_rdev;
+ file.rdev = st.st_rdev;
#endif
#if SUPPORT_LINKS
int l;
char lnk[MAXPATHLEN];
if ((l=readlink(fname,lnk,MAXPATHLEN-1)) == -1) {
- fprintf(stderr,"readlink %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"readlink %s : %s\n",fname,strerror(errno));
return NULL;
}
lnk[l] = 0;
d = opendir(dir);
if (!d) {
- fprintf(stderr,"%s: %s\n",
+ fprintf(FERROR,"%s: %s\n",
dir,strerror(errno));
return;
}
struct file_list *flist;
if (verbose && recurse) {
- fprintf(am_server?stderr:stdout,"building file list ... ");
- fflush(am_server?stderr:stdout);
+ fprintf(FINFO,"building file list ... ");
+ fflush(FINFO);
}
flist = (struct file_list *)malloc(sizeof(flist[0]));
}
if (lstat(fname,&st) != 0) {
- fprintf(stderr,"%s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
continue;
}
if (S_ISDIR(st.st_mode) && !recurse) {
- fprintf(stderr,"skipping directory %s\n",fname);
+ fprintf(FERROR,"skipping directory %s\n",fname);
continue;
}
if (dir && *dir) {
if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
- fprintf(stderr,"getwd : %s\n",strerror(errno));
+ fprintf(FERROR,"getwd : %s\n",strerror(errno));
exit_cleanup(1);
}
if (chdir(dir) != 0) {
- fprintf(stderr,"chdir %s : %s\n",dir,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
continue;
}
flist_dir = dir;
send_file_name(f,flist,recurse,fname);
flist_dir = NULL;
if (chdir(dbuf) != 0) {
- fprintf(stderr,"chdir %s : %s\n",dbuf,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s\n",dbuf,strerror(errno));
exit_cleanup(1);
}
continue;
write_flush(f);
}
- clean_flist(flist);
-
if (verbose && recurse)
- fprintf(am_server?stderr:stdout,"done\n");
+ fprintf(FINFO,"done\n");
+
+ clean_flist(flist);
return flist;
}
unsigned char flags;
if (verbose > 2)
- fprintf(stderr,"recv_file_list starting\n");
+ fprintf(FERROR,"recv_file_list starting\n");
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist)
flist->count++;
if (verbose > 2)
- fprintf(stderr,"recv_file_name(%s)\n",flist->files[i].name);
+ fprintf(FERROR,"recv_file_name(%s)\n",flist->files[i].name);
}
if (verbose > 2)
- fprintf(stderr,"received %d names\n",flist->count);
+ fprintf(FERROR,"received %d names\n",flist->count);
clean_flist(flist);
}
-static int flist_compare(struct file_struct *f1,struct file_struct *f2)
+int file_compare(struct file_struct *f1,struct file_struct *f2)
{
if (!f1->name && !f2->name) return 0;
if (!f1->name) return -1;
while (low != high) {
int mid = (low+high)/2;
- int ret = flist_compare(&flist->files[mid],f);
+ int ret = file_compare(&flist->files[mid],f);
if (ret == 0) return mid;
if (ret > 0)
high=mid;
else
low=mid+1;
}
- if (flist_compare(&flist->files[low],f) == 0)
+ if (file_compare(&flist->files[low],f) == 0)
return low;
return -1;
}
qsort(flist->files,flist->count,
sizeof(flist->files[0]),
- (int (*)())flist_compare);
+ (int (*)())file_compare);
for (i=1;i<flist->count;i++) {
if (flist->files[i].name &&
strcmp(flist->files[i].name,flist->files[i-1].name) == 0) {
if (verbose > 1 && !am_server)
- fprintf(stderr,"removing duplicate name %s from file list\n",
- flist->files[i].name);
+ fprintf(FERROR,"removing duplicate name %s from file list %d\n",
+ flist->files[i-1].name,i-1);
free(flist->files[i-1].name);
- flist->files[i-1].name = NULL;
- }
+ bzero((char *)&flist->files[i-1],sizeof(flist->files[i-1]));
+ }
}
}
--- /dev/null
+/*
+ Copyright (C) Andrew Tridgell 1996
+ Copyright (C) Paul Mackerras 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "rsync.h"
+
+extern int am_server;
+extern int dry_run;
+
+#if SUPPORT_HARD_LINKS
+static int hlink_compare(struct file_struct *f1,struct file_struct *f2)
+{
+ if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode)) return 0;
+ if (!S_ISREG(f1->mode)) return -1;
+ if (!S_ISREG(f2->mode)) return 1;
+
+ if (f1->dev != f2->dev)
+ return (f1->dev - f2->dev);
+
+ if (f1->inode != f2->inode)
+ return (f1->inode - f2->inode);
+
+ return file_compare(f1,f2);
+}
+
+
+static struct file_struct *hlink_list = NULL;
+static int hlink_count=0;
+#endif
+
+void init_hard_links(struct file_list *flist)
+{
+#if SUPPORT_HARD_LINKS
+ if (flist->count < 2) return;
+
+ if (hlink_list) free(hlink_list);
+
+ if (!(hlink_list =
+ (struct file_struct *)malloc(sizeof(hlink_list[0])*flist->count)))
+ out_of_memory("init_hard_links");
+
+ bcopy((char *)flist->files,hlink_list,sizeof(hlink_list[0])*flist->count);
+
+ qsort(hlink_list,flist->count,
+ sizeof(hlink_list[0]),
+ (int (*)())hlink_compare);
+
+ hlink_count=flist->count;
+#endif
+}
+
+/* check if a file should be skipped because it is the same as an
+ earlier hard link */
+int check_hard_link(struct file_struct *file)
+{
+#if SUPPORT_HARD_LINKS
+ int low=0,high=hlink_count;
+ int mid=0,ret=0;
+
+ if (!hlink_list || !S_ISREG(file->mode)) return 0;
+
+ while (low != high) {
+ mid = (low+high)/2;
+ ret = hlink_compare(&hlink_list[mid],file);
+ if (ret == 0) break;
+ if (ret > 0)
+ high=mid;
+ else
+ low=mid+1;
+ }
+
+ if (hlink_compare(&hlink_list[mid],file) != 0) return 0;
+
+ if (mid > 0 &&
+ S_ISREG(hlink_list[mid-1].mode) &&
+ file->dev == hlink_list[mid-1].dev &&
+ file->inode == hlink_list[mid-1].inode)
+ return 1;
+#endif
+
+ return 0;
+}
+
+
+/* create any hard links in the flist */
+void do_hard_links(struct file_list *flist)
+{
+#if SUPPORT_HARD_LINKS
+ int i;
+
+ if (!hlink_list) return;
+
+ 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].dev == hlink_list[i-1].dev &&
+ hlink_list[i].inode == hlink_list[i-1].inode) {
+ struct stat st1,st2;
+
+ if (stat(hlink_list[i-1].name,&st1) != 0) continue;
+ if (stat(hlink_list[i].name,&st2) != 0) {
+ if (!dry_run && link(hlink_list[i-1].name,hlink_list[i].name) != 0) {
+ fprintf(FINFO,"link %s => %s : %s\n",
+ hlink_list[i].name,hlink_list[i-1].name,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)) {
+ fprintf(FINFO,"link %s => %s : %s\n",
+ hlink_list[i].name,hlink_list[i-1].name,strerror(errno));
+ continue;
+ }
+ }
+ fprintf(FINFO,"%s => %s\n",
+ hlink_list[i].name,hlink_list[i-1].name);
+ }
+ }
+#endif
+}
static int total_read = 0;
extern int verbose;
+extern int sparse_files;
int write_total(void)
{
char b[4];
if ((ret=readfd(f,b,4)) != 4) {
if (verbose > 1)
- fprintf(stderr,"Error reading %d bytes : %s\n",
+ fprintf(FERROR,"Error reading %d bytes : %s\n",
4,ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
int ret;
if ((ret=readfd(f,buf,len)) != len) {
if (verbose > 1)
- fprintf(stderr,"Error reading %d bytes : %s\n",
+ fprintf(FERROR,"Error reading %d bytes : %s\n",
len,ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
int sparse_end(int f)
{
-#if SPARSE_FILES
if (last_sparse) {
lseek(f,-1,SEEK_CUR);
return (write(f,&last_byte,1) == 1 ? 0 : -1);
}
-#endif
last_sparse = 0;
return 0;
}
int write_sparse(int f,char *buf,int len)
{
- int l=0;
+ int l1=0,l2=0;
+ int ret;
-#if SPARSE_FILES
- for (l=0;l<len && buf[l]==0;l++) ;
+ if (!sparse_files)
+ return write(f,buf,len);
- if (l > 0)
- lseek(f,l,SEEK_CUR);
+ for (l1=0;l1<len && buf[l1]==0;l1++) ;
+ for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
last_byte = buf[len-1];
-#endif
- if (l == len) {
- last_sparse = 1;
+ if (l1 == len || l2 > 0)
+ last_sparse=1;
+
+ if (l1 > 0)
+ lseek(f,l1,SEEK_CUR);
+
+ if (l1 == len)
return len;
- }
- last_sparse = 0;
+ if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
+ if (ret == -1 || ret == 0) return ret;
+ return (l1+ret);
+ }
+
+ if (l2 > 0)
+ lseek(f,l2,SEEK_CUR);
- return (l + write(f,buf+l,len-l));
+ return len;
}
int read_write(int fd_in,int fd_out,int size)
{
static char *buf=NULL;
- static int bufsize = CHUNK_SIZE;
+ int bufsize = sparse_files?SPARSE_WRITE_SIZE:WRITE_SIZE;
int total=0;
if (!buf) {
char b[4];
SIVAL(b,0,x);
if ((ret=writefd(f,b,4)) != 4) {
- fprintf(stderr,"write_int failed : %s\n",
+ fprintf(FERROR,"write_int failed : %s\n",
ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
{
int ret;
if ((ret=writefd(f,buf,len)) != len) {
- fprintf(stderr,"write_buf failed : %s\n",
+ fprintf(FERROR,"write_buf failed : %s\n",
ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
int make_backups = 0;
int preserve_links = 0;
+int preserve_hard_links = 0;
int preserve_perms = 0;
int preserve_devices = 0;
int preserve_uid = 0;
int delete_mode=0;
int one_file_system=0;
int remote_version=0;
+int sparse_files=0;
extern int csum_length;
int am_server = 0;
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
+ if (preserve_hard_links)
+ argstr[x++] = 'H';
if (preserve_uid)
argstr[x++] = 'o';
if (preserve_gid)
argstr[x++] = 'I';
if (one_file_system)
argstr[x++] = 'x';
+ if (sparse_files)
+ argstr[x++] = 'S';
argstr[x] = 0;
if (x != 1) args[ac++] = argstr;
args[argc] = NULL;
if (verbose > 3) {
- fprintf(stderr,"cmd=");
+ fprintf(FERROR,"cmd=");
for (i=0;i<argc;i++)
- fprintf(stderr,"%s ",args[i]);
- fprintf(stderr,"\n");
+ fprintf(FERROR,"%s ",args[i]);
+ fprintf(FERROR,"\n");
}
return piped_child(args,f_in,f_out);
if (stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (chdir(name) != 0) {
- fprintf(stderr,"chdir %s : %s\n",name,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s\n",name,strerror(errno));
exit_cleanup(1);
}
return NULL;
}
if (flist->count > 1) {
- fprintf(stderr,"ERROR: destination must be a directory when copying more than 1 file\n");
+ fprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
exit_cleanup(1);
}
return name;
return NULL;
if (mkdir(name,0777) != 0) {
- fprintf(stderr,"mkdir %s : %s\n",name,strerror(errno));
+ fprintf(FERROR,"mkdir %s : %s\n",name,strerror(errno));
exit_cleanup(1);
} else {
- fprintf(am_server?stderr:stdout,"created directory %s\n",name);
+ fprintf(FINFO,"created directory %s\n",name);
}
if (chdir(name) != 0) {
- fprintf(stderr,"chdir %s : %s\n",name,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s\n",name,strerror(errno));
exit_cleanup(1);
}
struct file_list *flist;
if (verbose > 2)
- fprintf(stderr,"server_sender starting pid=%d\n",(int)getpid());
+ fprintf(FERROR,"server_sender starting pid=%d\n",(int)getpid());
if (chdir(dir) != 0) {
- fprintf(stderr,"chdir %s: %s\n",dir,strerror(errno));
+ fprintf(FERROR,"chdir %s: %s\n",dir,strerror(errno));
exit_cleanup(1);
}
argc--;
}
+static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
+{
+ int pid;
+ int status=0;
+
+ if (preserve_hard_links)
+ init_hard_links(flist);
+
+ if ((pid=fork()) == 0) {
+ recv_files(f_in,flist,local_name);
+ if (preserve_hard_links)
+ do_hard_links(flist);
+ if (verbose > 2)
+ fprintf(FERROR,"receiver read %d\n",read_total());
+ exit_cleanup(0);
+ }
+
+ generate_files(f_out,flist,local_name);
+
+ waitpid(pid, &status, 0);
+
+ return status;
+}
+
void do_server_recv(int argc,char *argv[])
{
- int pid,status;
+ int status;
char *dir = NULL;
struct file_list *flist;
char *local_name=NULL;
if (verbose > 2)
- fprintf(stderr,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
+ fprintf(FERROR,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
if (argc > 0) {
dir = argv[0];
argc--;
argv++;
if (chdir(dir) != 0) {
- fprintf(stderr,"chdir %s : %s\n",dir,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
exit_cleanup(1);
}
}
flist = recv_file_list(STDIN_FILENO);
if (!flist || flist->count == 0) {
- fprintf(stderr,"nothing to do\n");
+ fprintf(FERROR,"nothing to do\n");
exit_cleanup(1);
}
local_name = get_local_name(flist,argv[0]);
}
- if ((pid=fork()) == 0) {
- recv_files(STDIN_FILENO,flist,local_name);
- if (verbose > 2)
- fprintf(stderr,"receiver read %d\n",read_total());
- exit_cleanup(0);
- }
-
- generate_files(STDOUT_FILENO,flist,local_name);
-
- waitpid(pid, &status, 0);
+ status = do_recv(STDIN_FILENO,STDOUT_FILENO,flist,local_name);
exit_cleanup(status);
}
fprintf(f,"-b, --backup make backups (default ~ extension)\n");
fprintf(f,"-u, --update update only (don't overwrite newer files)\n");
fprintf(f,"-l, --links preserve soft links\n");
+ fprintf(f,"-H, --hard-links preserve hard links\n");
fprintf(f,"-p, --perms preserve permissions\n");
fprintf(f,"-o, --owner preserve owner (root only)\n");
fprintf(f,"-g, --group preserve group\n");
fprintf(f,"-D, --devices preserve devices (root only)\n");
fprintf(f,"-t, --times preserve times\n");
+ fprintf(f,"-S, --sparse handle sparse files efficiently\n");
fprintf(f,"-n, --dry-run show what would have been transferred\n");
fprintf(f,"-x, --one-file-system don't cross filesystem boundaries\n");
fprintf(f,"-B, --block-size SIZE checksum blocking size\n");
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_RSYNC_PATH,OPT_CSUM_LENGTH};
-static char *short_options = "oblpguDCtcahvrIxne:B:";
+static char *short_options = "oblHpguDCtcahvrIxnSe:B:";
static struct option long_options[] = {
{"version", 0, 0, OPT_VERSION},
{"ignore-times",0, 0, 'I'},
{"help", 0, 0, 'h'},
{"dry-run", 0, 0, 'n'},
+ {"sparse", 0, 0, 'S'},
{"cvs-exclude", 0, 0, 'C'},
{"archive", 0, 0, 'a'},
{"checksum", 0, 0, 'c'},
{"devices", 0, 0, 'D'},
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
+ {"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
{"group", 0, 0, 'g'},
{"times", 0, 0, 't'},
int main(int argc,char *argv[])
{
- int pid, status, pid2, status2;
+ int pid, status, status2;
int opt;
int option_index;
char *shell_cmd = NULL;
break;
case 'h':
- usage(stdout);
+ usage(FINFO);
exit_cleanup(0);
case 'b':
dry_run=1;
break;
+ case 'S':
+ sparse_files=1;
+ break;
+
case 'C':
cvs_exclude=1;
break;
update_only=1;
break;
-#if SUPPORT_LINKS
case 'l':
+#if SUPPORT_LINKS
preserve_links=1;
+#endif
break;
+
+ case 'H':
+#if SUPPORT_HARD_LINKS
+ preserve_hard_links=1;
#endif
+ break;
case 'p':
preserve_perms=1;
if (getuid() == 0) {
preserve_uid=1;
} else {
- fprintf(stderr,"-o only allowed for root\n");
+ fprintf(FERROR,"-o only allowed for root\n");
exit_cleanup(1);
}
break;
if (getuid() == 0) {
preserve_devices=1;
} else {
- fprintf(stderr,"-D only allowed for root\n");
+ fprintf(FERROR,"-D only allowed for root\n");
exit_cleanup(1);
}
break;
case OPT_SENDER:
if (!am_server) {
- usage(stderr);
+ usage(FERROR);
exit_cleanup(1);
}
sender = 1;
break;
default:
- fprintf(stderr,"bad option -%c\n",opt);
+ fprintf(FERROR,"bad option -%c\n",opt);
exit_cleanup(1);
}
}
remote_version = read_int(STDIN_FILENO);
if (remote_version < MIN_PROTOCOL_VERSION ||
remote_version > MAX_PROTOCOL_VERSION) {
- fprintf(stderr,"protocol version mismatch - is your shell clean?\n");
+ fprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
exit_cleanup(1);
}
write_int(STDOUT_FILENO,PROTOCOL_VERSION);
}
if (argc < 2) {
- usage(stderr);
+ usage(FERROR);
exit_cleanup(1);
}
}
if (verbose > 3) {
- fprintf(stderr,"cmd=%s machine=%s user=%s path=%s\n",
+ fprintf(FERROR,"cmd=%s machine=%s user=%s path=%s\n",
shell_cmd?shell_cmd:"",
shell_machine?shell_machine:"",
shell_user?shell_user:"",
}
if (!sender && argc != 1) {
- usage(stderr);
+ usage(FERROR);
exit_cleanup(1);
}
remote_version = read_int(f_in);
if (remote_version < MIN_PROTOCOL_VERSION ||
remote_version > MAX_PROTOCOL_VERSION) {
- fprintf(stderr,"protocol version mismatch - is your shell clean?\n");
+ fprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
exit_cleanup(1);
}
}
setup_protocol();
if (verbose > 3)
- fprintf(stderr,"parent=%d child=%d sender=%d recurse=%d\n",
+ fprintf(FERROR,"parent=%d child=%d sender=%d recurse=%d\n",
(int)getpid(),pid,sender,recurse);
if (sender) {
send_exclude_list(f_out);
flist = send_file_list(f_out,recurse,argc,argv);
if (verbose > 3)
- fprintf(stderr,"file list sent\n");
+ fprintf(FERROR,"file list sent\n");
send_files(flist,f_out,f_in);
if (verbose > 3)
- fprintf(stderr,"waiting on %d\n",pid);
+ fprintf(FERROR,"waiting on %d\n",pid);
waitpid(pid, &status, 0);
report(-1);
exit_cleanup(status);
flist = recv_file_list(f_in);
if (!flist || flist->count == 0) {
- fprintf(stderr,"nothing to do\n");
+ fprintf(FERROR,"nothing to do\n");
exit_cleanup(0);
}
local_name = get_local_name(flist,argv[0]);
- if ((pid2=fork()) == 0) {
- recv_files(f_in,flist,local_name);
- if (verbose > 1)
- fprintf(stderr,"receiver read %d\n",read_total());
- exit_cleanup(0);
- }
-
- generate_files(f_out,flist,local_name);
-
- waitpid(pid2, &status2, 0);
+ status2 = do_recv(f_in,f_out,flist,local_name);
report(f_in);
if (verbose > 2)
if (i != -1)
- fprintf(stderr,"match at %d last_match=%d j=%d len=%d n=%d\n",
+ 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 (n > 0) {
char *map;
if (verbose > 2)
- fprintf(stderr,"hash search b=%d len=%d\n",s->n,(int)len);
+ fprintf(FERROR,"hash search b=%d len=%d\n",s->n,(int)len);
k = MIN(len, s->n);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
- fprintf(stderr, "sum=%.8x k=%d\n", sum, k);
+ fprintf(FERROR, "sum=%.8x k=%d\n", sum, k);
offset = 0;
end = len + 1 - s->sums[s->count-1].len;
if (verbose > 3)
- fprintf(stderr,"hash search s->n=%d len=%d count=%d\n",
+ 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(stderr,"offset=%d sum=%08x\n",
+ fprintf(FERROR,"offset=%d sum=%08x\n",
offset,sum);
if (j != NULL_TAG) {
if (sum == s->sums[i].sum1) {
if (verbose > 3)
- fprintf(stderr,"potential match at %d target=%d %d sum=%08x\n",
+ fprintf(FERROR,"potential match at %d target=%d %d sum=%08x\n",
offset,j,i,sum);
if (!done_csum2) {
build_hash_table(s);
if (verbose > 2)
- fprintf(stderr,"built hash table\n");
+ fprintf(FERROR,"built hash table\n");
hash_search(f,s,buf,len);
if (verbose > 2)
- fprintf(stderr,"done hash search\n");
+ fprintf(FERROR,"done hash search\n");
} else {
matched(f,s,buf,len,len,-1);
}
}
if (verbose > 2)
- fprintf(stderr, "false_alarms=%d tag_hits=%d matches=%d\n",
+ fprintf(FERROR, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
total_tag_hits += tag_hits;
if (verbose <= 1)
return;
- fprintf(am_server?stderr:stdout,
+ 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);
extern int update_only;
extern int make_backups;
extern int preserve_links;
+extern int preserve_hard_links;
extern int preserve_perms;
extern int preserve_devices;
extern int preserve_uid;
}
if (verbose > 3)
- fprintf(stderr,"count=%d rem=%d n=%d flength=%d\n",
+ fprintf(FERROR,"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);
s->sums[i].i = i;
if (verbose > 3)
- fprintf(stderr,"chunk[%d] offset=%d len=%d sum1=%08x\n",
+ fprintf(FERROR,"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;
s->sums = NULL;
if (verbose > 3)
- fprintf(stderr,"count=%d n=%d rem=%d\n",
+ fprintf(FERROR,"count=%d n=%d rem=%d\n",
s->count,s->n,s->remainder);
block_len = s->n;
offset += s->sums[i].len;
if (verbose > 3)
- fprintf(stderr,"chunk[%d] len=%d offset=%d sum1=%08x\n",
+ fprintf(FERROR,"chunk[%d] len=%d offset=%d sum1=%08x\n",
i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
}
if (!st) {
if (stat(fname,&st2) != 0) {
- fprintf(stderr,"stat %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
return;
}
st = &st2;
st->st_mtime != file->modtime) {
updated = 1;
if (set_modtime(fname,file->modtime) != 0) {
- fprintf(stderr,"failed to set times on %s : %s\n",
+ fprintf(FERROR,"failed to set times on %s : %s\n",
fname,strerror(errno));
return;
}
st->st_mode != file->mode) {
updated = 1;
if (chmod(fname,file->mode) != 0) {
- fprintf(stderr,"failed to set permissions on %s : %s\n",
+ fprintf(FERROR,"failed to set permissions on %s : %s\n",
fname,strerror(errno));
return;
}
preserve_uid?file->uid:-1,
preserve_gid?file->gid:-1) != 0) {
if (verbose>1 || preserve_uid)
- fprintf(stderr,"chown %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"chown %s : %s\n",fname,strerror(errno));
return;
}
}
if (verbose > 1 && report) {
if (updated)
- fprintf(am_server?stderr:stdout,"%s\n",fname);
+ fprintf(FINFO,"%s\n",fname);
else
- fprintf(am_server?stderr:stdout,"%s is uptodate\n",fname);
+ fprintf(FINFO,"%s is uptodate\n",fname);
}
}
struct sum_struct *s;
char sum[SUM_LENGTH];
int statret;
+ struct file_struct *file = &flist->files[i];
if (verbose > 2)
- fprintf(stderr,"recv_generator(%s)\n",fname);
+ fprintf(FERROR,"recv_generator(%s)\n",fname);
statret = lstat(fname,&st);
#if SUPPORT_LINKS
- if (preserve_links && S_ISLNK(flist->files[i].mode)) {
+ if (preserve_links && S_ISLNK(file->mode)) {
char lnk[MAXPATHLEN];
int l;
if (statret == 0) {
l = readlink(fname,lnk,MAXPATHLEN-1);
if (l > 0) {
lnk[l] = 0;
- if (strcmp(lnk,flist->files[i].link) == 0) {
- set_perms(fname,&flist->files[i],&st,1);
+ if (strcmp(lnk,file->link) == 0) {
+ set_perms(fname,file,&st,1);
return;
}
}
}
if (!dry_run) unlink(fname);
- if (!dry_run && symlink(flist->files[i].link,fname) != 0) {
- fprintf(stderr,"link %s -> %s : %s\n",
- fname,flist->files[i].link,strerror(errno));
+ if (!dry_run && symlink(file->link,fname) != 0) {
+ fprintf(FERROR,"link %s -> %s : %s\n",
+ fname,file->link,strerror(errno));
} else {
- set_perms(fname,&flist->files[i],NULL,0);
+ set_perms(fname,file,NULL,0);
if (verbose)
- fprintf(am_server?stderr:stdout,"%s -> %s\n",
- fname,flist->files[i].link);
+ fprintf(FINFO,"%s -> %s\n",
+ fname,file->link);
}
return;
}
#endif
#ifdef HAVE_MKNOD
- if (preserve_devices && IS_DEVICE(flist->files[i].mode)) {
+ if (preserve_devices && IS_DEVICE(file->mode)) {
if (statret != 0 ||
- st.st_mode != flist->files[i].mode ||
- st.st_rdev != flist->files[i].dev) {
+ st.st_mode != file->mode ||
+ st.st_rdev != file->rdev) {
if (!dry_run) unlink(fname);
if (verbose > 2)
- fprintf(stderr,"mknod(%s,0%o,0x%x)\n",
- fname,(int)flist->files[i].mode,(int)flist->files[i].dev);
+ fprintf(FERROR,"mknod(%s,0%o,0x%x)\n",
+ fname,(int)file->mode,(int)file->rdev);
if (!dry_run &&
- mknod(fname,flist->files[i].mode,flist->files[i].dev) != 0) {
- fprintf(stderr,"mknod %s : %s\n",fname,strerror(errno));
+ mknod(fname,file->mode,file->rdev) != 0) {
+ fprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
} else {
- set_perms(fname,&flist->files[i],NULL,0);
+ set_perms(fname,file,NULL,0);
if (verbose)
- fprintf(am_server?stderr:stdout,"%s\n",fname);
+ fprintf(FINFO,"%s\n",fname);
}
} else {
- set_perms(fname,&flist->files[i],&st,1);
+ set_perms(fname,file,&st,1);
}
return;
}
#endif
- if (!S_ISREG(flist->files[i].mode)) {
- fprintf(stderr,"skipping non-regular file %s\n",fname);
+ if (preserve_hard_links && check_hard_link(file)) {
+ if (verbose > 1)
+ fprintf(FINFO,"%s is a hard link\n",file->name);
+ return;
+ }
+
+ if (!S_ISREG(file->mode)) {
+ fprintf(FERROR,"skipping non-regular file %s\n",fname);
return;
}
if (!dry_run) send_sums(NULL,f_out);
} else {
if (verbose > 1)
- fprintf(stderr,"recv_generator failed to open %s\n",fname);
+ fprintf(FERROR,"recv_generator failed to open %s\n",fname);
}
return;
}
if (!S_ISREG(st.st_mode)) {
- fprintf(stderr,"%s : not a regular file\n",fname);
+ fprintf(FERROR,"%s : not a regular file\n",fname);
return;
}
- if (update_only && st.st_mtime >= flist->files[i].modtime) {
+ if (update_only && st.st_mtime >= file->modtime) {
if (verbose > 1)
- fprintf(stderr,"%s is newer\n",fname);
+ fprintf(FERROR,"%s is newer\n",fname);
return;
}
file_checksum(fname,sum,st.st_size);
}
- if (st.st_size == flist->files[i].length &&
- ((!ignore_times && st.st_mtime == flist->files[i].modtime) ||
+ if (st.st_size == file->length &&
+ ((!ignore_times && st.st_mtime == file->modtime) ||
(always_checksum && S_ISREG(st.st_mode) &&
- memcmp(sum,flist->files[i].sum,csum_length) == 0))) {
- set_perms(fname,&flist->files[i],&st,1);
+ memcmp(sum,file->sum,csum_length) == 0))) {
+ set_perms(fname,file,&st,1);
return;
}
fd = open(fname,O_RDONLY);
if (fd == -1) {
- fprintf(stderr,"failed to open %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"failed to open %s : %s\n",fname,strerror(errno));
return;
}
}
if (verbose > 3)
- fprintf(stderr,"mapped %s of size %d\n",fname,(int)st.st_size);
+ fprintf(FERROR,"mapped %s of size %d\n",fname,(int)st.st_size);
s = generate_sums(buf,st.st_size,block_size);
for (i=read_int(f_in); i != 0; i=read_int(f_in)) {
if (i > 0) {
if (verbose > 3)
- fprintf(stderr,"data recv %d at %d\n",i,(int)offset);
+ fprintf(FERROR,"data recv %d at %d\n",i,(int)offset);
if (read_write(f_in,fd,i) != i) {
- fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
offset += i;
len = remainder;
if (verbose > 3)
- fprintf(stderr,"chunk[%d] of size %d at %d offset=%d\n",
+ fprintf(FERROR,"chunk[%d] of size %d at %d offset=%d\n",
i,len,(int)offset2,(int)offset);
if (write_sparse(fd,map_ptr(buf,offset2,len),len) != len) {
- fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
offset += len;
}
if (offset > 0 && sparse_end(fd) != 0) {
- fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
}
{
if (!S_ISDIR(f->mode)) {
if (!dry_run && unlink(f->name) != 0) {
- fprintf(stderr,"unlink %s : %s\n",f->name,strerror(errno));
+ fprintf(FERROR,"unlink %s : %s\n",f->name,strerror(errno));
} else if (verbose) {
- fprintf(stderr,"deleting %s\n",f->name);
+ fprintf(FERROR,"deleting %s\n",f->name);
}
} else {
if (!dry_run && rmdir(f->name) != 0) {
if (errno != ENOTEMPTY)
- fprintf(stderr,"rmdir %s : %s\n",f->name,strerror(errno));
+ fprintf(FERROR,"rmdir %s : %s\n",f->name,strerror(errno));
} else if (verbose) {
- fprintf(stderr,"deleting directory %s\n",f->name);
+ fprintf(FERROR,"deleting directory %s\n",f->name);
}
}
}
char fnametmp[MAXPATHLEN];
char *buf;
int i;
+ struct file_struct *file;
if (verbose > 2) {
- fprintf(stderr,"recv_files(%d) starting\n",flist->count);
+ fprintf(FERROR,"recv_files(%d) starting\n",flist->count);
}
if (recurse && delete_mode && !local_name && flist->count>0) {
i = read_int(f_in);
if (i == -1) break;
- fname = flist->files[i].name;
+ file = &flist->files[i];
+ fname = file->name;
if (local_name)
fname = local_name;
}
if (verbose > 2)
- fprintf(stderr,"recv_files(%s)\n",fname);
+ fprintf(FERROR,"recv_files(%s)\n",fname);
/* open the file */
fd1 = open(fname,O_RDONLY);
if (fd1 != -1 && fstat(fd1,&st) != 0) {
- fprintf(stderr,"fstat %s : %s\n",fname,strerror(errno));
+ fprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno));
close(fd1);
return -1;
}
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
- fprintf(stderr,"%s : not a regular file\n",fname);
+ fprintf(FERROR,"%s : not a regular file\n",fname);
close(fd1);
return -1;
}
}
if (verbose > 2)
- fprintf(stderr,"mapped %s of size %d\n",fname,(int)st.st_size);
+ fprintf(FERROR,"mapped %s of size %d\n",fname,(int)st.st_size);
/* open tmp file */
sprintf(fnametmp,"%s.XXXXXX",fname);
if (NULL == mktemp(fnametmp)) {
- fprintf(stderr,"mktemp %s failed\n",fnametmp);
+ fprintf(FERROR,"mktemp %s failed\n",fnametmp);
return -1;
}
- fd2 = open(fnametmp,O_WRONLY|O_CREAT,flist->files[i].mode);
+ fd2 = open(fnametmp,O_WRONLY|O_CREAT,file->mode);
if (fd2 == -1) {
- fprintf(stderr,"open %s : %s\n",fnametmp,strerror(errno));
+ fprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
return -1;
}
close(fd2);
if (verbose > 2)
- fprintf(stderr,"renaming %s to %s\n",fnametmp,fname);
+ fprintf(FERROR,"renaming %s to %s\n",fnametmp,fname);
if (make_backups) {
char fnamebak[MAXPATHLEN];
sprintf(fnamebak,"%s%s",fname,backup_suffix);
if (rename(fname,fnamebak) != 0 && errno != ENOENT) {
- fprintf(stderr,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
+ fprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
exit_cleanup(1);
}
}
/* move tmp file over real file */
if (rename(fnametmp,fname) != 0) {
- fprintf(stderr,"rename %s -> %s : %s\n",
+ fprintf(FERROR,"rename %s -> %s : %s\n",
fnametmp,fname,strerror(errno));
}
cleanup_fname = NULL;
- set_perms(fname,&flist->files[i],NULL,0);
+ set_perms(fname,file,NULL,0);
}
if (verbose > 2)
- fprintf(stderr,"recv_files finished\n");
+ fprintf(FERROR,"recv_files finished\n");
return 0;
}
char fname[MAXPATHLEN];
off_t total=0;
int i;
+ struct file_struct *file;
if (verbose > 2)
- fprintf(stderr,"send_files starting\n");
+ fprintf(FERROR,"send_files starting\n");
setup_nonblocking(f_in,f_out);
i = read_int(f_in);
if (i == -1) break;
+ file = &flist->files[i];
+
fname[0] = 0;
- if (flist->files[i].dir) {
- strcpy(fname,flist->files[i].dir);
+ if (file->dir) {
+ strcpy(fname,file->dir);
strcat(fname,"/");
}
- strcat(fname,flist->files[i].name);
+ strcat(fname,file->name);
if (verbose > 2)
- fprintf(stderr,"send_files(%d,%s)\n",i,fname);
+ fprintf(FERROR,"send_files(%d,%s)\n",i,fname);
if (dry_run) {
if (!am_server && verbose)
s = receive_sums(f_in);
if (!s) {
- fprintf(stderr,"receive_sums failed\n");
+ fprintf(FERROR,"receive_sums failed\n");
return -1;
}
fd = open(fname,O_RDONLY);
if (fd == -1) {
- fprintf(stderr,"send_files failed to open %s: %s\n",
+ fprintf(FERROR,"send_files failed to open %s: %s\n",
fname,strerror(errno));
continue;
}
/* map the local file */
if (fstat(fd,&st) != 0) {
- fprintf(stderr,"fstat failed : %s\n",strerror(errno));
+ fprintf(FERROR,"fstat failed : %s\n",strerror(errno));
return -1;
}
}
if (verbose > 2)
- fprintf(stderr,"send_files mapped %s of size %d\n",
+ 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->remainder);
if (verbose > 2)
- fprintf(stderr,"calling match_sums %s\n",fname);
+ fprintf(FERROR,"calling match_sums %s\n",fname);
if (!am_server && verbose)
printf("%s\n",fname);
free_sums(s);
if (verbose > 2)
- fprintf(stderr,"sender finished %s\n",fname);
+ fprintf(FERROR,"sender finished %s\n",fname);
total += st.st_size;
}
+ if (verbose > 2)
+ fprintf(FERROR,"send files finished\n");
+
match_report();
write_int(f_out,-1);
int i;
if (verbose > 2)
- fprintf(stderr,"generator starting pid=%d count=%d\n",
+ fprintf(FERROR,"generator starting pid=%d count=%d\n",
(int)getpid(),flist->count);
for (i = 0; i < flist->count; i++) {
- if (!flist->files[i].name) continue;
- if (S_ISDIR(flist->files[i].mode)) {
+ struct file_struct *file = &flist->files[i];
+ if (!file->name) continue;
+ if (S_ISDIR(file->mode)) {
if (dry_run) continue;
- if (mkdir(flist->files[i].name,flist->files[i].mode) != 0 &&
+ if (mkdir(file->name,file->mode) != 0 &&
errno != EEXIST) {
- fprintf(stderr,"mkdir %s : %s\n",
- flist->files[i].name,strerror(errno));
+ fprintf(FERROR,"mkdir %s : %s\n",
+ file->name,strerror(errno));
}
continue;
}
- recv_generator(local_name?local_name:flist->files[i].name,
+ recv_generator(local_name?local_name:file->name,
flist,i,f);
}
write_int(f,-1);
write_flush(f);
if (verbose > 2)
- fprintf(stderr,"generator wrote %d\n",write_total());
+ fprintf(FERROR,"generator wrote %d\n",write_total());
}
+
+
#define FILE_VALID 1
#define SAME_MODE (1<<1)
-#define SAME_DEV (1<<2)
+#define SAME_RDEV (1<<2)
#define SAME_UID (1<<3)
#define SAME_GID (1<<4)
#define SAME_DIR (1<<5)
#define MIN_PROTOCOL_VERSION 10
#define MAX_PROTOCOL_VERSION 20
+#define SPARSE_WRITE_SIZE (4*1024)
+#define WRITE_SIZE (32*1024)
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (4*1024*1024)
#define BLOCKING_TIMEOUT 10
-/* do we try to create sparse files */
-#define SPARSE_FILES 1
+#define FERROR stderr
+#define FINFO (am_server?stderr:stdout)
#include "config.h"
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;
#endif
#define SUPPORT_LINKS (HAVE_READLINK && defined(S_ISLNK))
+#define SUPPORT_HARD_LINKS HAVE_LINK
#ifndef S_ISLNK
#define S_ISLNK(x) 0
if (lseek(map_fd,offset,SEEK_SET) != offset ||
read(map_fd,p,len) != len) {
- fprintf(stderr,"EOF in map_ptr!\n");
+ fprintf(FERROR,"EOF in map_ptr!\n");
exit_cleanup(1);
}
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
- fprintf(stderr,"pipe: %s\n",strerror(errno));
+ fprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
}
pid = fork();
if (pid < 0) {
- fprintf(stderr,"fork: %s\n",strerror(errno));
+ fprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
}
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
- fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
+ fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
}
execvp(command[0], command);
- fprintf(stderr,"Failed to exec %s : %s\n",
+ fprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
exit_cleanup(1);
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
- fprintf(stderr,"Failed to close : %s\n",strerror(errno));
+ fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
}
void out_of_memory(char *str)
{
- fprintf(stderr,"out of memory in %s\n",str);
+ fprintf(FERROR,"out of memory in %s\n",str);
exit_cleanup(1);
}