X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffindlib%2Ffind_one.c;h=c27060ca5d77c19a704284c6f4acd3d960decfee;hb=9cfbe86f83144637951ce85b5ecf1e653d21a75f;hp=106a519a6255735abc0c130cc8b36ac2d0068411;hpb=ab54e24ec150b9593621e898207605a94f135b29;p=bacula%2Fbacula diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 106a519a62..c27060ca5d 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -1,14 +1,14 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + Copyright (C) 2000-2008 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. This program is Free Software; you can redistribute it and/or modify it under the terms of version two of the GNU General Public - License as published by the Free Software Foundation plus additions - that are listed in the file LICENSE. + License as published by the Free Software Foundation and included + in the file LICENSE. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -257,6 +257,33 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) return false; } +/* + * In incremental/diffential or accurate backup, we + * say if the current file has changed. + */ +static bool check_changes(JCR *jcr, FF_PKT *ff_pkt) +{ + /* in special mode (like accurate backup), user can + * choose his comparison function. + */ + if (ff_pkt->check_fct) { + return ff_pkt->check_fct(jcr, ff_pkt); + } + + /* in normal modes (incr/diff), we use this default + * behaviour + */ + if (ff_pkt->incremental && + (ff_pkt->statp.st_mtime < ff_pkt->save_time && + ((ff_pkt->flags & FO_MTIMEONLY) || + ff_pkt->statp.st_ctime < ff_pkt->save_time))) + { + return false; + } + + return true; +} + /* * Find a single file. * handle_file is the callback for handling the file. @@ -267,8 +294,8 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) */ int find_one_file(JCR *jcr, FF_PKT *ff_pkt, - int handle_file(FF_PKT *ff, void *hpkt, bool top_level), - void *pkt, char *fname, dev_t parent_device, bool top_level) + int handle_file(JCR *jcr, FF_PKT *ff, bool top_level), + char *fname, dev_t parent_device, bool top_level) { struct utimbuf restore_times; int rtn_stat; @@ -280,7 +307,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, /* Cannot stat file */ ff_pkt->type = FT_NOSTAT; ff_pkt->ff_errno = errno; - return handle_file(ff_pkt, pkt, top_level); + return handle_file(jcr, ff_pkt, top_level); } Dmsg1(300, "File ----: %s\n", fname); @@ -327,22 +354,18 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } ff_pkt->volhas_attrlist = volume_has_attrlist(fname); } - /* * If this is an Incremental backup, see if file was modified * since our last "save_time", presumably the last Full save * or Incremental. */ - if (ff_pkt->incremental && !S_ISDIR(ff_pkt->statp.st_mode)) { - Dmsg1(300, "Non-directory incremental: %s\n", ff_pkt->fname); - /* Not a directory */ - if (ff_pkt->statp.st_mtime < ff_pkt->save_time - && ((ff_pkt->flags & FO_MTIMEONLY) || - ff_pkt->statp.st_ctime < ff_pkt->save_time)) { - /* Incremental option, file not changed */ - ff_pkt->type = FT_NOCHG; - return handle_file(ff_pkt, pkt, top_level); - } + if ( ff_pkt->incremental + && !S_ISDIR(ff_pkt->statp.st_mode) + && !check_changes(jcr, ff_pkt)) + { + Dmsg1(500, "Non-directory incremental: %s\n", ff_pkt->fname); + ff_pkt->type = FT_NOCHG; + return handle_file(jcr, ff_pkt, top_level); } #ifdef HAVE_DARWIN_OS @@ -358,7 +381,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, sizeof(ff_pkt->hfsinfo), FSOPT_NOFOLLOW) != 0) { ff_pkt->type = FT_NOSTAT; ff_pkt->ff_errno = errno; - return handle_file(ff_pkt, pkt, top_level); + return handle_file(jcr, ff_pkt, top_level); } } #endif @@ -397,7 +420,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, ff_pkt->link = lp->name; ff_pkt->type = FT_LNKSAVED; /* Handle link, file already saved */ ff_pkt->LinkFI = lp->FileIndex; - return handle_file(ff_pkt, pkt, top_level); + return handle_file(jcr, ff_pkt, top_level); } /* File not previously dumped. Chain it into our list. */ @@ -406,8 +429,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, lp->ino = ff_pkt->statp.st_ino; lp->dev = ff_pkt->statp.st_dev; bstrncpy(lp->name, fname, len); - lp->next = ff_pkt->linkhash[linkhash]; - ff_pkt->linkhash[linkhash] = lp; + lp->next = ff_pkt->linkhash[linkhash]; + ff_pkt->linkhash[linkhash] = lp; ff_pkt->linked = lp; /* mark saved link */ } else { ff_pkt->linked = NULL; @@ -427,7 +450,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } else { ff_pkt->type = FT_REG; } - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -446,7 +469,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, /* Could not follow link */ ff_pkt->type = FT_NOFOLLOW; ff_pkt->ff_errno = errno; - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -455,7 +478,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, buffer[size] = 0; ff_pkt->link = buffer; /* point to link */ ff_pkt->type = FT_LNK; /* got a real link */ - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -482,7 +505,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, /* Could not access() directory */ ff_pkt->type = FT_NOACCESS; ff_pkt->ff_errno = errno; - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -490,6 +513,28 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } } + /* + * Ignore this directory and everything below if the file .nobackup + * (or what is defined for IgnoreDir in this fileset) exists + */ + if (ff_pkt->ignoredir != NULL) { + struct stat sb; + char fname[MAXPATHLEN]; + + if (strlen(ff_pkt->fname) + strlen("/") + + strlen(ff_pkt->ignoredir) + 1 > MAXPATHLEN) + return 1; /* Is this wisdom? */ + + strcpy(fname, ff_pkt->fname); + strcat(fname, "/"); + strcat(fname, ff_pkt->ignoredir); + if (stat(fname, &sb) == 0) { + Dmsg2(100, "Directory '%s' ignored (found %s)\n", + ff_pkt->fname, ff_pkt->ignoredir); + return 1; /* Just ignore this directory */ + } + } + /* Build a canonical directory name with a trailing slash in link var */ len = strlen(fname); link_len = len + 200; @@ -502,15 +547,21 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, link[len] = 0; ff_pkt->link = link; - if (ff_pkt->incremental && - (ff_pkt->statp.st_mtime < ff_pkt->save_time && - ((ff_pkt->flags & FO_MTIMEONLY) || - ff_pkt->statp.st_ctime < ff_pkt->save_time))) { + if (ff_pkt->incremental && !check_changes(jcr, ff_pkt)) { /* Incremental option, directory entry not changed */ ff_pkt->type = FT_DIRNOCHG; } else { ff_pkt->type = FT_DIRBEGIN; } + /* + * We have set st_rdev to 1 if it is a reparse point, otherwise 0, + * if st_rdev is 2, it is a mount point + */ +#if defined(HAVE_WIN32) + if (ff_pkt->statp.st_rdev == WIN32_REPARSE_POINT) { + ff_pkt->type = FT_REPARSE; + } +#endif /* * Note, we return the directory to the calling program (handle_file) * when we first see the directory (FT_DIRBEGIN. @@ -519,8 +570,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * do not immediately save it, but do so only after everything * in the directory is seen (i.e. the FT_DIREND). */ - rtn_stat = handle_file(ff_pkt, pkt, top_level); - if (rtn_stat < 1) { /* ignore or error status */ + rtn_stat = handle_file(jcr, ff_pkt, top_level); + if (rtn_stat < 1 || ff_pkt->type == FT_REPARSE) { /* ignore or error status */ free(link); return rtn_stat; } @@ -548,10 +599,15 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * to cross, or we may be restricted by a list of permitted * file systems. */ + bool is_win32_mount_point = false; +#if defined(HAVE_WIN32) + is_win32_mount_point = ff_pkt->statp.st_rdev == WIN32_MOUNT_POINT; +#endif if (!top_level && ff_pkt->flags & FO_NO_RECURSION) { ff_pkt->type = FT_NORECURSE; recurse = false; - } else if (!top_level && parent_device != ff_pkt->statp.st_dev) { + } else if (!top_level && (parent_device != ff_pkt->statp.st_dev || + is_win32_mount_point)) { if(!(ff_pkt->flags & FO_MULTIFS)) { ff_pkt->type = FT_NOFSCHG; recurse = false; @@ -564,7 +620,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } /* If not recursing, just backup dir and return */ if (!recurse) { - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -587,7 +643,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, if ((directory = opendir(fname)) == NULL) { ff_pkt->type = FT_NOOPEN; ff_pkt->ff_errno = errno; - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -631,7 +687,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } *q = 0; if (!file_is_excluded(ff_pkt, link)) { - rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, false); + rtn_stat = find_one_file(jcr, ff_pkt, handle_file, link, our_device, false); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } @@ -648,7 +704,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * the directory modes and dates. Temp directory values * were used without this record. */ - handle_file(dir_ff_pkt, pkt, top_level); /* handle directory entry */ + handle_file(jcr, dir_ff_pkt, top_level); /* handle directory entry */ if (ff_pkt->linked) { ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex; } @@ -671,8 +727,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * On FreeBSD, all block devices are character devices, so * to be able to read a raw disk, we need the check for * a character device. -    * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/ad0s3 -    * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/rad0s3 + * crw-r----- 1 root operator - 116, 0x00040002 Jun 9 19:32 /dev/ad0s3 + * crw-r----- 1 root operator - 116, 0x00040002 Jun 9 19:32 /dev/rad0s3 */ if (top_level && (S_ISBLK(ff_pkt->statp.st_mode) || S_ISCHR(ff_pkt->statp.st_mode))) { #else @@ -686,7 +742,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, /* The only remaining types are special (character, ...) files */ ff_pkt->type = FT_SPEC; } - rtn_stat = handle_file(ff_pkt, pkt, top_level); + rtn_stat = handle_file(jcr, ff_pkt, top_level); if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; }