--- embedaddon/rsync/backup.c 2013/10/14 07:51:14 1.1.1.2 +++ 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-2013 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,16 +163,33 @@ 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, ACCESSPERMS, 0); + if (backup_dir_len > 1) + backup_dir_buf[backup_dir_len-1] = '/'; + if (ret < 0) + return NULL; + 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; @@ -208,24 +232,25 @@ static inline int link_or_rename(const char *from, con return 0; } -/* Hard-link, rename, or copy an item to the backup name. Returns 2 if item - * was duplicated into backup area, 1 if item was moved, or 0 for failure.*/ +/* Hard-link, rename, or copy an item to the backup name. Returns 0 for + * failure, 1 if item was moved, 2 if item was duplicated or hard linked + * into backup area, or 3 if item doesn't exist or isn't a regular file. */ int make_backup(const char *fname, BOOL prefer_rename) { stat_x sx; struct file_struct *file; int save_preserve_xattrs; - char *buf = get_backup_name(fname); + char *buf; int ret = 0; - if (!buf) - return 0; - init_stat_x(&sx); /* Return success if no file to keep. */ if (x_lstat(fname, &sx.st, NULL) < 0) - return 1; + return 3; + if (!(buf = get_backup_name(fname))) + return 0; + /* Try a hard-link or a rename first. Using rename is not atomic, but * is more efficient than forcing a copy for larger files when no hard- * linking is possible. */ @@ -244,7 +269,7 @@ int make_backup(const char *fname, BOOL prefer_rename) /* Fall back to making a copy. */ if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS))) - return 1; /* the file could have disappeared */ + return 3; /* the file could have disappeared */ #ifdef SUPPORT_ACLS if (preserve_acls && !S_ISLNK(file->mode)) { @@ -299,7 +324,7 @@ int make_backup(const char *fname, BOOL prefer_rename) #ifdef SUPPORT_XATTRS uncache_tmp_xattrs(); #endif - return 2; + return 3; } /* Copy to backup tree if a file. */ @@ -323,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); @@ -337,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; }