New logging categories added to allow differentiation between
[rsync/rsync.git] / receiver.c
index ed1111a..387567b 100644 (file)
@@ -60,7 +60,7 @@ extern struct filter_list_struct server_filter_list;
 static struct bitbag *delayed_bits = NULL;
 static int phase = 0, redoing = 0;
 /* We're either updating the basis file or an identical copy: */
-static int updating_basis;
+static int updating_basis_or_equiv;
 
 /*
  * get_tmpname() - create a tmp filename for a given filename
@@ -110,7 +110,7 @@ int get_tmpname(char *fnametmp, const char *fname)
        maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
 
        if (maxname < 1) {
-               rprintf(FERROR, "temporary filename too long: %s\n", fname);
+               rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
                fnametmp[0] = '\0';
                return 0;
        }
@@ -123,6 +123,43 @@ int get_tmpname(char *fnametmp, const char *fname)
        return 1;
 }
 
+/* Opens a temporary file for writing.
+ * Success: Writes name into fnametmp, returns fd.
+ * Failure: Clobbers fnametmp, returns -1.
+ * Calling cleanup_set() is the caller's job. */
+int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
+{
+       int fd;
+
+       if (!get_tmpname(fnametmp, fname))
+               return -1;
+
+       /* We initially set the perms without the setuid/setgid bits or group
+        * access to ensure that there is no race condition.  They will be
+        * correctly updated after the right owner and group info is set.
+        * (Thanks to snabb@epipe.fi for pointing this out.) */
+       fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+
+#if 0
+       /* 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 (fd == -1 && relative_paths && errno == ENOENT
+           && create_directory_path(fnametmp) == 0) {
+               /* Get back to name with XXXXXX in it. */
+               get_tmpname(fnametmp, fname);
+               fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+       }
+#endif
+
+       if (fd == -1) {
+               rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
+                       full_fname(fnametmp));
+               return -1;
+       }
+
+       return fd;
+}
 
 static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                        const char *fname, int fd, OFF_T total_size)
@@ -174,7 +211,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                }
                offset = sum.flength;
                if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
-                       rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
+                       rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
                                full_fname(fname), (double)j, (double)offset);
                        exit_cleanup(RERR_FILEIO);
                }
@@ -222,14 +259,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                        sum_update(map, len);
                }
 
