Added a missing "void" to the arg-spec of setup_iconv().
[rsync/rsync.git] / generator.c
index 6f02446..d93529c 100644 (file)
@@ -81,7 +81,6 @@ extern int copy_dest;
 extern int link_dest;
 extern int whole_file;
 extern int list_only;
-extern int new_root_dir;
 extern int read_batch;
 extern int safe_symlinks;
 extern long block_size; /* "long" because popt can't set an int32. */
@@ -1103,6 +1102,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        char *fnamecmp, *partialptr, *backupptr = NULL;
        char fnamecmpbuf[MAXPATHLEN];
        uchar fnamecmp_type;
+       int implied_dirs_are_missing = relative_paths && !implied_dirs && !inc_recurse;
        int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;
 
        if (list_only)
@@ -1114,7 +1114,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        if (server_filter_list.head) {
                if (excluded_below >= 0) {
                        if (F_DEPTH(file) > excluded_below
-                        && (implied_dirs || f_name_has_prefix(file, excluded_dir)))
+                        && (!implied_dirs_are_missing || f_name_has_prefix(file, excluded_dir)))
                                goto skipping;
                        excluded_below = -1;
                }
@@ -1136,7 +1136,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
 
        if (missing_below >= 0) {
                if (F_DEPTH(file) <= missing_below
-                || (!implied_dirs && !f_name_has_prefix(file, missing_dir))) {
+                || (implied_dirs_are_missing && !f_name_has_prefix(file, missing_dir))) {
                        if (dry_run)
                                dry_run--;
                        missing_below = -1;
@@ -1213,6 +1213,22 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        }
 
        if (S_ISDIR(file->mode)) {
+               if (!implied_dirs && !(file->flags & FLAG_XFER_DIR))
+                       goto cleanup;
+               if (inc_recurse && ndx != cur_flist->ndx_start - 1) {
+                       /* In inc_recurse mode we want ot make sure any missing
+                        * directories get created while we're still processing
+                        * the parent dir (which allows us to touch the parent
+                        * dir's mtime right away).  We will handle the dir in
+                        * full later (right before we handle its contents). */
+                       if (statret == 0
+                        && (S_ISDIR(sx.st.st_mode)
+                         || delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0))
+                               goto cleanup; /* Any errors get reported later. */
+                       if (do_mkdir(fname, file->mode & 0700) == 0)
+                               file->flags |= FLAG_DIR_CREATED;
+                       goto cleanup;
+               }
                /* The file to be received is a directory, so we need
                 * to prepare appropriately.  If there is already a
                 * file of that name and it is *not* a directory, then
@@ -1230,11 +1246,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                }
                real_ret = statret;
                real_sx = sx;
-               if (new_root_dir) {
-                       if (*fname == '.' && fname[1] == '\0')
-                               statret = -1;
-                       new_root_dir = 0;
-               }
+               if (file->flags & FLAG_DIR_CREATED)
+                       statret = -1;
                if (!preserve_perms) { /* See comment in non-dir code below. */
                        file->mode = dest_mode(file->mode, sx.st.st_mode,
                                               dflt_perms, statret == 0);
@@ -1768,7 +1781,8 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
         * transfer and/or re-set any tweaked modified-time values. */
        for (i = start; i <= end; i++, counter++) {
                file = flist->files[i];
-               if (!S_ISDIR(file->mode))
+               if (!S_ISDIR(file->mode)
+                || (relative_paths && !implied_dirs && !(file->flags & FLAG_XFER_DIR)))
                        continue;
                if (verbose > 3) {
                        fname = f_name(file, NULL);
@@ -1855,6 +1869,11 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
                        maybe_flush_socket(1);
                }
 
+               if (delete_during == 2 || !dir_tweaking) {
+                       /* Skip directory touch-up. */
+               } else if (first_flist->ndx_start != 0)
+                       touch_up_dirs(dir_flist, first_flist->parent_ndx);
+
                flist_free(first_flist); /* updates first_flist */
        }
 }
@@ -1921,9 +1940,12 @@ void generate_files(int f_out, const char *local_name)
 
        do {
 #ifdef SUPPORT_HARD_LINKS
-               if (inc_recurse && preserve_hard_links)
-                       match_hard_links(cur_flist);
+               if (preserve_hard_links && inc_recurse) {
+                       while (!flist_eof && file_total < FILECNT_LOOKAHEAD/2)
+                               wait_for_receiver();
+               }
 #endif
+
                if (inc_recurse && cur_flist->ndx_start) {
                        struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx];
                        f_name(fp, fbuf);
@@ -1947,14 +1969,6 @@ void generate_files(int f_out, const char *local_name)
                        if (!F_IS_ACTIVE(file))
                                continue;
 
-                       if (inc_recurse && S_ISDIR(file->mode)) {
-                               /* Regular dirs are at the end, so we can stop. */
-                               if (F_DEPTH(file))
-                                       break;
-                               /* A dot-dir is at the start, so just skip it. */
-                               continue;
-                       }
-
 #ifdef ICONV_OPTION
                        if (ic_ndx)
                                ndx = F_NDX(file);
@@ -2036,7 +2050,8 @@ void generate_files(int f_out, const char *local_name)
        if (delete_after && !solo_file && file_total > 0)
                do_delete_pass();
 
-       if ((need_retouch_dir_perms || need_retouch_dir_times) && dir_tweaking)
+       if ((need_retouch_dir_perms || need_retouch_dir_times)
+        && dir_tweaking && (!inc_recurse || delete_during == 2))
                touch_up_dirs(dir_flist, -1);
 
        if (max_delete >= 0 && deletion_count > max_delete) {