added a --partial option which tells rsync to keep partially
authorAndrew Tridgell <tridge@samba.org>
Wed, 1 Jul 1998 03:36:03 +0000 (03:36 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 1 Jul 1998 03:36:03 +0000 (03:36 +0000)
transferred files if the transfer is interrupted.

added a "options summary" section to the man page

main.c
options.c
rsync.c
rsync.yo

diff --git a/main.c b/main.c
index 3c4d99c..ed9dd17 100644 (file)
--- a/main.c
+++ b/main.c
@@ -172,6 +172,10 @@ static char *get_local_name(struct file_list *flist,char *name)
        STRUCT_STAT st;
        extern int orig_umask;
 
+       if (verbose > 2)
+               rprintf(FINFO,"get_local_name count=%d %s\n", 
+                       flist->count, name);
+
        if (do_stat(name,&st) == 0) {
                if (S_ISDIR(st.st_mode)) {
                        if (!push_dir(name, 0)) {
index 757598d..10c2773 100644 (file)
--- a/options.c
+++ b/options.c
@@ -56,6 +56,7 @@ int recurse = 0;
 int am_daemon=0;
 int am_client=0;
 int do_stats=0;
+int keep_partial=0;
 
 int block_size=BLOCK_SIZE;
 
@@ -108,6 +109,7 @@ void usage(int F)
   rprintf(F,"     --rsync-path=PATH       specify path to rsync on the remote machine\n");
   rprintf(F," -C, --cvs-exclude           auto ignore files in the same way CVS does\n");
   rprintf(F,"     --delete                delete files that don't exist on the sending side\n");
+  rprintf(F,"     --partial               keep partially transferred files\n");
   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
   rprintf(F,"     --timeout=TIME          set IO timeout in seconds\n");
@@ -137,7 +139,7 @@ void usage(int F)
 enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
       OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
       OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
-      OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS};
+      OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL};
 
 static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
 
@@ -183,6 +185,7 @@ static struct option long_options[] = {
   {"compress",   0,     0,    'z'},
   {"daemon",      0,     0,    OPT_DAEMON},
   {"stats",       0,     0,    OPT_STATS},
+  {"partial",     0,     0,    OPT_PARTIAL},
   {"config",      1,     0,    OPT_CONFIG},
   {"port",        1,     0,    OPT_PORT},
   {0,0,0,0}};
@@ -382,6 +385,10 @@ void parse_arguments(int argc, char *argv[])
                do_stats = 1;
                break;
 
+       case OPT_PARTIAL:
+               keep_partial = 1;
+               break;
+
        case OPT_CONFIG:
                config_file = optarg;
                break;
@@ -477,6 +484,9 @@ void server_options(char **args,int *argc)
   if (delete_mode)
     args[ac++] = "--delete";
 
+  if (keep_partial)
+    args[ac++] = "--partial";
+
   if (force_delete)
     args[ac++] = "--force";
 
diff --git a/rsync.c b/rsync.c
index 3832145..7ad7a9a 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -731,11 +731,19 @@ static void delete_files(struct file_list *flist)
 }
 
 static char *cleanup_fname;
+static char *cleanup_new_fname;
+static struct file_struct *cleanup_file;
+static void finish_transfer(char *fname, char *fnametmp, struct file_struct *file);
 
 void exit_cleanup(int code)
 {
+       extern int keep_partial;
+
+       if (cleanup_fname && keep_partial) {
+               finish_transfer(cleanup_new_fname, cleanup_fname, cleanup_file);
+       }
        io_flush();
-       if (cleanup_fname)
+       if (cleanup_fname && !keep_partial)
                do_unlink(cleanup_fname);
        signal(SIGUSR1, SIG_IGN);
        if (code) {
@@ -790,6 +798,46 @@ static int get_tmpname(char *fnametmp, char *fname)
        return 1;
 }
 
+/* finish off a file transfer, renaming the file and setting the permissions
+   and ownership */
+static void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
+{
+       if (make_backups) {
+               char fnamebak[MAXPATHLEN];
+               if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
+                       rprintf(FERROR,"backup filename too long\n");
+                       return;
+               }
+               slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
+               if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
+                       rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
+                       return;
+               }
+       }
+
+       /* move tmp file over real file */
+       if (do_rename(fnametmp,fname) != 0) {
+               if (errno == EXDEV) {
+                       /* rename failed on cross-filesystem link.  
+                          Copy the file instead. */
+                       if (copy_file(fnametmp,fname, file->mode)) {
+                               rprintf(FERROR,"copy %s -> %s : %s\n",
+                                       fnametmp,fname,strerror(errno));
+                       } else {
+                               set_perms(fname,file,NULL,0);
+                       }
+                       do_unlink(fnametmp);
+               } else {
+                       rprintf(FERROR,"rename %s -> %s : %s\n",
+                               fnametmp,fname,strerror(errno));
+                       do_unlink(fnametmp);
+               }
+       } else {
+               set_perms(fname,file,NULL,0);
+       }
+}
+
+
 int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
 {  
        int fd1,fd2;
@@ -811,6 +859,9 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
        }
 
        while (1) {      
+               cleanup_fname = NULL;
+               cleanup_new_fname = NULL;
+
                i = read_int(f_in);
                if (i == -1) {
                        if (phase==0 && remote_version >= 13) {
@@ -909,6 +960,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                }
       
                cleanup_fname = fnametmp;
+               cleanup_new_fname = fname;
+               cleanup_file = file;
 
                if (!am_server && verbose)
                        printf("%s\n",fname);
@@ -924,43 +977,12 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                
                if (verbose > 2)
                        rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
-               
-               if (make_backups) {
-                       char fnamebak[MAXPATHLEN];
-                       if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
-                               rprintf(FERROR,"backup filename too long\n");
-                               continue;
-                       }
-                       slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
-                       if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
-                               rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
-                               continue;
-                       }
-               }
-
-               /* move tmp file over real file */
-               if (do_rename(fnametmp,fname) != 0) {
-                       if (errno == EXDEV) {
-                               /* rename failed on cross-filesystem link.  
-                                  Copy the file instead. */
-                               if (copy_file(fnametmp,fname, file->mode)) {
-                                       rprintf(FERROR,"copy %s -> %s : %s\n",
-                                               fnametmp,fname,strerror(errno));
-                               } else {
-                                       set_perms(fname,file,NULL,0);
-                               }
-                               do_unlink(fnametmp);
-                       } else {
-                               rprintf(FERROR,"rename %s -> %s : %s\n",
-                                       fnametmp,fname,strerror(errno));
-                               do_unlink(fnametmp);
-                       }
-               } else {
-                       set_perms(fname,file,NULL,0);
-               }
 
