X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/ee1d11c495d0083afdad1725860bec7011e8377d..c70e07d9ac09da1f00c531bb9137347f516f88f9:/generator.c diff --git a/generator.c b/generator.c index f645bf75..0aae2707 100644 --- a/generator.c +++ b/generator.c @@ -108,10 +108,9 @@ static int delete_item(char *fname, int mode, int flags) int j, dlen, zap_dir, ok; void *save_filters; - if (max_delete && deletion_count >= max_delete) - return -1; - if (!S_ISDIR(mode)) { + if (max_delete && ++deletion_count > max_delete) + return 0; if (make_backups && (backup_dir || !is_backup_file(fname))) ok = make_backup(fname); else @@ -119,11 +118,12 @@ static int delete_item(char *fname, int mode, int flags) if (ok) { if (!(flags & DEL_TERSE)) log_delete(fname, mode); - deletion_count++; return 0; } - if (errno == ENOENT) + if (errno == ENOENT) { + deletion_count--; return 0; + } rsyserr(FERROR, errno, "delete_file: unlink %s failed", full_fname(fname)); return -1; @@ -131,7 +131,8 @@ static int delete_item(char *fname, int mode, int flags) zap_dir = (flags & DEL_FORCE_RECURSE || (force_delete && recurse)) && !(flags & DEL_NO_RECURSE); - if (dry_run && zap_dir) { + if ((max_delete && ++deletion_count > max_delete) + || (dry_run && zap_dir)) { ok = 0; errno = ENOTEMPTY; } else if (make_backups && !backup_dir && !is_backup_file(fname) @@ -142,17 +143,19 @@ static int delete_item(char *fname, int mode, int flags) if (ok) { if (!(flags & DEL_TERSE)) log_delete(fname, mode); - deletion_count++; return 0; } - if (errno == ENOENT) + if (errno == ENOENT) { + deletion_count--; return 0; + } if (!zap_dir || (errno != ENOTEMPTY && errno != EEXIST)) { rsyserr(FERROR, errno, "delete_file: rmdir %s failed", full_fname(fname)); return -1; } flags |= DEL_FORCE_RECURSE; /* mark subdir dels as not "in the way" */ + deletion_count--; dlen = strlcpy(buf, fname, MAXPATHLEN); save_filters = push_local_filters(buf, dlen); @@ -174,13 +177,12 @@ static int delete_item(char *fname, int mode, int flags) pop_local_filters(save_filters); - if (max_delete && deletion_count >= max_delete) - return -1; + if (max_delete && ++deletion_count > max_delete) + return 0; if (do_rmdir(fname) == 0) { if (!(flags & DEL_TERSE)) log_delete(fname, mode); - deletion_count++; } else if (errno != ENOTEMPTY && errno != ENOENT) { rsyserr(FERROR, errno, "delete_file: rmdir %s failed", full_fname(fname)); @@ -201,6 +203,7 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, { static int min_depth = MAXPATHLEN, cur_depth = -1; static void *filt_array[MAXPATHLEN/2+1]; + static int already_output_warning = 0; struct file_list *dirlist; char delbuf[MAXPATHLEN]; STRUCT_STAT st; @@ -223,13 +226,12 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, if (file->dir.depth >= MAXPATHLEN/2+1) return; /* Impossible... */ - if (max_delete && deletion_count >= max_delete) - return; - if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) { + if (already_output_warning) + return; rprintf(FINFO, "IO error encountered -- skipping file deletion\n"); - max_delete = -1; /* avoid duplicating the above warning */ + already_output_warning = 1; return; } @@ -272,6 +274,9 @@ static void do_delete_pass(struct file_list *flist) char fbuf[MAXPATHLEN]; int j; + if (dry_run > 1) /* destination doesn't exist yet */ + return; + for (j = 0; j < flist->count; j++) { struct file_struct *file = flist->files[j]; @@ -380,7 +385,7 @@ static int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st) * The block size is a rounded square root of file length. * * The checksum size is determined according to: - * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len) + * blocksum_bits = BLOCKSUM_BIAS + 2*log2(file_len) - log2(block_len) * provided by Donovan Baarda which gives a probability of rsync * algorithm corrupting data and falling back using the whole md4 * checksums. @@ -565,6 +570,8 @@ void check_for_finished_hlinks(int itemizing, enum logcode code) } } +static int phase = 0; + /* Acts on the_file_list->file's ndx'th item, whose name is fname. If a dir, * make sure it exists, and has the right permissions/timestamp info. For * all other non-regular files (symlinks, etc.) we create them here. For @@ -704,7 +711,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (set_perms(fname, file, statret ? NULL : &st, 0) && verbose && code && f_out != -1) rprintf(code, "%s/\n", safe_fname(fname)); - if (delete_during && f_out != -1 && csum_length != SUM_LENGTH + if (delete_during && f_out != -1 && !phase && dry_run < 2 && (file->flags & FLAG_DEL_HERE)) delete_in_dir(the_file_list, fname, file); return; @@ -1088,7 +1095,6 @@ void generate_files(int f_out, struct file_list *flist, char *local_name, int f_out_name) { int i, lull_mod; - int phase = 0; char fbuf[MAXPATHLEN]; int itemizing, maybe_PERMS_REPORT; enum logcode code; @@ -1140,24 +1146,28 @@ void generate_files(int f_out, struct file_list *flist, char *local_name, for (i = 0; i < flist->count; i++) { struct file_struct *file = flist->files[i]; - struct file_struct copy; if (!file->basename) continue; + recv_generator(local_name ? local_name : f_name_to(file, fbuf), + file, i, itemizing, maybe_PERMS_REPORT, code, + f_out, f_out_name); + /* 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. */ if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) { - copy = *file; - copy.mode |= S_IWUSR; /* user write */ - file = © + int mode = file->mode | S_IWUSR; /* user write */ + char *fname = local_name ? local_name : fbuf; + if (do_chmod(fname, mode & CHMOD_BITS) < 0) { + rsyserr(FERROR, errno, + "failed to modify permissions on %s", + full_fname(fname)); + } need_retouch_dir_perms = 1; } - recv_generator(local_name ? local_name : f_name_to(file, fbuf), - file, i, itemizing, maybe_PERMS_REPORT, code, - f_out, f_out_name); if (preserve_hard_links) check_for_finished_hlinks(itemizing, code); @@ -1229,6 +1239,13 @@ void generate_files(int f_out, struct file_list *flist, char *local_name, } recv_generator(NULL, NULL, 0, 0, 0, code, -1, -1); + if (max_delete > 0 && deletion_count > max_delete) { + rprintf(FINFO, + "Deletions stopped due to --max-delete limit (%d skipped)\n", + deletion_count - max_delete); + io_error |= IOERR_DEL_LIMIT; + } + if (verbose > 2) rprintf(FINFO,"generate_files finished\n"); }