X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffindlib%2Ffind_one.c;h=c27060ca5d77c19a704284c6f4acd3d960decfee;hb=9cfbe86f83144637951ce85b5ecf1e653d21a75f;hp=704ee9c4448c2531a2ef56dc3d093ec1c7e3ff6a;hpb=dca40049701012f57ee10d2aab330a2240e7c471;p=bacula%2Fbacula diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 704ee9c444..c27060ca5d 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -1,7 +1,7 @@ /* 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. @@ -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,19 +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 (have_win32_api() && ff_pkt->statp.st_rdev) { + /* + * 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. @@ -523,7 +570,7 @@ 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); + 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; @@ -552,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; @@ -568,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; } @@ -591,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; } @@ -635,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; } @@ -652,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; } @@ -690,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; }