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)
52 extern int win32_client;
55 match_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool), void *his_pkt)
57 ff->callback = callback;
59 struct s_included_file *inc = NULL;
61 /* This is the old deprecated way */
62 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
63 /* Copy options for this file */
64 bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
65 Dmsg1(100, "find_files: file=%s\n", inc->fname);
66 if (!file_is_excluded(ff, inc->fname)) {
67 if (find_one_file(jcr, ff, callback, his_pkt, inc->fname, (dev_t)-1, 1) ==0) {
68 return 0; /* error return */
77 * Done doing filename matching, release all
80 void term_include_exclude_files(FF_PKT *ff)
82 struct s_included_file *inc, *next_inc;
83 struct s_excluded_file *exc, *next_exc;
85 for (inc=ff->included_files_list; inc; ) {
90 ff->included_files_list = NULL;
92 for (exc=ff->excluded_files_list; exc; ) {
97 ff->excluded_files_list = NULL;
99 for (exc=ff->excluded_paths_list; exc; ) {
100 next_exc = exc->next;
104 ff->excluded_paths_list = NULL;
108 * Add a filename to list of included files
110 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
113 struct s_included_file *inc;
119 inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
121 inc->VerifyOpts[0] = 'V';
122 inc->VerifyOpts[1] = ':';
123 inc->VerifyOpts[2] = 0;
125 /* prefixed = preceded with options */
127 for (rp=fname; *rp && *rp != ' '; rp++) {
129 case 'a': /* alway replace */
130 case '0': /* no option */
133 inc->options |= FO_MULTIFS;
135 case 'h': /* no recursion */
136 inc->options |= FO_NO_RECURSION;
139 inc->options |= FO_MD5;
142 inc->options |= FO_NOREPLACE;
144 case 'p': /* use portable data format */
145 inc->options |= FO_PORTABLE;
147 case 'r': /* read fifo */
148 inc->options |= FO_READFIFO;
151 inc->options |= FO_SHA1;
154 inc->options |= FO_SPARSE;
157 inc->options |= FO_MTIMEONLY;
160 inc->options |= FO_KEEPATIME;
162 case 'V': /* verify options */
163 /* Copy Verify Options */
164 for (j=0; *rp && *rp != ':'; rp++) {
165 inc->VerifyOpts[j] = *rp;
166 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
170 inc->VerifyOpts[j] = 0;
173 inc->options |= FO_IF_NEWER;
176 inc->options |= FO_ACL;
178 case 'Z': /* gzip compression */
179 inc->options |= FO_GZIP;
180 inc->level = *++rp - '0';
181 Dmsg1(200, "Compression level=%d\n", inc->level);
184 inc->options |= FO_NOATIME;
187 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
191 /* Skip past space(s) */
192 for ( ; *rp == ' '; rp++)
198 strcpy(inc->fname, rp);
201 /* Zap trailing slashes. */
203 while (p > inc->fname && *p == '/') {
208 /* Check for wild cards */
210 for (p=inc->fname; *p; p++) {
211 if (*p == '*' || *p == '[' || *p == '?') {
216 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
217 /* Convert any \'s into /'s */
218 for (p=inc->fname; *p; p++) {
225 /* Chain this one on the end of the list */
226 if (!ff->included_files_list) {
227 /* First one, so set head */
228 ff->included_files_list = inc;
230 struct s_included_file *next;
231 /* Walk to end of list */
232 for (next=ff->included_files_list; next->next; next=next->next)
236 Dmsg1(50, "add_fname_to_include fname=%s\n", inc->fname);
240 * We add an exclude name to either the exclude path
241 * list or the exclude filename list.
243 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
246 struct s_excluded_file *exc, **list;
248 Dmsg1(20, "Add name to exclude: %s\n", fname);
250 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
251 if (strchr(fname, '/') || strchr(fname, '\\')) {
253 if (strchr(fname, '/')) {
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);
266 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
267 /* Convert any \'s into /'s */
268 for (char *p=exc->fname; *p; p++) {
279 * Get next included file
281 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
283 struct s_included_file *inc;
286 inc = ff->included_files_list;
291 * copy inc_options for this file into the ff packet
294 ff->flags = inc->options;
295 ff->GZIP_level = inc->level;
301 * Walk through the included list to see if this
302 * file is included possibly with wild-cards.
305 int file_is_included(FF_PKT *ff, const char *file)
307 struct s_included_file *inc = ff->included_files_list;
310 for ( ; inc; inc=inc->next ) {
312 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
318 * No wild cards. We accept a match to the
319 * end of any component.
321 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
323 if (inc->len == len && strcmp(inc->fname, file) == 0) {
326 if (inc->len < len && file[inc->len] == '/' &&
327 strncmp(inc->fname, file, inc->len) == 0) {
330 if (inc->len == 1 && inc->fname[0] == '/') {
339 * This is the workhorse of excluded_file().
340 * Determine if the file is excluded or not.
343 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
346 Dmsg0(900, "exc is NULL\n");
348 for ( ; exc; exc=exc->next ) {
349 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
350 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
353 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
360 * Walk through the excluded lists to see if this
361 * file is excluded, or if it matches a component
362 * of an excluded directory.
365 int file_is_excluded(FF_PKT *ff, const char *file)
370 * ***NB*** this removes the drive from the exclude
373 if (win32_client && file[1] == ':') {
377 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
381 /* Try each component */
382 for (p = file; *p; p++) {
383 /* Match from the beginning of a component only */
384 if ((p == file || (*p != '/' && *(p-1) == '/'))
385 && file_in_excluded_list(ff->excluded_files_list, p)) {