X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffindlib%2Ffind_one.c;h=b87a57108f53049b9607601e72a9591586c87a41;hb=b6a1f7208143a51f07573fe986fcea297f90944b;hp=38fbfa47b350c6de370d197d03870675cbfaf5dd;hpb=0ca08a92931dc6677546cbc9026bd6eac6bafea1;p=bacula%2Fbacula diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 38fbfa47b3..b87a57108f 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -1,29 +1,17 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2009 Free Software Foundation Europe e.V. + Copyright (C) 2000-2014 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 and included - in the file LICENSE. + 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 distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. + You may use this file and others of this release according to the + license defined in the LICENSE file, which includes the Affero General + Public License, v3.0 ("AGPLv3") and some additional permissions and + terms pursuant to its AGPLv3 Section 7. Bacula® is a registered trademark of Kern Sibbald. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. */ /* @@ -34,8 +22,6 @@ Thanks to the TAR programmers. - Version $Id$ - */ #include "bacula.h" @@ -61,6 +47,9 @@ struct f_link { dev_t dev; /* device */ ino_t ino; /* inode with device is unique */ uint32_t FileIndex; /* Bacula FileIndex of this file */ + int32_t digest_stream; /* Digest type if needed */ + uint32_t digest_len; /* Digest len if needed */ + char *digest; /* Checksum of the file if needed */ char name[1]; /* The name */ }; @@ -86,7 +75,7 @@ static inline int LINKHASH(const struct stat &info) /* * Create a new directory Find File packet, but copy * some of the essential info from the current packet. - * However, be careful to zero out the rest of the + * However, be careful to zero out the rest of the * packet. */ static FF_PKT *new_dir_ff_pkt(FF_PKT *ff_pkt) @@ -102,6 +91,7 @@ static FF_PKT *new_dir_ff_pkt(FF_PKT *ff_pkt) dir_ff_pkt->linkhash = NULL; dir_ff_pkt->fname_save = NULL; dir_ff_pkt->link_save = NULL; + dir_ff_pkt->ignoredir_fname = NULL; return dir_ff_pkt; } @@ -119,6 +109,9 @@ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt) if (dir_ff_pkt->link_save) { free_pool_memory(dir_ff_pkt->link_save); } + if (dir_ff_pkt->ignoredir_fname) { + free_pool_memory(dir_ff_pkt->ignoredir_fname); + } free(dir_ff_pkt); } @@ -239,33 +232,30 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) if (lstat(ff_pkt->fname, &statp) != 0) { berrno be; - Jmsg(jcr, M_WARNING, 0, + Jmsg(jcr, M_WARNING, 0, _("Cannot stat file %s: ERR=%s\n"),ff_pkt->fname,be.bstrerror()); return true; } if (statp.st_mtime != ff_pkt->statp.st_mtime) { - /* TODO: add time of changes */ Jmsg(jcr, M_ERROR, 0, _("%s mtime changed during backup.\n"), ff_pkt->fname); + Dmsg3(50, "%s mtime (%lld) changed during backup (%lld).\n", ff_pkt->fname, + (int64_t)ff_pkt->statp.st_mtime, (int64_t)statp.st_mtime); return true; } if (statp.st_ctime != ff_pkt->statp.st_ctime) { - /* TODO: add time of changes */ Jmsg(jcr, M_ERROR, 0, _("%s ctime changed during backup.\n"), ff_pkt->fname); - return true; - } - - if (statp.st_size != ff_pkt->statp.st_size) { - /* TODO: add size change */ - Jmsg(jcr, M_ERROR, 0, _("%s size changed during backup.\n"),ff_pkt->fname); + Dmsg3(50, "%s ctime (%lld) changed during backup (%lld).\n", ff_pkt->fname, + (int64_t)ff_pkt->statp.st_ctime, (int64_t)statp.st_ctime); return true; } - if ((statp.st_blksize != ff_pkt->statp.st_blksize) || - (statp.st_blocks != ff_pkt->statp.st_blocks)) { - /* TODO: add size change */ - Jmsg(jcr, M_ERROR, 0, _("%s size changed during backup.\n"),ff_pkt->fname); + if ((int64_t)statp.st_size != (int64_t)ff_pkt->statp.st_size) { + Jmsg(jcr, M_ERROR, 0, _("%s size of %lld changed during backup to %lld.n"),ff_pkt->fname, + (int64_t)ff_pkt->statp.st_size, (int64_t)statp.st_size); + Dmsg3(50, "%s size (%lld) changed during backup (%lld).\n", ff_pkt->fname, + (int64_t)ff_pkt->statp.st_size, (int64_t)statp.st_size); return true; } @@ -276,9 +266,9 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) * For incremental/diffential or accurate backups, we * determine if the current file has changed. */ -static bool check_changes(JCR *jcr, FF_PKT *ff_pkt) +bool check_changes(JCR *jcr, FF_PKT *ff_pkt) { - /* in special mode (like accurate backup), the programmer can + /* in special mode (like accurate backup), the programmer can * choose his comparison function. */ if (ff_pkt->check_fct) { @@ -291,14 +281,55 @@ static bool check_changes(JCR *jcr, FF_PKT *ff_pkt) 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))) + ff_pkt->statp.st_ctime < ff_pkt->save_time))) { return false; - } + } return true; } +static bool have_ignoredir(FF_PKT *ff_pkt) +{ + struct stat sb; + char *ignoredir; + + /* Ensure that pointers are defined */ + if (!ff_pkt->fileset || !ff_pkt->fileset->incexe) { + return false; + } + ignoredir = ff_pkt->fileset->incexe->ignoredir; + + if (ignoredir) { + if (!ff_pkt->ignoredir_fname) { + ff_pkt->ignoredir_fname = get_pool_memory(PM_FNAME); + } + Mmsg(ff_pkt->ignoredir_fname, "%s/%s", ff_pkt->fname, ignoredir); + if (stat(ff_pkt->ignoredir_fname, &sb) == 0) { + Dmsg2(100, "Directory '%s' ignored (found %s)\n", + ff_pkt->fname, ignoredir); + return true; /* Just ignore this directory */ + } + } + return false; +} + +/* + * When the current file is a hardlink, the backup code can compute + * the checksum and store it into the link_t structure. + */ +void +ff_pkt_set_link_digest(FF_PKT *ff_pkt, + int32_t digest_stream, const char *digest, uint32_t len) +{ + if (ff_pkt->linked && !ff_pkt->linked->digest) { /* is a hardlink */ + ff_pkt->linked->digest = (char *) bmalloc(len); + memcpy(ff_pkt->linked->digest, digest, len); + ff_pkt->linked->digest_len = len; + ff_pkt->linked->digest_stream = digest_stream; + } +} + /* * Find a single file. * handle_file is the callback for handling the file. @@ -308,7 +339,7 @@ static bool check_changes(JCR *jcr, FF_PKT *ff_pkt) * descending into a directory. */ int -find_one_file(JCR *jcr, FF_PKT *ff_pkt, +find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(JCR *jcr, FF_PKT *ff, bool top_level), char *fname, dev_t parent_device, bool top_level) { @@ -384,8 +415,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * since our last "save_time", presumably the last Full save * or Incremental. */ - if ( !S_ISDIR(ff_pkt->statp.st_mode) - && !check_changes(jcr, ff_pkt)) + if ( !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; @@ -407,6 +438,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, ff_pkt->ff_errno = errno; return handle_file(jcr, ff_pkt, top_level); } + return -1; /* ignore */ } #endif @@ -446,8 +478,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, ff_pkt->type = FT_LNKSAVED; /* Handle link, file already saved */ ff_pkt->LinkFI = lp->FileIndex; ff_pkt->linked = 0; + ff_pkt->digest = lp->digest; + ff_pkt->digest_stream = lp->digest_stream; + ff_pkt->digest_len = lp->digest_len; rtn_stat = handle_file(jcr, ff_pkt, top_level); - Dmsg3(400, "FT_LNKSAVED FI=%d LinkFI=%d file=%s\n", + Dmsg3(400, "FT_LNKSAVED FI=%d LinkFI=%d file=%s\n", ff_pkt->FileIndex, lp->FileIndex, lp->name); return rtn_stat; } @@ -455,6 +490,9 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, /* File not previously dumped. Chain it into our list. */ len = strlen(fname) + 1; lp = (struct f_link *)bmalloc(sizeof(struct f_link) + len); + lp->digest = NULL; /* set later */ + lp->digest_stream = 0; /* set later */ + lp->digest_len = 0; /* set later */ lp->ino = ff_pkt->statp.st_ino; lp->dev = ff_pkt->statp.st_dev; lp->FileIndex = 0; /* set later */ @@ -485,11 +523,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, if (ff_pkt->linked) { ff_pkt->linked->FileIndex = ff_pkt->FileIndex; } - Dmsg3(400, "FT_REG FI=%d linked=%d file=%s\n", ff_pkt->FileIndex, + Dmsg3(400, "FT_REG FI=%d linked=%d file=%s\n", ff_pkt->FileIndex, ff_pkt->linked ? 1 : 0, fname); if (ff_pkt->flags & FO_KEEPATIME) { utime(fname, &restore_times); - } + } return rtn_stat; @@ -528,44 +566,12 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, bool recurse = true; bool volhas_attrlist = ff_pkt->volhas_attrlist; /* Remember this if we recurse */ - /* - * If we are using Win32 (non-portable) backup API, don't check - * access as everything is more complicated, and - * in principle, we should be able to access everything. - */ - if (!have_win32_api() || (ff_pkt->flags & FO_PORTABLE)) { - if (access(fname, R_OK) == -1 && geteuid() != 0) { - /* Could not access() directory */ - ff_pkt->type = FT_NOACCESS; - ff_pkt->ff_errno = errno; - rtn_stat = handle_file(jcr, ff_pkt, top_level); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - return rtn_stat; - } - } - /* * 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 */ - } + if (have_ignoredir(ff_pkt)) { + return 1; /* Just ignore this directory */ } /* Build a canonical directory name with a trailing slash in link var */ @@ -588,13 +594,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } /* * 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 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. @@ -604,7 +605,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * in the directory is seen (i.e. the FT_DIREND). */ rtn_stat = handle_file(jcr, ff_pkt, top_level); - if (rtn_stat < 1 || ff_pkt->type == FT_REPARSE) { /* ignore or error status */ + if (rtn_stat < 1 || ff_pkt->type == FT_REPARSE || + ff_pkt->type == FT_JUNCTION) { /* ignore or error status */ free(link); return rtn_stat; } @@ -632,15 +634,10 @@ 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 || - is_win32_mount_point)) { + } else if (!top_level && (parent_device != ff_pkt->statp.st_dev)) { if(!(ff_pkt->flags & FO_MULTIFS)) { ff_pkt->type = FT_NOFSCHG; recurse = false; @@ -788,21 +785,24 @@ int term_find_one(FF_PKT *ff) int count = 0; int i; - + if (ff->linkhash == NULL) return 0; for (i =0 ; i < LINK_HASHTABLE_SIZE; i ++) { /* Free up list of hard linked files */ - lp = ff->linkhash[i]; - while (lp) { - lc = lp; - lp = lp->next; - if (lc) { - free(lc); - count++; + lp = ff->linkhash[i]; + while (lp) { + lc = lp; + lp = lp->next; + if (lc) { + if (lc->digest) { + free(lc->digest); + } + free(lc); + count++; + } } - } - ff->linkhash[i] = NULL; + ff->linkhash[i] = NULL; } free(ff->linkhash); ff->linkhash = NULL;