X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/b8595e609a45f703de523a1022fada376141e5d3..b5c6a6aeeb7d526e023454ea681b7381945bced8:/generator.c diff --git a/generator.c b/generator.c index afa56a2a..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; @@ -217,14 +218,13 @@ 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]; static int already_warned = 0; struct file_list *dirlist; char delbuf[MAXPATHLEN]; - STRUCT_STAT st; int dlen, i; if (!flist) { @@ -261,13 +261,10 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, dlen = strlen(fbuf); filt_array[cur_depth] = push_local_filters(fbuf, dlen); - if (link_stat(fbuf, &st, keep_dirlinks) < 0 || !S_ISDIR(st.st_mode)) - return; - if (one_file_system) { if (file->flags & FLAG_TOP_DIR) - filesystem_dev = st.st_dev; - else if (filesystem_dev != st.st_dev) + filesystem_dev = stp->st_dev; + else if (filesystem_dev != stp->st_dev) return; } @@ -294,6 +291,7 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, static void do_delete_pass(struct file_list *flist) { char fbuf[MAXPATHLEN]; + STRUCT_STAT st; int j; if (dry_run > 1 /* destination doesn't exist yet */ @@ -310,9 +308,13 @@ static void do_delete_pass(struct file_list *flist) if (verbose > 1 && file->flags & FLAG_TOP_DIR) rprintf(FINFO, "deleting in %s\n", fbuf); - delete_in_dir(flist, fbuf, file); + if (link_stat(fbuf, &st, keep_dirlinks) < 0 + || !S_ISDIR(st.st_mode)) + continue; + + 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"); @@ -360,7 +362,7 @@ void itemize(struct file_struct *file, int ndx, int statret, STRUCT_STAT *st, iflags &= 0xffff; if ((iflags & SIGNIFICANT_ITEM_FLAGS || verbose > 1 - || (xname && *xname)) && !read_batch) { + || log_format_has_i > 1 || (xname && *xname)) && !read_batch) { if (protocol_version >= 29) { if (ndx >= 0) write_int(sock_f_out, ndx); @@ -715,10 +717,12 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, || !unchanged_attrs(file, &st)) continue; if (S_ISLNK(file->mode)) { +#ifdef SUPPORT_LINKS if ((len = readlink(fnamebuf, lnk, MAXPATHLEN-1)) <= 0) continue; lnk[len] = '\0'; if (strcmp(lnk, file->u.link) != 0) +#endif continue; } else { if (!IS_DEVICE(st.st_mode) || st.st_rdev != file->u.rdev) @@ -892,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; } @@ -983,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, @@ -1004,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", @@ -1195,7 +1201,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, close(fd); return; } - if (!(back_file = make_file(fname, NULL, NO_FILTERS))) { + if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) { close(fd); goto pretend_missing; } @@ -1267,7 +1273,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, close(fd); } - void generate_files(int f_out, struct file_list *flist, char *local_name) { int i; @@ -1364,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; @@ -1430,6 +1435,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name) * modified-time values. */ for (i = 0; i < flist->count; i++) { struct file_struct *file = flist->files[i]; + if (!file->basename || !S_ISDIR(file->mode)) continue; if (!need_retouch_dir_times && file->mode & S_IWUSR)