Annotation of embedaddon/rsync/backup.c, revision 1.1.1.4
1.1 misho 1: /*
2: * Backup handling code.
3: *
4: * Copyright (C) 1999 Andrew Tridgell
1.1.1.4 ! misho 5: * Copyright (C) 2003-2020 Wayne Davison
1.1 misho 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"
1.1.1.2 misho 22: #include "ifuncs.h"
1.1 misho 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;
1.1.1.4 ! misho 32: extern int backup_dir_dels_len;
1.1 misho 33: extern unsigned int backup_dir_remainder;
1.1.1.4 ! misho 34: extern unsigned int backup_dir_dels_remainder;
1.1 misho 35: extern char backup_dir_buf[MAXPATHLEN];
1.1.1.4 ! misho 36: extern char backup_dir_dels_buf[MAXPATHLEN];
1.1 misho 37: extern char *backup_suffix;
1.1.1.4 ! misho 38: extern char *backup_suffix_dels;
1.1 misho 39: extern char *backup_dir;
1.1.1.4 ! misho 40: extern char *backup_dir_dels;
! 41:
! 42: static BOOL deleting;
1.1 misho 43:
1.1.1.2 misho 44: /* Returns -1 on error, 0 on missing dir, and 1 on present dir. */
1.1.1.4 ! misho 45: static int validate_backup_dir(char *buf)
1.1 misho 46: {
1.1.1.2 misho 47: STRUCT_STAT st;
1.1 misho 48:
1.1.1.4 ! misho 49: if (do_lstat(buf, &st) < 0) {
1.1.1.2 misho 50: if (errno == ENOENT)
51: return 0;
1.1.1.4 ! misho 52: rsyserr(FERROR, errno, "backup lstat %s failed", buf);
1.1.1.2 misho 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;
1.1.1.4 ! misho 57: if (delete_item(buf, st.st_mode, flags) == 0)
1.1.1.2 misho 58: return 0;
59: return -1;
1.1 misho 60: }
61: return 1;
62: }
63:
1.1.1.2 misho 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). */
1.1.1.4 ! misho 68: static BOOL copy_valid_path(const char *fname, char *buf, int prefix_len, unsigned int remainder, const char *suffix)
1.1 misho 69: {
1.1.1.2 misho 70: const char *f;
71: int val;
72: BOOL ret = True;
1.1 misho 73: stat_x sx;
1.1.1.4 ! misho 74: char *b, *rel = buf + prefix_len, *name = rel;
1.1 misho 75:
1.1.1.2 misho 76: for (f = fname, b = rel; *f && *f == *b; f++, b++) {
77: if (*b == '/')
78: name = b + 1;
1.1 misho 79: }
80:
1.1.1.4 ! misho 81: if (stringjoin(rel, remainder, fname, suffix, NULL) >= remainder) {
1.1.1.2 misho 82: rprintf(FERROR, "backup filename too long\n");
83: *name = '\0';
84: return False;
85: }
1.1 misho 86:
1.1.1.2 misho 87: for ( ; ; name = b + 1) {
88: if ((b = strchr(name, '/')) == NULL)
89: return True;
90: *b = '\0';
1.1 misho 91:
1.1.1.4 ! misho 92: val = validate_backup_dir(buf);
1.1.1.2 misho 93: if (val == 0)
94: break;
95: if (val < 0) {
96: *name = '\0';
97: return False;
1.1 misho 98: }
1.1.1.2 misho 99:
100: *b = '/';
1.1 misho 101: }
102:
1.1.1.2 misho 103: init_stat_x(&sx);
104:
105: for ( ; b; name = b + 1, b = strchr(name, '/')) {
106: *b = '\0';
107:
1.1.1.4 ! misho 108: while (do_mkdir(buf, ACCESSPERMS) < 0) {
1.1.1.2 misho 109: if (errno == EEXIST) {
1.1.1.4 ! misho 110: val = validate_backup_dir(buf);
1.1.1.2 misho 111: if (val > 0)
112: break;
113: if (val == 0)
1.1 misho 114: continue;
1.1.1.2 misho 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;
1.1 misho 130: #ifdef SUPPORT_ACLS
1.1.1.2 misho 131: if (preserve_acls && !S_ISLNK(file->mode)) {
132: get_acl(rel, &sx);
133: cache_tmp_acl(file, &sx);
134: free_acl(&sx);
135: }
1.1 misho 136: #endif
137: #ifdef SUPPORT_XATTRS
1.1.1.2 misho 138: if (preserve_xattrs) {
139: get_xattr(rel, &sx);
140: cache_tmp_xattr(file, &sx);
141: free_xattr(&sx);
142: }
1.1 misho 143: #endif
1.1.1.4 ! misho 144: set_file_attrs(buf, file, NULL, NULL, 0);
1.1.1.2 misho 145: unmake_file(file);
146: }
147:
148: *b = '/';
149: }
150:
151: cleanup:
152:
1.1 misho 153: #ifdef SUPPORT_ACLS
1.1.1.2 misho 154: uncache_tmp_acls();
1.1 misho 155: #endif
156: #ifdef SUPPORT_XATTRS
1.1.1.2 misho 157: uncache_tmp_xattrs();
1.1 misho 158: #endif
1.1.1.2 misho 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: {
1.1.1.4 ! misho 166: char *buf = deleting ? backup_dir_dels_buf : backup_dir_buf;
! 167: char *suffix = deleting ? backup_suffix_dels : backup_suffix;
! 168:
1.1.1.2 misho 169: if (backup_dir) {
1.1.1.4 ! misho 170: int prefix_len = deleting ? backup_dir_dels_len : backup_dir_len;
! 171: unsigned int remainder = deleting ? backup_dir_dels_remainder : backup_dir_remainder;
1.1.1.3 misho 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';
1.1.1.4 ! misho 177: ret = make_path(backup_dir_buf, ACCESSPERMS, 0);
1.1.1.3 misho 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: }
1.1.1.2 misho 184: /* copy fname into backup_dir_buf while validating the dirs. */
1.1.1.4 ! misho 185: if (copy_valid_path(fname, buf, prefix_len, remainder, suffix))
! 186: return buf;
1.1.1.2 misho 187: /* copy_valid_path() has printed an error message. */
188: return NULL;
1.1 misho 189: }
190:
1.1.1.4 ! misho 191: if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN)
! 192: return buf;
1.1.1.2 misho 193:
194: rprintf(FERROR, "backup filename too long\n");
195: return NULL;
1.1 misho 196: }
197:
1.1.1.2 misho 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)
1.1 misho 201: {
1.1.1.2 misho 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... */
1.1 misho 227: }
1.1.1.2 misho 228: if (DEBUG_GTE(BACKUP, 1))
229: rprintf(FINFO, "make_backup: RENAME %s successful.\n", from);
230: return 1;
1.1 misho 231: }
232: return 0;
233: }
234:
1.1.1.3 misho 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. */
1.1.1.2 misho 238: int make_backup(const char *fname, BOOL prefer_rename)
1.1 misho 239: {
240: stat_x sx;
241: struct file_struct *file;
1.1.1.2 misho 242: int save_preserve_xattrs;
1.1.1.3 misho 243: char *buf;
1.1.1.2 misho 244: int ret = 0;
1.1 misho 245:
1.1.1.2 misho 246: init_stat_x(&sx);
247: /* Return success if no file to keep. */
1.1 misho 248: if (x_lstat(fname, &sx.st, NULL) < 0)
1.1.1.3 misho 249: return 3;
250:
251: if (!(buf = get_backup_name(fname)))
252: return 0;
1.1 misho 253:
1.1.1.2 misho 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;
1.1 misho 268: }
269:
1.1.1.2 misho 270: /* Fall back to making a copy. */
271: if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
1.1.1.3 misho 272: return 3; /* the file could have disappeared */
1.1.1.2 misho 273:
1.1 misho 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))) {
1.1.1.2 misho 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;
1.1 misho 297: }
298:
299: #ifdef SUPPORT_LINKS
1.1.1.2 misho 300: if (!ret && preserve_links && S_ISLNK(file->mode)) {
1.1 misho 301: const char *sl = F_SYMLINK(file);
302: if (safe_symlinks && unsafe_symlink(sl, fname)) {
1.1.1.2 misho 303: if (INFO_GTE(SYMSAFE, 1)) {
1.1 misho 304: rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
305: fname, sl);
306: }
1.1.1.2 misho 307: ret = 2;
1.1 misho 308: } else {
1.1.1.2 misho 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;
1.1 misho 314: }
315: }
316: #endif
317:
1.1.1.2 misho 318: if (!ret && !S_ISREG(file->mode)) {
319: rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
1.1 misho 320: unmake_file(file);
321: #ifdef SUPPORT_ACLS
322: uncache_tmp_acls();
323: #endif
324: #ifdef SUPPORT_XATTRS
325: uncache_tmp_xattrs();
326: #endif
1.1.1.3 misho 327: return 3;
1.1 misho 328: }
329:
1.1.1.2 misho 330: /* Copy to backup tree if a file. */
331: if (!ret) {
332: if (copy_file(fname, buf, -1, file->mode) < 0) {
1.1 misho 333: rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
334: full_fname(fname), buf);
1.1.1.2 misho 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;
1.1 misho 343: }
1.1.1.2 misho 344: if (DEBUG_GTE(BACKUP, 1))
345: rprintf(FINFO, "make_backup: COPY %s successful.\n", fname);
346: ret = 2;
1.1 misho 347: }
1.1.1.2 misho 348:
349: save_preserve_xattrs = preserve_xattrs;
1.1 misho 350: preserve_xattrs = 0;
1.1.1.4 ! misho 351: set_file_attrs(buf, file, NULL, fname, ATTRS_ACCURATE_TIME);
1.1 misho 352: preserve_xattrs = save_preserve_xattrs;
1.1.1.2 misho 353:
1.1 misho 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:
1.1.1.2 misho 362: success:
363: if (INFO_GTE(BACKUP, 1))
364: rprintf(FINFO, "backed up %s to %s\n", fname, buf);
365: return ret;
1.1 misho 366: }
1.1.1.4 ! misho 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>