1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2016 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, November MM
25 */
26 /**
27 * @file
28 * Create a file, and reset the modes
29 */
30
31 #include "include/bareos.h"
32 #include "include/jcr.h"
33 #include "find.h"
34 #include "findlib/makepath.h"
35 #include "findlib/create_file.h"
36 #include "lib/path_list.h"
37 #include "lib/btimers.h"
38
39 #ifndef S_IRWXUGO
40 #define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
41 #endif
42
43 #ifndef IS_CTG
44 #define IS_CTG(x) 0
45 #define O_CTG 0
46 #endif
47
48 static int SeparatePathAndFile(JobControlRecord *jcr, char *fname, char *ofile);
49 static int PathAlreadySeen(JobControlRecord *jcr, char *path, int pnl);
50
51 /**
52 * Create the file, or the directory
53 *
54 * fname is the original filename
55 * ofile is the output filename (may be in a different directory)
56 *
57 * Returns: CF_SKIP if file should be skipped
58 * CF_ERROR on error
59 * CF_EXTRACT file created and data to restore
60 * CF_CREATED file created no data to restore
61 *
62 * Note, we create the file here, except for special files,
63 * we do not set the attributes because we want to first
64 * write the file, then when the writing is done, set the
65 * attributes.
66 *
67 * So, we return with the file descriptor open for normal files.
68 */
CreateFile(JobControlRecord * jcr,Attributes * attr,BareosWinFilePacket * bfd,int replace)69 int CreateFile(JobControlRecord *jcr, Attributes *attr, BareosWinFilePacket *bfd, int replace)
70 {
71 mode_t new_mode, parent_mode;
72 int flags;
73 uid_t uid;
74 gid_t gid;
75 int pnl;
76 bool exists = false;
77 struct stat mstatp;
78 #ifndef HAVE_WIN32
79 bool isOnRoot;
80 #endif
81
82 bfd->reparse_point = false;
83 if (is_win32_stream(attr->data_stream)) {
84 set_win32_backup(bfd);
85 } else {
86 SetPortableBackup(bfd);
87 }
88
89 new_mode = attr->statp.st_mode;
90 Dmsg3(200, "type=%d newmode=%04o file=%s\n", attr->type, (new_mode & ~S_IFMT), attr->ofname);
91 parent_mode = S_IWUSR | S_IXUSR | new_mode;
92 gid = attr->statp.st_gid;
93 uid = attr->statp.st_uid;
94
95 #ifdef HAVE_WIN32
96 if (!bfd->use_backup_api) {
97 /*
98 * Eliminate invalid windows filename characters from foreign filenames
99 */
100 char *ch = (char *)attr->ofname;
101 if (ch[0] != 0 && ch[1] != 0) {
102 ch += 2;
103 while (*ch) {
104 switch (*ch) {
105 case ':':
106 case '<':
107 case '>':
108 case '*':
109 case '?':
110 case '|':
111 *ch = '_';
112 break;
113 }
114 ch++;
115 }
116 }
117 }
118 #endif
119
120 Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
121 if (lstat(attr->ofname, &mstatp) == 0) {
122 exists = true;
123 switch (replace) {
124 case REPLACE_IFNEWER:
125 if (attr->statp.st_mtime <= mstatp.st_mtime) {
126 Qmsg(jcr, M_INFO, 0, _("File skipped. Not newer: %s\n"), attr->ofname);
127 return CF_SKIP;
128 }
129 break;
130 case REPLACE_IFOLDER:
131 if (attr->statp.st_mtime >= mstatp.st_mtime) {
132 Qmsg(jcr, M_INFO, 0, _("File skipped. Not older: %s\n"), attr->ofname);
133 return CF_SKIP;
134 }
135 break;
136 case REPLACE_NEVER:
137 /*
138 * Set attributes if we created this directory
139 */
140 if (attr->type == FT_DIREND && PathListLookup(jcr->path_list, attr->ofname)) {
141 break;
142 }
143 Qmsg(jcr, M_INFO, 0, _("File skipped. Already exists: %s\n"), attr->ofname);
144 return CF_SKIP;
145 case REPLACE_ALWAYS:
146 break;
147 }
148 }
149
150 switch (attr->type) {
151 case FT_RAW: /* Raw device to be written */
152 case FT_FIFO: /* FIFO to be written to */
153 case FT_LNKSAVED: /* Hard linked, file already saved */
154 case FT_LNK:
155 case FT_SPEC: /* Fifo, ... to be backed up */
156 case FT_REGE: /* Empty file */
157 case FT_REG: /* Regular file */
158 /*
159 * Note, we do not delete FT_RAW because these are device files
160 * or FIFOs that should already exist. If we blow it away,
161 * we may blow away a FIFO that is being used to read the
162 * restore data, or we may blow away a partition definition.
163 */
164 if (exists && attr->type != FT_RAW && attr->type != FT_FIFO) {
165 /* Get rid of old copy */
166 Dmsg1(400, "unlink %s\n", attr->ofname);
167 if (SecureErase(jcr, attr->ofname) == -1) {
168 BErrNo be;
169
170 Qmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"),
171 attr->ofname, be.bstrerror());
172 /* Continue despite error */
173 }
174 }
175
176 /*
177 * Here we do some preliminary work for all the above
178 * types to create the path to the file if it does
179 * not already exist. Below, we will split to
180 * do the file type specific work
181 */
182 pnl = SeparatePathAndFile(jcr, attr->fname, attr->ofname);
183 if (pnl < 0) {
184 return CF_ERROR;
185 }
186
187 /*
188 * If path length is <= 0 we are making a file in the root
189 * directory. Assume that the directory already exists.
190 */
191 if (pnl > 0) {
192 char savechr;
193 savechr = attr->ofname[pnl];
194 attr->ofname[pnl] = 0; /* Terminate path */
195
196 if (!PathAlreadySeen(jcr, attr->ofname, pnl)) {
197 Dmsg1(400, "Make path %s\n", attr->ofname);
198 /*
199 * If we need to make the directory, ensure that it is with
200 * execute bit set (i.e. parent_mode), and preserve what already
201 * exists. Normally, this should do nothing.
202 */
203 if (!makepath(attr, attr->ofname, parent_mode, parent_mode, uid, gid, 1)) {
204 Dmsg1(10, "Could not make path. %s\n", attr->ofname);
205 attr->ofname[pnl] = savechr; /* restore full name */
206 return CF_ERROR;
207 }
208 }
209 attr->ofname[pnl] = savechr; /* restore full name */
210 }
211
212 /*
213 * Now we do the specific work for each file type
214 */
215 switch(attr->type) {
216 case FT_REGE:
217 case FT_REG:
218 Dmsg1(100, "Create=%s\n", attr->ofname);
219 flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /* O_NOFOLLOW; */
220 if (IS_CTG(attr->statp.st_mode)) {
221 flags |= O_CTG; /* set contiguous bit if needed */
222 }
223
224 if (IsBopen(bfd)) {
225 Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
226 bclose(bfd);
227 }
228
229 if (bopen(bfd, attr->ofname, flags, 0, attr->statp.st_rdev) < 0) {
230 BErrNo be;
231
232 be.SetErrno(bfd->BErrNo);
233 Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), attr->ofname, be.bstrerror());
234 Dmsg2(100,"Could not create %s: ERR=%s\n", attr->ofname, be.bstrerror());
235
236 return CF_ERROR;
237 }
238
239 return CF_EXTRACT;
240
241 #ifndef HAVE_WIN32 /* None of these exist in MS Windows */
242 case FT_RAW: /* Bareos raw device e.g. /dev/sda1 */
243 case FT_FIFO: /* Bareos fifo to save data */
244 case FT_SPEC:
245 flags = O_WRONLY | O_BINARY;
246
247 isOnRoot = bstrcmp(attr->fname, attr->ofname) ? 1 : 0;
248 if (S_ISFIFO(attr->statp.st_mode)) {
249 Dmsg1(400, "Restore fifo: %s\n", attr->ofname);
250 if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
251 BErrNo be;
252 Qmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
253 attr->ofname, be.bstrerror());
254 return CF_ERROR;
255 }
256 } else if (S_ISSOCK(attr->statp.st_mode)) {
257 Dmsg1(200, "Skipping restore of socket: %s\n", attr->ofname);
258 #ifdef S_IFDOOR /* Solaris high speed RPC mechanism */
259 } else if (S_ISDOOR(attr->statp.st_mode)) {
260 Dmsg1(200, "Skipping restore of door file: %s\n", attr->ofname);
261 #endif
262 #ifdef S_IFPORT /* Solaris event port for handling AIO */
263 } else if (S_ISPORT(attr->statp.st_mode)) {
264 Dmsg1(200, "Skipping restore of event port file: %s\n", attr->ofname);
265 #endif
266 } else if ((S_ISBLK(attr->statp.st_mode) || S_ISCHR(attr->statp.st_mode)) && !exists && isOnRoot) {
267 /*
268 * Fatal: Restoring a device on root-file system, but device node does not exist.
269 * Should not create a dump file.
270 */
271 Qmsg1(jcr, M_ERROR, 0, _("Device restore on root failed, device %s missing.\n"), attr->fname);
272 return CF_ERROR;
273 } else if (S_ISBLK(attr->statp.st_mode) || S_ISCHR(attr->statp.st_mode)) {
274 Dmsg1(400, "Restoring a device as a file: %s\n", attr->ofname);
275 flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
276 } else {
277 Dmsg1(400, "Restore node: %s\n", attr->ofname);
278 if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
279 BErrNo be;
280 Qmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
281 attr->ofname, be.bstrerror());
282 return CF_ERROR;
283 }
284 }
285
286 /*
287 * Here we are going to attempt to restore to a FIFO, which
288 * means that the FIFO must already exist, AND there must
289 * be some process already attempting to read from the
290 * FIFO, so we open it write-only.
291 */
292 if (attr->type == FT_RAW || attr->type == FT_FIFO) {
293 btimer_t *tid;
294 Dmsg1(400, "FT_RAW|FT_FIFO %s\n", attr->ofname);
295 /*
296 * Timeout open() in 60 seconds
297 */
298 if (attr->type == FT_FIFO) {
299 Dmsg0(400, "Set FIFO timer\n");
300 tid = start_thread_timer(jcr, pthread_self(), 60);
301 } else {
302 tid = NULL;
303 }
304 if (IsBopen(bfd)) {
305 Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
306 }
307 Dmsg2(400, "open %s flags=%08o\n", attr->ofname, flags);
308 if ((bopen(bfd, attr->ofname, flags, 0, 0)) < 0) {
309 BErrNo be;
310 be.SetErrno(bfd->BErrNo);
311 Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
312 attr->ofname, be.bstrerror());
313 Dmsg2(400, "Could not open %s: ERR=%s\n", attr->ofname, be.bstrerror());
314 StopThreadTimer(tid);
315 return CF_ERROR;
316 }
317 StopThreadTimer(tid);
318 return CF_EXTRACT;
319 }
320 Dmsg1(400, "FT_SPEC %s\n", attr->ofname);
321 return CF_CREATED;
322
323 case FT_LNKSAVED: /* Hard linked, file already saved */
324 Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
325 if (link(attr->olname, attr->ofname) != 0) {
326 BErrNo be;
327 #ifdef HAVE_CHFLAGS
328 struct stat s;
329
330 /*
331 * If using BSD user flags, maybe has a file flag preventing this.
332 * So attempt to disable, retry link, and reset flags.
333 * Note that BSD securelevel may prevent disabling flag.
334 */
335 if (stat(attr->olname, &s) == 0 && s.st_flags != 0) {
336 if (chflags(attr->olname, 0) == 0) {
337 if (link(attr->olname, attr->ofname) != 0) {
338 /*
339 * Restore original file flags even when linking failed
340 */
341 if (chflags(attr->olname, s.st_flags) < 0) {
342 Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"),
343 attr->olname, be.bstrerror());
344 }
345 #endif /* HAVE_CHFLAGS */
346 Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
347 attr->ofname, attr->olname, be.bstrerror());
348 Dmsg3(200, "Could not hard link %s -> %s: ERR=%s\n",
349 attr->ofname, attr->olname, be.bstrerror());
350 return CF_ERROR;
351 #ifdef HAVE_CHFLAGS
352 }
353 /*
354 * Finally restore original file flags
355 */
356 if (chflags(attr->olname, s.st_flags) < 0) {
357 Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"),
358 attr->olname, be.bstrerror());
359 }
360 } else {
361 Qmsg2(jcr, M_ERROR, 0, _("Could not reset file flags for file %s: ERR=%s\n"),
362 attr->olname, be.bstrerror());
363 }
364 } else {
365 Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
366 attr->ofname, attr->olname, be.bstrerror());
367 return CF_ERROR;
368 }
369 #endif /* HAVE_CHFLAGS */
370
371 }
372 return CF_CREATED;
373
374 #endif /* HAVE_WIN32 */
375 #ifdef HAVE_WIN32
376 case FT_LNK:
377 /*
378 * Handle Windows Symlink-Like Reparse Points
379 * - Directory Symlinks
380 * - File Symlinks
381 * - Volume Mount Points
382 * - Junctions
383 */
384 Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
385 if (attr->statp.st_rdev & FILE_ATTRIBUTE_VOLUME_MOUNT_POINT) {
386 /*
387 * We do not restore volume mount points
388 */
389 Dmsg0(130, "Skipping Volume Mount Point\n");
390 return CF_SKIP;
391 }
392 if (win32_symlink(attr->olname, attr->ofname, attr->statp.st_rdev) != 0 && errno != EEXIST) {
393 BErrNo be;
394 Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
395 attr->ofname, attr->olname, be.bstrerror());
396 return CF_ERROR;
397 }
398 return CF_CREATED;
399 #else
400 case FT_LNK:
401 /*
402 * Unix/Linux symlink handling
403 */
404 Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
405 if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
406 BErrNo be;
407 Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
408 attr->ofname, attr->olname, be.bstrerror());
409 return CF_ERROR;
410 }
411 return CF_CREATED;
412 #endif
413 } /* End inner switch */
414
415 case FT_REPARSE:
416 case FT_JUNCTION:
417 bfd->reparse_point = true;
418 /*
419 * Fall through wanted
420 */
421 case FT_DIRBEGIN:
422 case FT_DIREND:
423 Dmsg2(200, "Make dir mode=%04o dir=%s\n", (new_mode & ~S_IFMT), attr->ofname);
424 if (!makepath(attr, attr->ofname, new_mode, parent_mode, uid, gid, 0)) {
425 return CF_ERROR;
426 }
427 /*
428 * If we are using the Win32 Backup API, we open the directory so
429 * that the security info will be read and saved.
430 */
431 if (!IsPortableBackup(bfd)) {
432 if (IsBopen(bfd)) {
433 Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
434 }
435 if (bopen(bfd, attr->ofname, O_WRONLY | O_BINARY, 0, attr->statp.st_rdev) < 0) {
436 BErrNo be;
437 be.SetErrno(bfd->BErrNo);
438 #ifdef HAVE_WIN32
439 /*
440 * Check for trying to create a drive, if so, skip
441 */
442 if (attr->ofname[1] == ':' &&
443 IsPathSeparator(attr->ofname[2]) &&
444 attr->ofname[3] == '\0') {
445 return CF_SKIP;
446 }
447 #endif
448 Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
449 attr->ofname, be.bstrerror());
450 return CF_ERROR;
451 }
452 return CF_EXTRACT;
453 } else {
454 return CF_CREATED;
455 }
456
457 case FT_DELETED:
458 Qmsg2(jcr, M_INFO, 0, _("Original file %s have been deleted: type=%d\n"), attr->fname, attr->type);
459 break;
460 /*
461 * The following should not occur
462 */
463 case FT_NOACCESS:
464 case FT_NOFOLLOW:
465 case FT_NOSTAT:
466 case FT_DIRNOCHG:
467 case FT_NOCHG:
468 case FT_ISARCH:
469 case FT_NORECURSE:
470 case FT_NOFSCHG:
471 case FT_NOOPEN:
472 Qmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
473 break;
474 default:
475 Qmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
476 break;
477 }
478 return CF_ERROR;
479 }
480
481 /**
482 * Returns: > 0 index into path where last path char is.
483 * 0 no path
484 * -1 filename is zero length
485 */
SeparatePathAndFile(JobControlRecord * jcr,char * fname,char * ofile)486 static int SeparatePathAndFile(JobControlRecord *jcr, char *fname, char *ofile)
487 {
488 char *f, *p, *q;
489 int fnl, pnl;
490
491 /* Separate pathname and filename */
492 for (q=p=f=ofile; *p; p++) {
493 #ifdef HAVE_WIN32
494 if (IsPathSeparator(*p)) {
495 f = q;
496 if (IsPathSeparator(p[1])) {
497 p++;
498 }
499 }
500 *q++ = *p; /* copy data */
501 #else
502 if (IsPathSeparator(*p)) {
503 f = q; /* possible filename */
504 }
505 q++;
506 #endif
507 }
508
509 if (IsPathSeparator(*f)) {
510 f++;
511 }
512 *q = 0; /* Terminate string */
513
514 fnl = q - f;
515 if (fnl == 0) {
516 /* The filename length must not be zero here because we
517 * are dealing with a file (i.e. FT_REGE or FT_REG).
518 */
519 Jmsg1(jcr, M_ERROR, 0, _("Zero length filename: %s\n"), fname);
520 return -1;
521 }
522 pnl = f - ofile - 1;
523 return pnl;
524 }
525
526 /**
527 * Primitive caching of path to prevent recreating a pathname
528 * each time as long as we remain in the same directory.
529 */
PathAlreadySeen(JobControlRecord * jcr,char * path,int pnl)530 static int PathAlreadySeen(JobControlRecord *jcr, char *path, int pnl)
531 {
532 if (!jcr->cached_path) {
533 jcr->cached_path = GetPoolMemory(PM_FNAME);
534 }
535 if (jcr->cached_pnl == pnl && bstrcmp(path, jcr->cached_path)) {
536 return 1;
537 }
538 PmStrcpy(jcr->cached_path, path);
539 jcr->cached_pnl = pnl;
540 return 0;
541 }
542