2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
31 * Routines used to keep and match include and exclude
32 * filename/pathname patterns.
34 * Note, this file is used for the old style include and
35 * excludes, so is deprecated. The new style code is
37 * This code is still used for lists in testls and bextract.
39 * Kern E. Sibbald, December MMI
46 #include <sys/types.h>
48 #ifndef FNM_LEADING_DIR
49 #define FNM_LEADING_DIR 0
52 /* Fold case in fnmatch() on Win32 */
54 static const int fnmode = FNM_CASEFOLD;
56 static const int fnmode = 0;
61 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
65 match_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *, FF_PKT *ff_pkt, bool))
67 ff->file_save = file_save;
69 struct s_included_file *inc = NULL;
71 /* This is the old deprecated way */
72 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
73 /* Copy options for this file */
74 bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
75 Dmsg1(100, "find_files: file=%s\n", inc->fname);
76 if (!file_is_excluded(ff, inc->fname)) {
77 if (find_one_file(jcr, ff, file_save, inc->fname, (dev_t)-1, 1) ==0) {
78 return 0; /* error return */
87 * Done doing filename matching, release all
90 void term_include_exclude_files(FF_PKT *ff)
92 struct s_included_file *inc, *next_inc;
93 struct s_excluded_file *exc, *next_exc;
95 for (inc=ff->included_files_list; inc; ) {
100 ff->included_files_list = NULL;
102 for (exc=ff->excluded_files_list; exc; ) {
103 next_exc = exc->next;
107 ff->excluded_files_list = NULL;
109 for (exc=ff->excluded_paths_list; exc; ) {
110 next_exc = exc->next;
114 ff->excluded_paths_list = NULL;
118 * Add a filename to list of included files
120 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
123 struct s_included_file *inc;
129 inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
131 inc->VerifyOpts[0] = 'V';
132 inc->VerifyOpts[1] = ':';
133 inc->VerifyOpts[2] = 0;
135 /* prefixed = preceded with options */
137 for (rp=fname; *rp && *rp != ' '; rp++) {
139 case 'a': /* alway replace */
140 case '0': /* no option */
143 inc->options |= FO_MULTIFS;
145 case 'h': /* no recursion */
146 inc->options |= FO_NO_RECURSION;
149 inc->options |= FO_MD5;
152 inc->options |= FO_NOREPLACE;
154 case 'p': /* use portable data format */
155 inc->options |= FO_PORTABLE;
157 case 'r': /* read fifo */
158 inc->options |= FO_READFIFO;
161 inc->options |= FO_SHA1;
164 inc->options |= FO_SPARSE;
167 inc->options |= FO_MTIMEONLY;
170 inc->options |= FO_KEEPATIME;
172 case 'V': /* verify options */
173 /* Copy Verify Options */
174 for (j=0; *rp && *rp != ':'; rp++) {
175 inc->VerifyOpts[j] = *rp;
176 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
180 inc->VerifyOpts[j] = 0;
183 inc->options |= FO_IF_NEWER;
186 inc->options |= FO_ACL;
188 case 'Z': /* gzip compression */
189 inc->options |= FO_GZIP;
190 inc->level = *++rp - '0';
191 Dmsg1(200, "Compression level=%d\n", inc->level);
194 inc->options |= FO_NOATIME;
197 inc->options |= FO_XATTR;
200 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
204 /* Skip past space(s) */
205 for ( ; *rp == ' '; rp++)
211 strcpy(inc->fname, rp);
214 /* Zap trailing slashes. */
216 while (p > inc->fname && IsPathSeparator(*p)) {
221 /* Check for wild cards */
223 for (p=inc->fname; *p; p++) {
224 if (*p == '*' || *p == '[' || *p == '?') {
229 #if defined(HAVE_WIN32)
230 /* Convert any \'s into /'s */
231 for (p=inc->fname; *p; p++) {
238 /* Chain this one on the end of the list */
239 if (!ff->included_files_list) {
240 /* First one, so set head */
241 ff->included_files_list = inc;
243 struct s_included_file *next;
244 /* Walk to end of list */
245 for (next=ff->included_files_list; next->next; next=next->next)
249 Dmsg3(100, "add_fname_to_include prefix=%d gzip=%d fname=%s\n",
250 prefixed, !!(inc->options & FO_GZIP), inc->fname);
254 * We add an exclude name to either the exclude path
255 * list or the exclude filename list.
257 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
260 struct s_excluded_file *exc, **list;
262 Dmsg1(20, "Add name to exclude: %s\n", fname);
264 if (first_path_separator(fname) != NULL) {
265 list = &ff->excluded_paths_list;
267 list = &ff->excluded_files_list;
272 exc = (struct s_excluded_file *)bmalloc(sizeof(struct s_excluded_file) + len + 1);
275 strcpy(exc->fname, fname);
276 #if defined(HAVE_WIN32)
277 /* Convert any \'s into /'s */
278 for (char *p=exc->fname; *p; p++) {
289 * Get next included file
291 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
293 struct s_included_file *inc;
296 inc = ff->included_files_list;
301 * copy inc_options for this file into the ff packet
304 ff->flags = inc->options;
305 ff->GZIP_level = inc->level;
311 * Walk through the included list to see if this
312 * file is included possibly with wild-cards.
315 int file_is_included(FF_PKT *ff, const char *file)
317 struct s_included_file *inc = ff->included_files_list;
320 for ( ; inc; inc=inc->next ) {
322 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
328 * No wild cards. We accept a match to the
329 * end of any component.
331 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
333 if (inc->len == len && strcmp(inc->fname, file) == 0) {
336 if (inc->len < len && IsPathSeparator(file[inc->len]) &&
337 strncmp(inc->fname, file, inc->len) == 0) {
340 if (inc->len == 1 && IsPathSeparator(inc->fname[0])) {
349 * This is the workhorse of excluded_file().
350 * Determine if the file is excluded or not.
353 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
356 Dmsg0(900, "exc is NULL\n");
358 for ( ; exc; exc=exc->next ) {
359 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
360 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
363 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
370 * Walk through the excluded lists to see if this
371 * file is excluded, or if it matches a component
372 * of an excluded directory.
375 int file_is_excluded(FF_PKT *ff, const char *file)
379 #if defined(HAVE_WIN32)
381 * ***NB*** this removes the drive from the exclude
384 if (file[1] == ':') {
389 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
393 /* Try each component */
394 for (p = file; *p; p++) {
395 /* Match from the beginning of a component only */
396 if ((p == file || (!IsPathSeparator(*p) && IsPathSeparator(p[-1])))
397 && file_in_excluded_list(ff->excluded_files_list, p)) {