X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/da1319128ac3e8d563a6959e82e471e8f5544a83..13710874ce907cd9405f83814cbebbe73f884e2e:/generator.c diff --git a/generator.c b/generator.c index 438d940b..e6e50032 100644 --- a/generator.c +++ b/generator.c @@ -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. */ @@ -516,7 +515,7 @@ static void do_delete_pass(void) rprintf(FINFO, " \r"); } -int unchanged_attrs(const char *fname, struct file_struct *file, statx *sxp) +int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) { if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) return 0; @@ -548,7 +547,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, statx *sxp) } void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret, - statx *sxp, int32 iflags, uchar fnamecmp_type, + stat_x *sxp, int32 iflags, uchar fnamecmp_type, const char *xname) { if (statret >= 0) { /* A from-dest-dir statret can == 1! */ @@ -830,7 +829,7 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist) * handling the file, -1 if no dest-linking occurred, or a non-negative * value if we found an alternate basis file. */ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, - char *cmpbuf, statx *sxp, int itemizing, + char *cmpbuf, stat_x *sxp, int itemizing, enum logcode code) { int best_match = -1; @@ -900,7 +899,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, #ifdef SUPPORT_HARD_LINKS try_a_copy: /* Copy the file locally. */ #endif - if (copy_file(cmpbuf, fname, file->mode) < 0) { + if (copy_file(cmpbuf, fname, file->mode, 0) < 0) { if (verbose) { rsyserr(FINFO, errno, "copy_file %s => %s", full_fname(cmpbuf), fname); @@ -935,7 +934,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, * handling the file, or -1 if no dest-linking occurred, or a non-negative * value if we found an alternate basis file. */ static int try_dests_non(struct file_struct *file, char *fname, int ndx, - char *cmpbuf, statx *sxp, int itemizing, + char *cmpbuf, stat_x *sxp, int itemizing, enum logcode code) { char lnk[MAXPATHLEN]; @@ -1073,6 +1072,35 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, return j; } +static void list_file_entry(struct file_struct *f) +{ + char permbuf[PERMSTRING_SIZE]; + double len; + + if (!F_IS_ACTIVE(f)) { + /* this can happen if duplicate names were removed */ + return; + } + + permstring(permbuf, f->mode); + len = F_LENGTH(f); + + /* TODO: indicate '+' if the entry has an ACL. */ + +#ifdef SUPPORT_LINKS + if (preserve_links && S_ISLNK(f->mode)) { + rprintf(FINFO, "%s %11.0f %s %s -> %s\n", + permbuf, len, timestring(f->modtime), + f_name(f, NULL), F_SYMLINK(f)); + } else +#endif + { + rprintf(FINFO, "%s %11.0f %s %s\n", + permbuf, len, timestring(f->modtime), + f_name(f, NULL)); + } +} + static int phase = 0; static int dflt_perms; @@ -1096,25 +1124,32 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, static int need_fuzzy_dirlist = 0; struct file_struct *fuzzy_file = NULL; int fd = -1, f_copy = -1; - statx sx, real_sx; + stat_x sx, real_sx; STRUCT_STAT partial_st; struct file_struct *back_file = NULL; int statret, real_ret, stat_errno; 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) - return; - if (verbose > 2) rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx); + if (list_only) { + if (S_ISDIR(file->mode) + && ((!implied_dirs && !(file->flags & FLAG_XFER_DIR)) + || (inc_recurse && ndx != cur_flist->ndx_start - 1))) + return; + list_file_entry(file); + return; + } + 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 +1171,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 +1248,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 +1281,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); @@ -1618,9 +1666,24 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, statret = 0; } - if (!do_xfers || read_batch || whole_file) + if (!do_xfers) goto notify_others; + if (read_batch || whole_file) { + if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) { + if (!(backupptr = get_backup_name(fname))) + goto cleanup; + if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) + goto pretend_missing; + if (copy_file(fname, backupptr, back_file->mode, 1) < 0) { + unmake_file(back_file); + back_file = NULL; + goto cleanup; + } + } + goto notify_others; + } + if (fuzzy_dirlist) { int j = flist_find(fuzzy_dirlist, file); if (j >= 0) /* don't use changing file as future fuzzy basis */ @@ -1628,9 +1691,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } /* open the file */ - fd = do_open(fnamecmp, O_RDONLY, 0); - - if (fd == -1) { + if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) { rsyserr(FERROR, errno, "failed to open %s, continuing", full_fname(fnamecmp)); pretend_missing: @@ -1658,14 +1719,17 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, rsyserr(FERROR, errno, "unlink %s", full_fname(backupptr)); unmake_file(back_file); + back_file = NULL; close(fd); goto cleanup; } - if ((f_copy = do_open(backupptr, - O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) { + if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0 + && (errno != ENOENT || make_bak_dir(backupptr) < 0 + || (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) { rsyserr(FERROR, errno, "open %s", full_fname(backupptr)); unmake_file(back_file); + back_file = NULL; close(fd); goto cleanup; } @@ -1720,15 +1784,17 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (read_batch) goto cleanup; - if (statret != 0 || whole_file) { + if (statret != 0 || whole_file) write_sum_head(f_out, NULL); - goto cleanup; + else { + generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy); + close(fd); } - generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy); - - if (f_copy >= 0) { - close(f_copy); + cleanup: + if (back_file) { + if (f_copy >= 0) + close(f_copy); set_file_attrs(backupptr, back_file, NULL, NULL, 0); if (verbose > 1) { rprintf(FINFO, "backed up %s to %s\n", @@ -1737,9 +1803,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, unmake_file(back_file); } - close(fd); - - cleanup: #ifdef SUPPORT_ACLS if (preserve_acls) free_acl(&sx); @@ -1768,7 +1831,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 +1919,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 */ } } @@ -1950,14 +2019,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); @@ -2039,7 +2100,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) {