X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/f1773e09ab4993014f9cae0b80a569c2670624da..f8057304930f9c6dcb7fca57f3c25cc2c09b3c1d:/flist.c diff --git a/flist.c b/flist.c index a95a3d9c..ed26bb8b 100644 --- a/flist.c +++ b/flist.c @@ -522,7 +522,7 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags, static gid_t gid; static char lastname[MAXPATHLEN], *lastdir; static int lastdir_depth, lastdir_len = -1; - static unsigned int del_heir_name_len = 0; + static unsigned int del_hier_name_len = 0; static int in_del_hier = 0; char thisname[MAXPATHLEN]; unsigned int l1 = 0, l2 = 0; @@ -646,11 +646,11 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags, if (S_ISDIR(mode)) { if (flags & XMIT_DEL_START) { in_del_hier = 1; - del_heir_name_len = l1 + l2; + del_hier_name_len = l1 + l2; file->flags |= FLAG_DEL_START; } else if (delete_during && in_del_hier) { - if (!relative_paths || (l1 >= del_heir_name_len - && thisname[del_heir_name_len] == '/')) + if (!relative_paths || (l1 >= del_hier_name_len + && thisname[del_hier_name_len] == '/')) file->flags |= FLAG_DEL_START; else in_del_hier = 0; @@ -1008,7 +1008,7 @@ void send_file_name(int f, struct file_list *flist, char *fname, /* Note that the "recurse" value either contains -1, for infinite recursion, * or a number >= 0 indicating how many levels of recursion we will allow. */ static void send_directory(int f, struct file_list *flist, - char *fbuf, unsigned int dirlen) + char *fbuf, unsigned int len) { struct dirent *di; char *p; @@ -1020,8 +1020,8 @@ static void send_directory(int f, struct file_list *flist, return; } - p = fbuf + dirlen; - if (dirlen != 1 || *fbuf != '/') + p = fbuf + len; + if (len != 1 || *fbuf != '/') *p++ = '/'; *p = '\0'; @@ -1030,7 +1030,7 @@ static void send_directory(int f, struct file_list *flist, if (dname[0] == '.' && (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))) continue; - if (strlcpy(p, dname, MAXPATHLEN - dirlen) < MAXPATHLEN - dirlen) { + if (strlcpy(p, dname, MAXPATHLEN - len) < MAXPATHLEN - len) { int do_subdirs = recurse >= 1 ? recurse-- : recurse; send_file_name(f, flist, fbuf, do_subdirs, 0); } else { @@ -1669,40 +1669,82 @@ static int is_backup_file(char *fn) /* This function is used to implement --delete-during. */ void delete_in_dir(struct file_list *flist, char *fname) { + static void *filt_array[MAXPATHLEN/2]; + static BOOL need_first_push = True; + static int fa_lvl = 0; + static char fbuf[MAXPATHLEN]; struct file_list *dir_list; - char dirbuf[MAXPATHLEN]; - void *save_filters; STRUCT_STAT st; - int dirlen; + int dlen, j; + + if (!flist) { + while (fa_lvl) + pop_local_filters(filt_array[--fa_lvl]); + need_first_push = True; + *fbuf = '\0'; + return; + } if (max_delete && deletion_count >= max_delete) return; if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) { rprintf(FINFO, - "IO error encountered - skipping file deletion\n"); + "IO error encountered -- skipping file deletion\n"); max_delete = -1; /* avoid duplicating the above warning */ return; } + for (j = 0; fbuf[j]; j++) { + if (fbuf[j] != fname[j]) { + while (fa_lvl) { + if (fbuf[j] == '/') + pop_local_filters(filt_array[--fa_lvl]); + if (!fbuf[++j]) + break; + } + break; + } + } + + dlen = strlcpy(fbuf, fname, MAXPATHLEN); + if (need_first_push) { + if (dlen != 1 || fbuf[0] != '.') { + char *s = strrchr(fbuf, '/'); + int first_dlen; + if (s) + first_dlen = s - fbuf; + else + first_dlen = 0; + if (!s || s[1] != '.' || s[2] != '\0') { + filt_array[fa_lvl++] = push_local_filters(fbuf, + first_dlen); + } + } + need_first_push = False; + } + + if (dlen >= MAXPATHLEN - 1) + return; + if (fa_lvl >= MAXPATHLEN/2) + return; /* impossible... */ + if (link_stat(fname, &st, keep_dirlinks) < 0) return; if (one_file_system) filesystem_dev = st.st_dev; - dirlen = strlcpy(dirbuf, fname, MAXPATHLEN); - if (dirlen >= MAXPATHLEN - 1) - return; - dir_list = flist_new(WITHOUT_HLINK, "delete_in_dir"); recurse = 0; - save_filters = push_local_filters(dirbuf, dirlen); - send_directory(-1, dir_list, dirbuf, dirlen); - pop_local_filters(save_filters); + filt_array[fa_lvl++] = push_local_filters(fbuf, dlen); + send_directory(-1, dir_list, fbuf, dlen); recurse = -1; + if (dlen == 1 && *fbuf == '.') + *fbuf = '\0'; + clean_flist(dir_list, 0, 0); if (verbose > 3)