Keeping silent about stat() errors is never a good idea -- it hides
[rsync/rsync.git] / generator.c
index f4dbb9c..b795f0f 100644 (file)
@@ -446,8 +446,8 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
        sum->flength    = len;
        sum->blength    = blength;
        sum->s2length   = s2length;
-       sum->count      = (len + (blength - 1)) / blength;
-       sum->remainder  = (len % blength);
+       sum->remainder  = len % blength;
+       sum->count      = len / blength + (sum->remainder != 0);
 
        if (sum->count && verbose > 2) {
                rprintf(FINFO,
@@ -731,6 +731,11 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                return;
        }
 
+       if (preserve_hard_links && file->link_u.links
+           && hard_link_check(file, ndx, fname, statret, &st,
+                              itemizing, code, HL_CHECK_MASTER))
+               return;
+
        if (preserve_links && S_ISLNK(file->mode)) {
 #ifdef SUPPORT_LINKS
                if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
@@ -761,6 +766,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                        }
                                        set_perms(fname, file, &st,
                                                  maybe_PERMS_REPORT);
+                                       if (preserve_hard_links
+                                           && file->link_u.links) {
+                                               hard_link_cluster(file, ndx,
+                                                                 itemizing,
+                                                                 code);
+                                       }
                                        return;
                                }
                        }
@@ -771,6 +782,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        if (!S_ISLNK(st.st_mode))
                                statret = -1;
                }
+               if (preserve_hard_links && file->link_u.links
+                   && hard_link_check(file, ndx, fname, -1, &st,
+                                      itemizing, code, HL_SKIP))
+                       return;
                if (do_symlink(file->u.link,fname) != 0) {
                        rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
                                full_fname(fname), safe_fname(file->u.link));
@@ -789,17 +804,23 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                SIVAL(numbuf, 0, ndx);
                                send_msg(MSG_SUCCESS, numbuf, 4);
                        }
+                       if (preserve_hard_links && file->link_u.links)
+                               hard_link_cluster(file, ndx, itemizing, code);
                }
 #endif
                return;
        }
 
        if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
-               if (statret != 0 ||
-                   st.st_mode != file->mode ||
-                   st.st_rdev != file->u.rdev) {
+               if (statret != 0
+                || (st.st_mode & ~CHMOD_BITS) != (file->mode & ~CHMOD_BITS)
+                || st.st_rdev != file->u.rdev) {
                        if (delete_item(fname, st.st_mode, DEL_TERSE) < 0)
                                return;
+                       if (preserve_hard_links && file->link_u.links
+                           && hard_link_check(file, ndx, fname, -1, &st,
+                                              itemizing, code, HL_SKIP))
+                               return;
                        if (!IS_DEVICE(st.st_mode))
                                statret = -1;
                        if (verbose > 2) {
@@ -820,20 +841,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                        rprintf(code, "%s\n",
                                                safe_fname(fname));
                                }
+                               if (preserve_hard_links && file->link_u.links) {
+                                       hard_link_cluster(file, ndx,
+                                                         itemizing, code);
+                               }
                        }
                } else {
                        if (itemizing)
                                itemize(file, ndx, statret, &st, 0, 0, NULL);
                        set_perms(fname, file, &st, maybe_PERMS_REPORT);
+                       if (preserve_hard_links && file->link_u.links)
+                               hard_link_cluster(file, ndx, itemizing, code);
                }
                return;
        }
 
-       if (preserve_hard_links
-           && hard_link_check(file, ndx, fname, statret, &st,
-                              itemizing, code, HL_CHECK_MASTER))
-               return;
-
        if (!S_ISREG(file->mode)) {
                if (the_file_list->count == 1)
                        fname = f_name(file);
@@ -1001,17 +1023,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        }
 
        if (statret != 0) {
-               if (preserve_hard_links
+               if (preserve_hard_links && file->link_u.links
                    && hard_link_check(file, ndx, fname, statret, &st,
                                       itemizing, code, HL_SKIP))
                        return;
                if (stat_errno == ENOENT)
                        goto notify_others;
-               if (verbose > 1) {
-                       rsyserr(FERROR, stat_errno,
-                               "recv_generator: failed to stat %s",
-                               full_fname(fname));
-               }
+               rsyserr(FERROR, stat_errno, "recv_generator: failed to stat %s",
+                       full_fname(fname));
                return;
        }
 
@@ -1064,7 +1083,7 @@ prepare_to_open:
                        full_fname(fnamecmp));
            pretend_missing:
                /* pretend the file didn't exist */
-               if (preserve_hard_links
+               if (preserve_hard_links && file->link_u.links
                    && hard_link_check(file, ndx, fname, statret, &st,
                                       itemizing, code, HL_SKIP))
                        return;