Tweaking the license text a bit more.
[rsync/rsync.git] / generator.c
index c15e20f..1064ff5 100644 (file)
@@ -7,8 +7,9 @@
  * Copyright (C) 2003-2007 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -112,6 +113,7 @@ static int deldelay_fd = -1;
 static int lull_mod;
 static int dir_tweaking;
 static int need_retouch_dir_times;
+static int need_retouch_dir_perms;
 static const char *solo_file = NULL;
 
 /* For calling delete_item() and delete_dir_contents(). */
@@ -1261,11 +1263,27 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
                    && verbose && code != FNONE && f_out != -1)
                        rprintf(code, "%s/\n", fname);
+
+               /* We need to ensure that the dirs in the transfer have writable
+                * permissions during the time we are putting files within them.
+                * This is then fixed after the transfer is done. */
+#ifdef HAVE_CHMOD
+               if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) {
+                       mode_t mode = file->mode | S_IWUSR;
+                       if (do_chmod(fname, mode) < 0) {
+                               rsyserr(FERROR, errno,
+                                       "failed to modify permissions on %s",
+                                       full_fname(fname));
+                       }
+                       need_retouch_dir_perms = 1;
+               }
+#endif
+
                if (real_ret != 0 && one_file_system)
                        real_sx.st.st_dev = filesystem_dev;
                if (inc_recurse) {
                        if (one_file_system) {
-                               uint32 *devp = F_DIRDEV_P(file);
+                               uint32 *devp = F_DIR_DEV_P(file);
                                DEV_MAJOR(devp) = major(real_sx.st.st_dev);
                                DEV_MINOR(devp) = minor(real_sx.st.st_dev);
                        }
@@ -1821,13 +1839,6 @@ 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);
-               else if (relative_paths && implied_dirs)
-                       touch_up_dirs(first_flist, -1);
-
                flist_free(first_flist); /* updates first_flist */
        }
 }
@@ -1838,7 +1849,6 @@ void generate_files(int f_out, const char *local_name)
        char fbuf[MAXPATHLEN];
        int itemizing;
        enum logcode code;
-       int need_retouch_dir_perms = 0;
        int save_do_progress = do_progress;
 
        if (protocol_version >= 29) {
@@ -1894,16 +1904,21 @@ void generate_files(int f_out, const char *local_name)
        dflt_perms = (ACCESSPERMS & ~orig_umask);
 
        do {
-               if (inc_recurse && delete_during && cur_flist->ndx_start) {
+               if (inc_recurse && cur_flist->ndx_start) {
                        struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx];
-                       if (BITS_SETnUNSET(fp->flags, FLAG_XFER_DIR, FLAG_MISSING_DIR)) {
-                               dev_t dirdev;
-                               if (one_file_system) {
-                                       uint32 *devp = F_DIRDEV_P(fp);
-                                       dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
-                               } else
-                                       dirdev = MAKEDEV(0, 0);
-                               delete_in_dir(f_name(fp, fbuf), fp, &dirdev);
+                       f_name(fp, fbuf);
+                       ndx = cur_flist->ndx_start - 1;
+                       recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
+                       if (delete_during) {
+                               if (BITS_SETnUNSET(fp->flags, FLAG_XFER_DIR, FLAG_MISSING_DIR)) {
+                                       dev_t dirdev;
+                                       if (one_file_system) {
+                                               uint32 *devp = F_DIR_DEV_P(fp);
+                                               dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
+                                       } else
+                                               dirdev = MAKEDEV(0, 0);
+                                       delete_in_dir(f_name(fp, fbuf), fp, &dirdev);
+                               }
                        }
                }
                for (i = cur_flist->low; i <= cur_flist->high; i++) {
@@ -1912,6 +1927,14 @@ 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);
@@ -1925,24 +1948,6 @@ void generate_files(int f_out, const char *local_name)
                                f_name(file, fbuf);
                        recv_generator(fbuf, file, ndx, itemizing, code, f_out);
 
-                       /* We need to ensure that any dirs we create have
-                        * writeable permissions during the time we are putting
-                        * files within them.  This is then fixed after the
-                        * transfer is done. */
-#ifdef HAVE_CHMOD
-                       if (!am_root && S_ISDIR(file->mode)
-                        && !(file->mode & S_IWUSR) && dir_tweaking) {
-                               mode_t mode = file->mode | S_IWUSR;
-                               const char *fname = solo_file ? solo_file : fbuf;
-                               if (do_chmod(fname, mode) < 0) {
-                                       rsyserr(FERROR, errno,
-                                           "failed to modify permissions on %s",
-                                           full_fname(fname));
-                               }
-                               need_retouch_dir_perms = 1;
-                       }
-#endif
-
                        check_for_finished_files(itemizing, code, 0);
 
                        if (allowed_lull && !(i % lull_mod))
@@ -2011,8 +2016,7 @@ 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 && (!inc_recurse || delete_during == 2))
+       if ((need_retouch_dir_perms || need_retouch_dir_times) && dir_tweaking)
                touch_up_dirs(dir_flist, -1);
 
        if (max_delete >= 0 && deletion_count > max_delete) {