]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/find.c
- Correct segfault in message.c with debug=200 (new code).
[bacula/bacula] / bacula / src / findlib / find.c
1 /*
2  * Main routine for finding files on a file system.
3  *  The heart of the work is done in find_one.c
4  *
5  *  Kern E. Sibbald, MM
6  */
7 /*
8    Copyright (C) 2000-2004 Kern Sibbald and John Walker
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of
13    the License, or (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public
21    License along with this program; if not, write to the Free
22    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23    MA 02111-1307, USA.
24
25  */
26
27
28 #include "bacula.h"
29 #include "find.h"
30
31 int32_t name_max;              /* filename max length */
32 int32_t path_max;              /* path name max length */
33
34
35 /* ****FIXME**** debug until stable */
36 #undef bmalloc
37 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
38 static int our_callback(FF_PKT *ff, void *hpkt);
39 static bool accept_file(FF_PKT *ff);
40
41
42 /* 
43  * Initialize the find files "global" variables
44  */
45 FF_PKT *init_find_files()
46 {
47   FF_PKT *ff;    
48
49   ff = (FF_PKT *)bmalloc(sizeof(FF_PKT));
50   memset(ff, 0, sizeof(FF_PKT));
51
52   ff->sys_fname = get_pool_memory(PM_FNAME);
53
54   init_include_exclude_files(ff);           /* init lists */
55
56    /* Get system path and filename maximum lengths */
57    path_max = pathconf(".", _PC_PATH_MAX);
58    if (path_max < 1024) {
59       path_max = 1024;
60    }
61
62    name_max = pathconf(".", _PC_NAME_MAX);
63    if (name_max < 1024) {
64       name_max = 1024;
65    }
66    path_max++;                        /* add for EOS */
67    name_max++;                        /* add for EOS */
68
69   Dmsg1(100, "init_find_files ff=%p\n", ff);
70   return ff;
71 }
72
73 /* 
74  * Set find_files options. For the moment, we only
75  * provide for full/incremental saves, and setting
76  * of save_time. For additional options, see above
77  */
78 void
79 set_find_options(FF_PKT *ff, int incremental, time_t save_time)
80 {
81   Dmsg0(100, "Enter set_find_options()\n");
82   ff->incremental = incremental;
83   ff->save_time = save_time;
84   Dmsg0(100, "Leave set_find_options()\n");
85 }
86
87
88 /* 
89  * Find all specified files (determined by calls to name_add()
90  * This routine calls the (handle_file) subroutine with all
91  * sorts of good information for the final disposition of
92  * the file.
93  * 
94  * Call this subroutine with a callback subroutine as the first
95  * argument and a packet as the second argument, this packet
96  * will be passed back to the callback subroutine as the last
97  * argument.
98  *
99  * The callback subroutine gets called with:
100  *  arg1 -- the FF_PKT containing filename, link, stat, ftype, flags, etc
101  *  arg2 -- the user supplied packet
102  *
103  */
104 int
105 find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt), void *his_pkt) 
106 {
107    ff->callback = callback;
108
109    /* This is the new way */
110    findFILESET *fileset = ff->fileset;
111    if (fileset) {
112       int i, j;
113       ff->flags = 0;
114       ff->VerifyOpts[0] = 'V';
115       ff->VerifyOpts[1] = 0;
116       for (i=0; i<fileset->include_list.size(); i++) {
117          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
118          fileset->incexe = incexe;
119          /*
120           * By setting all options, we in effect or the global options
121           *   which is what we want.
122           */
123          for (j=0; j<incexe->opts_list.size(); j++) {
124             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
125             ff->flags |= fo->flags;
126             ff->GZIP_level = fo->GZIP_level;
127             bstrncat(ff->VerifyOpts, fo->VerifyOpts, sizeof(ff->VerifyOpts)); 
128          }
129          for (j=0; j<incexe->name_list.size(); j++) {
130             Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
131             char *fname = (char *)incexe->name_list.get(j);
132             if (find_one_file(jcr, ff, our_callback, his_pkt, fname, (dev_t)-1, 1) == 0) {
133                return 0;                  /* error return */
134             }
135          }
136       }
137    } else {
138       struct s_included_file *inc = NULL;
139
140       /* This is the old deprecated way */
141       while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
142          /* Copy options for this file */
143          bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts)); 
144          Dmsg1(50, "find_files: file=%s\n", inc->fname);
145          if (!file_is_excluded(ff, inc->fname)) {
146             if (find_one_file(jcr, ff, callback, his_pkt, inc->fname, (dev_t)-1, 1) ==0) {
147                return 0;                  /* error return */
148             }
149          }
150       }
151    }
152    return 1;
153 }
154
155 static bool accept_file(FF_PKT *ff)
156 {
157    int i, j, k;
158    findFILESET *fileset = ff->fileset;
159    findINCEXE *incexe = fileset->incexe;
160
161    for (j=0; j<incexe->opts_list.size(); j++) {
162       findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
163       ff->flags = fo->flags;
164       ff->GZIP_level = fo->GZIP_level;
165       ff->reader = fo->reader;
166       ff->writer = fo->writer;
167       for (k=0; k<fo->wild.size(); k++) {
168          if (fnmatch((char *)fo->wild.get(k), ff->fname, 0) == 0) {
169             if (ff->flags & FO_EXCLUDE) {
170                return false;          /* reject file */
171             }
172             return true;              /* accept file */
173          }
174       }
175 #ifndef WIN32
176       for (k=0; k<fo->regex.size(); k++) {
177          const int nmatch = 30;
178          regmatch_t pmatch[nmatch];
179          if (regexec((regex_t *)fo->regex.get(k), ff->fname, nmatch, pmatch,  0) == 0) {
180             if (ff->flags & FO_EXCLUDE) {
181                return false;          /* reject file */
182             }
183             return true;              /* accept file */
184          }
185       }
186 #endif
187    }
188
189    for (i=0; i<fileset->exclude_list.size(); i++) {
190       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
191       for (j=0; j<incexe->opts_list.size(); j++) {
192          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
193          for (k=0; k<fo->wild.size(); k++) {
194             if (fnmatch((char *)fo->wild.get(k), ff->fname, 0) == 0) {
195                Dmsg1(400, "Reject wild1: %s\n", ff->fname);
196                return false;          /* reject file */
197             }
198          }
199       }
200       for (j=0; j<incexe->name_list.size(); j++) {
201          if (fnmatch((char *)incexe->name_list.get(j), ff->fname, 0) == 0) {
202             Dmsg1(400, "Reject wild2: %s\n", ff->fname);
203             return false;          /* reject file */
204          }
205       }
206    }
207    return true;
208 }
209
210 /*
211  * The code comes here for each file examined.
212  * We filter the files, then call the user's callback if
213  *    the file is included. 
214  */
215 static int our_callback(FF_PKT *ff, void *hpkt)
216 {
217    switch (ff->type) {
218    case FT_NOACCESS:
219    case FT_NOFOLLOW:
220    case FT_NOSTAT:
221    case FT_NOCHG:
222    case FT_ISARCH:
223    case FT_NORECURSE:
224    case FT_NOFSCHG:
225    case FT_NOOPEN:
226       return ff->callback(ff, hpkt);
227
228    /* These items can be filtered */
229    case FT_LNKSAVED:
230    case FT_REGE:
231    case FT_REG:
232    case FT_LNK:
233    case FT_DIRBEGIN:
234    case FT_DIREND:
235    case FT_RAW:
236    case FT_FIFO:
237    case FT_SPEC:
238    case FT_DIRNOCHG:
239       if (accept_file(ff)) {
240          return ff->callback(ff, hpkt);
241       } else {
242          Dmsg1(100, "Skip file %s\n", ff->fname);
243          return -1;                   /* ignore this file */
244       }
245
246    default:
247       Dmsg1(000, "Unknown FT code %d\n", ff->type);
248       return 0;
249    }
250 }
251
252
253 /*
254  * Terminate find_files() and release
255  * all allocated memory   
256  */
257 int
258 term_find_files(FF_PKT *ff)
259 {
260   int hard_links;
261
262   term_include_exclude_files(ff);
263   free_pool_memory(ff->sys_fname);
264   hard_links = term_find_one(ff);
265   free(ff);
266   return hard_links;
267 }