return (unsigned char)c;
}
+
+static char last_byte=0;
+static int last_sparse = 0;
+
+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
+ return 0;
+}
+
+int write_sparse(int f,char *buf,int len)
+{
+ int l=0;
+
+#if SPARSE_FILES
+ for (l=0;l<len && buf[l]==0;l++) ;
+
+ if (l > 0)
+ lseek(f,l,SEEK_CUR);
+
+ last_byte = buf[len-1];
+#endif
+
+ if (l == len) {
+ last_sparse = 1;
+ return len;
+ }
+
+ last_sparse = 0;
+
+ return (l + write(f,buf+l,len-l));
+}
+
int read_write(int fd_in,int fd_out,int size)
{
static char *buf=NULL;
while (total < size) {
int n = MIN(size-total,bufsize);
read_buf(fd_in,buf,n);
- if (write(fd_out,buf,n) != n)
+ if (write_sparse(fd_out,buf,n) != n)
return total;
total += n;
}
if (am_server) {
remote_version = read_int(STDIN_FILENO);
- if (remote_version < MIN_PROTOCOL_VERSION) {
- fprintf(stderr,"protocol version mismatch %d %d\n",
- remote_version,PROTOCOL_VERSION);
+ if (remote_version < MIN_PROTOCOL_VERSION ||
+ remote_version > MAX_PROTOCOL_VERSION) {
+ fprintf(stderr,"protocol version mismatch - is your shell clean?\n");
exit(1);
}
write_int(STDOUT_FILENO,PROTOCOL_VERSION);
write_flush(f_out);
{
remote_version = read_int(f_in);
- if (remote_version < MIN_PROTOCOL_VERSION) {
- fprintf(stderr,"protocol version mismatch\n");
+ if (remote_version < MIN_PROTOCOL_VERSION ||
+ remote_version > MAX_PROTOCOL_VERSION) {
+ fprintf(stderr,"protocol version mismatch - is your shell clean?\n");
exit(1);
}
}
st = &st2;
}
- if (preserve_times && st->st_mtime != file->modtime) {
+ if (preserve_times && !S_ISLNK(st->st_mode) &&
+ st->st_mtime != file->modtime) {
updated = 1;
if (set_modtime(fname,file->modtime) != 0) {
fprintf(stderr,"failed to set times on %s : %s\n",
}
#ifdef HAVE_CHMOD
- if (preserve_perms && st->st_mode != file->mode) {
+ if (preserve_perms && !S_ISLNK(st->st_mode) &&
+ st->st_mode != file->mode) {
updated = 1;
if (chmod(fname,file->mode) != 0) {
fprintf(stderr,"failed to set permissions on %s : %s\n",
if (l > 0) {
lnk[l] = 0;
if (strcmp(lnk,flist->files[i].link) == 0) {
- if (verbose > 1)
- fprintf(am_server?stderr:stdout,"%s is uptodate\n",fname);
+ set_perms(fname,&flist->files[i],&st,1);
return;
}
}
fprintf(stderr,"link %s -> %s : %s\n",
fname,flist->files[i].link,strerror(errno));
} else {
+ set_perms(fname,&flist->files[i],NULL,0);
if (verbose)
- fprintf(am_server?stderr:stdout,"%s -> %s\n",fname,flist->files[i].link);
+ fprintf(am_server?stderr:stdout,"%s -> %s\n",
+ fname,flist->files[i].link);
}
return;
}
fprintf(stderr,"chunk[%d] of size %d at %d offset=%d\n",
i,len,(int)offset2,(int)offset);
- if (write(fd,map_ptr(buf,offset2,len),len) != len) {
+ if (write_sparse(fd,map_ptr(buf,offset2,len),len) != len) {
fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
exit(1);
}
offset += len;
}
}
+
+ if (offset > 0 && sparse_end(fd) != 0) {
+ fprintf(stderr,"write failed on %s : %s\n",fname,strerror(errno));
+ exit(1);
+ }
}
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 11
#define MIN_PROTOCOL_VERSION 10
+#define MAX_PROTOCOL_VERSION 20
/* block size to write files in */
#define WRITE_BLOCK_SIZE (32*1024)
#define BLOCKING_TIMEOUT 10
+/* do we try to create sparse files */
+#define SPARSE_FILES 1
+
#include "config.h"
#include <sys/types.h>
#endif
#include <errno.h>
+#ifdef HAVE_MMAP
#include <sys/mman.h>
+#endif
+
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
#define SUPPORT_LINKS (HAVE_READLINK && defined(S_ISLNK))
+#ifndef S_ISLNK
+#define S_ISLNK(x) 0
+#endif
+
#if !SUPPORT_LINKS
#define lstat stat
#endif
#endif
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
+