X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/9decb4d2ef51599425f12a68dbeba2b4f3a2d908..2b967218eb530c649fe342faab4470a4ad4036d4:/generator.c diff --git a/generator.c b/generator.c index c15e20f8..b3a31f05 100644 --- a/generator.c +++ b/generator.c @@ -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 && dry_run < 2) { + 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) {