X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffindlib%2Ffind_one.c;h=8e4beb931275ea4b3bfc8b007a49b95b60705f01;hb=10cfd798ced2d27f61ead2de6fe9b1bcc8e3468d;hp=d6c25fbdee2ad89290ce2a770c7798a8b794abbc;hpb=d269487ecbe16d55a1f4399c2b12a100d9c46405;p=bacula%2Fbacula diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index d6c25fbdee..8e4beb9312 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -1,42 +1,31 @@ /* + Bacula(R) - The Network Backup Solution - This file is based on GNU TAR source code. Except for a few key + Copyright (C) 2000-2018 Kern Sibbald + + The original author of Bacula is Kern Sibbald, with contributions + from many others, a complete list can be found in the file AUTHORS. + + 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. + + This notice must be preserved when any source code is + conveyed and/or propagated. + + Bacula(R) is a registered trademark of Kern Sibbald. +*/ +/* + + This file was derived from GNU TAR source code. Except for a few key ideas, it has been entirely rewritten for Bacula. Kern Sibbald, MM Thanks to the TAR programmers. - Version $Id$ - */ -/* - Bacula® - The Network Backup Solution - - Copyright (C) 2000-2006 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. - - 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. - - Bacula® is a registered trademark of John Walker. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. -*/ #include "bacula.h" #include "find.h" @@ -60,8 +49,10 @@ struct f_link { struct f_link *next; dev_t dev; /* device */ ino_t ino; /* inode with device is unique */ - short linkcount; 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 */ }; @@ -84,11 +75,53 @@ static inline int LINKHASH(const struct stat &info) return hash & LINK_HASHTABLE_MASK; } +/* + * 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 + * packet. + */ +static FF_PKT *new_dir_ff_pkt(FF_PKT *ff_pkt) +{ + FF_PKT *dir_ff_pkt = (FF_PKT *)bmalloc(sizeof(FF_PKT)); + memcpy(dir_ff_pkt, ff_pkt, sizeof(FF_PKT)); + dir_ff_pkt->fname = bstrdup(ff_pkt->fname); + dir_ff_pkt->link = bstrdup(ff_pkt->link); + dir_ff_pkt->sys_fname = get_pool_memory(PM_FNAME); + + if (ff_pkt->strip_snap_path) { + dir_ff_pkt->fname_save = get_pool_memory(PM_FNAME); + dir_ff_pkt->link_save = get_pool_memory(PM_FNAME); + pm_strcpy(dir_ff_pkt->fname_save, ff_pkt->fname_save); + pm_strcpy(dir_ff_pkt->link_save, ff_pkt->link_save); + + } else { + dir_ff_pkt->fname_save = NULL; + dir_ff_pkt->link_save = NULL; + } + + dir_ff_pkt->included_files_list = NULL; + dir_ff_pkt->excluded_files_list = NULL; + dir_ff_pkt->excluded_paths_list = NULL; + dir_ff_pkt->linkhash = NULL; + dir_ff_pkt->ignoredir_fname = NULL; + return dir_ff_pkt; +} + +/* + * Free the temp directory ff_pkt + */ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt) { free(dir_ff_pkt->fname); free(dir_ff_pkt->link); free_pool_memory(dir_ff_pkt->sys_fname); + if (dir_ff_pkt->fname_save) { + free_pool_memory(dir_ff_pkt->fname_save); + } + if (dir_ff_pkt->link_save) { + free_pool_memory(dir_ff_pkt->link_save); + } free(dir_ff_pkt); } @@ -103,7 +136,7 @@ static int accept_fstype(FF_PKT *ff, void *dummy) { if (ff->fstypes.size()) { accept = false; - if (!fstype(ff->fname, fs, sizeof(fs))) { + if (!fstype(ff, fs, sizeof(fs))) { Dmsg1(50, "Cannot determine file system type for \"%s\"\n", ff->fname); } else { for (i = 0; i < ff->fstypes.size(); ++i) { @@ -181,6 +214,22 @@ static bool volume_has_attrlist(const char *fname) return false; } +/* + * check for BSD nodump flag + */ +static bool no_dump(JCR *jcr, FF_PKT *ff_pkt) +{ +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) + if ( (ff_pkt->flags & FO_HONOR_NODUMP) && + (ff_pkt->statp.st_flags & UF_NODUMP) ) { + Jmsg(jcr, M_INFO, 1, _(" NODUMP flag set - will not process %s\n"), + ff_pkt->fname); + return true; /* do not backup this file */ + } +#endif + return false; /* do backup */ +} + /* check if a file have changed during backup and display an error */ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) { @@ -193,39 +242,104 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) if (lstat(ff_pkt->fname, &statp) != 0) { berrno be; - Jmsg(jcr, M_WARNING, 0, - _("Cannot stat file %s: ERR=%s\n"),ff_pkt->fname,be.strerror()); + 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); + 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_size != ff_pkt->statp.st_size) { - /* 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; } - 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); - return true; + return false; +} + +/* + * For incremental/diffential or accurate backups, we + * determine if the current file has changed. + */ +bool check_changes(JCR *jcr, FF_PKT *ff_pkt) +{ + /* in special mode (like accurate backup), the programmer can + * choose his comparison function. + */ + if (ff_pkt->check_fct) { + return ff_pkt->check_fct(jcr, ff_pkt); + } + + /* For normal backups (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; +} + +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. @@ -235,9 +349,9 @@ bool has_file_changed(JCR *jcr, FF_PKT *ff_pkt) * descending into a directory. */ 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) +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) { struct utimbuf restore_times; int rtn_stat; @@ -249,7 +363,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); @@ -272,7 +386,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, char fs[100]; - if (!fstype(ff_pkt->fname, fs, sizeof(fs))) { + if (!fstype(ff_pkt, fs, sizeof(fs))) { bstrncpy(fs, "unknown", sizeof(fs)); } @@ -297,21 +411,26 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, ff_pkt->volhas_attrlist = volume_has_attrlist(fname); } + /* + * Ignore this entry if no_dump() returns true + */ + if (no_dump(jcr, ff_pkt)) { + Dmsg1(100, "'%s' ignored (NODUMP flag set)\n", + ff_pkt->fname); + return 1; + } + /* * 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 ( !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 @@ -327,19 +446,12 @@ 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); } + return -1; /* ignore */ } #endif -/* ***FIXME*** implement this */ -#if xxxxxxx - /* See if we are trying to dump the archive. */ - if (ar_dev && ff_pkt->statp.st_dev == ar_dev && ff_pkt->statp.st_ino == ar_ino) { - ff_pkt->type = FT_ISARCH; - return handle_file(ff_pkt, pkt, top_level); - } -#endif ff_pkt->LinkFI = 0; /* * Handle hard linked files @@ -369,23 +481,36 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, lp->dev == (dev_t)ff_pkt->statp.st_dev) { /* If we have already backed up the hard linked file don't do it again */ if (strcmp(lp->name, fname) == 0) { + Dmsg2(400, "== Name identical skip FI=%d file=%s\n", lp->FileIndex, fname); return 1; /* ignore */ } 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); + 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", + ff_pkt->FileIndex, lp->FileIndex, lp->name); + return rtn_stat; } /* 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 */ 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 */ + Dmsg2(400, "added to hash FI=%d file=%s\n", ff_pkt->FileIndex, lp->name); } else { ff_pkt->linked = NULL; } @@ -404,13 +529,15 @@ 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; } + 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; @@ -423,7 +550,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; } @@ -432,7 +559,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; } @@ -450,21 +577,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, 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. + * Ignore this directory and everything below if the file .nobackup + * (or what is defined for IgnoreDir in this fileset) exists */ - 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(ff_pkt, pkt, top_level); - if (ff_pkt->linked) { - ff_pkt->linked->FileIndex = ff_pkt->FileIndex; - } - return rtn_stat; - } + if (have_ignoredir(ff_pkt)) { + return 1; /* Just ignore this directory */ } /* Build a canonical directory name with a trailing slash in link var */ @@ -479,15 +596,40 @@ 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))) { - /* Incremental option, directory entry not changed */ + if (!check_changes(jcr, ff_pkt)) { + /* Incremental/Full+Base 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) + /* + * A reparse point (WIN32_REPARSE_POINT) + * is something special like one of the following: + * IO_REPARSE_TAG_DFS 0x8000000A + * IO_REPARSE_TAG_DFSR 0x80000012 + * IO_REPARSE_TAG_HSM 0xC0000004 + * IO_REPARSE_TAG_HSM2 0x80000006 + * IO_REPARSE_TAG_SIS 0x80000007 + * IO_REPARSE_TAG_SYMLINK 0xA000000C + * + * A junction point is a: + * IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 + * which can be either a link to a Volume (WIN32_MOUNT_POINT) + * or a link to a directory (WIN32_JUNCTION_POINT) + * + * Ignore WIN32_REPARSE_POINT and WIN32_JUNCTION_POINT + */ + if (ff_pkt->statp.st_rdev == WIN32_REPARSE_POINT) { + ff_pkt->type = FT_REPARSE; + } else if (ff_pkt->statp.st_rdev == WIN32_JUNCTION_POINT) { + ff_pkt->type = FT_JUNCTION; + } +#endif /* * Note, we return the directory to the calling program (handle_file) * when we first see the directory (FT_DIRBEGIN. @@ -496,8 +638,9 @@ 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 || + ff_pkt->type == FT_JUNCTION) { /* ignore or error status */ free(link); return rtn_stat; } @@ -515,15 +658,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * be reset after all the files have been restored. */ Dmsg1(300, "Create temp ff packet for dir: %s\n", ff_pkt->fname); - FF_PKT *dir_ff_pkt = (FF_PKT *)bmalloc(sizeof(FF_PKT)); - memcpy(dir_ff_pkt, ff_pkt, sizeof(FF_PKT)); - dir_ff_pkt->fname = bstrdup(ff_pkt->fname); - dir_ff_pkt->link = bstrdup(ff_pkt->link); - dir_ff_pkt->sys_fname = get_pool_memory(PM_FNAME); - dir_ff_pkt->included_files_list = NULL; - dir_ff_pkt->excluded_files_list = NULL; - dir_ff_pkt->excluded_paths_list = NULL; - dir_ff_pkt->linkhash = NULL; + FF_PKT *dir_ff_pkt = new_dir_ff_pkt(ff_pkt); /* * Do not descend into subdirectories (recurse) if the @@ -533,10 +668,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; @@ -549,7 +689,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; } @@ -572,7 +712,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; } @@ -616,7 +756,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; } @@ -633,7 +773,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; } @@ -656,8 +796,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 @@ -671,7 +811,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; } @@ -684,21 +824,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;