--- embedaddon/rsync/delete.c 2016/11/01 09:54:32 1.1.1.2 +++ embedaddon/rsync/delete.c 2021/03/17 00:32:36 1.1.1.3 @@ -4,7 +4,7 @@ * Copyright (C) 1996-2000 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2002 Martin Pool - * Copyright (C) 2003-2015 Wayne Davison + * Copyright (C) 2003-2020 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,25 +25,35 @@ extern int am_root; extern int make_backups; extern int max_delete; +extern int detect_renamed; extern char *backup_dir; extern char *backup_suffix; extern int backup_suffix_len; +extern char *backup_dir_dels; +extern char *backup_suffix_dels; +extern int backup_suffix_dels_len; extern struct stats stats; int ignore_perishable = 0; int non_perishable_cnt = 0; int skipped_deletes = 0; +/* Function now compares both backup_suffix and backup_suffix_dels. */ static inline int is_backup_file(char *fn) { int k = strlen(fn) - backup_suffix_len; - return k > 0 && strcmp(fn+k, backup_suffix) == 0; + if (k > 0 && strcmp(fn+k, backup_suffix) == 0) + return 1; + k += backup_suffix_len - backup_suffix_dels_len; + return k > 0 && strcmp(fn+k, backup_suffix_dels) == 0; } /* The directory is about to be deleted: if DEL_RECURSE is given, delete all * its contents, otherwise just checks for content. Returns DR_SUCCESS or * DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The * buffer is used for recursion, but returned unchanged.) + * + * Note: --detect-rename may use this routine with DEL_NO_DELETIONS set! */ static enum delret delete_dir_contents(char *fname, uint16 flags) { @@ -63,7 +73,9 @@ static enum delret delete_dir_contents(char *fname, ui save_filters = push_local_filters(fname, dlen); non_perishable_cnt = 0; + file_extra_cnt += SUM_EXTRA_CNT; dirlist = get_dirlist(fname, dlen, 0); + file_extra_cnt -= SUM_EXTRA_CNT; ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS; if (!dirlist->used) @@ -89,21 +101,26 @@ static enum delret delete_dir_contents(char *fname, ui if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) { if (DEBUG_GTE(DEL, 1)) { rprintf(FINFO, - "mount point, %s, pins parent directory\n", - f_name(fp, NULL)); + "mount point, %s, pins parent directory\n", + f_name(fp, NULL)); } ret = DR_NOT_EMPTY; continue; } strlcpy(p, fp->basename, remainder); +#ifdef SUPPORT_FORCE_CHANGE + if (force_change) + make_mutable(fname, fp->mode, F_FFLAGS(fp), force_change); +#endif if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US) - do_chmod(fname, fp->mode | S_IWUSR); + do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS); /* Save stack by recursing to ourself directly. */ if (S_ISDIR(fp->mode)) { if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS) ret = DR_NOT_EMPTY; - } + } else if (detect_renamed && S_ISREG(fp->mode)) + look_for_rename(fp, fname); if (delete_item(fname, fp->mode, flags) != DR_SUCCESS) ret = DR_NOT_EMPTY; } @@ -126,6 +143,8 @@ static enum delret delete_dir_contents(char *fname, ui * * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's * a directory! (The buffer is used for recursion, but returned unchanged.) + * + * Also note: --detect-rename may use this routine with DEL_NO_DELETIONS set! */ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) { @@ -139,11 +158,18 @@ enum delret delete_item(char *fbuf, uint16 mode, uint1 } if (flags & DEL_NO_UID_WRITE) - do_chmod(fbuf, mode | S_IWUSR); + do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS); if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) { /* This only happens on the first call to delete_item() since * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */ +#ifdef SUPPORT_FORCE_CHANGE + if (force_change) { + STRUCT_STAT st; + if (x_lstat(fbuf, &st, NULL) == 0) + make_mutable(fbuf, st.st_mode, st.st_flags, force_change); + } +#endif ignore_perishable = 1; /* If DEL_RECURSE is not set, this just reports emptiness. */ ret = delete_dir_contents(fbuf, flags); @@ -153,6 +179,9 @@ enum delret delete_item(char *fbuf, uint16 mode, uint1 /* OK: try to delete the directory. */ } + if (flags & DEL_NO_DELETIONS) + return DR_SUCCESS; + if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && stats.deleted_files >= max_delete) { skipped_deletes++; return DR_AT_LIMIT; @@ -162,9 +191,9 @@ enum delret delete_item(char *fbuf, uint16 mode, uint1 what = "rmdir"; ok = do_rmdir(fbuf) == 0; } else { - if (make_backups > 0 && !(flags & DEL_FOR_BACKUP) && (backup_dir || !is_backup_file(fbuf))) { + if (make_backups > 0 && !(flags & DEL_FOR_BACKUP) && (backup_dir_dels || !is_backup_file(fbuf))) { what = "make_backup"; - ok = make_backup(fbuf, True); + ok = safe_delete(fbuf); if (ok == 2) { what = "unlink"; ok = robust_unlink(fbuf) == 0;