+               finish_transfer(fname, fnametmp, file);
+               
                cleanup_fname = NULL;
-
+               cleanup_new_fname = NULL;
+               cleanup_file = NULL;
                
                if (!recv_ok) {
                        if (csum_length == SUM_LENGTH) {
index 4a8fe04..b13a8b8 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -187,6 +187,56 @@ quote(rsync -az -e ssh --delete ~ftp/pub/samba/ nimbus:"~ftp/pub/tridge/samba")
 
 this is launched from cron every few hours.
 
+manpagesection(OPTIONS SUMMARY)
+
+Here is a short summary of the options avalable in rsync. Please refer
+to the detailed description below for a complete description.
+
+verb(
+ -v, --verbose               increase verbosity
+ -c, --checksum              always checksum
+ -a, --archive               archive mode
+ -r, --recursive             recurse into directories
+ -R, --relative              use relative path names
+ -b, --backup                make backups (default ~ extension)
+ -u, --update                update only (don't overwrite newer files)
+ -l, --links                 preserve soft links
+ -L, --copy-links            treat soft links like regular files
+ -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
+ -W, --whole-file            copy whole files, no incremental checks
+ -x, --one-file-system       don't cross filesystem boundaries
+ -B, --block-size=SIZE       checksum blocking size
+ -e, --rsh=COMMAND           specify rsh replacement
+     --rsync-path=PATH       specify path to rsync on the remote machine
+ -C, --cvs-exclude           auto ignore files in the same way CVS does
+     --delete                delete files that don't exist on the sending side
+     --partial               keep partially transferred files
+     --force                 force deletion of directories even if not empty
+     --numeric-ids           don't map uid/gid values by user/group name
+     --timeout=TIME          set IO timeout in seconds
+ -I, --ignore-times          don't exclude files that match length and time
+ -T  --temp-dir=DIR          create temporary files in directory DIR
+ -z, --compress              compress file data
+     --exclude=PATTERN       exclude file FILE
+     --exclude-from=PATTERN  exclude files listed in FILE
+     --include=PATTERN       don't exclude file FILE
+     --include-from=PATTERN  don't exclude files listed in FILE
+     --suffix=SUFFIX         override backup suffix
+     --version               print version number
+     --daemon                run as a rsync daemon
+     --config=FILE           specify alternate rsyncd.conf file
+     --port=PORT             specify alternate rsyncd port number
+     --stats                 give some file transfer stats
+ -h, --help                  show this help screen
+)
+
 manpageoptions()
 
 rsync uses the GNU long options package. Many of the command line
@@ -269,6 +319,12 @@ dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
 is  not used  and  the whole file is sent as-is instead. This may be
 useful when using rsync with a local machine.
 
+dit(bf(--partial)) By default rsync will delete any partially
+transferred file if the transfer is interrupted. In some circumstances
+it is more desirable to keep partially transferred files. Using the
+--partial option tells rsync to keep the partial file which should
+make a subsequent transfer of the rest of the file much faster.
+
 dit(bf(-p, --perms)) This option causes rsync to update the remote
 permissions to be the same as the local permissions.