2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
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 General Public License for more details.
18 You should have received a copy of the GNU 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
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 This file was derived from GNU TAR source code. Except for a few key
31 ideas, it has been entirely rewritten for Bacula.
35 Thanks to the TAR programmers.
44 #include <sys/param.h>
45 #include <sys/mount.h>
49 extern int32_t name_max; /* filename max length */
50 extern int32_t path_max; /* path name max length */
53 * Structure for keeping track of hard linked files, we
54 * keep an entry for each hardlinked file that we save,
55 * which is the first one found. For all the other files that
56 * are linked to this one, we save only the directory
57 * entry so we can link it.
61 dev_t dev; /* device */
62 ino_t ino; /* inode with device is unique */
64 uint32_t FileIndex; /* Bacula FileIndex of this file */
65 char name[1]; /* The name */
68 typedef struct f_link link_t;
69 #define LINK_HASHTABLE_BITS 16
70 #define LINK_HASHTABLE_SIZE (1<<LINK_HASHTABLE_BITS)
71 #define LINK_HASHTABLE_MASK (LINK_HASHTABLE_SIZE-1)
73 static inline int LINKHASH(const struct stat &info)
75 int hash = info.st_dev;
76 unsigned long long i = info.st_ino;
84 return hash & LINK_HASHTABLE_MASK;
88 * Create a new directory Find File packet, but copy
89 * some of the essential info from the current packet.
90 * However, be careful to zero out the rest of the
93 static FF_PKT *new_dir_ff_pkt(FF_PKT *ff_pkt)
95 FF_PKT *dir_ff_pkt = (FF_PKT *)bmalloc(sizeof(FF_PKT));
96 memcpy(dir_ff_pkt, ff_pkt, sizeof(FF_PKT));
97 dir_ff_pkt->fname = bstrdup(ff_pkt->fname);
98 dir_ff_pkt->link = bstrdup(ff_pkt->link);
99 dir_ff_pkt->sys_fname = get_pool_memory(PM_FNAME);
100 dir_ff_pkt->included_files_list = NULL;
101 dir_ff_pkt->excluded_files_list = NULL;
102 dir_ff_pkt->excluded_paths_list = NULL;
103 dir_ff_pkt->linkhash = NULL;
104 dir_ff_pkt->fname_save = NULL;
105 dir_ff_pkt->link_save = NULL;
110 * Free the temp directory ff_pkt
112 static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
114 free(dir_ff_pkt->fname);
115 free(dir_ff_pkt->link);
116 free_pool_memory(dir_ff_pkt->sys_fname);
117 if (dir_ff_pkt->fname_save) {
118 free_pool_memory(dir_ff_pkt->fname_save);
120 if (dir_ff_pkt->link_save) {
121 free_pool_memory(dir_ff_pkt->link_save);
127 * Check to see if we allow the file system type of a file or directory.
128 * If we do not have a list of file system types, we accept anything.
130 static int accept_fstype(FF_PKT *ff, void *dummy) {
135 if (ff->fstypes.size()) {
137 if (!fstype(ff->fname, fs, sizeof(fs))) {
138 Dmsg1(50, "Cannot determine file system type for \"%s\"\n", ff->fname);
140 for (i = 0; i < ff->fstypes.size(); ++i) {
141 if (strcmp(fs, (char *)ff->fstypes.get(i)) == 0) {
142 Dmsg2(100, "Accepting fstype %s for \"%s\"\n", fs, ff->fname);
146 Dmsg3(200, "fstype %s for \"%s\" does not match %s\n", fs,
147 ff->fname, ff->fstypes.get(i));
155 * Check to see if we allow the drive type of a file or directory.
156 * If we do not have a list of drive types, we accept anything.
158 static int accept_drivetype(FF_PKT *ff, void *dummy) {
163 if (ff->drivetypes.size()) {
165 if (!drivetype(ff->fname, dt, sizeof(dt))) {
166 Dmsg1(50, "Cannot determine drive type for \"%s\"\n", ff->fname);
168 for (i = 0; i < ff->drivetypes.size(); ++i) {
169 if (strcmp(dt, (char *)ff->drivetypes.get(i)) == 0) {
170 Dmsg2(100, "Accepting drive type %s for \"%s\"\n", dt, ff->fname);
174 Dmsg3(200, "drive type %s for \"%s\" does not match %s\n", dt,
175 ff->fname, ff->drivetypes.get(i));
183 * This function determines whether we can use getattrlist()
184 * It's odd, but we have to use the function to determine that...
185 * Also, the man pages talk about things as if they were implemented.
187 * On Mac OS X, this succesfully differentiates between HFS+ and UFS
188 * volumes, which makes me trust it is OK for others, too.
190 static bool volume_has_attrlist(const char *fname)
192 #ifdef HAVE_DARWIN_OS
194 struct volinfo_struct {
195 unsigned long length; /* Mandatory field */
196 vol_capabilities_attr_t info; /* Volume capabilities */
198 struct attrlist attrList;
200 memset(&attrList, 0, sizeof(attrList));
201 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
202 attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES;
203 if (statfs(fname, &st) == 0) {
204 /* We need to check on the mount point */
205 if (getattrlist(st.f_mntonname, &attrList, &vol, sizeof(vol), FSOPT_NOFOLLOW) == 0
206 && (vol.info.capabilities[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_ATTRLIST)
207 && (vol.info.valid[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_ATTRLIST)) {
215 /* check if a file have changed during backup and display an error */
216 bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt)
219 Dmsg1(500, "has_file_changed fname=%s\n",ff_pkt->fname);
221 if (ff_pkt->type != FT_REG) { /* not a regular file */
225 if (lstat(ff_pkt->fname, &statp) != 0) {
227 Jmsg(jcr, M_WARNING, 0,
228 _("Cannot stat file %s: ERR=%s\n"),ff_pkt->fname,be.bstrerror());
232 if (statp.st_mtime != ff_pkt->statp.st_mtime) {
233 /* TODO: add time of changes */
234 Jmsg(jcr, M_ERROR, 0, _("%s mtime changed during backup.\n"), ff_pkt->fname);
238 if (statp.st_ctime != ff_pkt->statp.st_ctime) {
239 /* TODO: add time of changes */
240 Jmsg(jcr, M_ERROR, 0, _("%s ctime changed during backup.\n"), ff_pkt->fname);
244 if (statp.st_size != ff_pkt->statp.st_size) {
245 /* TODO: add size change */
246 Jmsg(jcr, M_ERROR, 0, _("%s size changed during backup.\n"),ff_pkt->fname);
250 if ((statp.st_blksize != ff_pkt->statp.st_blksize) ||
251 (statp.st_blocks != ff_pkt->statp.st_blocks)) {
252 /* TODO: add size change */
253 Jmsg(jcr, M_ERROR, 0, _("%s size changed during backup.\n"),ff_pkt->fname);
261 * Find a single file.
262 * handle_file is the callback for handling the file.
264 * parent_device is the device we are currently on
265 * top_level is 1 when not recursing or 0 when
266 * descending into a directory.
269 find_one_file(JCR *jcr, FF_PKT *ff_pkt,
270 int handle_file(FF_PKT *ff, void *hpkt, bool top_level),
271 void *pkt, char *fname, dev_t parent_device, bool top_level)
273 struct utimbuf restore_times;
277 ff_pkt->fname = ff_pkt->link = fname;
279 if (lstat(fname, &ff_pkt->statp) != 0) {
280 /* Cannot stat file */
281 ff_pkt->type = FT_NOSTAT;
282 ff_pkt->ff_errno = errno;
283 return handle_file(ff_pkt, pkt, top_level);
286 Dmsg1(300, "File ----: %s\n", fname);
288 /* Save current times of this directory in case we need to
289 * reset them because the user doesn't want them changed.
291 restore_times.actime = ff_pkt->statp.st_atime;
292 restore_times.modtime = ff_pkt->statp.st_mtime;
295 * We check for allowed fstypes and drivetypes at top_level and fstype change (below).
298 if (!accept_fstype(ff_pkt, NULL)) {
299 ff_pkt->type = FT_INVALIDFS;
300 if (ff_pkt->flags & FO_KEEPATIME) {
301 utime(fname, &restore_times);
306 if (!fstype(ff_pkt->fname, fs, sizeof(fs))) {
307 bstrncpy(fs, "unknown", sizeof(fs));
310 Jmsg(jcr, M_INFO, 0, _("Top level directory \"%s\" has unlisted fstype \"%s\"\n"), fname, fs);
311 return 1; /* Just ignore this error - or the whole backup is cancelled */
313 if (!accept_drivetype(ff_pkt, NULL)) {
314 ff_pkt->type = FT_INVALIDDT;
315 if (ff_pkt->flags & FO_KEEPATIME) {
316 utime(fname, &restore_times);
321 if (!drivetype(ff_pkt->fname, dt, sizeof(dt))) {
322 bstrncpy(dt, "unknown", sizeof(dt));
325 Jmsg(jcr, M_INFO, 0, _("Top level directory \"%s\" has an unlisted drive type \"%s\"\n"), fname, dt);
326 return 1; /* Just ignore this error - or the whole backup is cancelled */
328 ff_pkt->volhas_attrlist = volume_has_attrlist(fname);
332 * If this is an Incremental backup, see if file was modified
333 * since our last "save_time", presumably the last Full save
336 if (ff_pkt->incremental && !S_ISDIR(ff_pkt->statp.st_mode)) {
337 Dmsg1(300, "Non-directory incremental: %s\n", ff_pkt->fname);
338 /* Not a directory */
339 if (ff_pkt->statp.st_mtime < ff_pkt->save_time
340 && ((ff_pkt->flags & FO_MTIMEONLY) ||
341 ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
342 /* Incremental option, file not changed */
343 ff_pkt->type = FT_NOCHG;
344 return handle_file(ff_pkt, pkt, top_level);
348 #ifdef HAVE_DARWIN_OS
349 if (ff_pkt->flags & FO_HFSPLUS && ff_pkt->volhas_attrlist
350 && S_ISREG(ff_pkt->statp.st_mode)) {
351 /* TODO: initialise attrList once elsewhere? */
352 struct attrlist attrList;
353 memset(&attrList, 0, sizeof(attrList));
354 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
355 attrList.commonattr = ATTR_CMN_FNDRINFO;
356 attrList.fileattr = ATTR_FILE_RSRCLENGTH;
357 if (getattrlist(fname, &attrList, &ff_pkt->hfsinfo,
358 sizeof(ff_pkt->hfsinfo), FSOPT_NOFOLLOW) != 0) {
359 ff_pkt->type = FT_NOSTAT;
360 ff_pkt->ff_errno = errno;
361 return handle_file(ff_pkt, pkt, top_level);
368 * Handle hard linked files
370 * Maintain a list of hard linked files already backed up. This
371 * allows us to ensure that the data of each file gets backed
374 if (!(ff_pkt->flags & FO_NO_HARDLINK)
375 && ff_pkt->statp.st_nlink > 1
376 && (S_ISREG(ff_pkt->statp.st_mode)
377 || S_ISCHR(ff_pkt->statp.st_mode)
378 || S_ISBLK(ff_pkt->statp.st_mode)
379 || S_ISFIFO(ff_pkt->statp.st_mode)
380 || S_ISSOCK(ff_pkt->statp.st_mode))) {
383 if (ff_pkt->linkhash == NULL) {
384 ff_pkt->linkhash = (link_t **)bmalloc(LINK_HASHTABLE_SIZE * sizeof(link_t *));
385 memset(ff_pkt->linkhash, 0, LINK_HASHTABLE_SIZE * sizeof(link_t *));
387 const int linkhash = LINKHASH(ff_pkt->statp);
389 /* Search link list of hard linked files */
390 for (lp = ff_pkt->linkhash[linkhash]; lp; lp = lp->next)
391 if (lp->ino == (ino_t)ff_pkt->statp.st_ino &&
392 lp->dev == (dev_t)ff_pkt->statp.st_dev) {
393 /* If we have already backed up the hard linked file don't do it again */
394 if (strcmp(lp->name, fname) == 0) {
395 return 1; /* ignore */
397 ff_pkt->link = lp->name;
398 ff_pkt->type = FT_LNKSAVED; /* Handle link, file already saved */
399 ff_pkt->LinkFI = lp->FileIndex;
400 return handle_file(ff_pkt, pkt, top_level);
403 /* File not previously dumped. Chain it into our list. */
404 len = strlen(fname) + 1;
405 lp = (struct f_link *)bmalloc(sizeof(struct f_link) + len);
406 lp->ino = ff_pkt->statp.st_ino;
407 lp->dev = ff_pkt->statp.st_dev;
408 bstrncpy(lp->name, fname, len);
409 lp->next = ff_pkt->linkhash[linkhash];
410 ff_pkt->linkhash[linkhash] = lp;
411 ff_pkt->linked = lp; /* mark saved link */
413 ff_pkt->linked = NULL;
416 /* This is not a link to a previously dumped file, so dump it. */
417 if (S_ISREG(ff_pkt->statp.st_mode)) {
420 sizeleft = ff_pkt->statp.st_size;
422 /* Don't bother opening empty, world readable files. Also do not open
423 files when archive is meant for /dev/null. */
424 if (ff_pkt->null_output_device || (sizeleft == 0
425 && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) {
426 ff_pkt->type = FT_REGE;
428 ff_pkt->type = FT_REG;
430 rtn_stat = handle_file(ff_pkt, pkt, top_level);
431 if (ff_pkt->linked) {
432 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
434 if (ff_pkt->flags & FO_KEEPATIME) {
435 utime(fname, &restore_times);
440 } else if (S_ISLNK(ff_pkt->statp.st_mode)) { /* soft link */
442 char *buffer = (char *)alloca(path_max + name_max + 102);
444 size = readlink(fname, buffer, path_max + name_max + 101);
446 /* Could not follow link */
447 ff_pkt->type = FT_NOFOLLOW;
448 ff_pkt->ff_errno = errno;
449 rtn_stat = handle_file(ff_pkt, pkt, top_level);
450 if (ff_pkt->linked) {
451 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
456 ff_pkt->link = buffer; /* point to link */
457 ff_pkt->type = FT_LNK; /* got a real link */
458 rtn_stat = handle_file(ff_pkt, pkt, top_level);
459 if (ff_pkt->linked) {
460 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
464 } else if (S_ISDIR(ff_pkt->statp.st_mode)) {
466 struct dirent *entry, *result;
471 dev_t our_device = ff_pkt->statp.st_dev;
473 bool volhas_attrlist = ff_pkt->volhas_attrlist; /* Remember this if we recurse */
476 * If we are using Win32 (non-portable) backup API, don't check
477 * access as everything is more complicated, and
478 * in principle, we should be able to access everything.
480 if (!have_win32_api() || (ff_pkt->flags & FO_PORTABLE)) {
481 if (access(fname, R_OK) == -1 && geteuid() != 0) {
482 /* Could not access() directory */
483 ff_pkt->type = FT_NOACCESS;
484 ff_pkt->ff_errno = errno;
485 rtn_stat = handle_file(ff_pkt, pkt, top_level);
486 if (ff_pkt->linked) {
487 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
493 /* Build a canonical directory name with a trailing slash in link var */
495 link_len = len + 200;
496 link = (char *)bmalloc(link_len + 2);
497 bstrncpy(link, fname, link_len);
498 /* Strip all trailing slashes */
499 while (len >= 1 && IsPathSeparator(link[len - 1]))
501 link[len++] = '/'; /* add back one */
505 if (ff_pkt->incremental &&
506 (ff_pkt->statp.st_mtime < ff_pkt->save_time &&
507 ((ff_pkt->flags & FO_MTIMEONLY) ||
508 ff_pkt->statp.st_ctime < ff_pkt->save_time))) {
509 /* Incremental option, directory entry not changed */
510 ff_pkt->type = FT_DIRNOCHG;
512 ff_pkt->type = FT_DIRBEGIN;
515 * Note, we return the directory to the calling program (handle_file)
516 * when we first see the directory (FT_DIRBEGIN.
517 * This allows the program to apply matches and make a
518 * choice whether or not to accept it. If it is accepted, we
519 * do not immediately save it, but do so only after everything
520 * in the directory is seen (i.e. the FT_DIREND).
522 rtn_stat = handle_file(ff_pkt, pkt, top_level);
523 if (rtn_stat < 1) { /* ignore or error status */
527 /* Done with DIRBEGIN, next call will be DIREND */
528 if (ff_pkt->type == FT_DIRBEGIN) {
529 ff_pkt->type = FT_DIREND;
533 * Create a temporary ff packet for this directory
534 * entry, and defer handling the directory until
535 * we have recursed into it. This saves the
536 * directory after all files have been processed, and
537 * during the restore, the directory permissions will
538 * be reset after all the files have been restored.
540 Dmsg1(300, "Create temp ff packet for dir: %s\n", ff_pkt->fname);
541 FF_PKT *dir_ff_pkt = new_dir_ff_pkt(ff_pkt);
544 * Do not descend into subdirectories (recurse) if the
545 * user has turned it off for this directory.
547 * If we are crossing file systems, we are either not allowed
548 * to cross, or we may be restricted by a list of permitted
551 if (!top_level && ff_pkt->flags & FO_NO_RECURSION) {
552 ff_pkt->type = FT_NORECURSE;
554 } else if (!top_level && parent_device != ff_pkt->statp.st_dev) {
555 if(!(ff_pkt->flags & FO_MULTIFS)) {
556 ff_pkt->type = FT_NOFSCHG;
558 } else if (!accept_fstype(ff_pkt, NULL)) {
559 ff_pkt->type = FT_INVALIDFS;
562 ff_pkt->volhas_attrlist = volume_has_attrlist(fname);
565 /* If not recursing, just backup dir and return */
567 rtn_stat = handle_file(ff_pkt, pkt, top_level);
568 if (ff_pkt->linked) {
569 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
572 free_dir_ff_pkt(dir_ff_pkt);
573 ff_pkt->link = ff_pkt->fname; /* reset "link" */
574 if (ff_pkt->flags & FO_KEEPATIME) {
575 utime(fname, &restore_times);
580 ff_pkt->link = ff_pkt->fname; /* reset "link" */
583 * Descend into or "recurse" into the directory to read
584 * all the files in it.
587 if ((directory = opendir(fname)) == NULL) {
588 ff_pkt->type = FT_NOOPEN;
589 ff_pkt->ff_errno = errno;
590 rtn_stat = handle_file(ff_pkt, pkt, top_level);
591 if (ff_pkt->linked) {
592 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
595 free_dir_ff_pkt(dir_ff_pkt);
600 * Process all files in this directory entry (recursing).
601 * This would possibly run faster if we chdir to the directory
602 * before traversing it.
605 entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
606 for ( ; !job_canceled(jcr); ) {
610 status = readdir_r(directory, entry, &result);
611 if (status != 0 || result == NULL) {
612 // Dmsg2(99, "readdir returned stat=%d result=0x%x\n",
613 // status, (long)result);
616 ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
618 /* Skip `.', `..', and excluded file names. */
619 if (p[0] == '\0' || (p[0] == '.' && (p[1] == '\0' ||
620 (p[1] == '.' && p[2] == '\0')))) {
624 if ((int)NAMELEN(entry) + len >= link_len) {
625 link_len = len + NAMELEN(entry) + 1;
626 link = (char *)brealloc(link, link_len + 1);
629 for (i=0; i < (int)NAMELEN(entry); i++) {
633 if (!file_is_excluded(ff_pkt, link)) {
634 rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, false);
635 if (ff_pkt->linked) {
636 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
645 * Now that we have recursed through all the files in the
646 * directory, we "save" the directory so that after all
647 * the files are restored, this entry will serve to reset
648 * the directory modes and dates. Temp directory values
649 * were used without this record.
651 handle_file(dir_ff_pkt, pkt, top_level); /* handle directory entry */
652 if (ff_pkt->linked) {
653 ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex;
655 free_dir_ff_pkt(dir_ff_pkt);
657 if (ff_pkt->flags & FO_KEEPATIME) {
658 utime(fname, &restore_times);
660 ff_pkt->volhas_attrlist = volhas_attrlist; /* Restore value in case it changed. */
662 } /* end check for directory */
665 * If it is explicitly mentioned (i.e. top_level) and is
666 * a block device, we do a raw backup of it or if it is
667 * a fifo, we simply read it.
669 #ifdef HAVE_FREEBSD_OS
671 * On FreeBSD, all block devices are character devices, so
672 * to be able to read a raw disk, we need the check for
673 * a character device.
674 * crw-r----- 1 root operator - 116, 0x00040002 Jun 9 19:32 /dev/ad0s3
675 * crw-r----- 1 root operator - 116, 0x00040002 Jun 9 19:32 /dev/rad0s3
677 if (top_level && (S_ISBLK(ff_pkt->statp.st_mode) || S_ISCHR(ff_pkt->statp.st_mode))) {
679 if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) {
681 ff_pkt->type = FT_RAW; /* raw partition */
682 } else if (top_level && S_ISFIFO(ff_pkt->statp.st_mode) &&
683 ff_pkt->flags & FO_READFIFO) {
684 ff_pkt->type = FT_FIFO;
686 /* The only remaining types are special (character, ...) files */
687 ff_pkt->type = FT_SPEC;
689 rtn_stat = handle_file(ff_pkt, pkt, top_level);
690 if (ff_pkt->linked) {
691 ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
696 int term_find_one(FF_PKT *ff)
698 struct f_link *lp, *lc;
703 if (ff->linkhash == NULL) return 0;
705 for (i =0 ; i < LINK_HASHTABLE_SIZE; i ++) {
706 /* Free up list of hard linked files */
707 lp = ff->linkhash[i];
716 ff->linkhash[i] = NULL;