X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/bb0d8edfadbe84135631491f41d4b7b0548d3365..b5c6a6aeeb7d526e023454ea681b7381945bced8:/generator.c diff --git a/generator.c b/generator.c index 1a22794b..b7aa8cfa 100644 --- a/generator.c +++ b/generator.c @@ -38,6 +38,7 @@ extern int relative_paths; extern int keep_dirlinks; extern int preserve_links; extern int preserve_devices; +extern int preserve_specials; extern int preserve_hard_links; extern int preserve_perms; extern int preserve_uid; @@ -83,7 +84,9 @@ extern int safe_symlinks; extern long block_size; /* "long" because popt can't set an int32. */ extern int max_delete; extern int force_delete; +extern int one_file_system; extern struct stats stats; +extern dev_t filesystem_dev; extern char *backup_dir; extern char *backup_suffix; extern int backup_suffix_len; @@ -215,7 +218,7 @@ static int delete_item(char *fname, int mode, int flags) * call will append names onto the end, but the old dir value will be restored * on exit). */ static void delete_in_dir(struct file_list *flist, char *fbuf, - struct file_struct *file) + struct file_struct *file, STRUCT_STAT *stp) { static int min_depth = MAXPATHLEN, cur_depth = -1; static void *filt_array[MAXPATHLEN/2+1]; @@ -258,8 +261,12 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, dlen = strlen(fbuf); filt_array[cur_depth] = push_local_filters(fbuf, dlen); - if (file->flags & FLAG_MOUNT_POINT) - return; + if (one_file_system) { + if (file->flags & FLAG_TOP_DIR) + filesystem_dev = stp->st_dev; + else if (filesystem_dev != stp->st_dev) + return; + } dirlist = get_dirlist(fbuf, dlen, 0); @@ -267,14 +274,8 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, * from the filesystem. */ for (i = dirlist->count; i--; ) { struct file_struct *fp = dirlist->files[i]; - if (!fp->basename) + if (!fp->basename || fp->flags & FLAG_MOUNT_POINT) continue; - if (fp->flags & FLAG_MOUNT_POINT) { - int j = flist_find(flist, fp); - if (j >= 0) - flist->files[j]->flags |= FLAG_MOUNT_POINT; - continue; - } if (flist_find(flist, fp) < 0) { int mode = fp->mode; f_name(fp, delbuf); @@ -311,9 +312,9 @@ static void do_delete_pass(struct file_list *flist) || !S_ISDIR(st.st_mode)) continue; - delete_in_dir(flist, fbuf, file); + delete_in_dir(flist, fbuf, file, &st); } - delete_in_dir(NULL, NULL, NULL); + delete_in_dir(NULL, NULL, NULL, NULL); if (do_progress && !am_server) rprintf(FINFO, " \r"); @@ -895,7 +896,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, rprintf(code, "%s/\n", fname); if (delete_during && f_out != -1 && !phase && dry_run < 2 && (file->flags & FLAG_DEL_HERE)) - delete_in_dir(the_file_list, fname, file); + delete_in_dir(the_file_list, fname, file, &st); return; } @@ -986,7 +987,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, return; } - if (am_root && preserve_devices && IS_DEVICE(file->mode)) { + if ((am_root && preserve_devices && IS_DEVICE(file->mode)) + || (preserve_specials && IS_SPECIAL(file->mode))) { if (statret != 0 && (basis_dir[0] != NULL && can_link_devices)) { if (try_dests_non(file, fname, ndx, itemizing, @@ -1007,7 +1009,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, && hard_link_check(file, ndx, fname, -1, &st, itemizing, code, HL_SKIP)) return; - if (!IS_DEVICE(st.st_mode)) + if ((IS_DEVICE(file->mode) && !IS_DEVICE(st.st_mode)) + || (IS_SPECIAL(file->mode) && !IS_SPECIAL(st.st_mode))) statret = -1; if (verbose > 2) { rprintf(FINFO,"mknod(%s,0%o,0x%x)\n", @@ -1366,7 +1369,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name) } recv_generator(NULL, NULL, 0, 0, 0, code, -1); if (delete_during) - delete_in_dir(NULL, NULL, NULL); + delete_in_dir(NULL, NULL, NULL, NULL); phase++; csum_length = SUM_LENGTH;