2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many 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 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
22 * Routines used to keep and match include and exclude
23 * filename/pathname patterns.
25 * Note, this file is used for the old style include and
26 * excludes, so is deprecated. The new style code is
28 * This code is still used for lists in testls and bextract.
30 * Kern E. Sibbald, December MMI
38 #include <sys/types.h>
40 #ifndef FNM_LEADING_DIR
41 #define FNM_LEADING_DIR 0
44 /* Fold case in fnmatch() on Win32 */
45 static const int fnmode = 0;
49 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
53 match_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *, FF_PKT *ff_pkt, bool))
55 ff->file_save = file_save;
57 struct s_included_file *inc = NULL;
59 /* This is the old deprecated way */
60 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
61 /* Copy options for this file */
62 bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
63 Dmsg1(100, "find_files: file=%s\n", inc->fname);
64 if (!file_is_excluded(ff, inc->fname)) {
65 if (find_one_file(jcr, ff, file_save, inc->fname, (dev_t)-1, 1) ==0) {
66 return 0; /* error return */
75 * Done doing filename matching, release all
78 void term_include_exclude_files(FF_PKT *ff)
80 struct s_included_file *inc, *next_inc;
81 struct s_excluded_file *exc, *next_exc;
83 for (inc=ff->included_files_list; inc; ) {
88 ff->included_files_list = NULL;
90 for (exc=ff->excluded_files_list; exc; ) {
95 ff->excluded_files_list = NULL;
97 for (exc=ff->excluded_paths_list; exc; ) {
102 ff->excluded_paths_list = NULL;
106 * Add a filename to list of included files
108 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
111 struct s_included_file *inc;
117 inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
119 inc->VerifyOpts[0] = 'V';
120 inc->VerifyOpts[1] = ':';
121 inc->VerifyOpts[2] = 0;
123 /* prefixed = preceded with options */
125 for (rp=fname; *rp && *rp != ' '; rp++) {
127 case 'a': /* alway replace */
128 case '0': /* no option */
131 inc->options |= FO_MULTIFS;
133 case 'h': /* no recursion */
134 inc->options |= FO_NO_RECURSION;
137 inc->options |= FO_MD5;
140 inc->options |= FO_NOREPLACE;
142 case 'p': /* use portable data format */
143 inc->options |= FO_PORTABLE;
145 case 'r': /* read fifo */
146 inc->options |= FO_READFIFO;
149 inc->options |= FO_SHA1;
152 inc->options |= FO_SPARSE;
155 inc->options |= FO_MTIMEONLY;
158 inc->options |= FO_KEEPATIME;
160 case 'V': /* verify options */
161 /* Copy Verify Options */
162 for (j=0; *rp && *rp != ':'; rp++) {
163 inc->VerifyOpts[j] = *rp;
164 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
168 inc->VerifyOpts[j] = 0;
171 inc->options |= FO_IF_NEWER;
174 inc->options |= FO_ACL;
176 case 'Z': /* compression */
178 if (*rp >= '0' && *rp <= '9') {
179 inc->options |= FO_COMPRESS;
180 inc->algo = COMPRESS_GZIP;
181 inc->Compress_level = *rp - '0';
183 else if (*rp == 'o') {
184 inc->options |= FO_COMPRESS;
185 inc->algo = COMPRESS_LZO1X;
186 inc->Compress_level = 1; /* not used with LZO */
188 Dmsg2(200, "Compression alg=%d level=%d\n", inc->algo, inc->Compress_level);
191 inc->options |= FO_NOATIME;
194 inc->options |= FO_XATTR;
197 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
201 /* Skip past space(s) */
202 for ( ; *rp == ' '; rp++)
208 strcpy(inc->fname, rp);
211 /* Zap trailing slashes. */
213 while (p > inc->fname && IsPathSeparator(*p)) {
218 /* Check for wild cards */
220 for (p=inc->fname; *p; p++) {
221 if (*p == '*' || *p == '[' || *p == '?') {
227 /* Chain this one on the end of the list */
228 if (!ff->included_files_list) {
229 /* First one, so set head */
230 ff->included_files_list = inc;
232 struct s_included_file *next;
233 /* Walk to end of list */
234 for (next=ff->included_files_list; next->next; next=next->next)
238 Dmsg4(100, "add_fname_to_include prefix=%d compres=%d alg= %d fname=%s\n",
239 prefixed, !!(inc->options & FO_COMPRESS), inc->algo, inc->fname);
243 * We add an exclude name to either the exclude path
244 * list or the exclude filename list.
246 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
249 struct s_excluded_file *exc, **list;
251 Dmsg1(20, "Add name to exclude: %s\n", fname);
253 if (first_path_separator(fname) != NULL) {
254 list = &ff->excluded_paths_list;
256 list = &ff->excluded_files_list;
261 exc = (struct s_excluded_file *)bmalloc(sizeof(struct s_excluded_file) + len + 1);
264 strcpy(exc->fname, fname);
270 * Get next included file
272 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
274 struct s_included_file *inc;
277 inc = ff->included_files_list;
282 * copy inc_options for this file into the ff packet
285 ff->flags = inc->options;
286 ff->Compress_algo = inc->algo;
287 ff->Compress_level = inc->Compress_level;
293 * Walk through the included list to see if this
294 * file is included possibly with wild-cards.
297 int file_is_included(FF_PKT *ff, const char *file)
299 struct s_included_file *inc = ff->included_files_list;
302 for ( ; inc; inc=inc->next ) {
304 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
310 * No wild cards. We accept a match to the
311 * end of any component.
313 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
315 if (inc->len == len && strcmp(inc->fname, file) == 0) {
318 if (inc->len < len && IsPathSeparator(file[inc->len]) &&
319 strncmp(inc->fname, file, inc->len) == 0) {
322 if (inc->len == 1 && IsPathSeparator(inc->fname[0])) {
331 * This is the workhorse of excluded_file().
332 * Determine if the file is excluded or not.
335 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
338 Dmsg0(900, "exc is NULL\n");
340 for ( ; exc; exc=exc->next ) {
341 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
342 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
345 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
352 * Walk through the excluded lists to see if this
353 * file is excluded, or if it matches a component
354 * of an excluded directory.
357 int file_is_excluded(FF_PKT *ff, const char *file)
361 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
365 /* Try each component */
366 for (p = file; *p; p++) {
367 /* Match from the beginning of a component only */
368 if ((p == file || (!IsPathSeparator(*p) && IsPathSeparator(p[-1])))
369 && file_in_excluded_list(ff->excluded_files_list, p)) {