Add understanding of RSYNC_PROTECT_ARGS environment var.
[rsync/rsync.git] / backup.c
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 #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 unsigned int backup_dir_remainder;
33 extern char backup_dir_buf[MAXPATHLEN];
34 extern char *backup_suffix;
35 extern char *backup_dir;
36
37 /* Create a backup path from the given fname, putting the result into
38  * backup_dir_buf.  Any new directories (compared to the prior backup
39  * path) are ensured to exist as directories, replacing anything else
40  * that may be in the way (e.g. a symlink). */
41 static BOOL copy_valid_path(const char *fname)
42 {
43         const char *f;
44         int flags;
45         BOOL ret = True;
46         stat_x sx;
47         char *b, *rel = backup_dir_buf + backup_dir_len, *name = rel;
48
49         for (f = fname, b = rel; *f && *f == *b; f++, b++) {
50                 if (*b == '/')
51                         name = b + 1;
52         }
53
54         if (stringjoin(rel, backup_dir_remainder, fname, backup_suffix, NULL) >= backup_dir_remainder) {
55                 rprintf(FERROR, "backup filename too long\n");
56                 *name = '\0';
57                 return False;
58         }
59
60         for ( ; ; name = b + 1) {
61                 if ((b = strchr(name, '/')) == NULL)
62                         return True;
63                 *b = '\0';
64
65                 if (do_lstat(backup_dir_buf, &sx.st) < 0) {
66                         if (errno == ENOENT)
67                                 break;
68                         rsyserr(FERROR, errno, "backup lstat %s failed", backup_dir_buf);
69                         *name = '\0';
70                         return False;
71                 }
72                 if (!S_ISDIR(sx.st.st_mode)) {
73                         flags = get_del_for_flag(sx.st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
74                         if (delete_item(backup_dir_buf, sx.st.st_mode, flags) == 0)
75                                 break;
76                         *name = '\0';
77                         return False;
78                 }
79
80                 *b = '/';
81         }
82
83         init_stat_x(&sx);
84
85         for ( ; b; name = b + 1, b = strchr(name, '/')) {
86                 *b = '\0';
87
88                 if (mkdir_defmode(backup_dir_buf) < 0) {
89                         rsyserr(FERROR, errno, "backup mkdir %s failed", backup_dir_buf);
90                         *name = '\0';
91                         ret = False;
92                         break;
93                 }
94
95                 /* Try to transfer the directory settings of the actual dir
96                  * that the files are coming from. */
97                 if (x_stat(rel, &sx.st, NULL) < 0)
98                         rsyserr(FERROR, errno, "backup stat %s failed", full_fname(rel));
99                 else {
100                         struct file_struct *file;
101                         if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
102                                 continue;
103 #ifdef SUPPORT_ACLS
104                         if (preserve_acls && !S_ISLNK(file->mode)) {
105                                 get_acl(rel, &sx);
106                                 cache_tmp_acl(file, &sx);
107                                 free_acl(&sx);
108                         }
109 #endif
110 #ifdef SUPPORT_XATTRS
111                         if (preserve_xattrs) {
112                                 get_xattr(rel, &sx);
113                                 cache_tmp_xattr(file, &sx);
114                                 free_xattr(&sx);
115                         }
116 #endif
117                         set_file_attrs(backup_dir_buf, file, NULL, NULL, 0);
118                         unmake_file(file);
119                 }
120
121                 *b = '/';
122         }
123
124 #ifdef SUPPORT_ACLS
125         uncache_tmp_acls();
126 #endif
127 #ifdef SUPPORT_XATTRS
128         uncache_tmp_xattrs();
129 #endif
130
131         return ret;
132 }
133
134 /* Make a complete pathname for backup file and verify any new path elements. */
135 char *get_backup_name(const char *fname)
136 {
137         if (backup_dir) {
138                 /* copy fname into backup_dir_buf while validating the dirs. */
139                 if (copy_valid_path(fname))
140                         return backup_dir_buf;
141                 return NULL;
142         } else {
143                 if (stringjoin(backup_dir_buf, MAXPATHLEN,
144                                fname, backup_suffix, NULL) < MAXPATHLEN)
145                         return backup_dir_buf;
146         }
147
148         rprintf(FERROR, "backup filename too long\n");
149         return NULL;
150 }
151
152 /* Has same return codes as make_backup(). */
153 static inline int link_or_rename(const char *from, const char *to,
154                                  BOOL prefer_rename, STRUCT_STAT *stp)
155 {
156 #ifdef SUPPORT_HARD_LINKS
157         if (!prefer_rename) {
158 #ifndef CAN_HARDLINK_SYMLINK
159                 if (S_ISLNK(stp->st_mode))
160                         return 0; /* Use copy code. */
161 #endif
162 #ifndef CAN_HARDLINK_SPECIAL
163                 if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
164                         return 0; /* Use copy code. */
165 #endif
166                 if (do_link(from, to) == 0) {
167                         if (DEBUG_GTE(BACKUP, 1))
168                                 rprintf(FINFO, "make_backup: HLINK %s successful.\n", from);
169                         return 2;
170                 }
171                 /* We prefer to rename a regular file rather than copy it. */
172                 if (!S_ISREG(stp->st_mode) || errno == EEXIST || errno == EISDIR)
173                         return 0;
174         }
175 #endif
176         if (do_rename(from, to) == 0) {
177                 if (stp->st_nlink > 1 && !S_ISDIR(stp->st_mode)) {
178                         /* If someone has hard-linked the file into the backup
179                          * dir, rename() might return success but do nothing! */
180                         robust_unlink(from); /* Just in case... */
181                 }
182                 if (DEBUG_GTE(BACKUP, 1))
183                         rprintf(FINFO, "make_backup: RENAME %s successful.\n", from);
184                 return 1;
185         }
186         return 0;
187 }
188
189 /* Hard-link, rename, or copy an item to the backup name.  Returns 2 if item
190  * was duplicated into backup area, 1 if item was moved, or 0 for failure.*/
191 int make_backup(const char *fname, BOOL prefer_rename)
192 {
193         stat_x sx;
194         struct file_struct *file;
195         int save_preserve_xattrs;
196         char *buf = get_backup_name(fname);
197         int ret = 0;
198
199         if (!buf)
200                 return 0;
201
202         init_stat_x(&sx);
203         /* Return success if no file to keep. */
204         if (x_lstat(fname, &sx.st, NULL) < 0)
205                 return 1;
206
207         /* Try a hard-link or a rename first.  Using rename is not atomic, but
208          * is more efficient than forcing a copy for larger files when no hard-
209          * linking is possible. */
210         if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
211                 goto success;
212         if (errno == EEXIST || errno == EISDIR) {
213                 STRUCT_STAT bakst;
214                 if (do_lstat(buf, &bakst) == 0) {
215                         int flags = get_del_for_flag(bakst.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
216                         if (delete_item(buf, bakst.st_mode, flags) != 0)
217                                 return 0;
218                 }
219                 if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
220                         goto success;
221         }
222
223         /* Fall back to making a copy. */
224         if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
225                 return 1; /* the file could have disappeared */
226
227 #ifdef SUPPORT_ACLS
228         if (preserve_acls && !S_ISLNK(file->mode)) {
229                 get_acl(fname, &sx);
230                 cache_tmp_acl(file, &sx);
231                 free_acl(&sx);
232         }
233 #endif
234 #ifdef SUPPORT_XATTRS
235         if (preserve_xattrs) {
236                 get_xattr(fname, &sx);
237                 cache_tmp_xattr(file, &sx);
238                 free_xattr(&sx);
239         }
240 #endif
241
242         /* Check to see if this is a device file, or link */
243         if ((am_root && preserve_devices && IS_DEVICE(file->mode))
244          || (preserve_specials && IS_SPECIAL(file->mode))) {
245                 if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
246                         rsyserr(FERROR, errno, "mknod %s failed", full_fname(buf));
247                 else if (DEBUG_GTE(BACKUP, 1))
248                         rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
249                 ret = 2;
250         }
251
252 #ifdef SUPPORT_LINKS
253         if (!ret && preserve_links && S_ISLNK(file->mode)) {
254                 const char *sl = F_SYMLINK(file);
255                 if (safe_symlinks && unsafe_symlink(sl, fname)) {
256                         if (INFO_GTE(SYMSAFE, 1)) {
257                                 rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
258                                         full_fname(buf), sl);
259                         }
260                         ret = 2;
261                 } else {
262                         if (do_symlink(sl, buf) < 0)
263                                 rsyserr(FERROR, errno, "link %s -> \"%s\"", full_fname(buf), sl);
264                         else if (DEBUG_GTE(BACKUP, 1))
265                                 rprintf(FINFO, "make_backup: SYMLINK %s successful.\n", fname);
266                         ret = 2;
267                 }
268         }
269 #endif
270
271         if (!ret && !S_ISREG(file->mode)) {
272                 rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
273                 unmake_file(file);
274 #ifdef SUPPORT_ACLS
275                 uncache_tmp_acls();
276 #endif
277 #ifdef SUPPORT_XATTRS
278                 uncache_tmp_xattrs();
279 #endif
280                 return 2;
281         }
282
283         /* Copy to backup tree if a file. */
284         if (!ret) {
285                 if (copy_file(fname, buf, -1, file->mode) < 0) {
286                         rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
287                                 full_fname(fname), buf);
288                         unmake_file(file);
289 #ifdef SUPPORT_ACLS
290                         uncache_tmp_acls();
291 #endif
292 #ifdef SUPPORT_XATTRS
293                         uncache_tmp_xattrs();
294 #endif
295                         return 0;
296                 }
297                 if (DEBUG_GTE(BACKUP, 1))
298                         rprintf(FINFO, "make_backup: COPY %s successful.\n", fname);
299                 ret = 2;
300         }
301
302         save_preserve_xattrs = preserve_xattrs;
303         preserve_xattrs = 0;
304         set_file_attrs(buf, file, NULL, fname, 0);
305         preserve_xattrs = save_preserve_xattrs;
306
307         unmake_file(file);
308 #ifdef SUPPORT_ACLS
309         uncache_tmp_acls();
310 #endif
311 #ifdef SUPPORT_XATTRS
312         uncache_tmp_xattrs();
313 #endif
314
315   success:
316         if (INFO_GTE(BACKUP, 1))
317                 rprintf(FINFO, "backed up %s to %s\n", fname, buf);
318         return ret;
319 }