fixed mdfour code on Cray (64 bit problems)
[rsync/rsync.git] / receiver.c
index ac9c669..3cd7f9e 100644 (file)
@@ -33,6 +33,8 @@ extern int cvs_exclude;
 extern int io_error;
 extern char *tmpdir;
 extern char *compare_dest;
+extern int make_backups;
+extern char *backup_suffix;
 
 
 static struct delete_list {
@@ -81,7 +83,7 @@ static void add_delete_entry(struct file_struct *file)
 static void delete_one(struct file_struct *f)
 {
        if (!S_ISDIR(f->mode)) {
-               if (do_unlink(f_name(f)) != 0) {
+               if (robust_unlink(f_name(f)) != 0) {
                        rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
                } else if (verbose) {
                        rprintf(FINFO,"deleting %s\n",f_name(f));
@@ -107,11 +109,12 @@ static void delete_files(struct file_list *flist)
        struct file_list *local_file_list;
        int i, j;
        char *name;
+       extern int module_id;
 
        if (cvs_exclude)
                add_cvs_excludes();
 
-       if (io_error) {
+       if (io_error && !lp_ignore_errors(module_id)) {
                rprintf(FINFO,"IO error encountered - skipping file deletion\n");
                return;
        }
@@ -139,8 +142,15 @@ static void delete_files(struct file_list *flist)
                            S_ISDIR(local_file_list->files[i]->mode))
                                add_delete_entry(local_file_list->files[i]);
                        if (-1 == flist_find(flist,local_file_list->files[i])) {
-                               delete_one(local_file_list->files[i]);
-                       }    
+                               char *f = f_name(local_file_list->files[i]);
+                               int k = strlen(f) - strlen(backup_suffix);
+                               if (make_backups && ((k <= 0) ||
+                                           (strcmp(f+k,backup_suffix) != 0))) {
+                                       (void) make_backup(f);
+                               } else {
+                                       delete_one(local_file_list->files[i]);
+                               }
+                       }
                }
                flist_free(local_file_list);
                free(name);
@@ -163,7 +173,7 @@ static int get_tmpname(char *fnametmp, char *fname)
                        rprintf(FERROR,"filename too long\n");
                        return 0;
                }
-               slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f);
+               slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
                return 1;
        } 
 
@@ -176,11 +186,11 @@ static int get_tmpname(char *fnametmp, char *fname)
 
        if (f) {
                *f = 0;
-               slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX",
+               slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
                         fname,f+1);
                *f = '/';
        } else {
-               slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname);
+               slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
        }
 
        return 1;
@@ -293,14 +303,18 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
        int phase=0;
        int recv_ok;
        extern struct stats stats;              
+       extern int preserve_perms;
+       extern int delete_after;
        struct stats initial_stats;
 
        if (verbose > 2) {
                rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
        }
 
-       if (recurse && delete_mode && !local_name && flist->count>0) {
-               delete_files(flist);
+       if (!delete_after) {
+               if (recurse && delete_mode && !local_name && flist->count>0) {
+                       delete_files(flist);
+               }
        }
 
        while (1) {      
@@ -349,14 +363,14 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                fnamecmp = fname;
 
                /* open the file */  
-               fd1 = open(fnamecmp,O_RDONLY);
+               fd1 = do_open(fnamecmp, O_RDONLY, 0);
 
                if ((fd1 == -1) && (compare_dest != NULL)) {
                        /* try the file at compare_dest instead */
-                       slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s",
+                       slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
                                                compare_dest,fname);
                        fnamecmp = fnamecmpbuf;
-                       fd1 = open(fnamecmp,O_RDONLY);
+                       fd1 = do_open(fnamecmp, O_RDONLY, 0);
                }
 
                if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
@@ -373,6 +387,13 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                        continue;
                }
 
+               if (fd1 != -1 && !preserve_perms) {
+                       /* if the file exists already and we aren't perserving
+                          presmissions then act as though the remote end sent
+                          us the file permissions we already have */
+                       file->mode = st.st_mode;
+               }
+
                if (fd1 != -1 && st.st_size > 0) {
                        buf = map_file(fd1,st.st_size);
                        if (verbose > 2)
@@ -403,17 +424,21 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                   setuid/setgid bits to ensure that there is no race
                   condition. They are then correctly updated after
                   the lchown. Thanks to snabb@epipe.fi for pointing
-                  this out */
+                  this out.  We also set it initially without group
+                  access because of a similar race condition. */
                fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
-                             file->mode & ACCESSPERMS);
+                             file->mode & INITACCESSPERMS);
 
+               /* in most cases parent directories will already exist
+                  because their information should have been previously
+                  transferred, but that may not be the case with -R */
                if (fd2 == -1 && relative_paths && errno == ENOENT && 
                    create_directory_path(fnametmp) == 0) {
                        fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
-                                     file->mode & ACCESSPERMS);
+                                     file->mode & INITACCESSPERMS);
                }
                if (fd2 == -1) {
-                       rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
+                       rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno));
                        receive_data(f_in,buf,-1,NULL,file->length);
                        if (buf) unmap_file(buf);
                        if (fd1 != -1) close(fd1);
@@ -443,7 +468,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                finish_transfer(fname, fnametmp, file);
 
                cleanup_disable();
-                               
+
                if (!recv_ok) {
                        if (csum_length == SUM_LENGTH) {
                                rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
@@ -456,6 +481,12 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                }
        }
 
+       if (delete_after) {
+               if (recurse && delete_mode && !local_name && flist->count>0) {
+                       delete_files(flist);
+               }
+       }
+
        if (preserve_hard_links)
                do_hard_links(flist);
 
@@ -464,7 +495,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
        for (i = 0; i < flist->count; i++) {
                file = flist->files[i];
                if (!file->basename || !S_ISDIR(file->mode)) continue;
-               recv_generator(f_name(file),flist,i,-1);
+               recv_generator(local_name?local_name:f_name(file),flist,i,-1);
        }
 
        if (verbose > 2)