X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffindlib%2Ffind.c;h=77ac196dabf57b33a94e31ff276227f6cf98666c;hb=4ef5c93bf8dc429d479e23c7ddcee8b5e1ddf1ae;hp=90b66bcc94bffda34f4ba97352ab5d6a977710b1;hpb=d2623318ddf378c21bf842fc7aafe6eb143933e0;p=bacula%2Fbacula diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index 90b66bcc94..77ac196dab 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2010 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 three of the GNU Affero General Public + 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 + 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 Affero 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 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. +*/ /* * Main routine for finding files on a file system. * The heart of the work to find the files on the @@ -7,27 +34,14 @@ * * Kern E. Sibbald, MM * - * Version $Id$ - */ -/* - Copyright (C) 2000-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - - 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 - the file LICENSE for additional details. - */ #include "bacula.h" #include "find.h" +static const int dbglvl = 450; + int32_t name_max; /* filename max length */ int32_t path_max; /* path name max length */ @@ -35,7 +49,7 @@ int32_t path_max; /* path name max length */ #undef bmalloc #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x) #endif -static int our_callback(FF_PKT *ff, void *hpkt, bool top_level); +static int our_callback(JCR *jcr, FF_PKT *ff, bool top_level); static bool accept_file(FF_PKT *ff); static const int fnmode = 0; @@ -54,18 +68,18 @@ FF_PKT *init_find_files() /* Get system path and filename maximum lengths */ path_max = pathconf(".", _PC_PATH_MAX); - if (path_max < 1024) { - path_max = 1024; + if (path_max < 2048) { + path_max = 2048; } name_max = pathconf(".", _PC_NAME_MAX); - if (name_max < 1024) { - name_max = 1024; + if (name_max < 2048) { + name_max = 2048; } path_max++; /* add for EOS */ name_max++; /* add for EOS */ - Dmsg1(100, "init_find_files ff=%p\n", ff); + Dmsg1(dbglvl, "init_find_files ff=%p\n", ff); return ff; } @@ -77,10 +91,17 @@ FF_PKT *init_find_files() void set_find_options(FF_PKT *ff, int incremental, time_t save_time) { - Dmsg0(100, "Enter set_find_options()\n"); + Dmsg0(dbglvl, "Enter set_find_options()\n"); ff->incremental = incremental; ff->save_time = save_time; - Dmsg0(100, "Leave set_find_options()\n"); + Dmsg0(dbglvl, "Leave set_find_options()\n"); +} + +void +set_find_changed_function(FF_PKT *ff, bool check_fct(JCR *jcr, FF_PKT *ff)) +{ + Dmsg0(dbglvl, "Enter set_find_changed_function()\n"); + ff->check_fct = check_fct; } /* @@ -100,20 +121,25 @@ get_win32_driveletters(FF_PKT *ff, char* szDrives) #if !defined(HAVE_WIN32) return 0; #endif + int nCount; + /* Can be already filled by plugin, so check that everything + * is on upper case. TODO: can check for dupplicate? + */ + for (nCount = 0; nCount < 27 && szDrives[nCount] ; nCount++) { + szDrives[nCount] = toupper(szDrives[nCount]); + } - szDrives[0] = 0; /* make empty */ - int nCount = 0; - findFILESET *fileset = ff->fileset; if (fileset) { - int i, j; + int i; + dlistString *node; for (i=0; iinclude_list.size(); i++) { findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i); /* look through all files and check */ - for (j=0; jname_list.size(); j++) { - char *fname = (char *)incexe->name_list.get(j); + foreach_dlist(node, &incexe->name_list) { + char *fname = node->c_str(); /* fname should match x:/ */ if (strlen(fname) >= 2 && B_ISALPHA(fname[0]) && fname[1] == ':') { @@ -134,26 +160,18 @@ get_win32_driveletters(FF_PKT *ff, char* szDrives) } /* - * Find all specified files (determined by calls to name_add() - * This routine calls the (handle_file) subroutine with all - * sorts of good information for the final disposition of - * the file. - * * Call this subroutine with a callback subroutine as the first * argument and a packet as the second argument, this packet * will be passed back to the callback subroutine as the last * argument. * - * The callback subroutine gets called with: - * arg1 -- the FF_PKT containing filename, link, stat, ftype, flags, etc - * arg2 -- the user supplied packet - * */ int -find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool top_level), - void *his_pkt) +find_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level), + int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)) { - ff->callback = callback; + ff->file_save = file_save; + ff->plugin_save = plugin_save; /* This is the new way */ findFILESET *fileset = ff->fileset; @@ -162,33 +180,101 @@ find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool t ff->flags = 0; ff->VerifyOpts[0] = 'V'; ff->VerifyOpts[1] = 0; + strcpy(ff->AccurateOpts, "Cmcs"); /* mtime+ctime+size by default */ + strcpy(ff->BaseJobOpts, "Jspug5"); /* size+perm+user+group+chk */ for (i=0; iinclude_list.size(); i++) { findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i); fileset->incexe = incexe; /* - * By setting all options, we in effect or the global options + * By setting all options, we in effect OR the global options * which is what we want. */ for (j=0; jopts_list.size(); j++) { findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); ff->flags |= fo->flags; ff->GZIP_level = fo->GZIP_level; + ff->strip_path = fo->strip_path; ff->fstypes = fo->fstype; ff->drivetypes = fo->drivetype; bstrncat(ff->VerifyOpts, fo->VerifyOpts, sizeof(ff->VerifyOpts)); + if (fo->AccurateOpts[0]) { + bstrncpy(ff->AccurateOpts, fo->AccurateOpts, sizeof(ff->AccurateOpts)); + } + if (fo->BaseJobOpts[0]) { + bstrncpy(ff->BaseJobOpts, fo->BaseJobOpts, sizeof(ff->BaseJobOpts)); + } } - for (j=0; jname_list.size(); j++) { - Dmsg1(100, "F %s\n", (char *)incexe->name_list.get(j)); - ff->top_fname = (char *)incexe->name_list.get(j); - if (find_one_file(jcr, ff, our_callback, his_pkt, ff->top_fname, (dev_t)-1, true) == 0) { + Dmsg3(50, "Verify=<%s> Accurate=<%s> BaseJob=<%s>\n", ff->VerifyOpts, ff->AccurateOpts, ff->BaseJobOpts); + dlistString *node; + foreach_dlist(node, &incexe->name_list) { + char *fname = node->c_str(); + Dmsg1(dbglvl, "F %s\n", fname); + ff->top_fname = fname; + if (find_one_file(jcr, ff, our_callback, ff->top_fname, (dev_t)-1, true) == 0) { return 0; /* error return */ } + if (job_canceled(jcr)) { + return 0; + } + } + foreach_dlist(node, &incexe->plugin_list) { + char *fname = node->c_str(); + if (!plugin_save) { + Jmsg(jcr, M_FATAL, 0, _("Plugin: \"%s\" not found.\n"), fname); + return 0; + } + Dmsg1(dbglvl, "PluginCommand: %s\n", fname); + ff->top_fname = fname; + ff->cmd_plugin = true; + plugin_save(jcr, ff, true); + ff->cmd_plugin = false; + if (job_canceled(jcr)) { + return 0; + } } } } return 1; } +/* + * Test if the currently selected directory (in ff->fname) is + * explicitly in the Include list or explicitly in the Exclude + * list. + */ +bool is_in_fileset(FF_PKT *ff) +{ + dlistString *node; + char *fname; + int i; + findINCEXE *incexe; + findFILESET *fileset = ff->fileset; + if (fileset) { + for (i=0; iinclude_list.size(); i++) { + incexe = (findINCEXE *)fileset->include_list.get(i); + foreach_dlist(node, &incexe->name_list) { + fname = node->c_str(); + Dmsg2(dbglvl, "Inc fname=%s ff->fname=%s\n", fname, ff->fname); + if (strcmp(fname, ff->fname) == 0) { + return true; + } + } + } + for (i=0; iexclude_list.size(); i++) { + incexe = (findINCEXE *)fileset->exclude_list.get(i); + foreach_dlist(node, &incexe->name_list) { + fname = node->c_str(); + Dmsg2(dbglvl, "Exc fname=%s ff->fname=%s\n", fname, ff->fname); + if (strcmp(fname, ff->fname) == 0) { + return true; + } + } + } + } + return false; +} + + static bool accept_file(FF_PKT *ff) { int i, j, k; @@ -198,8 +284,10 @@ static bool accept_file(FF_PKT *ff) const char *basename; int (*match_func)(const char *pattern, const char *string, int flags); + Dmsg1(dbglvl, "enter accept_file: fname=%s\n", ff->fname); if (ff->flags & FO_ENHANCEDWILD) { - match_func = enh_fnmatch; +// match_func = enh_fnmatch; + match_func = fnmatch; if ((basename = last_path_separator(ff->fname)) != NULL) basename++; else @@ -213,8 +301,6 @@ static bool accept_file(FF_PKT *ff) findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); ff->flags = fo->flags; ff->GZIP_level = fo->GZIP_level; - ff->reader = fo->reader; - ff->writer = fo->writer; ff->fstypes = fo->fstype; ff->drivetypes = fo->drivetype; @@ -225,7 +311,7 @@ static bool accept_file(FF_PKT *ff) for (k=0; kwilddir.size(); k++) { if (match_func((char *)fo->wilddir.get(k), ff->fname, fnmode|fnm_flags) == 0) { if (ff->flags & FO_EXCLUDE) { - Dmsg2(100, "Exclude wilddir: %s file=%s\n", (char *)fo->wilddir.get(k), + Dmsg2(dbglvl, "Exclude wilddir: %s file=%s\n", (char *)fo->wilddir.get(k), ff->fname); return false; /* reject dir */ } @@ -236,7 +322,7 @@ static bool accept_file(FF_PKT *ff) for (k=0; kwildfile.size(); k++) { if (match_func((char *)fo->wildfile.get(k), ff->fname, fnmode|fnm_flags) == 0) { if (ff->flags & FO_EXCLUDE) { - Dmsg2(100, "Exclude wildfile: %s file=%s\n", (char *)fo->wildfile.get(k), + Dmsg2(dbglvl, "Exclude wildfile: %s file=%s\n", (char *)fo->wildfile.get(k), ff->fname); return false; /* reject file */ } @@ -247,7 +333,7 @@ static bool accept_file(FF_PKT *ff) for (k=0; kwildbase.size(); k++) { if (match_func((char *)fo->wildbase.get(k), basename, fnmode|fnm_flags) == 0) { if (ff->flags & FO_EXCLUDE) { - Dmsg2(100, "Exclude wildbase: %s file=%s\n", (char *)fo->wildbase.get(k), + Dmsg2(dbglvl, "Exclude wildbase: %s file=%s\n", (char *)fo->wildbase.get(k), basename); return false; /* reject file */ } @@ -258,7 +344,7 @@ static bool accept_file(FF_PKT *ff) for (k=0; kwild.size(); k++) { if (match_func((char *)fo->wild.get(k), ff->fname, fnmode|fnm_flags) == 0) { if (ff->flags & FO_EXCLUDE) { - Dmsg2(100, "Exclude wild: %s file=%s\n", (char *)fo->wild.get(k), + Dmsg2(dbglvl, "Exclude wild: %s file=%s\n", (char *)fo->wild.get(k), ff->fname); return false; /* reject file */ } @@ -319,16 +405,18 @@ static bool accept_file(FF_PKT *ff) fnm_flags = (fo->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0; for (k=0; kwild.size(); k++) { if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|fnm_flags) == 0) { - Dmsg1(100, "Reject wild1: %s\n", ff->fname); + Dmsg1(dbglvl, "Reject wild1: %s\n", ff->fname); return false; /* reject file */ } } } fnm_flags = (incexe->current_opts != NULL && incexe->current_opts->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0; - for (j=0; jname_list.size(); j++) { - if (fnmatch((char *)incexe->name_list.get(j), ff->fname, fnmode|fnm_flags) == 0) { - Dmsg1(100, "Reject wild2: %s\n", ff->fname); + dlistString *node; + foreach_dlist(node, &incexe->name_list) { + char *fname = node->c_str(); + if (fnmatch(fname, ff->fname, fnmode|fnm_flags) == 0) { + Dmsg1(dbglvl, "Reject wild2: %s\n", ff->fname); return false; /* reject file */ } } @@ -341,10 +429,10 @@ static bool accept_file(FF_PKT *ff) * We filter the files, then call the user's callback if * the file is included. */ -static int our_callback(FF_PKT *ff, void *hpkt, bool top_level) +static int our_callback(JCR *jcr, FF_PKT *ff, bool top_level) { if (top_level) { - return ff->callback(ff, hpkt, top_level); /* accept file */ + return ff->file_save(jcr, ff, top_level); /* accept file */ } switch (ff->type) { case FT_NOACCESS: @@ -357,7 +445,7 @@ static int our_callback(FF_PKT *ff, void *hpkt, bool top_level) case FT_INVALIDFS: case FT_INVALIDDT: case FT_NOOPEN: -// return ff->callback(ff, hpkt, top_level); +// return ff->file_save(jcr, ff, top_level); /* These items can be filtered */ case FT_LNKSAVED: @@ -370,11 +458,12 @@ static int our_callback(FF_PKT *ff, void *hpkt, bool top_level) case FT_FIFO: case FT_SPEC: case FT_DIRNOCHG: + case FT_REPARSE: + case FT_JUNCTION: if (accept_file(ff)) { -// Dmsg2(000, "Accept file %s; reader=%s\n", ff->fname, NPRT(ff->reader)); - return ff->callback(ff, hpkt, top_level); + return ff->file_save(jcr, ff, top_level); } else { - Dmsg1(100, "Skip file %s\n", ff->fname); + Dmsg1(dbglvl, "Skip file %s\n", ff->fname); return -1; /* ignore this file */ } @@ -392,10 +481,16 @@ static int our_callback(FF_PKT *ff, void *hpkt, bool top_level) int term_find_files(FF_PKT *ff) { - int hard_links; + int hard_links; - free_pool_memory(ff->sys_fname); - hard_links = term_find_one(ff); - free(ff); - return hard_links; + free_pool_memory(ff->sys_fname); + if (ff->fname_save) { + free_pool_memory(ff->fname_save); + } + if (ff->link_save) { + free_pool_memory(ff->link_save); + } + hard_links = term_find_one(ff); + free(ff); + return hard_links; }