Hi,

i finished my storage compression patch for rsync.

WARNING - THIS IS ONLY FOR TESTING!

How does this work?

Just add a "-Z" option to your common rsync commandline parameters. The 
destination files will be stored in a compressed way (by using a hardwired 
call of gzip).

This works in both directions:

rsync -Z -av mydir user@remote:/dir

and

rsync -Z -av user@remote:/dir localdir

The remote:/dir and localdir will keep the files compressed.

If you want to compress or decompress any local directory, add a link to the 
rsync exe file:

ln -s rsync rscompress

and

ln -s rsync rsuncompress

With "rscompress" you can compress a local directory (e.g. if you want to use 
existing files without wanting to transfer then first from your server). 
rsuncompress will decomress a compressed directory.

I have no idea if this works with: links, devices and any other strange stuff. 
Also make sure if you use rsync over a network connection that there is gzip 
in your $PATH if the destionation side should be saved compressed.
WARNING! I have no idea if the system( "gzip ..." ) call might be a security 
issue!

A final advise. This is only for testing ;)


-- 
Bye,
Harald
Email:             [EMAIL PROTECTED] ICQ: #15582696
A cool os:         www.linux.org
PGP Finger-print:  C2 8F 7B 55 7B 9B 8C 7E  48 35 48 21 8A DF 01 66
Index: rsync/backup.c
diff -c rsync/backup.c:1.1.1.1 rsync/backup.c:1.2
*** rsync/backup.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/backup.c	Sat Jan 18 00:08:43 2003
***************
*** 135,141 ****
  
  	while (keep_trying) {
  		if (keep_path_extfs) {
! 			failed = copy_file(src, dst, 0755);
  			if (!failed) {
  				do_unlink(src);
  			}
--- 135,141 ----
  
  	while (keep_trying) {
  		if (keep_path_extfs) {
! 			failed = copy_file(src, dst, 0755, 0);
  			if (!failed) {
  				do_unlink(src);
  			}
Index: rsync/flist.c
diff -c rsync/flist.c:1.1.1.1 rsync/flist.c:1.2
*** rsync/flist.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/flist.c	Wed Jan 15 11:41:11 2003
***************
*** 57,62 ****
--- 57,63 ----
  extern int remote_version;
  extern int io_error;
  extern int sanitize_paths;
+ extern int do_storage_compression;
  
  extern int read_batch;
  extern int write_batch;
***************
*** 480,485 ****
--- 481,491 ----
  	read_sbuf(f, &thisname[l1], l2);
  	thisname[l1 + l2] = 0;
  
+     if (do_storage_compression) {
+         /* we are using storage compression - add ".rsc" to every name */
+         strcat( thisname, ".rsc" );
+     }
+ 
  	strlcpy(lastname, thisname, MAXPATHLEN);
  	lastname[MAXPATHLEN - 1] = 0;
  
***************
*** 495,501 ****
  		if (lastdir && strcmp(thisname, lastdir) == 0) {
  			file->dirname = lastdir;
  		} else {
! 			file->dirname = strdup(thisname);
  			lastdir = file->dirname;
  		}
  		file->basename = strdup(p + 1);
--- 501,533 ----
  		if (lastdir && strcmp(thisname, lastdir) == 0) {
  			file->dirname = lastdir;
  		} else {
!             if (do_storage_compression) {
!                 /* we are using storage compression - add ".rsc" to every name */
!                 char *p2,*p3;
! 			    file->dirname = (char *) malloc(MAXPATHLEN);
! 			    *(file->dirname) = 0;
! 
!                 p2=thisname;
!                 while( 1 ) {
!                     p3=strchr(p2, '/' );
!                     if( !p3 ) {
!                         if( p2==thisname ) {
!                             strcpy( file->dirname, thisname );
!                         } else {
!                             strcat( file->dirname, p2 );
!                         }
!                         strcat( file->dirname, ".rsc" );
!                         break;
!                     }
!                     *p3=0;
!                     p3++;
!                     strcat( file->dirname, p2 );
!                     strcat( file->dirname, ".rsc/" );
!                     p2=p3;
!                 }
!             } else {
! 			    file->dirname = strdup(thisname);
!             }
  			lastdir = file->dirname;
  		}
  		file->basename = strdup(p + 1);
Index: rsync/generator.c
diff -c rsync/generator.c:1.1.1.1 rsync/generator.c:1.3
*** rsync/generator.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/generator.c	Sat Jan 18 15:56:49 2003
***************
*** 41,46 ****
--- 41,212 ----
  extern int always_checksum;
  extern int modify_window;
  extern char *compare_dest;
+ extern int do_storage_compression;
+ 
+ 
+ /* decompress the given file */
+ void storage_decompress ( char *fname, STRUCT_STAT *st ) 
+ {
+     char fnametmp[MAXPATHLEN];
+     char cmd[MAXPATHLEN+MAXPATHLEN];
+     FILE *f;
+     int c;
+     long offset;
+ 
+     if( !(f=fopen( fname, "r" ) ) )
+         return;
+ 
+     /* read the position of the first occurence of a space in the file */
+     while(1) {
+         if( (c=fgetc(f)) == EOF )
+             break;
+         if( c==' ' )
+             break;
+     }
+ 
+     if( feof(f) ) {
+         return;
+     }
+ 
+     offset=ftell( f );
+     fclose( f );
+ 
+     /* tmp file before decompress */
+     strcpy (fnametmp, fname);
+     strcat (fnametmp, "-tmp.gz");
+ 
+     if( verbose >2 )
+ 	    rprintf(FINFO,"storage_decompress... - %ld\n", offset );
+ 
+     /* copy original file to a temp file - but without the header*/
+     if( copy_file(fname, fnametmp, INITACCESSPERMS, offset) == -1 )
+         return;
+ 
+     /* delete the current file */
+     do_unlink( fname );
+ 
+     /* create command string */
+     snprintf( cmd, MAXPATHLEN, "%s -d %s", "gzip", fnametmp );
+ 
+     /* decompress the file */
+     if( system( cmd ) == -1 ) {
+         rprintf(FERROR,"decompress cmd %s failed", cmd );
+         return;
+     }
+ 
+     /* tmp file after decompress */
+     strcpy (fnametmp, fname);
+     strcat (fnametmp, "-tmp");
+ 
+     /* now we rename the file */
+     robust_rename( fnametmp, fname );
+ 
+     /* apply stat */
+     do_chmod( fname, st->st_mode );
+ 
+     /* apply mtime */
+     set_modtime(fname,st->st_mtime);
+ }
+ 
+ 
+ /* function checks if we have a rsc file and uptates the stats struct */
+ static void compressed_file_checksum( char *fname, char *sum) {
+     char buffer[1024];
+     int buffsize=sizeof(buffer);
+     FILE *f;
+     int size;
+     char *p, *p2, *magic1, *compressor, *sumascii, *magic2;
+     OFF_T size_raw;
+     OFF_T size_compressed;
+     int i;
+     char ascii[3];
+ 
+ 	rprintf(FINFO,"compressed_file_checksum\n" );
+     /* zero the sum */
+     for( i=0; i<MD4_SUM_LENGTH; i++ ) {
+         sum[i]=0;
+     }
+ 
+     if( !(f=fopen( fname, "r" ) ) )
+         return;
+ 
+     size=fread( buffer, 1, buffsize, f );
+ 
+ 
+     magic1=buffer;
+     for( p=buffer; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     if( strcmp( magic1, "rsc1.00" ) != 0 ) 
+         return;
+ 
+     p2=p;
+     for( ; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     size_raw=atol( p2 );
+ 
+     p2=p;
+     for( ; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     size_compressed=atol( p2 );
+ 
+     compressor=p;
+     for( p=buffer; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     if( strcmp( compressor, "gzip" ) != 0 ) 
+         return;
+ 
+     sumascii=p;
+     for( p=buffer; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+ 
+     magic2=p;
+     for( p=buffer; p; p ++ ) {
+         if( *p==' ' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+ 
+     if( strcmp( magic2, "rsc1.00" ) != 0 ) 
+         return;
+ 
+ 	if (verbose > 2) {
+ 		rprintf(FINFO,"compressed file header is ok\n" );
+ 	}
+ 
+     /* get the sum back from ascii*/
+     for( i=0; i<MD4_SUM_LENGTH*2; i+=2 ) {
+         ascii[0] = sumascii[i];
+         ascii[1] = sumascii[i+1];
+         ascii[2] = 0;
+ 
+         if( sscanf( ascii, "%x", &(sum[i/2]) ) != 1 ) {
+             rprintf(FERROR,"error reading sum from comressed storage file\n" );
+             return;
+         }
+     }
+ 
+ }
  
  
  /* choose whether to skip a particular file */
***************
*** 48,54 ****
  		     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 
--- 214,222 ----
  		     struct file_struct *file, STRUCT_STAT *st)
  {
  	if (st->st_size != file->length) {
!         if (!do_storage_compression) {
! 		    return 0;
!         }
  	}
  	
  	/* if always checksum is set then we use the checksum instead 
***************
*** 64,70 ****
  				fname = fnamecmpdest;
  			}
  		}
! 		file_checksum(fname,sum,st->st_size);
  		if (remote_version < 21) {
  			return (memcmp(sum,file->sum,2) == 0);
  		} else {
--- 232,243 ----
  				fname = fnamecmpdest;
  			}
  		}
!         /* compress file if compression is enabled */
!         if (do_storage_compression) {
!             compressed_file_checksum( fname, sum );
!         } else {
! 		    file_checksum(fname,sum,st->st_size);
!         }
  		if (remote_version < 21) {
  			return (memcmp(sum,file->sum,2) == 0);
  		} else {
***************
*** 427,432 ****
--- 600,610 ----
  			set_perms(fname,file,&st,1);
  		return;
  	}
+ 
+     /* decompress the stored file - we might need an update */
+     if (do_storage_compression) {
+         storage_decompress( fname, &st );
+     }
  
  	if (dry_run) {
  		write_int(f_out,i);
Index: rsync/main.c
diff -c rsync/main.c:1.1.1.1 rsync/main.c:1.3
*** rsync/main.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/main.c	Sat Jan 18 15:56:49 2003
***************
*** 26,31 ****
--- 26,32 ----
  struct stats stats;
  
  extern int verbose;
+ extern int do_storage_compression;
  
  static void show_malloc_stats(void);
  
***************
*** 207,212 ****
--- 208,216 ----
  
  		args[argc++] = rsync_path;
  
+         if( do_storage_compression )
+ 		    args[argc++] = "-Z";
+ 
  		if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
  			blocking_io = 1;
  
***************
*** 843,848 ****
--- 847,861 ----
  
  	orig_argc = argc;
  	orig_argv = argv;
+ 
+     if( argc == 2 ) {
+         if( strstr( argv[0], "rscompress" ) != NULL ) {
+             return rscompress( argv[1] );
+         }
+         if( strstr( argv[0], "rsuncompress" )!= NULL  ) {
+             return rsuncompress( argv[1] );
+         }
+     }
  
  	signal(SIGUSR1, sigusr1_handler);
  	signal(SIGUSR2, sigusr2_handler);
Index: rsync/options.c
diff -c rsync/options.c:1.1.1.1 rsync/options.c:1.3
*** rsync/options.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/options.c	Sat Jan 18 16:00:20 2003
***************
*** 55,60 ****
--- 55,61 ----
  int remote_version=0;
  int sparse_files=0;
  int do_compression=0;
+ int do_storage_compression=0;
  int am_root=0;
  int orig_umask=0;
  int relative_paths=0;
***************
*** 247,252 ****
--- 248,254 ----
    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
    rprintf(F," -P                          equivalent to --partial --progress\n");
    rprintf(F," -z, --compress              compress file data\n");
+   rprintf(F," -Z, --store-compressed      compress the destination file data by using gzip\n");
    rprintf(F,"     --exclude=PATTERN       exclude files matching PATTERN\n");
    rprintf(F,"     --exclude-from=FILE     exclude patterns listed in FILE\n");
    rprintf(F,"     --include=PATTERN       don't exclude files matching PATTERN\n");
***************
*** 343,348 ****
--- 345,351 ----
    {"compare-dest",     0,  POPT_ARG_STRING, &compare_dest , 0, 0, 0 },
    /* TODO: Should this take an optional int giving the compression level? */
    {"compress",        'z', POPT_ARG_NONE,   &do_compression , 0, 0, 0 },
+   {"store-compressed",'Z', POPT_ARG_NONE,   &do_storage_compression , 0, 0, 0 },
    {"daemon",           0,  POPT_ARG_NONE,   &am_daemon , 0, 0, 0 },
    {"no-detach",        0,  POPT_ARG_NONE,   &no_detach , 0, 0, 0 },
    {"stats",            0,  POPT_ARG_NONE,   &do_stats , 0, 0, 0 },
Index: rsync/proto.h
diff -c rsync/proto.h:1.1.1.1 rsync/proto.h:1.4
*** rsync/proto.h:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/proto.h	Sat Jan 18 15:56:49 2003
***************
*** 89,94 ****
--- 89,95 ----
  struct file_list *flist_new();
  void flist_free(struct file_list *flist);
  char *f_name(struct file_struct *f);
+ void storage_decompress ( char *fname, STRUCT_STAT *st ) ;
  void recv_generator(char *fname,struct file_list *flist,int i,int f_out);
  void generate_files(int f,struct file_list *flist,char *local_name,int f_recv);
  int main(int argc, char *argv[]);
***************
*** 182,187 ****
--- 183,190 ----
  	      int report);
  void sig_int(void);
  void finish_transfer(char *fname, char *fnametmp, struct file_struct *file);
+ int rscompress (char *dir) ;
+ int rsuncompress(char *dir) ;
  void send_files(struct file_list *flist,int f_out,int f_in);
  int try_bind_local(int s,
  		   int ai_family, int ai_socktype,
***************
*** 235,241 ****
  void overflow(char *str);
  int set_modtime(char *fname, time_t modtime);
  int create_directory_path(char *fname);
! int copy_file(char *source, char *dest, mode_t mode);
  int robust_unlink(char *fname);
  int robust_rename(char *from, char *to);
  pid_t do_fork(void);
--- 238,245 ----
  void overflow(char *str);
  int set_modtime(char *fname, time_t modtime);
  int create_directory_path(char *fname);
! int append_file(char *source, char *dest, mode_t mode);
! int copy_file(char *source, char *dest, mode_t mode, long offset);
  int robust_unlink(char *fname);
  int robust_rename(char *from, char *to);
  pid_t do_fork(void);
Index: rsync/receiver.c
diff -c rsync/receiver.c:1.1.1.1 rsync/receiver.c:1.3
*** rsync/receiver.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/receiver.c	Sat Jan 18 00:08:43 2003
***************
*** 36,41 ****
--- 36,43 ----
  extern char *compare_dest;
  extern int make_backups;
  extern char *backup_suffix;
+ extern int do_storage_compression;
+ 
  
  static struct delete_list {
  	DEV64_T dev;
***************
*** 297,302 ****
--- 299,390 ----
  }
  
  
+ /* function checks if we have a rsc file and uptates the stats struct */
+ static int storage_decompress_update_stats ( char *fname, STRUCT_STAT *st ) {
+     char buffer[1024];
+     int buffsize=sizeof(buffer);
+     FILE *f;
+     int size;
+     char *p, *p2, *magic1, *compressor, *sumascii, *magic2;
+     OFF_T size_raw;
+     OFF_T size_compressed;
+ 
+         rprintf(FINFO,"storage_decompress_update_stats\n" );
+ 
+ 
+     if( !(f=fopen( fname, "r" ) ) )
+         return -1;
+ 
+     size=fread( buffer, 1, buffsize, f );
+ 
+ 
+     magic1=buffer;
+     for( p=buffer; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     if( strcmp( magic1, "rsc1.00" ) != 0 ) 
+         return -1;
+ 
+     p2=p;
+     for( ; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     size_raw=atol( p2 );
+ 
+     p2=p;
+     for( ; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     size_compressed=atol( p2 );
+ 
+     compressor=p;
+     for( p=buffer; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+     if( strcmp( compressor, "gzip" ) != 0 ) 
+         return -1;
+ 
+     sumascii=p;
+     for( p=buffer; p; p ++ ) {
+         if( *p=='-' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+ 
+     magic2=p;
+     for( p=buffer; p; p ++ ) {
+         if( *p==' ' ) {
+             *p=0; p++;
+             break;
+         }
+     }
+ 
+     if( strcmp( magic2, "rsc1.00" ) != 0 ) 
+         return -1;
+ 
+ 	if (verbose > 2) {
+ 		rprintf(FINFO,"compressed file header is ok\n" );
+ 	}
+ 
+     /* fake size */
+     st->st_size=size_raw;
+ 
+     return 0;
+ }
+ 
  /* main routine for receiver process. Receiver process runs on the
  	same host as the generator process. */
  
***************
*** 385,390 ****
--- 473,483 ----
  			close(fd1);
  			continue;
  		}
+ 
+         /* report the size of the file */
+         if( do_storage_compression ) {
+             storage_decompress_update_stats( fname, &st );
+         }
  
  		if (fd1 != -1 && !S_ISREG(st.st_mode)) {
  			rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
Index: rsync/rsync.c
diff -c rsync/rsync.c:1.1.1.1 rsync/rsync.c:1.4
*** rsync/rsync.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/rsync.c	Sat Jan 18 15:56:49 2003
***************
*** 30,35 ****
--- 30,36 ----
  extern int preserve_gid;
  extern int preserve_perms;
  extern int make_backups;
+ extern int do_storage_compression;
  
  
  /*
***************
*** 229,234 ****
--- 230,318 ----
  	exit_cleanup(RERR_SIGNAL);
  }
  
+ /* compress a file after transfer including a headder */
+ static int storage_compress(char *fsname, char *fname)
+ {
+     char fnametmp[MAXPATHLEN];
+     char cmd[MAXPATHLEN+MAXPATHLEN];
+     STRUCT_STAT st;
+     OFF_T size_raw;
+     OFF_T size_compressed;
+     float factor;
+     int fd;
+     FILE *f;
+     char sum[MD4_SUM_LENGTH];
+     char sumascii[MD4_SUM_LENGTH*2+1];
+     char ascii[3];
+     int i;
+ 
+ 
+     /* tmp file */
+     strcpy (fnametmp, fname);
+     strcat (fnametmp, ".gz");
+ 
+     /* check if we can write*/
+     if (! (fd = do_mkstemp(fnametmp, INITACCESSPERMS)) )
+         return 0;
+     close( fd );
+ 
+     /* save stat before compressing */
+     if( do_stat(fname, &st) == -1 ) 
+         return 0;
+     size_raw=st.st_size;
+ 
+     /* read the sum */
+     file_checksum(fname,sum,st.st_size);
+ 
+     /* make ascii value from sum*/
+     sumascii[0]=0;
+     for(i=0; i<MD4_SUM_LENGTH; i++ ) {
+         snprintf( ascii, sizeof( ascii ), "%x", sum[i] );
+         strcat( sumascii, ascii );
+     }
+  
+     /* create command string */
+     snprintf( cmd, MAXPATHLEN, "%s %s", "gzip", fname );
+ 
+     if( system( cmd ) == -1 ) {
+ 		rprintf(FERROR,"compress cmd %s failed", cmd );
+         return 0;
+     }
+ 
+     /* save stats after compressing */
+     if( do_stat(fnametmp, &st) == -1 )
+         return 0;
+     size_compressed=st.st_size;
+ 
+     factor = ((float)size_compressed/(float)size_raw) * 100.0;
+     if( verbose >1 )
+         rprintf(FINFO, "compressing storage file \"%s\" (%3.2f%%)\n", fsname, factor);
+ 
+     /* note: gzip will rename the file from fname to fnametmp */
+ 
+     if( !(f=fopen( fname, "w" ) ) ){
+         rprintf(FERROR, "can't open temp file" );
+         return 0;
+     }
+ 
+     /* write header */
+     fprintf( f, "%s-%ld-%ld-%s-%s-%s ",   "rsc1.00", (long) size_raw,
+                 (long) size_compressed, "gzip", sumascii, "rsc1.00" );
+     fclose( f );
+ 
+     append_file(fnametmp, fname, INITACCESSPERMS);
+ 
+     /* delete file with .gz extension */
+ 	do_unlink(fnametmp);
+ 
+     /* apply stat */
+     do_chmod( fname, st.st_mode );
+ 
+     /* apply mtime */
+     set_modtime(fname,st.st_mtime);
+ 
+     return 1;
+ }
  
  /* finish off a file transfer, renaming the file and setting the permissions
     and ownership */
***************
*** 237,248 ****
  	if (make_backups && !make_backup(fname))
  		return;
  
  	/* move tmp file over real file */
  	if (robust_rename(fnametmp,fname) != 0) {
  		if (errno == EXDEV) {
  			/* rename failed on cross-filesystem link.  
  			   Copy the file instead. */
! 			if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
  				rprintf(FERROR,"copy %s -> %s : %s\n",
  					fnametmp,fname,strerror(errno));
  			} else {
--- 321,339 ----
  	if (make_backups && !make_backup(fname))
  		return;
  
+     /* compress file if compression is enabled */
+     if (do_storage_compression) {
+         if( !storage_compress( fname, fnametmp ) ) {
+ 			rprintf(FERROR,"storage compression of%s failed\n", fnametmp );
+         }
+     }
+ 
  	/* move tmp file over real file */
  	if (robust_rename(fnametmp,fname) != 0) {
  		if (errno == EXDEV) {
  			/* rename failed on cross-filesystem link.  
  			   Copy the file instead. */
! 			if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS, 0)) {
  				rprintf(FERROR,"copy %s -> %s : %s\n",
  					fnametmp,fname,strerror(errno));
  			} else {
***************
*** 256,259 ****
--- 347,499 ----
  	} else {
  		set_perms(fname,file,NULL,0);
  	}
+ }
+ 
+ /* recursive compression of a directory */
+ int rscompress (char *dir) 
+ {
+     DIR *d;
+     struct dirent *di;
+     char fname[MAXPATHLEN];
+     char newname[MAXPATHLEN];
+     int l;
+     char *p;
+     STRUCT_STAT st;
+ 
+     d = opendir(dir);
+     if (!d) {
+         rprintf(FERROR, "opendir(%s): %s\n", dir, strerror(errno));
+         return 1;
+     }
+ 
+     strlcpy(fname, dir, MAXPATHLEN);
+     l = strlen(fname);
+     if (fname[l - 1] != '/') {
+         if (l == MAXPATHLEN - 1) {
+             rprintf(FERROR,
+                 "skipping long-named directory %s\n",
+                 fname);
+             closedir(d);
+             return 1;
+         }
+         strlcat(fname, "/", MAXPATHLEN);
+         l++;
+     }
+     p = fname + strlen(fname);
+ 
+     newname[0] = 0;
+ 
+     for (di = readdir(d); di; di = readdir(d)) {
+         char *dname = d_name(di);
+         if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0)
+             continue;
+         strlcpy(p, dname, MAXPATHLEN - l);
+         /* check stat */
+         if( do_stat(fname, &st) == -1 ) {
+             rprintf(FERROR, "can't read stat for '%s'\n", fname );
+             continue;
+         }
+ 
+         /* avoid compressing of compressed stuff */
+         /* also fixes a race condition when renaming a directory/file */
+         /* while still in readdir() */
+         if( strlen( fname ) > strlen( ".rsc" ) ) {
+             char *p;
+             p = &fname[ strlen(fname) - strlen( ".rsc" )];
+             if( strcmp( p, ".rsc" ) == 0) {
+                 continue;
+             }
+         }
+ 
+         /* append .rsc to the filename */
+         strcpy( newname, fname );
+         strcat( newname, ".rsc" );
+ 
+         if (S_ISDIR(st.st_mode)) { 
+             rscompress( fname );
+         } else if (S_ISREG(st.st_mode)) { 
+             storage_compress( "", fname );
+         }
+         if( do_rename( fname, newname ) == -1 ) {
+             rprintf(FERROR, "can't rename '%s' to '%s'\n", fname, newname );
+         }
+         if( do_chmod( newname, st.st_mode ) == -1 ) {
+             rprintf(FERROR, "can't stat '%s'\n", newname );
+         }
+     }
+ 
+     closedir(d);
+ 
+     return 0;
+ }
+ 
+ /* recursive uncompression of a directory */
+ int rsuncompress(char *dir) 
+ {
+     DIR *d;
+     struct dirent *di;
+     char fname[MAXPATHLEN];
+     char newname[MAXPATHLEN];
+     int l;
+     char *p;
+     STRUCT_STAT st;
+ 
+     d = opendir(dir);
+     if (!d) {
+         rprintf(FERROR, "opendir(%s): %s\n", dir, strerror(errno));
+         return 1;
+     }
+ 
+     strlcpy(fname, dir, MAXPATHLEN);
+     l = strlen(fname);
+     if (fname[l - 1] != '/') {
+         if (l == MAXPATHLEN - 1) {
+             rprintf(FERROR,
+                 "skipping long-named directory %s\n",
+                 fname);
+             closedir(d);
+             return 1;
+         }
+         strlcat(fname, "/", MAXPATHLEN);
+         l++;
+     }
+     p = fname + strlen(fname);
+ 
+     for (di = readdir(d); di; di = readdir(d)) {
+         char *dname = d_name(di);
+         if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0)
+             continue;
+         strlcpy(p, dname, MAXPATHLEN - l);
+         /* check stat */
+         if( do_stat(fname, &st) == -1 ) {
+             rprintf(FERROR, "can't read stat for '%s'\n", fname );
+             continue;
+         }
+         if( !strstr( fname, ".rsc" ) ) {
+             rprintf(FERROR, "'%s' has no .rsc extension! \n", fname );
+             continue;
+         }
+ 
+         /* create filename for new name */
+         strcpy( newname, fname );
+         newname[strlen(fname)-strlen( ".rsc" )]=0;
+ 
+         if (S_ISDIR(st.st_mode)) { 
+             /* recursive call */
+             rsuncompress( fname );
+         } else if (S_ISREG(st.st_mode)) { 
+             /* decompress the file */
+             storage_decompress ( fname, &st );
+         }
+         if( do_rename( fname, newname ) == -1 ) {
+             rprintf(FERROR, "can't rename '%s' to '%s'\n", fname, newname );
+         }
+         if( do_chmod( newname, st.st_mode ) == -1 ) {
+             rprintf(FERROR, "can't stat '%s'\n", newname );
+         }
+     }
+ 
+     closedir(d);
+ 
+     return 0;
  }
Index: rsync/util.c
diff -c rsync/util.c:1.1.1.1 rsync/util.c:1.3
*** rsync/util.c:1.1.1.1	Tue Jan 14 00:25:59 2003
--- rsync/util.c	Sat Jan 18 00:08:43 2003
***************
*** 349,361 ****
  }
  
  
  /* 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 = do_open(source, O_RDONLY, 0);
  	if (ifd == -1) {
--- 349,407 ----
  }
  
  
+ /* appends a file - this is used in conjunction with the --temp-dir option */
+ int append_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 = do_open(source, O_RDONLY, 0);
+ 	if (ifd == -1) {
+ 		rprintf(FERROR,"open %s: %s\n",
+ 			source,strerror(errno));
+ 		return -1;
+ 	}
+ 
+ 	ofd = do_open(dest, O_WRONLY | O_APPEND | O_EXCL, mode);
+ 	if (ofd == -1) {
+ 		rprintf(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) {
+ 			rprintf(FERROR,"write %s: %s\n",
+ 				dest,strerror(errno));
+ 			close(ifd);
+ 			close(ofd);
+ 			return -1;
+ 		}
+ 	}
+ 
+ 	close(ifd);
+ 	close(ofd);
+ 
+ 	if (len < 0) {
+ 		rprintf(FERROR,"read %s: %s\n",
+ 			source,strerror(errno));
+ 		return -1;
+ 	}
+ 
+ 	return 0;
+ }
+ 
  /* copy a file - this is used in conjunction with the --temp-dir option */
! int copy_file(char *source, char *dest, mode_t mode, long offset)
  {
  	int ifd;
  	int ofd;
  	char buf[1024 * 8];
  	int len;   /* Number of bytes read into `buf'. */
+     long readlen, readbytes=0;
  
  	ifd = do_open(source, O_RDONLY, 0);
  	if (ifd == -1) {
***************
*** 377,382 ****
--- 423,443 ----
  		close(ifd);
  		return -1;
  	}
+ 
+     if( offset > 0 ) {
+         readlen=offset;
+         if( offset > sizeof( buf ) ) {
+             readlen=sizeof( buf );
+         } 
+ 	    while ((len = safe_read(ifd, buf, readlen)) > 0) {
+             readbytes+=len;
+             if( readbytes==offset )
+                 break;
+             if( (readbytes-offset) < sizeof( buf ) ) {
+                 readlen=offset;
+             } 
+         }
+     }
  
  	while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
  		if (full_write(ofd, buf, len) < 0) {

Reply via email to