-               if (updating_basis) {
+               if (updating_basis_or_equiv) {
                        if (offset == offset2 && fd != -1) {
                                OFF_T pos;
                                if (flush_write_file(fd) < 0)
                                        goto report_write_error;
                                offset += len;
                                if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
-                                       rsyserr(FERROR, errno,
+                                       rsyserr(FERROR_XFER, errno,
                                                "lseek of %s returned %.0f, not %.0f",
                                                full_fname(fname),
                                                (double)pos, (double)offset);
@@ -256,7 +293,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
 
        if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
            report_write_error:
-               rsyserr(FERROR, errno, "write failed on %s",
+               rsyserr(FERROR_XFER, errno, "write failed on %s",
                        full_fname(fname));
                exit_cleanup(RERR_FILEIO);
        }
@@ -298,7 +335,7 @@ static void handle_delayed_updates(char *local_name)
                        /* We don't use robust_rename() here because the
                         * partial-dir must be on the same drive. */
                        if (do_rename(partialptr, fname) < 0) {
-                               rsyserr(FERROR, errno,
+                               rsyserr(FERROR_XFER, errno,
                                        "rename failed for %s (from %s)",
                                        full_fname(fname), partialptr);
                        } else {
@@ -516,14 +553,18 @@ int recv_files(int f_in, char *local_name)
                                break;
                        }
                        if (!fnamecmp || (server_filter_list.head
-                         && check_filter(&server_filter_list, fname, 0) < 0))
+                         && check_filter(&server_filter_list, fname, 0) < 0)) {
                                fnamecmp = fname;
+                               fnamecmp_type = FNAMECMP_FNAME;
+                       }
                } else {
                        /* Reminder: --inplace && --partial-dir are never
                         * enabled at the same time. */
                        if (inplace && make_backups > 0) {
                                if (!(fnamecmp = get_backup_name(fname)))
                                        fnamecmp = fname;
+                               else
+                                       fnamecmp_type = FNAMECMP_BACKUP;
                        } else if (partial_dir && partialptr)
                                fnamecmp = partialptr;
                        else
@@ -549,13 +590,15 @@ int recv_files(int f_in, char *local_name)
                                fd1 = do_open(fnamecmp, O_RDONLY, 0);
                        }
                }
-               updating_basis = inplace && fnamecmp == fname;
+
+               updating_basis_or_equiv = inplace
+                   && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);
 
                if (fd1 == -1) {
                        st.st_mode = 0;
                        st.st_size = 0;
                } else if (do_fstat(fd1,&st) != 0) {
-                       rsyserr(FERROR, errno, "fstat %s failed",
+                       rsyserr(FERROR_XFER, errno, "fstat %s failed",
                                full_fname(fnamecmp));
                        discard_receive_data(f_in, F_LENGTH(file));
                        close(fd1);
@@ -570,7 +613,7 @@ int recv_files(int f_in, char *local_name)
                         * and the underlying robust_unlink could cope
                         * with directories
                         */
-                       rprintf(FERROR,"recv_files: %s is a directory\n",
+                       rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
                                full_fname(fnamecmp));
                        discard_receive_data(f_in, F_LENGTH(file));
                        close(fd1);
@@ -604,54 +647,22 @@ int recv_files(int f_in, char *local_name)
                if (inplace)  {
                        fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
                        if (fd2 == -1) {
-                               rsyserr(FERROR, errno, "open %s failed",
+                               rsyserr(FERROR_XFER, errno, "open %s failed",
                                        full_fname(fname));
-                               discard_receive_data(f_in, F_LENGTH(file));
-                               if (fd1 != -1)
-                                       close(fd1);
-                               if (inc_recurse)
-                                       send_msg_int(MSG_NO_SEND, ndx);
-                               continue;
                        }
                } else {
-                       if (!get_tmpname(fnametmp,fname)) {
-                               discard_receive_data(f_in, F_LENGTH(file));
-                               if (fd1 != -1)
-                                       close(fd1);
-                               if (inc_recurse)
-                                       send_msg_int(MSG_NO_SEND, ndx);
-                               continue;
-                       }
-
-                       /* we initially set the perms without the
-                        * 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.  We also set it initially without group
-                        * access because of a similar race condition. */
-                       fd2 = do_mkstemp(fnametmp, 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) {
-                               /* Get back to name with XXXXXX in it. */
-                               get_tmpname(fnametmp, fname);
-                               fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
-                       }
-                       if (fd2 == -1) {
-                               rsyserr(FERROR, errno, "mkstemp %s failed",
-                                       full_fname(fnametmp));
-                               discard_receive_data(f_in, F_LENGTH(file));
-                               if (fd1 != -1)
-                                       close(fd1);
-                               if (inc_recurse)
-                                       send_msg_int(MSG_NO_SEND, ndx);
-                               continue;
-                       }
+                       fd2 = open_tmpfile(fnametmp, fname, file);
+                       if (fd2 != -1)
+                               cleanup_set(fnametmp, partialptr, file, fd1, fd2);
+               }
 
-                       cleanup_set(fnametmp, partialptr, file, fd1, fd2);
+               if (fd2 == -1) {
+                       discard_receive_data(f_in, F_LENGTH(file));
+                       if (fd1 != -1)
+                               close(fd1);
+                       if (inc_recurse)
+                               send_msg_int(MSG_NO_SEND, ndx);
+                       continue;
                }
 
                /* log the transfer */
@@ -708,7 +719,7 @@ int recv_files(int f_in, char *local_name)
                         || (preserve_hard_links && F_IS_HLINKED(file)))
                                send_msg_int(MSG_SUCCESS, ndx);
                } else if (!recv_ok) {
-                       enum logcode msgtype = redoing || read_batch ? FERROR : FINFO;
+                       enum logcode msgtype = redoing || read_batch ? FERROR : FWARNING;
                        if (msgtype == FERROR || verbose) {
                                char *errstr, *redostr, *keptstr;
                                if (!(keep_partial && partialptr) && !inplace)