File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / backup.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    1: /*
    2:  * Backup handling code.
    3:  *
    4:  * Copyright (C) 1999 Andrew Tridgell
    5:  * Copyright (C) 2003-2020 Wayne Davison
    6:  *
    7:  * This program is free software; you can redistribute it and/or modify
    8:  * it under the terms of the GNU General Public License as published by
    9:  * the Free Software Foundation; either version 3 of the License, or
   10:  * (at your option) any later version.
   11:  *
   12:  * This program is distributed in the hope that it will be useful,
   13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15:  * GNU General Public License for more details.
   16:  *
   17:  * You should have received a copy of the GNU General Public License along
   18:  * with this program; if not, visit the http://fsf.org website.
   19:  */
   20: 
   21: #include "rsync.h"
   22: #include "ifuncs.h"
   23: 
   24: extern int am_root;
   25: extern int preserve_acls;
   26: extern int preserve_xattrs;
   27: extern int preserve_devices;
   28: extern int preserve_specials;
   29: extern int preserve_links;
   30: extern int safe_symlinks;
   31: extern int backup_dir_len;
   32: extern int backup_dir_dels_len;
   33: extern unsigned int backup_dir_remainder;
   34: extern unsigned int backup_dir_dels_remainder;
   35: extern char backup_dir_buf[MAXPATHLEN];
   36: extern char backup_dir_dels_buf[MAXPATHLEN];
   37: extern char *backup_suffix;
   38: extern char *backup_suffix_dels;
   39: extern char *backup_dir;
   40: extern char *backup_dir_dels;
   41: 
   42: static BOOL deleting;
   43: 
   44: /* Returns -1 on error, 0 on missing dir, and 1 on present dir. */
   45: static int validate_backup_dir(char *buf)
   46: {
   47: 	STRUCT_STAT st;
   48: 
   49: 	if (do_lstat(buf, &st) < 0) {
   50: 		if (errno == ENOENT)
   51: 			return 0;
   52: 		rsyserr(FERROR, errno, "backup lstat %s failed", buf);
   53: 		return -1;
   54: 	}
   55: 	if (!S_ISDIR(st.st_mode)) {
   56: 		int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
   57: 		if (delete_item(buf, st.st_mode, flags) == 0)
   58: 			return 0;
   59: 		return -1;
   60: 	}
   61: 	return 1;
   62: }
   63: 
   64: /* Create a backup path from the given fname, putting the result into
   65:  * backup_dir_buf.  Any new directories (compared to the prior backup
   66:  * path) are ensured to exist as directories, replacing anything else
   67:  * that may be in the way (e.g. a symlink). */
   68: static BOOL copy_valid_path(const char *fname, char *buf, int prefix_len, unsigned int remainder, const char *suffix)
   69: {
   70: 	const char *f;
   71: 	int val;
   72: 	BOOL ret = True;
   73: 	stat_x sx;
   74: 	char *b, *rel = buf + prefix_len, *name = rel;
   75: 
   76: 	for (f = fname, b = rel; *f && *f == *b; f++, b++) {
   77: 		if (*b == '/')
   78: 			name = b + 1;
   79: 	}
   80: 
   81: 	if (stringjoin(rel, remainder, fname, suffix, NULL) >= remainder) {
   82: 		rprintf(FERROR, "backup filename too long\n");
   83: 		*name = '\0';
   84: 		return False;
   85: 	}
   86: 
   87: 	for ( ; ; name = b + 1) {
   88: 		if ((b = strchr(name, '/')) == NULL)
   89: 			return True;
   90: 		*b = '\0';
   91: 
   92: 		val = validate_backup_dir(buf);
   93: 		if (val == 0)
   94: 			break;
   95: 		if (val < 0) {
   96: 			*name = '\0';
   97: 			return False;
   98: 		}
   99: 
  100: 		*b = '/';
  101: 	}
  102: 
  103: 	init_stat_x(&sx);
  104: 
  105: 	for ( ; b; name = b + 1, b = strchr(name, '/')) {
  106: 		*b = '\0';
  107: 
  108: 		while (do_mkdir(buf, ACCESSPERMS) < 0) {
  109: 			if (errno == EEXIST) {
  110: 				val = validate_backup_dir(buf);
  111: 				if (val > 0)
  112: 					break;
  113: 				if (val == 0)
  114: 					continue;
  115: 			} else
  116: 				rsyserr(FERROR, errno, "backup mkdir %s failed", backup_dir_buf);
  117: 			*name = '\0';
  118: 			ret = False;
  119: 			goto cleanup;
  120: 		}
  121: 
  122: 		/* Try to transfer the directory settings of the actual dir
  123: 		 * that the files are coming from. */
  124: 		if (x_stat(rel, &sx.st, NULL) < 0)
  125: 			rsyserr(FERROR, errno, "backup stat %s failed", full_fname(rel));
  126: 		else {
  127: 			struct file_struct *file;
  128: 			if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
  129: 				continue;
  130: #ifdef SUPPORT_ACLS
  131: 			if (preserve_acls && !S_ISLNK(file->mode)) {
  132: 				get_acl(rel, &sx);
  133: 				cache_tmp_acl(file, &sx);
  134: 				free_acl(&sx);
  135: 			}
  136: #endif
  137: #ifdef SUPPORT_XATTRS
  138: 			if (preserve_xattrs) {
  139: 				get_xattr(rel, &sx);
  140: 				cache_tmp_xattr(file, &sx);
  141: 				free_xattr(&sx);
  142: 			}
  143: #endif
  144: 			set_file_attrs(buf, file, NULL, NULL, 0);
  145: 			unmake_file(file);
  146: 		}
  147: 
  148: 		*b = '/';
  149: 	}
  150: 
  151:   cleanup:
  152: 
  153: #ifdef SUPPORT_ACLS
  154: 	uncache_tmp_acls();
  155: #endif
  156: #ifdef SUPPORT_XATTRS
  157: 	uncache_tmp_xattrs();
  158: #endif
  159: 
  160: 	return ret;
  161: }
  162: 
  163: /* Make a complete pathname for backup file and verify any new path elements. */
  164: char *get_backup_name(const char *fname)
  165: {
  166: 	char *buf = deleting ? backup_dir_dels_buf : backup_dir_buf;
  167: 	char *suffix = deleting ? backup_suffix_dels : backup_suffix;
  168: 
  169: 	if (backup_dir) {
  170: 		int prefix_len = deleting ? backup_dir_dels_len : backup_dir_len;
  171: 		unsigned int remainder = deleting ? backup_dir_dels_remainder : backup_dir_remainder;
  172: 		static int initialized = 0;
  173: 		if (!initialized) {
  174: 			int ret;
  175: 			if (backup_dir_len > 1)
  176: 				backup_dir_buf[backup_dir_len-1] = '\0';
  177: 			ret = make_path(backup_dir_buf, ACCESSPERMS, 0);
  178: 			if (backup_dir_len > 1)
  179: 				backup_dir_buf[backup_dir_len-1] = '/';
  180: 			if (ret < 0)
  181: 				return NULL;
  182: 			initialized = 1;
  183: 		}
  184: 		/* copy fname into backup_dir_buf while validating the dirs. */
  185: 		if (copy_valid_path(fname, buf, prefix_len, remainder, suffix))
  186: 			return buf;
  187: 		/* copy_valid_path() has printed an error message. */
  188: 		return NULL;
  189: 	}
  190: 
  191: 	if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN)
  192: 		return buf;
  193: 
  194: 	rprintf(FERROR, "backup filename too long\n");
  195: 	return NULL;
  196: }
  197: 
  198: /* Has same return codes as make_backup(). */
  199: static inline int link_or_rename(const char *from, const char *to,
  200: 				 BOOL prefer_rename, STRUCT_STAT *stp)
  201: {
  202: #ifdef SUPPORT_HARD_LINKS
  203: 	if (!prefer_rename) {
  204: #ifndef CAN_HARDLINK_SYMLINK
  205: 		if (S_ISLNK(stp->st_mode))
  206: 			return 0; /* Use copy code. */
  207: #endif
  208: #ifndef CAN_HARDLINK_SPECIAL
  209: 		if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
  210: 			return 0; /* Use copy code. */
  211: #endif
  212: 		if (do_link(from, to) == 0) {
  213: 			if (DEBUG_GTE(BACKUP, 1))
  214: 				rprintf(FINFO, "make_backup: HLINK %s successful.\n", from);
  215: 			return 2;
  216: 		}
  217: 		/* We prefer to rename a regular file rather than copy it. */
  218: 		if (!S_ISREG(stp->st_mode) || errno == EEXIST || errno == EISDIR)
  219: 			return 0;
  220: 	}
  221: #endif
  222: 	if (do_rename(from, to) == 0) {
  223: 		if (stp->st_nlink > 1 && !S_ISDIR(stp->st_mode)) {
  224: 			/* If someone has hard-linked the file into the backup
  225: 			 * dir, rename() might return success but do nothing! */
  226: 			robust_unlink(from); /* Just in case... */
  227: 		}
  228: 		if (DEBUG_GTE(BACKUP, 1))
  229: 			rprintf(FINFO, "make_backup: RENAME %s successful.\n", from);
  230: 		return 1;
  231: 	}
  232: 	return 0;
  233: }
  234: 
  235: /* Hard-link, rename, or copy an item to the backup name.  Returns 0 for
  236:  * failure, 1 if item was moved, 2 if item was duplicated or hard linked
  237:  * into backup area, or 3 if item doesn't exist or isn't a regular file. */
  238: int make_backup(const char *fname, BOOL prefer_rename)
  239: {
  240: 	stat_x sx;
  241: 	struct file_struct *file;
  242: 	int save_preserve_xattrs;
  243: 	char *buf;
  244: 	int ret = 0;
  245: 
  246: 	init_stat_x(&sx);
  247: 	/* Return success if no file to keep. */
  248: 	if (x_lstat(fname, &sx.st, NULL) < 0)
  249: 		return 3;
  250: 
  251: 	if (!(buf = get_backup_name(fname)))
  252: 		return 0;
  253: 
  254: 	/* Try a hard-link or a rename first.  Using rename is not atomic, but
  255: 	 * is more efficient than forcing a copy for larger files when no hard-
  256: 	 * linking is possible. */
  257: 	if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
  258: 		goto success;
  259: 	if (errno == EEXIST || errno == EISDIR) {
  260: 		STRUCT_STAT bakst;
  261: 		if (do_lstat(buf, &bakst) == 0) {
  262: 			int flags = get_del_for_flag(bakst.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
  263: 			if (delete_item(buf, bakst.st_mode, flags) != 0)
  264: 				return 0;
  265: 		}
  266: 		if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
  267: 			goto success;
  268: 	}
  269: 
  270: 	/* Fall back to making a copy. */
  271: 	if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
  272: 		return 3; /* the file could have disappeared */
  273: 
  274: #ifdef SUPPORT_ACLS
  275: 	if (preserve_acls && !S_ISLNK(file->mode)) {
  276: 		get_acl(fname, &sx);
  277: 		cache_tmp_acl(file, &sx);
  278: 		free_acl(&sx);
  279: 	}
  280: #endif
  281: #ifdef SUPPORT_XATTRS
  282: 	if (preserve_xattrs) {
  283: 		get_xattr(fname, &sx);
  284: 		cache_tmp_xattr(file, &sx);
  285: 		free_xattr(&sx);
  286: 	}
  287: #endif
  288: 
  289: 	/* Check to see if this is a device file, or link */
  290: 	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
  291: 	 || (preserve_specials && IS_SPECIAL(file->mode))) {
  292: 		if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
  293: 			rsyserr(FERROR, errno, "mknod %s failed", full_fname(buf));
  294: 		else if (DEBUG_GTE(BACKUP, 1))
  295: 			rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
  296: 		ret = 2;
  297: 	}
  298: 
  299: #ifdef SUPPORT_LINKS
  300: 	if (!ret && preserve_links && S_ISLNK(file->mode)) {
  301: 		const char *sl = F_SYMLINK(file);
  302: 		if (safe_symlinks && unsafe_symlink(sl, fname)) {
  303: 			if (INFO_GTE(SYMSAFE, 1)) {
  304: 				rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
  305: 					fname, sl);
  306: 			}
  307: 			ret = 2;
  308: 		} else {
  309: 			if (do_symlink(sl, buf) < 0)
  310: 				rsyserr(FERROR, errno, "link %s -> \"%s\"", full_fname(buf), sl);
  311: 			else if (DEBUG_GTE(BACKUP, 1))
  312: 				rprintf(FINFO, "make_backup: SYMLINK %s successful.\n", fname);
  313: 			ret = 2;
  314: 		}
  315: 	}
  316: #endif
  317: 
  318: 	if (!ret && !S_ISREG(file->mode)) {
  319: 		rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
  320: 		unmake_file(file);
  321: #ifdef SUPPORT_ACLS
  322: 		uncache_tmp_acls();
  323: #endif
  324: #ifdef SUPPORT_XATTRS
  325: 		uncache_tmp_xattrs();
  326: #endif
  327: 		return 3;
  328: 	}
  329: 
  330: 	/* Copy to backup tree if a file. */
  331: 	if (!ret) {
  332: 		if (copy_file(fname, buf, -1, file->mode) < 0) {
  333: 			rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
  334: 				full_fname(fname), buf);
  335: 			unmake_file(file);
  336: #ifdef SUPPORT_ACLS
  337: 			uncache_tmp_acls();
  338: #endif
  339: #ifdef SUPPORT_XATTRS
  340: 			uncache_tmp_xattrs();
  341: #endif
  342: 			return 0;
  343: 		}
  344: 		if (DEBUG_GTE(BACKUP, 1))
  345: 			rprintf(FINFO, "make_backup: COPY %s successful.\n", fname);
  346: 		ret = 2;
  347: 	}
  348: 
  349: 	save_preserve_xattrs = preserve_xattrs;
  350: 	preserve_xattrs = 0;
  351: 	set_file_attrs(buf, file, NULL, fname, ATTRS_ACCURATE_TIME);
  352: 	preserve_xattrs = save_preserve_xattrs;
  353: 
  354: 	unmake_file(file);
  355: #ifdef SUPPORT_ACLS
  356: 	uncache_tmp_acls();
  357: #endif
  358: #ifdef SUPPORT_XATTRS
  359: 	uncache_tmp_xattrs();
  360: #endif
  361: 
  362:   success:
  363: 	if (INFO_GTE(BACKUP, 1))
  364: 		rprintf(FINFO, "backed up %s to %s\n", fname, buf);
  365: 	return ret;
  366: }
  367: 
  368: /* backup switch routine called only when backing-up removed file */
  369: int safe_delete(const char *fname)
  370: {
  371: 	int ret;
  372: 	deleting = 1;
  373: 	ret = make_backup(fname, True);
  374: 	deleting = 0;
  375: 	return ret;
  376: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>