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