2 * Main routine for finding files on a file system.
3 * The heart of the work is done in find_one.c
8 Copyright (C) 2000-2004 Kern Sibbald and John Walker
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.
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.
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,
32 int32_t name_max; /* filename max length */
33 int32_t path_max; /* path name max length */
36 /* ****FIXME**** debug until stable */
38 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
39 static void set_options(FF_PKT *ff, const char *opts);
40 static int our_callback(FF_PKT *ff, void *hpkt);
41 static bool accept_file(FF_PKT *ff);
45 * Initialize the find files "global" variables
47 FF_PKT *init_find_files()
51 ff = (FF_PKT *)bmalloc(sizeof(FF_PKT));
52 memset(ff, 0, sizeof(FF_PKT));
54 ff->sys_fname = get_pool_memory(PM_FNAME);
56 init_include_exclude_files(ff); /* init lists */
58 /* Get system path and filename maximum lengths */
59 path_max = pathconf(".", _PC_PATH_MAX);
60 if (path_max < 1024) {
64 name_max = pathconf(".", _PC_NAME_MAX);
65 if (name_max < 1024) {
68 path_max++; /* add for EOS */
69 name_max++; /* add for EOS */
71 Dmsg1(100, "init_find_files ff=%p\n", ff);
76 * Set find_files options. For the moment, we only
77 * provide for full/incremental saves, and setting
78 * of save_time. For additional options, see above
81 set_find_options(FF_PKT *ff, int incremental, time_t save_time)
83 Dmsg0(100, "Enter set_find_options()\n");
84 ff->incremental = incremental;
85 ff->save_time = save_time;
86 Dmsg0(100, "Leave set_find_options()\n");
91 * Find all specified files (determined by calls to name_add()
92 * This routine calls the (handle_file) subroutine with all
93 * sorts of good information for the final disposition of
96 * Call this subroutine with a callback subroutine as the first
97 * argument and a packet as the second argument, this packet
98 * will be passed back to the callback subroutine as the last
101 * The callback subroutine gets called with:
102 * arg1 -- the FF_PKT containing filename, link, stat, ftype, flags, etc
103 * arg2 -- the user supplied packet
107 find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt), void *his_pkt)
109 ff->callback = callback;
111 /* This is the new way */
112 findFILESET *fileset = ff->fileset;
115 for (i=0; i<fileset->include_list.size(); i++) {
116 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
117 fileset->incexe = incexe;
119 * By setting all options, we in effect or the global options
120 * which is what we want.
122 for (j=0; j<incexe->opts_list.size(); j++) {
123 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
124 Dmsg1(400, "Find global options O %s\n", fo->opts);
125 set_options(ff, fo->opts);
127 for (j=0; j<incexe->name_list.size(); j++) {
128 Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
129 char *fname = (char *)incexe->name_list.get(j);
130 if (!find_one_file(jcr, ff, our_callback, his_pkt, fname, (dev_t)-1, 1)) {
131 return 0; /* error return */
136 struct s_included_file *inc = NULL;
138 /* This is the old deprecated way */
139 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
140 /* Copy options for this file */
141 bstrncpy(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
142 Dmsg1(50, "find_files: file=%s\n", inc->fname);
143 if (!file_is_excluded(ff, inc->fname)) {
144 if (!find_one_file(jcr, ff, callback, his_pkt, inc->fname, (dev_t)-1, 1)) {
145 return 0; /* error return */
153 static bool accept_file(FF_PKT *ff)
156 findFILESET *fileset = ff->fileset;
157 findINCEXE *incexe = fileset->incexe;
159 for (j=0; j<incexe->opts_list.size(); j++) {
160 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
161 for (k=0; k<fo->wild.size(); k++) {
166 for (i=0; i<fileset->exclude_list.size(); i++) {
167 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
168 for (j=0; j<incexe->opts_list.size(); j++) {
169 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
170 for (k=0; k<fo->wild.size(); k++) {
171 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
172 if (fnmatch((char *)fo->wild.get(k), ff->fname, FNM_PATHNAME) == 0) {
173 Dmsg1(000, "Reject wild: %s\n", ff->fname);
174 return false; /* reject file */
178 for (j=0; j<incexe->name_list.size(); j++) {
179 Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
180 if (fnmatch((char *)incexe->name_list.get(j), ff->fname, FNM_PATHNAME) == 0) {
181 Dmsg1(000, "Reject: %s\n", ff->fname);
182 return false; /* reject file */
186 Dmsg1(000, "Accept: %s\n", ff->fname);
191 * The code comes here for each file examined.
192 * We filter the files, then call the user's callback if
193 * the file is included.
195 static int our_callback(FF_PKT *ff, void *hpkt)
206 Dmsg1(000, "File=%s\n", ff->fname);
207 return ff->callback(ff, hpkt);
209 /* These items can be filtered */
217 if (accept_file(ff)) {
218 return ff->callback(ff, hpkt);
228 * As an optimization, we should do this during
229 * "compile" time in filed/job.c, and keep only a bit mask
230 * and the Verify options.
232 static void set_options(FF_PKT *ff, const char *opts)
237 for (p=opts; *p; p++) {
239 case 'a': /* alway replace */
240 case '0': /* no option */
243 ff->flags |= FO_EXCLUDE;
246 ff->flags |= FO_MULTIFS;
248 case 'h': /* no recursion */
249 ff->flags |= FO_NO_RECURSION;
255 ff->flags |= FO_NOREPLACE;
257 case 'p': /* use portable data format */
258 ff->flags |= FO_PORTABLE;
260 case 'r': /* read fifo */
261 ff->flags |= FO_READFIFO;
264 ff->flags |= FO_SHA1;
267 ff->flags |= FO_SPARSE;
270 ff->flags |= FO_MTIMEONLY;
273 ff->flags |= FO_KEEPATIME;
275 case 'V': /* verify options */
276 /* Copy Verify Options */
277 for (j=0; *p && *p != ':'; p++) {
278 ff->VerifyOpts[j] = *p;
279 if (j < (int)sizeof(ff->VerifyOpts) - 1) {
283 ff->VerifyOpts[j] = 0;
286 ff->flags |= FO_IF_NEWER;
288 case 'Z': /* gzip compression */
289 ff->flags |= FO_GZIP;
290 ff->GZIP_level = *++p - '0';
291 Dmsg1(200, "Compression level=%d\n", ff->GZIP_level);
294 Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p);
302 * Terminate find_files() and release
303 * all allocated memory
306 term_find_files(FF_PKT *ff)
310 term_include_exclude_files(ff);
311 free_pool_memory(ff->sys_fname);
312 hard_links = term_find_one(ff);