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>