--- embedaddon/rsync/backup.c 2016/11/01 09:54:32 1.1.1.3 +++ embedaddon/rsync/backup.c 2021/03/17 00:32:36 1.1.1.4 @@ -2,7 +2,7 @@ * Backup handling code. * * Copyright (C) 1999 Andrew Tridgell - * 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 @@ -29,25 +29,32 @@ extern int preserve_specials; extern int preserve_links; extern int safe_symlinks; extern int backup_dir_len; +extern int backup_dir_dels_len; extern unsigned int backup_dir_remainder; +extern unsigned int backup_dir_dels_remainder; extern char backup_dir_buf[MAXPATHLEN]; +extern char backup_dir_dels_buf[MAXPATHLEN]; extern char *backup_suffix; +extern char *backup_suffix_dels; extern char *backup_dir; +extern char *backup_dir_dels; +static BOOL deleting; + /* Returns -1 on error, 0 on missing dir, and 1 on present dir. */ -static int validate_backup_dir(void) +static int validate_backup_dir(char *buf) { STRUCT_STAT st; - if (do_lstat(backup_dir_buf, &st) < 0) { + if (do_lstat(buf, &st) < 0) { if (errno == ENOENT) return 0; - rsyserr(FERROR, errno, "backup lstat %s failed", backup_dir_buf); + rsyserr(FERROR, errno, "backup lstat %s failed", buf); return -1; } if (!S_ISDIR(st.st_mode)) { int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE; - if (delete_item(backup_dir_buf, st.st_mode, flags) == 0) + if (delete_item(buf, st.st_mode, flags) == 0) return 0; return -1; } @@ -58,20 +65,20 @@ static int validate_backup_dir(void) * backup_dir_buf. Any new directories (compared to the prior backup * path) are ensured to exist as directories, replacing anything else * that may be in the way (e.g. a symlink). */ -static BOOL copy_valid_path(const char *fname) +static BOOL copy_valid_path(const char *fname, char *buf, int prefix_len, unsigned int remainder, const char *suffix) { const char *f; int val; BOOL ret = True; stat_x sx; - char *b, *rel = backup_dir_buf + backup_dir_len, *name = rel; + char *b, *rel = buf + prefix_len, *name = rel; for (f = fname, b = rel; *f && *f == *b; f++, b++) { if (*b == '/') name = b + 1; } - if (stringjoin(rel, backup_dir_remainder, fname, backup_suffix, NULL) >= backup_dir_remainder) { + if (stringjoin(rel, remainder, fname, suffix, NULL) >= remainder) { rprintf(FERROR, "backup filename too long\n"); *name = '\0'; return False; @@ -82,7 +89,7 @@ static BOOL copy_valid_path(const char *fname) return True; *b = '\0'; - val = validate_backup_dir(); + val = validate_backup_dir(buf); if (val == 0) break; if (val < 0) { @@ -98,9 +105,9 @@ static BOOL copy_valid_path(const char *fname) for ( ; b; name = b + 1, b = strchr(name, '/')) { *b = '\0'; - while (do_mkdir(backup_dir_buf, ACCESSPERMS) < 0) { + while (do_mkdir(buf, ACCESSPERMS) < 0) { if (errno == EEXIST) { - val = validate_backup_dir(); + val = validate_backup_dir(buf); if (val > 0) break; if (val == 0) @@ -134,7 +141,7 @@ static BOOL copy_valid_path(const char *fname) free_xattr(&sx); } #endif - set_file_attrs(backup_dir_buf, file, NULL, NULL, 0); + set_file_attrs(buf, file, NULL, NULL, 0); unmake_file(file); } @@ -156,13 +163,18 @@ static BOOL copy_valid_path(const char *fname) /* Make a complete pathname for backup file and verify any new path elements. */ char *get_backup_name(const char *fname) { + char *buf = deleting ? backup_dir_dels_buf : backup_dir_buf; + char *suffix = deleting ? backup_suffix_dels : backup_suffix; + if (backup_dir) { + int prefix_len = deleting ? backup_dir_dels_len : backup_dir_len; + unsigned int remainder = deleting ? backup_dir_dels_remainder : backup_dir_remainder; static int initialized = 0; if (!initialized) { int ret; if (backup_dir_len > 1) backup_dir_buf[backup_dir_len-1] = '\0'; - ret = make_path(backup_dir_buf, 0); + ret = make_path(backup_dir_buf, ACCESSPERMS, 0); if (backup_dir_len > 1) backup_dir_buf[backup_dir_len-1] = '/'; if (ret < 0) @@ -170,14 +182,14 @@ char *get_backup_name(const char *fname) initialized = 1; } /* copy fname into backup_dir_buf while validating the dirs. */ - if (copy_valid_path(fname)) - return backup_dir_buf; + if (copy_valid_path(fname, buf, prefix_len, remainder, suffix)) + return buf; /* copy_valid_path() has printed an error message. */ return NULL; } - if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, backup_suffix, NULL) < MAXPATHLEN) - return backup_dir_buf; + if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN) + return buf; rprintf(FERROR, "backup filename too long\n"); return NULL; @@ -336,7 +348,7 @@ int make_backup(const char *fname, BOOL prefer_rename) save_preserve_xattrs = preserve_xattrs; preserve_xattrs = 0; - set_file_attrs(buf, file, NULL, fname, 0); + set_file_attrs(buf, file, NULL, fname, ATTRS_ACCURATE_TIME); preserve_xattrs = save_preserve_xattrs; unmake_file(file); @@ -350,5 +362,15 @@ int make_backup(const char *fname, BOOL prefer_rename) success: if (INFO_GTE(BACKUP, 1)) rprintf(FINFO, "backed up %s to %s\n", fname, buf); + return ret; +} + +/* backup switch routine called only when backing-up removed file */ +int safe_delete(const char *fname) +{ + int ret; + deleting = 1; + ret = make_backup(fname, True); + deleting = 0; return ret; }