Man page: Move the description of --info=progress2 to a better place.
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index a53ea29..abf0cd4 100644 (file)
--- a/util.c
+++ b/util.c
@@ -30,6 +30,7 @@ extern int modify_window;
 extern int relative_paths;
 extern int preserve_times;
 extern int preserve_xattrs;
+extern int preallocate_files;
 extern char *module_dir;
 extern unsigned int module_dirlen;
 extern char *partial_dir;
@@ -93,6 +94,7 @@ int fd_pair(int fd[2])
 
 void print_child_argv(const char *prefix, char **cmd)
 {
+       int cnt = 0;
        rprintf(FCLIENT, "%s ", prefix);
        for (; *cmd; cmd++) {
                /* Look for characters that ought to be quoted.  This
@@ -106,8 +108,9 @@ void print_child_argv(const char *prefix, char **cmd)
                } else {
                        rprintf(FCLIENT, "%s ", *cmd);
                }
+               cnt++;
        }
-       rprintf(FCLIENT, "\n");
+       rprintf(FCLIENT, " (%d args)\n", cnt);
 }
 
 NORETURN void out_of_memory(const char *str)
@@ -315,6 +318,9 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
        int ifd;
        char buf[1024 * 8];
        int len;   /* Number of bytes read into `buf'. */
+#ifdef PREALLOCATE_NEEDS_TRUNCATE
+       OFF_T preallocated_len = 0, offset = 0;
+#endif
 
        if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
                int save_errno = errno;
@@ -345,6 +351,25 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
                }
        }
 
+#ifdef SUPPORT_PREALLOCATION
+       if (preallocate_files) {
+               STRUCT_STAT srcst;
+
+               /* Try to preallocate enough space for file's eventual length.  Can
+                * reduce fragmentation on filesystems like ext4, xfs, and NTFS. */
+               if (do_fstat(ifd, &srcst) < 0)
+                       rsyserr(FWARNING, errno, "fstat %s", full_fname(source));
+               else if (srcst.st_size > 0) {
+                       if (do_fallocate(ofd, 0, srcst.st_size) == 0) {
+#ifdef PREALLOCATE_NEEDS_TRUNCATE
+                               preallocated_len = srcst.st_size;
+#endif
+                       } else
+                               rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(dest));
+               }
+       }
+#endif
+
        while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
                if (full_write(ofd, buf, len) < 0) {
                        int save_errno = errno;
@@ -354,6 +379,9 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
                        errno = save_errno;
                        return -1;
                }
+#ifdef PREALLOCATE_NEEDS_TRUNCATE
+               offset += len;
+#endif
        }
 
        if (len < 0) {
@@ -370,6 +398,16 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
                        full_fname(source));
        }
 
+#ifdef PREALLOCATE_NEEDS_TRUNCATE
+       /* Source file might have shrunk since we fstatted it.
+        * Cut off any extra preallocated zeros from dest file. */
+       if (offset < preallocated_len && do_ftruncate(ofd, offset) < 0) {
+               /* If we fail to truncate, the dest file may be wrong, so we
+                * must trigger the "partial transfer" error. */
+               rsyserr(FERROR_XFER, errno, "ftruncate %s", full_fname(dest));
+       }
+#endif
+
        if (close(ofd) < 0) {
                int save_errno = errno;
                rsyserr(FERROR_XFER, errno, "close failed on %s",
@@ -1026,8 +1064,9 @@ int change_dir(const char *dir, int set_path_only)
                        errno = ENAMETOOLONG;
                        return 0;
                }
-               curr_dir[curr_dir_len] = '/';
-               memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
+               if (!(curr_dir_len && curr_dir[curr_dir_len-1] == '/'))
+                       curr_dir[curr_dir_len++] = '/';
+               memcpy(curr_dir + curr_dir_len, dir, len + 1);
 
                if (!set_path_only && chdir(curr_dir)) {
                        curr_dir[curr_dir_len] = '\0';