Use ftruncate() at the end of a --sparse file.
[rsync/rsync.git] / generator.c
index b5db075..be36e63 100644 (file)
@@ -71,7 +71,6 @@ extern int io_error;
 extern int flist_eof;
 extern int allowed_lull;
 extern int sock_f_out;
-extern int ignore_timeout;
 extern int protocol_version;
 extern int file_total;
 extern int fuzzy_basis;
@@ -290,7 +289,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                rprintf(FINFO, "delete_in_dir(%s)\n", fbuf);
 
        if (allowed_lull)
-               maybe_send_keepalive();
+               maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
 
        if (io_error && !ignore_errors) {
                if (already_warned)
@@ -391,12 +390,9 @@ static void do_delete_pass(void)
 
 int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 {
-#ifndef CAN_SET_SYMLINK_TIMES
-       if (S_ISLNK(file->mode)) {
+       if (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(file->mode)) {
                ;
-       } else
-#endif
-       if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
+       } else if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
                return 0;
 
        if (preserve_perms) {
@@ -438,12 +434,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
 {
        if (statret >= 0) { /* A from-dest-dir statret can == 1! */
                int keep_time = !preserve_times ? 0
-                   : S_ISDIR(file->mode) ? preserve_times > 1 :
-#ifdef CAN_SET_SYMLINK_TIMES
-                   1;
-#else
-                   !S_ISLNK(file->mode);
-#endif
+                   : S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
+                   : S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
+                   : 1;
 
                if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
                        iflags |= ITEM_REPORT_SIZE;
@@ -568,6 +561,12 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
        int s2length;
        int64 l;
 
+       if (len < 0) {
+               /* The file length overflowed our int64 var, so we can't process this file. */
+               sum->count = -1; /* indicate overflow error */
+               return;
+       }
+
        if (block_size)
                blength = block_size;
        else if (len <= BLOCK_SIZE * BLOCK_SIZE)
@@ -1033,7 +1032,7 @@ static void list_file_entry(struct file_struct *f)
 #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
                rprintf(FINFO, "%s %*s %s %s -> %s\n",
-                       permbuf, colwidth, comma_num(len),
+                       permbuf, colwidth, human_num(len),
                        timestring(f->modtime), f_name(f, NULL),
                        F_SYMLINK(f));
        } else
@@ -1044,7 +1043,7 @@ static void list_file_entry(struct file_struct *f)
                        f_name(f, NULL));
        } else {
                rprintf(FINFO, "%s %*s %s %s\n",
-                       permbuf, colwidth, comma_num(len),
+                       permbuf, colwidth, human_num(len),
                        timestring(f->modtime), f_name(f, NULL));
        }
 }
@@ -1120,6 +1119,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                skip_dir = NULL;
        }
 
+       init_stat_x(&sx);
        if (daemon_filter_list.head && (*fname != '.' || fname[1])) {
                if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {
                        if (is_dir < 0)
@@ -1137,7 +1137,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                }
        }
 
-       init_stat_x(&sx);
        if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
          parent_is_dry_missing:
                if (fuzzy_dirlist) {
@@ -1355,11 +1354,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                const char *sl = F_SYMLINK(file);
                if (safe_symlinks && unsafe_symlink(sl, fname)) {
                        if (INFO_GTE(NAME, 1)) {
-                               if (solo_file)
+                               if (solo_file) {
+                                       /* fname contains the destination path, but we
+                                        * want to report the source path. */
                                        fname = f_name(file, NULL);
+                               }
                                rprintf(FINFO,
-                                       "ignoring unsafe symlink %s -> \"%s\"\n",
-                                       full_fname(fname), sl);
+                                       "ignoring unsafe symlink \"%s\" -> \"%s\"\n",
+                                       fname, sl);
                        }
                        return;
                }
@@ -1929,7 +1931,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
                }
                if (counter >= loopchk_limit) {
                        if (allowed_lull)
-                               maybe_send_keepalive();
+                               maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
                        else
                                maybe_flush_socket(0);
                        counter = 0;
@@ -2048,7 +2050,7 @@ void generate_files(int f_out, const char *local_name)
        }
        solo_file = local_name;
        dir_tweaking = !(list_only || solo_file || dry_run);
-       need_retouch_dir_times = preserve_times > 1;
+       need_retouch_dir_times = preserve_times & PRESERVE_DIR_TIMES;
        loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
        symlink_timeset_failed_flags = ITEM_REPORT_TIME
            | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
@@ -2076,12 +2078,6 @@ void generate_files(int f_out, const char *local_name)
                        : "enabled");
        }
 
-       /* Since we often fill up the outgoing socket and then just sit around
-        * waiting for the other 2 processes to do their thing, we don't want
-        * to exit on a timeout.  If the data stops flowing, the receiver will
-        * notice that and let us know via the redo pipe (or its closing). */
-       ignore_timeout = 1;
-
        dflt_perms = (ACCESSPERMS & ~orig_umask);
 
        do {
@@ -2135,7 +2131,7 @@ void generate_files(int f_out, const char *local_name)
 
                        if (i + cur_flist->ndx_start >= next_loopchk) {
                                if (allowed_lull)
-                                       maybe_send_keepalive();
+                                       maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
                                else
                                        maybe_flush_socket(0);
                                next_loopchk += loopchk_limit;