- handle no mmap for munmap
authorAndrew Tridgell <tridge@samba.org>
Fri, 28 Jun 1996 08:01:55 +0000 (08:01 +0000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 28 Jun 1996 08:01:55 +0000 (08:01 +0000)
- handle sparse files
- add MAX_PROTOCOL_VERSION

.cvsignore
io.c
main.c
rsync.c
rsync.h
util.c

index 74ca656..18588e0 100644 (file)
@@ -46,6 +46,8 @@ rsync-1.2
 rsync-1.2.tar.gz
 rsync-1.3
 rsync-1.4
+rsync-1.4.1
+rsync-1.4.1.tar.gz
 rsync-1.4.tar.gz
 rsync-ERSION
 rsync.aux
diff --git a/io.c b/io.c
index 3886875..40ccc73 100644 (file)
--- a/io.c
+++ b/io.c
@@ -155,6 +155,44 @@ unsigned char read_byte(int f)
   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;
@@ -169,7 +207,7 @@ int read_write(int fd_in,int fd_out,int size)
   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;
   }
diff --git a/main.c b/main.c
index 95c6fde..d0583d6 100644 (file)
--- a/main.c
+++ b/main.c
@@ -597,9 +597,9 @@ int main(int argc,char *argv[])
 
     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);
@@ -683,8 +683,9 @@ int main(int argc,char *argv[])
     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);
       }        
     }
diff --git a/rsync.c b/rsync.c
index c9ffa78..cdf7c3e 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -205,7 +205,8 @@ static void set_perms(char *fname,struct file_struct *file,struct stat *st,
     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",
@@ -215,7 +216,8 @@ static void set_perms(char *fname,struct file_struct *file,struct stat *st,
   }
 
 #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",
@@ -269,8 +271,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
       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;
        }
       }
@@ -280,8 +281,10 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
       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;
   }
@@ -417,13 +420,18 @@ static void receive_data(int f_in,char *buf,int fd,char *fname)
        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);
+  }
 }
 
 
diff --git a/rsync.h b/rsync.h
index 79ccc66..36e8f5b 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -36,6 +36,7 @@
 /* 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)
@@ -43,6 +44,9 @@
 
 #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
@@ -245,6 +252,10 @@ extern int errno;
 
 #define SUPPORT_LINKS (HAVE_READLINK && defined(S_ISLNK))
 
+#ifndef S_ISLNK
+#define S_ISLNK(x) 0
+#endif
+
 #if !SUPPORT_LINKS
 #define lstat stat
 #endif
@@ -256,3 +267,4 @@ extern int errno;
 #endif
 
 #define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
+
diff --git a/util.c b/util.c
index 22ca8c2..537ec0b 100644 (file)
--- a/util.c
+++ b/util.c
@@ -91,8 +91,10 @@ char *map_ptr(char *buf,off_t offset,int len)
 
 void unmap_file(char *buf,off_t len)
 {
+#ifdef HAVE_MMAP
   if (len > 0 && buf)
     munmap(buf,len);
+#endif
   map_fd = -1;
   map_size = 0;
   p_len = 0;