4 * Routines used to keep and match include and exclude
5 * filename/pathname patterns.
7 * Note, this file is used for the old style include and
8 * excludes, so is deprecated. The new style code is
10 * This code is still used for lists in testls and bextract.
12 * Kern E. Sibbald, December MMI
16 Copyright (C) 2001-2005 Kern Sibbald
18 This program is free software; you can redistribute it and/or
19 modify it under the terms of the GNU General Public License
20 version 2 as amended with additional clauses defined in the
21 file LICENSE in the main source directory.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 the file LICENSE for additional details.
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 callback(FF_PKT *ff_pkt, void *hpkt, bool), void *his_pkt)
56 ff->callback = callback;
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, callback, his_pkt, 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': /* gzip compression */
178 inc->options |= FO_GZIP;
179 inc->level = *++rp - '0';
180 Dmsg1(200, "Compression level=%d\n", inc->level);
183 inc->options |= FO_NOATIME;
186 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
190 /* Skip past space(s) */
191 for ( ; *rp == ' '; rp++)
197 strcpy(inc->fname, rp);
200 /* Zap trailing slashes. */
202 while (p > inc->fname && *p == '/') {
207 /* Check for wild cards */
209 for (p=inc->fname; *p; p++) {
210 if (*p == '*' || *p == '[' || *p == '?') {
215 #if defined(HAVE_WIN32)
216 /* Convert any \'s into /'s */
217 for (p=inc->fname; *p; p++) {
224 /* Chain this one on the end of the list */
225 if (!ff->included_files_list) {
226 /* First one, so set head */
227 ff->included_files_list = inc;
229 struct s_included_file *next;
230 /* Walk to end of list */
231 for (next=ff->included_files_list; next->next; next=next->next)
235 Dmsg1(50, "add_fname_to_include fname=%s\n", inc->fname);
239 * We add an exclude name to either the exclude path
240 * list or the exclude filename list.
242 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
245 struct s_excluded_file *exc, **list;
247 Dmsg1(20, "Add name to exclude: %s\n", fname);
249 #if defined(HAVE_WIN32)
250 if (strchr(fname, '/') || strchr(fname, '\\')) {
252 if (strchr(fname, '/')) {
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);
265 #if defined(HAVE_WIN32)
266 /* Convert any \'s into /'s */
267 for (char *p=exc->fname; *p; p++) {
278 * Get next included file
280 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
282 struct s_included_file *inc;
285 inc = ff->included_files_list;
290 * copy inc_options for this file into the ff packet
293 ff->flags = inc->options;
294 ff->GZIP_level = inc->level;
300 * Walk through the included list to see if this
301 * file is included possibly with wild-cards.
304 int file_is_included(FF_PKT *ff, const char *file)
306 struct s_included_file *inc = ff->included_files_list;
309 for ( ; inc; inc=inc->next ) {
311 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
317 * No wild cards. We accept a match to the
318 * end of any component.
320 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
322 if (inc->len == len && strcmp(inc->fname, file) == 0) {
325 if (inc->len < len && file[inc->len] == '/' &&
326 strncmp(inc->fname, file, inc->len) == 0) {
329 if (inc->len == 1 && inc->fname[0] == '/') {
338 * This is the workhorse of excluded_file().
339 * Determine if the file is excluded or not.
342 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
345 Dmsg0(900, "exc is NULL\n");
347 for ( ; exc; exc=exc->next ) {
348 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
349 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
352 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
359 * Walk through the excluded lists to see if this
360 * file is excluded, or if it matches a component
361 * of an excluded directory.
364 int file_is_excluded(FF_PKT *ff, const char *file)
368 #if defined(HAVE_WIN32)
370 * ***NB*** this removes the drive from the exclude
373 if (file[1] == ':') {
378 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
382 /* Try each component */
383 for (p = file; *p; p++) {
384 /* Match from the beginning of a component only */
385 if ((p == file || (*p != '/' && *(p-1) == '/'))
386 && file_in_excluded_list(ff->excluded_files_list, p)) {