Annotation of embedaddon/rsync/backup.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Backup handling code.
3: *
4: * Copyright (C) 1999 Andrew Tridgell
5: * Copyright (C) 2003-2009 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:
23: extern int verbose;
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 unsigned int backup_dir_remainder;
33: extern char backup_dir_buf[MAXPATHLEN];
34: extern char *backup_suffix;
35: extern char *backup_dir;
36:
37: /* make a complete pathname for backup file */
38: char *get_backup_name(const char *fname)
39: {
40: if (backup_dir) {
41: if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
42: fname, backup_suffix, NULL) < backup_dir_remainder)
43: return backup_dir_buf;
44: } else {
45: if (stringjoin(backup_dir_buf, MAXPATHLEN,
46: fname, backup_suffix, NULL) < MAXPATHLEN)
47: return backup_dir_buf;
48: }
49:
50: rprintf(FERROR, "backup filename too long\n");
51: return NULL;
52: }
53:
54: /* simple backup creates a backup with a suffix in the same directory */
55: static int make_simple_backup(const char *fname)
56: {
57: int rename_errno;
58: const char *fnamebak = get_backup_name(fname);
59:
60: if (!fnamebak)
61: return 0;
62:
63: while (1) {
64: if (do_rename(fname, fnamebak) == 0) {
65: if (verbose > 1) {
66: rprintf(FINFO, "backed up %s to %s\n",
67: fname, fnamebak);
68: }
69: break;
70: }
71: /* cygwin (at least version b19) reports EINVAL */
72: if (errno == ENOENT || errno == EINVAL)
73: break;
74:
75: rename_errno = errno;
76: if (errno == EISDIR && do_rmdir(fnamebak) == 0)
77: continue;
78: if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
79: continue;
80:
81: rsyserr(FERROR, rename_errno, "rename %s to backup %s",
82: fname, fnamebak);
83: errno = rename_errno;
84: return 0;
85: }
86:
87: return 1;
88: }
89:
90:
91: /****************************************************************************
92: Create a directory given an absolute path, perms based upon another directory
93: path
94: ****************************************************************************/
95: int make_bak_dir(const char *fullpath)
96: {
97: char fbuf[MAXPATHLEN], *rel, *end, *p;
98: struct file_struct *file;
99: int len = backup_dir_len;
100: stat_x sx;
101:
102: while (*fullpath == '.' && fullpath[1] == '/') {
103: fullpath += 2;
104: len -= 2;
105: }
106:
107: if (strlcpy(fbuf, fullpath, sizeof fbuf) >= sizeof fbuf)
108: return -1;
109:
110: rel = fbuf + len;
111: end = p = rel + strlen(rel);
112:
113: /* Try to find an existing dir, starting from the deepest dir. */
114: while (1) {
115: if (--p == fbuf)
116: return -1;
117: if (*p == '/') {
118: *p = '\0';
119: if (mkdir_defmode(fbuf) == 0)
120: break;
121: if (errno != ENOENT) {
122: rsyserr(FERROR, errno,
123: "make_bak_dir mkdir %s failed",
124: full_fname(fbuf));
125: return -1;
126: }
127: }
128: }
129:
130: /* Make all the dirs that we didn't find on the way here. */
131: while (1) {
132: if (p >= rel) {
133: /* Try to transfer the directory settings of the
134: * actual dir that the files are coming from. */
135: if (x_stat(rel, &sx.st, NULL) < 0) {
136: rsyserr(FERROR, errno,
137: "make_bak_dir stat %s failed",
138: full_fname(rel));
139: } else {
140: #ifdef SUPPORT_ACLS
141: sx.acc_acl = sx.def_acl = NULL;
142: #endif
143: #ifdef SUPPORT_XATTRS
144: sx.xattr = NULL;
145: #endif
146: if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
147: continue;
148: #ifdef SUPPORT_ACLS
149: if (preserve_acls && !S_ISLNK(file->mode)) {
150: get_acl(rel, &sx);
151: cache_tmp_acl(file, &sx);
152: free_acl(&sx);
153: }
154: #endif
155: #ifdef SUPPORT_XATTRS
156: if (preserve_xattrs) {
157: get_xattr(rel, &sx);
158: cache_tmp_xattr(file, &sx);
159: free_xattr(&sx);
160: }
161: #endif
162: set_file_attrs(fbuf, file, NULL, NULL, 0);
163: unmake_file(file);
164: #ifdef SUPPORT_ACLS
165: uncache_tmp_acls();
166: #endif
167: #ifdef SUPPORT_XATTRS
168: uncache_tmp_xattrs();
169: #endif
170: }
171: }
172: *p = '/';
173: p += strlen(p);
174: if (p == end)
175: break;
176: if (mkdir_defmode(fbuf) < 0) {
177: rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
178: full_fname(fbuf));
179: return -1;
180: }
181: }
182:
183: return 0;
184: }
185:
186: /* robustly move a file, creating new directory structures if necessary */
187: static int robust_move(const char *src, char *dst)
188: {
189: if (robust_rename(src, dst, NULL, 0755) < 0) {
190: int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
191: if (errno == ENOENT && make_bak_dir(dst) == 0) {
192: if (robust_rename(src, dst, NULL, 0755) < 0)
193: save_errno = errno ? errno : save_errno;
194: else
195: save_errno = 0;
196: }
197: if (save_errno) {
198: errno = save_errno;
199: return -1;
200: }
201: }
202: return 0;
203: }
204:
205:
206: /* If we have a --backup-dir, then we get here from make_backup().
207: * We will move the file to be deleted into a parallel directory tree. */
208: static int keep_backup(const char *fname)
209: {
210: stat_x sx;
211: struct file_struct *file;
212: char *buf;
213: int save_preserve_xattrs = preserve_xattrs;
214: int kept = 0;
215: int ret_code;
216:
217: /* return if no file to keep */
218: if (x_lstat(fname, &sx.st, NULL) < 0)
219: return 1;
220: #ifdef SUPPORT_ACLS
221: sx.acc_acl = sx.def_acl = NULL;
222: #endif
223: #ifdef SUPPORT_XATTRS
224: sx.xattr = NULL;
225: #endif
226:
227: if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
228: return 1; /* the file could have disappeared */
229:
230: if (!(buf = get_backup_name(fname))) {
231: unmake_file(file);
232: #ifdef SUPPORT_ACLS
233: uncache_tmp_acls();
234: #endif
235: #ifdef SUPPORT_XATTRS
236: uncache_tmp_xattrs();
237: #endif
238: return 0;
239: }
240:
241: #ifdef SUPPORT_ACLS
242: if (preserve_acls && !S_ISLNK(file->mode)) {
243: get_acl(fname, &sx);
244: cache_tmp_acl(file, &sx);
245: free_acl(&sx);
246: }
247: #endif
248: #ifdef SUPPORT_XATTRS
249: if (preserve_xattrs) {
250: get_xattr(fname, &sx);
251: cache_tmp_xattr(file, &sx);
252: free_xattr(&sx);
253: }
254: #endif
255:
256: /* Check to see if this is a device file, or link */
257: if ((am_root && preserve_devices && IS_DEVICE(file->mode))
258: || (preserve_specials && IS_SPECIAL(file->mode))) {
259: int save_errno;
260: do_unlink(buf);
261: if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0) {
262: save_errno = errno ? errno : EINVAL; /* 0 paranoia */
263: if (errno == ENOENT && make_bak_dir(buf) == 0) {
264: if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
265: save_errno = errno ? errno : save_errno;
266: else
267: save_errno = 0;
268: }
269: if (save_errno) {
270: rsyserr(FERROR, save_errno, "mknod %s failed",
271: full_fname(buf));
272: }
273: } else
274: save_errno = 0;
275: if (verbose > 2 && save_errno == 0) {
276: rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
277: fname);
278: }
279: kept = 1;
280: do_unlink(fname);
281: }
282:
283: if (!kept && S_ISDIR(file->mode)) {
284: /* make an empty directory */
285: if (do_mkdir(buf, file->mode) < 0) {
286: int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
287: if (errno == ENOENT && make_bak_dir(buf) == 0) {
288: if (do_mkdir(buf, file->mode) < 0)
289: save_errno = errno ? errno : save_errno;
290: else
291: save_errno = 0;
292: }
293: if (save_errno) {
294: rsyserr(FINFO, save_errno, "mkdir %s failed",
295: full_fname(buf));
296: }
297: }
298:
299: ret_code = do_rmdir(fname);
300: if (verbose > 2) {
301: rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
302: full_fname(fname), ret_code);
303: }
304: kept = 1;
305: }
306:
307: #ifdef SUPPORT_LINKS
308: if (!kept && preserve_links && S_ISLNK(file->mode)) {
309: const char *sl = F_SYMLINK(file);
310: if (safe_symlinks && unsafe_symlink(sl, fname)) {
311: if (verbose) {
312: rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
313: fname, sl);
314: }
315: kept = 1;
316: } else {
317: do_unlink(buf);
318: if (do_symlink(sl, buf) < 0) {
319: int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
320: if (errno == ENOENT && make_bak_dir(buf) == 0) {
321: if (do_symlink(sl, buf) < 0)
322: save_errno = errno ? errno : save_errno;
323: else
324: save_errno = 0;
325: }
326: if (save_errno) {
327: rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
328: full_fname(buf), sl);
329: }
330: }
331: do_unlink(fname);
332: kept = 1;
333: }
334: }
335: #endif
336:
337: if (!kept && !S_ISREG(file->mode)) {
338: rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
339: fname);
340: unmake_file(file);
341: #ifdef SUPPORT_ACLS
342: uncache_tmp_acls();
343: #endif
344: #ifdef SUPPORT_XATTRS
345: uncache_tmp_xattrs();
346: #endif
347: return 1;
348: }
349:
350: /* move to keep tree if a file */
351: if (!kept) {
352: if (robust_move(fname, buf) != 0) {
353: rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
354: full_fname(fname), buf);
355: } else if (sx.st.st_nlink > 1) {
356: /* If someone has hard-linked the file into the backup
357: * dir, rename() might return success but do nothing! */
358: robust_unlink(fname); /* Just in case... */
359: }
360: }
361: preserve_xattrs = 0;
362: set_file_attrs(buf, file, NULL, fname, 0);
363: preserve_xattrs = save_preserve_xattrs;
364: unmake_file(file);
365: #ifdef SUPPORT_ACLS
366: uncache_tmp_acls();
367: #endif
368: #ifdef SUPPORT_XATTRS
369: uncache_tmp_xattrs();
370: #endif
371:
372: if (verbose > 1) {
373: rprintf(FINFO, "backed up %s to %s\n",
374: fname, buf);
375: }
376: return 1;
377: }
378:
379:
380: /* main backup switch routine */
381: int make_backup(const char *fname)
382: {
383: if (backup_dir)
384: return keep_backup(fname);
385: return make_simple_backup(fname);
386: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>