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) {