Split code out into separate files and remove some global variables to
[rsync/rsync.git] / generator.c
index 353e706..8e4ede0 100644 (file)
@@ -1,7 +1,10 @@
 /* -*- c-file-style: "linux" -*-
+
+   rsync -- fast file replication program
    
    Copyright (C) 1996-2000 by Andrew Tridgell 
    Copyright (C) Paul Mackerras 1996
+   Copyright (C) 2002 by Martin Pool <mbp@samba.org>
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -28,7 +31,7 @@ extern int am_root;
 extern int preserve_devices;
 extern int preserve_hard_links;
 extern int update_only;
-extern int whole_file;
+extern int opt_ignore_existing;
 extern int block_size;
 extern int csum_length;
 extern int ignore_times;
@@ -99,22 +102,58 @@ static int adapt_block_size(struct file_struct *file, int bsize)
 /*
   send a sums struct down a fd
   */
-static void send_sums(struct sum_struct *s,int f_out)
+static void send_sums(struct sum_struct *s, int f_out)
 {
-       int i;
-       
-       /* tell the other guy how many we are going to be doing and how many
-          bytes there are in the last chunk */
-       write_int(f_out,s?s->count:0);
-       write_int(f_out,s?s->n:block_size);
-       write_int(f_out,s?s->remainder:0);
+       if (s) {
+               size_t i;
+
+               /* tell the other guy how many we are going to be
+                  doing and how many bytes there are in the last
+                  chunk */
+               write_int(f_out, s->count);
+               write_int(f_out, s->n);
+               write_int(f_out, s->remainder);
+
+               for (i = 0; i < s->count; i++) {
+                       write_int(f_out, s->sums[i].sum1);
+                       write_buf(f_out, s->sums[i].sum2, csum_length);
+               }
+       } else {
+               /* we don't have checksums */
+               write_int(f_out, 0);
+               write_int(f_out, block_size);
+               write_int(f_out, 0);
+       }
+}
 
-       if (!s) return;
 
-       for (i=0;i<s->count;i++) {
-               write_int(f_out,s->sums[i].sum1);
-               write_buf(f_out,s->sums[i].sum2,csum_length);
-       }
+/**
+ * Perhaps we want to just send an empty checksum set for this file,
+ * which will force the whole thing to be literally transferred.
+ *
+ * When do we do this?  If the user's explicitly said they
+ * want the whole thing, or if { they haven't explicitly
+ * requested a delta, and it's local but not batch mode.}
+ *
+ * Whew. */
+static BOOL disable_deltas_p(void)
+{
+       extern int whole_file, no_whole_file;
+       extern int local_server;
+       extern int write_batch;
+
+       assert(whole_file == 0 || whole_file == 1);
+
+       /* whole_file and no_whole_file are never both on at the same time */
+
+       if (whole_file)
+               return True;
+       else if (no_whole_file)
+               return False;
+       else if (write_batch)
+               return False;
+       else
+               return local_server;
 }
 
 
@@ -200,6 +239,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
        extern int list_only;
        extern int preserve_perms;
        extern int only_existing;
+       extern int orig_umask;
 
        if (list_only) return;
 
@@ -210,8 +250,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
 
        if (only_existing && statret == -1 && errno == ENOENT) {
                /* we only want to update existing files */
-               if (verbose > 1) rprintf(FINFO, RSYNC_NAME
-                                        ": not creating new file \"%s\"\n",fname);
+               if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
                return;
        }
 
@@ -243,7 +282,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
                }
                if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
                        if (!(relative_paths && errno==ENOENT && 
-                             create_directory_path(fname)==0 && 
+                             create_directory_path(fname, orig_umask)==0 && 
                              do_mkdir(fname,file->mode)==0)) {
                                rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
                                        fname,strerror(errno));
@@ -264,7 +303,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
 
                if (safe_symlinks && unsafe_symlink(file->link, fname)) {
                        if (verbose) {
-                               rprintf(FINFO,RSYNC_NAME ": ignoring unsafe symlink \"%s\" -> \"%s\"\n",
+                               rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
                                        fname,file->link);
                        }
                        return;
@@ -292,8 +331,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
                } else {
                        set_perms(fname,file,NULL,0);
                        if (verbose) {
-                               rprintf(FINFO,RSYNC_NAME": %s -> %s\n",
-                                       fname,file->link);
+                               rprintf(FINFO,"%s -> %s\n", fname,file->link);
                        }
                }
 #endif
@@ -325,14 +363,12 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
 
        if (preserve_hard_links && check_hard_link(file)) {
                if (verbose > 1)
-                       rprintf(FINFO, RSYNC_NAME
-                               ": \"%s\" is a hard link\n",f_name(file));
+                       rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",f_name(file));
                return;
        }
 
        if (!S_ISREG(file->mode)) {
-               rprintf(FINFO, RSYNC_NAME
-                       ": skipping non-regular file \"%s\"\n",fname);
+               rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
                return;
        }
 
@@ -375,6 +411,12 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
                return;
        }
 
+       if (opt_ignore_existing && fnamecmp == fname) { 
+               if (verbose > 1)
+                       rprintf(FINFO,"%s exists\n",fname);
+               return;
+       } 
+
        if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
                if (verbose > 1)
                        rprintf(FINFO,"%s is newer\n",fname);
@@ -392,7 +434,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
                return;
        }
 
-       if (whole_file) {
+       if (disable_deltas_p()) {
                write_int(f_out,i);
                send_sums(NULL,f_out);    
                return;