2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
19 * Routines used to keep and match include and exclude
20 * filename/pathname patterns.
22 * Note, this file is used for the old style include and
23 * excludes, so is deprecated. The new style code is
25 * This code is still used for lists in testls and bextract.
27 * Kern E. Sibbald, December MMI
35 #include <sys/types.h>
37 #ifndef FNM_LEADING_DIR
38 #define FNM_LEADING_DIR 0
41 /* Fold case in fnmatch() on Win32 */
43 static const int fnmode = FNM_CASEFOLD;
45 static const int fnmode = 0;
50 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
54 match_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *, FF_PKT *ff_pkt, bool))
56 ff->file_save = file_save;
58 struct s_included_file *inc = NULL;
60 /* This is the old deprecated way */
61 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
62 /* Copy options for this file */
63 bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
64 Dmsg1(100, "find_files: file=%s\n", inc->fname);
65 if (!file_is_excluded(ff, inc->fname)) {
66 if (find_one_file(jcr, ff, file_save, inc->fname, (dev_t)-1, 1) ==0) {
67 return 0; /* error return */
76 * Done doing filename matching, release all
79 void term_include_exclude_files(FF_PKT *ff)
81 struct s_included_file *inc, *next_inc;
82 struct s_excluded_file *exc, *next_exc;
84 for (inc=ff->included_files_list; inc; ) {
89 ff->included_files_list = NULL;
91 for (exc=ff->excluded_files_list; exc; ) {
96 ff->excluded_files_list = NULL;
98 for (exc=ff->excluded_paths_list; exc; ) {
103 ff->excluded_paths_list = NULL;
107 * Add a filename to list of included files
109 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
112 struct s_included_file *inc;
118 inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
120 inc->VerifyOpts[0] = 'V';
121 inc->VerifyOpts[1] = ':';
122 inc->VerifyOpts[2] = 0;
124 /* prefixed = preceded with options */
126 for (rp=fname; *rp && *rp != ' '; rp++) {
128 case 'a': /* alway replace */
129 case '0': /* no option */
132 inc->options |= FO_MULTIFS;
134 case 'h': /* no recursion */
135 inc->options |= FO_NO_RECURSION;
138 inc->options |= FO_MD5;
141 inc->options |= FO_NOREPLACE;
143 case 'p': /* use portable data format */
144 inc->options |= FO_PORTABLE;
146 case 'r': /* read fifo */
147 inc->options |= FO_READFIFO;
150 inc->options |= FO_SHA1;
153 inc->options |= FO_SPARSE;
156 inc->options |= FO_MTIMEONLY;
159 inc->options |= FO_KEEPATIME;
161 case 'V': /* verify options */
162 /* Copy Verify Options */
163 for (j=0; *rp && *rp != ':'; rp++) {
164 inc->VerifyOpts[j] = *rp;
165 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
169 inc->VerifyOpts[j] = 0;
172 inc->options |= FO_IF_NEWER;
175 inc->options |= FO_ACL;
177 case 'Z': /* compression */
179 if (*rp >= '0' && *rp <= '9') {
180 inc->options |= FO_COMPRESS;
181 inc->algo = COMPRESS_GZIP;
182 inc->level = *rp - '0';
184 else if (*rp == 'o') {
185 inc->options |= FO_COMPRESS;
186 inc->algo = COMPRESS_LZO1X;
187 inc->level = 1; /* not used with LZO */
189 Dmsg2(200, "Compression alg=%d level=%d\n", inc->algo, inc->level);
192 inc->options |= FO_NOATIME;
195 inc->options |= FO_XATTR;
198 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
202 /* Skip past space(s) */
203 for ( ; *rp == ' '; rp++)
209 strcpy(inc->fname, rp);
212 /* Zap trailing slashes. */
214 while (p > inc->fname && IsPathSeparator(*p)) {
219 /* Check for wild cards */
221 for (p=inc->fname; *p; p++) {
222 if (*p == '*' || *p == '[' || *p == '?') {
228 /* Chain this one on the end of the list */
229 if (!ff->included_files_list) {
230 /* First one, so set head */
231 ff->included_files_list = inc;
233 struct s_included_file *next;
234 /* Walk to end of list */
235 for (next=ff->included_files_list; next->next; next=next->next)
239 Dmsg4(100, "add_fname_to_include prefix=%d compres=%d alg= %d fname=%s\n",
240 prefixed, !!(inc->options & FO_COMPRESS), inc->algo, inc->fname);
244 * We add an exclude name to either the exclude path
245 * list or the exclude filename list.
247 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
250 struct s_excluded_file *exc, **list;
252 Dmsg1(20, "Add name to exclude: %s\n", fname);
254 if (first_path_separator(fname) != NULL) {
255 list = &ff->excluded_paths_list;
257 list = &ff->excluded_files_list;
262 exc = (struct s_excluded_file *)bmalloc(sizeof(struct s_excluded_file) + len + 1);
265 strcpy(exc->fname, fname);
271 * Get next included file
273 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
275 struct s_included_file *inc;
278 inc = ff->included_files_list;
283 * copy inc_options for this file into the ff packet
286 ff->flags = inc->options;
287 ff->Compress_algo = inc->algo;
288 ff->Compress_level = inc->level;
294 * Walk through the included list to see if this
295 * file is included possibly with wild-cards.
298 int file_is_included(FF_PKT *ff, const char *file)
300 struct s_included_file *inc = ff->included_files_list;
303 for ( ; inc; inc=inc->next ) {
305 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
311 * No wild cards. We accept a match to the
312 * end of any component.
314 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
316 if (inc->len == len && strcmp(inc->fname, file) == 0) {
319 if (inc->len < len && IsPathSeparator(file[inc->len]) &&
320 strncmp(inc->fname, file, inc->len) == 0) {
323 if (inc->len == 1 && IsPathSeparator(inc->fname[0])) {
332 * This is the workhorse of excluded_file().
333 * Determine if the file is excluded or not.
336 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
339 Dmsg0(900, "exc is NULL\n");
341 for ( ; exc; exc=exc->next ) {
342 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
343 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
346 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
353 * Walk through the excluded lists to see if this
354 * file is excluded, or if it matches a component
355 * of an excluded directory.
358 int file_is_excluded(FF_PKT *ff, const char *file)
362 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
366 /* Try each component */
367 for (p = file; *p; p++) {
368 /* Match from the beginning of a component only */
369 if ((p == file || (!IsPathSeparator(*p) && IsPathSeparator(p[-1])))
370 && file_in_excluded_list(ff->excluded_files_list, p)) {