The Samba-Bugzilla – Attachment 1955 Details for
Bug 3825
rsync won't delete directory with excluded files
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed changes to deletion, filters, etc.
delete-improvements.diff (text/plain), 25.60 KB, created by
Matt McCutchen
on 2006-06-11 15:00:29 UTC
(
hide
)
Description:
Proposed changes to deletion, filters, etc.
Filename:
MIME Type:
Creator:
Matt McCutchen
Created:
2006-06-11 15:00:29 UTC
Size:
25.60 KB
patch
obsolete
>Index: rsync.h >=================================================================== >RCS file: /cvsroot/rsync/rsync.h,v >retrieving revision 1.294 >diff -u -r1.294 rsync.h >--- rsync.h 5 Jun 2006 16:52:34 -0000 1.294 >+++ rsync.h 11 Jun 2006 19:55:50 -0000 >@@ -67,7 +67,7 @@ > #define FLAG_MISSING (1<<6) /* generator */ > > /* update this if you make incompatible changes */ >-#define PROTOCOL_VERSION 29 >+#define PROTOCOL_VERSION 30 > > /* We refuse to interoperate with versions that are not in this range. > * Note that we assume we'll work with later versions: the onus is on >@@ -153,6 +153,8 @@ > /* These are outside the range of the transmitted flags. */ > #define ITEM_MISSING_DATA (1<<16) /* used by log_formatted() */ > #define ITEM_DELETED (1<<17) /* used by log_formatted() */ >+#define ITEM_PINNED (1<<18) /* used by log_formatted() */ >+#define ITEM_HIT_MAX_DELETE (1<<19) /* used by log_formatted() */ > > #define SIGNIFICANT_ITEM_FLAGS (~(\ > ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE)) >@@ -608,6 +610,7 @@ > #define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */ > #define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */ > #define MATCHFLG_CLEAR_LIST (1<<18)/* this item is the "!" token */ >+#define MATCHFLG_PARENT_PROTECT (1<<19)/* matching files perish with their parents (modifies P) */ > > #define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \ > | MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \ >Index: generator.c >=================================================================== >RCS file: /cvsroot/rsync/generator.c,v >retrieving revision 1.283 >diff -u -r1.283 generator.c >--- generator.c 5 Jun 2006 16:56:50 -0000 1.283 >+++ generator.c 11 Jun 2006 19:55:47 -0000 >@@ -94,9 +94,10 @@ > > static int deletion_count = 0; /* used to implement --max-delete */ > >-/* For calling delete_file() */ >-#define DEL_FORCE_RECURSE (1<<1) /* recurse even w/o --force */ >-#define DEL_TERSE (1<<3) >+/* For calling delete_item() */ >+#define DEL_PARENT_EXTRANEOUS (1<<0) /* parent-protect filters include */ >+#define DEL_RECURSE (1<<1) /* recurse */ >+#define DEL_REPLACE (1<<3) /* file will be replaced */ > > > static int is_backup_file(char *fn) >@@ -105,73 +106,36 @@ > return k > 0 && strcmp(fn+k, backup_suffix) == 0; > } > >+/* Declare here so empty_directory can call it */ >+static int delete_item(char *fname, int mode, int flags); > >-/* Delete a file or directory. If DEL_FORCE_RECURSE is set in the flags, or if >- * force_delete is set, this will delete recursively. >- * >- * Note that fname must point to a MAXPATHLEN buffer if the mode indicates it's >- * a directory! (The buffer is used for recursion, but returned unchanged.) >+/* The directory should be deleted. If DEL_RECURSE is given, delete unpinned >+ * files recursively and then signal whether the directory is pinned. If not, >+ * merely signal whether the directory is empty. >+ * >+ * Returns: 0 if OK, -3 if pinned, -4 if nonempty. > */ >-static int delete_item(char *fname, int mode, int flags) >+static int empty_directory(char *fname, int flags) > { > struct file_list *dirlist; >- int j, dlen, zap_dir, ok; >+ int j, dlen, result; > unsigned remainder; > void *save_filters; > char *p; >- >- 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 >- ok = robust_unlink(fname) == 0; >- if (ok) { >- if (!(flags & DEL_TERSE)) >- log_delete(fname, mode); >- return 0; >- } >- if (errno == ENOENT) { >- deletion_count--; >- return 0; >- } >- rsyserr(FERROR, errno, "delete_file: unlink %s failed", >- full_fname(fname)); >- return -1; >- } >- >- zap_dir = flags & DEL_FORCE_RECURSE || force_delete; >- 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) >- && !(flags & DEL_FORCE_RECURSE)) >- ok = make_backup(fname); >- else >- ok = do_rmdir(fname) == 0; >- if (ok) { >- if (!(flags & DEL_TERSE)) >- log_delete(fname, mode); >- return 0; >- } >- if (errno == ENOENT) { >- deletion_count--; >- return 0; >- } >- if (!zap_dir) { >- 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--; >- >+ BOOL pinned = False; >+ > dlen = strlen(fname); > save_filters = push_local_filters(fname, dlen); > >- dirlist = get_dirlist(fname, dlen, 0); >+ dirlist = get_dirlist(fname, dlen, 0, &pinned); >+ >+ if (!pinned && dirlist->count == 0) { >+ result = 0; >+ goto out; >+ } else if (!(flags & DEL_RECURSE)) { >+ result = -4; >+ goto out; >+ } > > p = fname + dlen; > if (dlen != 1 || *fname != '/') >@@ -181,31 +145,105 @@ > for (j = dirlist->count; j--; ) { > struct file_struct *fp = dirlist->files[j]; > >- if (fp->flags & FLAG_MOUNT_POINT) >+ if (fp->flags & FLAG_MOUNT_POINT) { >+ pinned = True; >+ if (verbose > 1) >+ rprintf(FINFO, "mount point %s pins parent directory\n", >+ f_name(fp, NULL)); > continue; >+ } > > strlcpy(p, fp->basename, remainder); >- delete_item(fname, fp->mode, flags & ~DEL_TERSE); >+ result = delete_item(fname, fp->mode, >+ (flags | DEL_PARENT_EXTRANEOUS) & ~DEL_REPLACE); >+ /* as long as nothing is pinned, we can ignore deletion errors; >+ * if the filesystem lets us rmdir anyway, great, otherwise we >+ * get ENOTEMPTY and can handle it there */ >+ if (result == -3) { >+ pinned = True; >+ if (verbose > 1) >+ rprintf(FINFO, "pinned directory %s pins parent directory\n", >+ f_name(fp, NULL)); >+ } > } >- flist_free(dirlist); > > fname[dlen] = '\0'; >+ >+ if (pinned) >+ result = -3; >+ else >+ result = 0; > >+out: > pop_local_filters(save_filters); >+ flist_free(dirlist); >+ return result; >+} > >- if (max_delete && ++deletion_count > max_delete) >- return 0; >+/* Delete a file or directory. If DEL_RECURSE is set in the flags, this will >+ * delete recursively. >+ * >+ * Note that fname must point to a MAXPATHLEN buffer if the mode indicates it's >+ * a directory! (The buffer is used for recursion, but returned unchanged.) >+ * >+ * Returns: 0 on success, -1 on failure, -2 if deletion limit hit, -3 if pinned, >+ * -4 if nonempty. >+ */ >+static int delete_item(char *fname, int mode, int flags) >+{ >+ int ok, result; >+ char *what; >+ >+ if (verbose > 2) >+ rprintf(FINFO, "delete_item %s mode %o flags %d\n", >+ fname, mode, flags); >+ >+ if (S_ISDIR(mode)) { >+ result = empty_directory(fname, flags); >+ if (result == -3) { >+ if (!(flags & DEL_REPLACE)) >+ log_pinned(fname, mode); >+ return -3; >+ } else if (result == -4) { >+ rprintf(FINFO, "nonempty directory %s not deleted " >+ "because --force not given\n", fname); >+ return -4; >+ } >+ /* otherwise try to delete the directory */ >+ } >+ >+ if (!(flags & DEL_REPLACE)) { >+ if (max_delete >= 0 && ++deletion_count > max_delete) { >+ log_hit_max_delete(fname, mode); >+ return -2; >+ } >+ } > >- if (do_rmdir(fname) == 0) { >- if (!(flags & DEL_TERSE)) >+ if (S_ISDIR(mode)) { >+ what = "rmdir"; >+ ok = do_rmdir(fname) == 0; >+ } else { >+ if (make_backups && (backup_dir || !is_backup_file(fname))) { >+ what = "make_backup"; >+ ok = make_backup(fname); >+ } else { >+ what = "unlink"; >+ ok = robust_unlink(fname) == 0; >+ } >+ } >+ >+ if (ok) { >+ if (!(flags & DEL_REPLACE)) > log_delete(fname, mode); >- } else if (errno != ENOTEMPTY && errno != EEXIST && errno != ENOENT) { >- rsyserr(FERROR, errno, "delete_file: rmdir %s failed", >- full_fname(fname)); >+ return 0; >+ } else if (errno == ENOENT) { >+ --deletion_count; >+ return 0; >+ } else { >+ rsyserr(FERROR, errno, "delete_file: %s %s failed", >+ what, full_fname(fname)); > return -1; > } >- >- return 0; > } > > >@@ -265,17 +303,23 @@ > return; > } > >- dirlist = get_dirlist(fbuf, dlen, 0); >+ dirlist = get_dirlist(fbuf, dlen, 0, NULL); > > /* If an item in dirlist is not found in flist, delete it > * from the filesystem. */ > for (i = dirlist->count; i--; ) { > struct file_struct *fp = dirlist->files[i]; >- if (!fp->basename || fp->flags & FLAG_MOUNT_POINT) >+ if (!fp->basename) > continue; >+ if (fp->flags & FLAG_MOUNT_POINT) { >+ if (verbose > 1) >+ rprintf(FINFO, "mount point %s not deleted\n", >+ f_name(fp, NULL)); >+ continue; >+ } > if (flist_find(flist, fp) < 0) { > f_name(fp, delbuf); >- delete_item(delbuf, fp->mode, DEL_FORCE_RECURSE); >+ delete_item(delbuf, fp->mode, DEL_RECURSE); > } > } > >@@ -802,7 +846,8 @@ > char *fnamecmp, *partialptr, *backupptr = NULL; > char fnamecmpbuf[MAXPATHLEN]; > uchar fnamecmp_type; >- int del_opts = DEL_TERSE | (delete_mode ? DEL_FORCE_RECURSE : 0); >+ int del_opts = DEL_REPLACE | >+ (delete_mode || force_delete ? DEL_RECURSE : 0); > > if (list_only) > return; >@@ -875,7 +920,7 @@ > parent_dirname = dn; > > if (need_fuzzy_dirlist && S_ISREG(file->mode)) { >- fuzzy_dirlist = get_dirlist(dn, -1, 1); >+ fuzzy_dirlist = get_dirlist(dn, -1, 1, NULL); > need_fuzzy_dirlist = 0; > } > >@@ -908,8 +953,10 @@ > * we need to delete it. If it doesn't exist, then > * (perhaps recursively) create it. */ > if (statret == 0 && !S_ISDIR(st.st_mode)) { >- if (delete_item(fname, st.st_mode, del_opts) < 0) >+ if (delete_item(fname, st.st_mode, del_opts) < 0) { >+ rprintf(FERROR, "could not make way for new directory at %s\n", fname); > return; >+ } > statret = -1; > } > if (dry_run && statret != 0 && missing_below < 0) { >@@ -991,8 +1038,10 @@ > } > /* Not the right symlink (or not a symlink), so > * delete it. */ >- if (delete_item(fname, st.st_mode, del_opts) < 0) >+ if (delete_item(fname, st.st_mode, del_opts) < 0) { >+ rprintf(FERROR, "could not make way for new symlink at %s\n", fname); > return; >+ } > if (!S_ISLNK(st.st_mode)) > statret = -1; > } else if (basis_dir[0] != NULL) { >@@ -1056,8 +1105,10 @@ > || (st.st_mode & ~CHMOD_BITS) != (file->mode & ~CHMOD_BITS) > || st.st_rdev != file->u.rdev) { > if (statret == 0 >- && delete_item(fname, st.st_mode, del_opts) < 0) >+ && delete_item(fname, st.st_mode, del_opts) < 0) { >+ rprintf(FERROR, "could not make way for new device or special at %s\n", fname); > return; >+ } > if (preserve_hard_links && file->link_u.links > && hard_link_check(file, ndx, fname, -1, &st, > itemizing, code, HL_SKIP)) >@@ -1137,8 +1188,10 @@ > fnamecmp_type = FNAMECMP_FNAME; > > if (statret == 0 && !S_ISREG(st.st_mode)) { >- if (delete_item(fname, st.st_mode, del_opts) != 0) >+ if (delete_item(fname, st.st_mode, del_opts) < 0) { >+ rprintf(FERROR, "could not make way for new regular file at %s\n", fname); > return; >+ } > statret = -1; > stat_errno = ENOENT; > } >@@ -1254,7 +1307,7 @@ > close(fd); > return; > } >- if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) { >+ if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS, NULL))) { > close(fd); > goto pretend_missing; > } >@@ -1515,7 +1568,7 @@ > } > recv_generator(NULL, NULL, 0, 0, 0, code, -1); > >- if (max_delete > 0 && deletion_count > max_delete) { >+ if (max_delete >= 0 && deletion_count > max_delete) { > rprintf(FINFO, > "Deletions stopped due to --max-delete limit (%d skipped)\n", > deletion_count - max_delete); >Index: options.c >=================================================================== >RCS file: /cvsroot/rsync/options.c,v >retrieving revision 1.346 >diff -u -r1.346 options.c >--- options.c 7 Jun 2006 23:05:24 -0000 1.346 >+++ options.c 11 Jun 2006 19:55:49 -0000 >@@ -106,7 +106,7 @@ > int ignore_existing = 0; > int ignore_non_existing = 0; > int need_messages_from_generator = 0; >-int max_delete = 0; >+int max_delete = -1; > OFF_T max_size = 0; > OFF_T min_size = 0; > int ignore_errors = 0; >@@ -1612,7 +1612,7 @@ > args[ac++] = arg; > } > >- if (max_delete && am_sender) { >+ if (max_delete >= 0 && am_sender) { > if (asprintf(&arg, "--max-delete=%d", max_delete) < 0) > goto oom; > args[ac++] = arg; >Index: compat.c >=================================================================== >RCS file: /cvsroot/rsync/compat.c,v >retrieving revision 1.34 >diff -u -r1.34 compat.c >--- compat.c 25 Apr 2006 23:51:12 -0000 1.34 >+++ compat.c 11 Jun 2006 19:55:44 -0000 >@@ -25,6 +25,7 @@ > int remote_protocol = 0; > > extern int verbose; >+extern int am_sender; > extern int am_server; > extern int inplace; > extern int fuzzy_basis; >@@ -32,6 +33,7 @@ > extern int checksum_seed; > extern int basis_dir_cnt; > extern int prune_empty_dirs; >+extern int max_delete; > extern int protocol_version; > extern char *dest_option; > >@@ -75,6 +77,16 @@ > exit_cleanup(RERR_PROTOCOL); > } > >+ if (protocol_version < 30) { >+ if (max_delete == 0 && am_sender) { >+ rprintf(FERROR, >+ "--max-delete=0 requires protocol 30 or higher" >+ " (negotiated %d).\n", >+ protocol_version); >+ exit_cleanup(RERR_PROTOCOL); >+ } >+ } >+ > if (protocol_version < 29) { > if (fuzzy_basis) { > rprintf(FERROR, >Index: flist.c >=================================================================== >RCS file: /cvsroot/rsync/flist.c,v >retrieving revision 1.349 >diff -u -r1.349 flist.c >--- flist.c 9 May 2006 18:31:13 -0000 1.349 >+++ flist.c 11 Jun 2006 19:55:46 -0000 >@@ -201,13 +201,16 @@ > > /* This function is used to check if a file should be included/excluded > * from the list of files based on its name and type etc. The value of >- * filter_level is set to either SERVER_FILTERS or ALL_FILTERS. */ >-static int is_excluded(char *fname, int is_dir, int filter_level) >+ * filter_level is set to either SERVER_FILTERS or ALL_FILTERS. If >+ * parent_extraneous is true, parent-protect counts as included. */ >+static int is_excluded(char *fname, int is_dir, int filter_level, >+ BOOL parent_extraneous) > { > #if 0 /* This currently never happens, so avoid a useless compare. */ > if (filter_level == NO_FILTERS) > return 0; > #endif >+ int fresult; > if (fname) { > /* never exclude '.', even if somebody does --exclude '*' */ > if (fname[0] == '.' && !fname[1]) >@@ -220,12 +223,14 @@ > } > } > if (server_filter_list.head >- && check_filter(&server_filter_list, fname, is_dir) < 0) >+ && (fresult = check_filter(&server_filter_list, fname, is_dir)) < 0 >+ && (!parent_extraneous || fresult != -2)) > return 1; > if (filter_level != ALL_FILTERS) > return 0; > if (filter_list.head >- && check_filter(&filter_list, fname, is_dir) < 0) >+ && (fresult = check_filter(&filter_list, fname, is_dir)) < 0 >+ && (!parent_extraneous || fresult != -2)) > return 1; > return 0; > } >@@ -247,7 +252,7 @@ > } > > static void send_directory(int f, struct file_list *flist, >- char *fbuf, int len); >+ char *fbuf, int len, BOOL *pinned); > > static char *flist_dir; > static int flist_dir_len; >@@ -713,7 +718,7 @@ > **/ > struct file_struct *make_file(char *fname, struct file_list *flist, > STRUCT_STAT *stp, unsigned short flags, >- int filter_level) >+ int filter_level, BOOL *protected_p) > { > static char *lastdir; > static int lastdir_len = -1; >@@ -724,6 +729,7 @@ > char linkname[MAXPATHLEN]; > int alloc_len, basename_len, dirname_len, linkname_len, sum_len; > char *basename, *dirname, *bp; >+ BOOL excluded; > > if (!flist || !flist->count) /* Ignore lastdir when invalid. */ > lastdir_len = -1; >@@ -745,8 +751,12 @@ > int save_errno = errno; > /* See if file is excluded before reporting an error. */ > if (filter_level != NO_FILTERS >- && is_excluded(thisname, 0, filter_level)) >+ && is_excluded(thisname, 0, filter_level, protected_p != NULL) >+ && is_excluded(thisname, 1, filter_level, protected_p != NULL)) { >+ if (protected_p) >+ *protected_p = True; > return NULL; >+ } > if (save_errno == ENOENT) { > #ifdef SUPPORT_LINKS > /* Avoid "vanished" error if symlink points nowhere. */ >@@ -796,7 +806,11 @@ > flags |= FLAG_MOUNT_POINT; > } > >- if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) >+ excluded = is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level, >+ protected_p != NULL); >+ if (protected_p) >+ *protected_p = excluded; >+ if (excluded) > return NULL; > > if (lp_ignore_nonreadable(module_id)) { >@@ -939,12 +953,12 @@ > > static struct file_struct *send_file_name(int f, struct file_list *flist, > char *fname, STRUCT_STAT *stp, >- unsigned short flags) >+ unsigned short flags, BOOL *protected_p) > { > struct file_struct *file; > > file = make_file(fname, flist, stp, flags, >- f == -2 ? SERVER_FILTERS : ALL_FILTERS); >+ f == -2 ? SERVER_FILTERS : ALL_FILTERS, protected_p); > if (!file) > return NULL; > >@@ -981,7 +995,7 @@ > return; > } > save_filters = push_local_filters(fbuf, len); >- send_directory(f, flist, fbuf, len); >+ send_directory(f, flist, fbuf, len, NULL); > pop_local_filters(save_filters); > fbuf[ol] = '\0'; > if (is_dot_dir) >@@ -995,13 +1009,14 @@ > * might call this with f set to -2, which also indicates that local filter > * rules should be ignored. */ > static void send_directory(int f, struct file_list *flist, >- char *fbuf, int len) >+ char *fbuf, int len, BOOL *pinned_p) > { > struct dirent *di; > unsigned remainder; > char *p; > DIR *d; > int start = flist->count; >+ BOOL protected; > > if (!(d = opendir(fbuf))) { > io_error |= IOERR_GENERAL; >@@ -1015,6 +1030,9 @@ > *p = '\0'; > remainder = MAXPATHLEN - (p - fbuf); > >+ if (pinned_p) >+ *pinned_p = False; >+ > for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) { > char *dname = d_name(di); > if (dname[0] == '.' && (dname[1] == '\0' >@@ -1028,7 +1046,17 @@ > continue; > } > >- send_file_name(f, flist, fbuf, NULL, 0); >+ if (pinned_p == NULL) >+ send_file_name(f, flist, fbuf, NULL, 0, NULL); >+ else { >+ send_file_name(f, flist, fbuf, NULL, 0, &protected); >+ if (protected) { >+ *pinned_p = True; >+ if (verbose > 1) >+ rprintf(FINFO, "protected file %s pins parent directory\n", >+ fbuf); >+ } >+ } > } > > fbuf[len] = '\0'; >@@ -1245,7 +1273,7 @@ > xfer_dirs = 1; > while ((slash = strchr(slash+1, '/')) != 0) { > *slash = '\0'; >- send_file_name(f, flist, fbuf, NULL, 0); >+ send_file_name(f, flist, fbuf, NULL, 0, NULL); > *slash = '/'; > } > copy_links = save_copy_links; >@@ -1261,11 +1289,11 @@ > > if (recurse || (xfer_dirs && is_dot_dir)) { > struct file_struct *file; >- file = send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR); >+ file = send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR, NULL); > if (file) > send_if_directory(f, flist, file, fbuf, len); > } else >- send_file_name(f, flist, fbuf, &st, 0); >+ send_file_name(f, flist, fbuf, &st, 0, NULL); > > if (olddir[0]) { > flist_dir = NULL; >@@ -1637,7 +1665,7 @@ > } > prev_depth = file->dir.depth; > if (is_excluded(f_name(file, fbuf), 1, >- ALL_FILTERS)) { >+ ALL_FILTERS, False)) { > /* Keep dirs through this dir. */ > for (j = prev_depth-1; ; j--) { > fp = flist->files[prev_i]; >@@ -1889,9 +1917,10 @@ > * exclude rules except for the daemon's. If "dlen" is >=0, it is the length > * of the dirname string, and also indicates that "dirname" is a MAXPATHLEN > * buffer (the functions we call will append names onto the end, but the old >- * dir value will be restored on exit). */ >+ * dir value will be restored on exit). If pinned is not NULL, store in >+ * *pinned whether the directory is pinned by a protected file. */ > struct file_list *get_dirlist(char *dirname, int dlen, >- int ignore_filter_rules) >+ int ignore_filter_rules, BOOL *pinned) > { > struct file_list *dirlist; > char dirbuf[MAXPATHLEN]; >@@ -1909,7 +1938,7 @@ > > recurse = 0; > xfer_dirs = 1; >- send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen); >+ send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, pinned); > xfer_dirs = save_xfer_dirs; > recurse = save_recurse; > if (do_progress) >Index: backup.c >=================================================================== >RCS file: /cvsroot/rsync/backup.c,v >retrieving revision 1.56 >diff -u -r1.56 backup.c >--- backup.c 25 Apr 2006 23:51:12 -0000 1.56 >+++ backup.c 11 Jun 2006 19:55:44 -0000 >@@ -180,7 +180,7 @@ > if (do_lstat(fname, &st) < 0) > return 1; > >- if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) >+ if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS, NULL))) > return 1; /* the file could have disappeared */ > > if (!(buf = get_backup_name(fname))) >Index: log.c >=================================================================== >RCS file: /cvsroot/rsync/log.c,v >retrieving revision 1.155 >diff -u -r1.155 log.c >--- log.c 7 Jun 2006 23:05:17 -0000 1.155 >+++ log.c 11 Jun 2006 19:55:48 -0000 >@@ -581,6 +581,14 @@ > n = "*deleting"; > break; > } >+ if (iflags & ITEM_PINNED) { >+ n = "*pinned "; >+ break; >+ } >+ if (iflags & ITEM_HIT_MAX_DELETE) { >+ n = "*maxdel "; >+ break; >+ } > n = buf2 + MAXPATHLEN - 32; > n[0] = iflags & ITEM_LOCAL_CHANGE > ? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c' >@@ -742,6 +750,52 @@ > log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL); > } > >+void log_pinned(char *fname, int mode) >+{ >+ static struct file_struct file; >+ char *fmt; >+ >+ file.mode = mode; >+ file.basename = fname; >+ >+ if (!verbose && !stdout_format) >+ ; >+ else { >+ fmt = stdout_format_has_o_or_i ? stdout_format : "%n is pinned"; >+ log_formatted(FCLIENT, fmt, "pin ", &file, &stats, >+ ITEM_PINNED, NULL); >+ } >+ >+ if (!logfile_name || dry_run || !logfile_format) >+ return; >+ >+ fmt = logfile_format_has_o_or_i ? logfile_format : "%n is pinned"; >+ log_formatted(FLOG, fmt, "pin ", &file, &stats, ITEM_PINNED, NULL); >+} >+ >+void log_hit_max_delete(char *fname, int mode) >+{ >+ static struct file_struct file; >+ char *fmt; >+ >+ file.mode = mode; >+ file.basename = fname; >+ >+ if (!verbose && !stdout_format) >+ ; >+ else { >+ fmt = stdout_format_has_o_or_i ? stdout_format : "%n is over --max-delete"; >+ log_formatted(FCLIENT, fmt, "mdel", &file, &stats, >+ ITEM_HIT_MAX_DELETE, NULL); >+ } >+ >+ if (!logfile_name || dry_run || !logfile_format) >+ return; >+ >+ fmt = logfile_format_has_o_or_i ? logfile_format : "%n is over --max-delete"; >+ log_formatted(FLOG, fmt, "mdel", &file, &stats, ITEM_HIT_MAX_DELETE, NULL); >+} >+ > /* > * Called when the transfer is interrupted for some reason. > * >Index: proto.h >=================================================================== >RCS file: /cvsroot/rsync/proto.h,v >retrieving revision 1.307 >diff -u -r1.307 proto.h >--- proto.h 7 Jun 2006 23:05:11 -0000 1.307 >+++ proto.h 11 Jun 2006 19:55:49 -0000 >@@ -72,7 +72,7 @@ > void flist_expand(struct file_list *flist); > struct file_struct *make_file(char *fname, struct file_list *flist, > STRUCT_STAT *stp, unsigned short flags, >- int filter_level); >+ int filter_level, BOOL *protected_p); > struct file_list *send_file_list(int f, int argc, char *argv[]); > struct file_list *recv_file_list(int f); > int flist_find(struct file_list *flist, struct file_struct *f); >@@ -82,7 +82,7 @@ > int f_name_cmp(struct file_struct *f1, struct file_struct *f2); > char *f_name(struct file_struct *f, char *fbuf); > struct file_list *get_dirlist(char *dirname, int dlen, >- int ignore_filter_rules); >+ int ignore_filter_rules, BOOL *pinned); > int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st); > void itemize(struct file_struct *file, int ndx, int statret, STRUCT_STAT *st, > int32 iflags, uchar fnamecmp_type, char *xname); >@@ -197,6 +197,8 @@ > void maybe_log_item(struct file_struct *file, int iflags, int itemizing, > char *buf); > void log_delete(char *fname, int mode); >+void log_pinned(char *fname, int mode); >+void log_hit_max_delete(char *fname, int mode); > void log_exit(int code, const char *file, int line); > pid_t wait_process(pid_t pid, int *status_ptr, int flags); > int child_main(int argc, char *argv[]); >Index: exclude.c >=================================================================== >RCS file: /cvsroot/rsync/exclude.c,v >retrieving revision 1.134 >diff -u -r1.134 exclude.c >--- exclude.c 11 May 2006 07:54:33 -0000 1.134 >+++ exclude.c 11 Jun 2006 19:55:45 -0000 >@@ -51,8 +51,8 @@ > #define MAX_RULE_PREFIX (16) > > #define MODIFIERS_MERGE_FILE "-+Cenw" >-#define MODIFIERS_INCL_EXCL "/!Crs" >-#define MODIFIERS_HIDE_PROTECT "/!" >+#define MODIFIERS_INCL_EXCL "/!Crsp" >+#define MODIFIERS_HIDE_PROTECT "/!p" > > /* The dirbuf is set by push_local_filters() to the current subdirectory > * relative to curr_dir that is being processed. The path always has a >@@ -595,7 +595,8 @@ > > /* > * Return -1 if file "name" is defined to be excluded by the specified >- * exclude list, 1 if it is included, and 0 if it was not matched. >+ * exclude list, -2 if it is excluded but parent protected, 1 if it is included, >+ * and 0 if it was not matched. > */ > int check_filter(struct filter_list_struct *listp, char *name, int name_is_dir) > { >@@ -619,7 +620,8 @@ > if (rule_matches(name, ent, name_is_dir)) { > report_filter_result(name, ent, name_is_dir, > listp->debug_type); >- return ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1; >+ return ent->match_flags & MATCHFLG_PARENT_PROTECT ? -2 : >+ ent->match_flags & MATCHFLG_INCLUDE ? 1 : -1; > } > } > >@@ -809,6 +811,13 @@ > case 'n': > new_mflags |= MATCHFLG_NO_INHERIT; > break; >+ case 'p': >+ if (new_mflags & MATCHFLG_INCLUDE >+ || new_mflags & MATCHFLG_SENDER_SIDE >+ || (delete_excluded && !(new_mflags & MATCHFLG_RECEIVER_SIDE))) >+ goto invalid; >+ new_mflags |= MATCHFLG_PARENT_PROTECT; >+ break; > case 'r': > new_mflags |= MATCHFLG_RECEIVER_SIDE; > break; >@@ -1079,6 +1088,12 @@ > && (!for_xfer || protocol_version >= 29 > || (delete_excluded && am_sender))) > *op++ = 'r'; >+ if (match_flags & MATCHFLG_PARENT_PROTECT) { >+ if (!for_xfer || protocol_version >= 30) >+ *op++ = 'p'; >+ else if (am_sender) >+ return NULL; >+ } > if (op - buf > legal_len) > return NULL; > if (legal_len) >@@ -1124,7 +1139,7 @@ > if (!p) { > rprintf(FERROR, > "filter rules are too modern for remote rsync.\n"); >- exit_cleanup(RERR_SYNTAX); >+ exit_cleanup(RERR_PROTOCOL); > } > if (f_out < 0) > continue;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 3825
:
1955
|
1977
|
2052