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
47 #include <sys/types.h>
49 #ifndef FNM_LEADING_DIR
50 #define FNM_LEADING_DIR 0
53 /* Fold case in fnmatch() on Win32 */
55 static const int fnmode = FNM_CASEFOLD;
57 static const int fnmode = 0;
62 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
66 match_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *, FF_PKT *ff_pkt, bool))
68 ff->file_save = file_save;
70 struct s_included_file *inc = NULL;
72 /* This is the old deprecated way */
73 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
74 /* Copy options for this file */
75 bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
76 Dmsg1(100, "find_files: file=%s\n", inc->fname);
77 if (!file_is_excluded(ff, inc->fname)) {
78 if (find_one_file(jcr, ff, file_save, inc->fname, (dev_t)-1, 1) ==0) {
79 return 0; /* error return */
88 * Done doing filename matching, release all
91 void term_include_exclude_files(FF_PKT *ff)
93 struct s_included_file *inc, *next_inc;
94 struct s_excluded_file *exc, *next_exc;
96 for (inc=ff->included_files_list; inc; ) {
101 ff->included_files_list = NULL;
103 for (exc=ff->excluded_files_list; exc; ) {
104 next_exc = exc->next;
108 ff->excluded_files_list = NULL;
110 for (exc=ff->excluded_paths_list; exc; ) {
111 next_exc = exc->next;
115 ff->excluded_paths_list = NULL;
119 * Add a filename to list of included files
121 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
124 struct s_included_file *inc;
130 inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
132 inc->VerifyOpts[0] = 'V';
133 inc->VerifyOpts[1] = ':';
134 inc->VerifyOpts[2] = 0;
136 /* prefixed = preceded with options */
138 for (rp=fname; *rp && *rp != ' '; rp++) {
140 case 'a': /* alway replace */
141 case '0': /* no option */
144 inc->options |= FO_MULTIFS;
146 case 'h': /* no recursion */
147 inc->options |= FO_NO_RECURSION;
150 inc->options |= FO_MD5;
153 inc->options |= FO_NOREPLACE;
155 case 'p': /* use portable data format */
156 inc->options |= FO_PORTABLE;
158 case 'r': /* read fifo */
159 inc->options |= FO_READFIFO;
162 inc->options |= FO_SHA1;
165 inc->options |= FO_SPARSE;
168 inc->options |= FO_MTIMEONLY;
171 inc->options |= FO_KEEPATIME;
173 case 'V': /* verify options */
174 /* Copy Verify Options */
175 for (j=0; *rp && *rp != ':'; rp++) {
176 inc->VerifyOpts[j] = *rp;
177 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
181 inc->VerifyOpts[j] = 0;
184 inc->options |= FO_IF_NEWER;
187 inc->options |= FO_ACL;
189 case 'Z': /* compression */
191 if (*rp >= '0' && *rp <= '9') {
192 inc->options |= FO_COMPRESS;
193 inc->algo = COMPRESS_GZIP;
194 inc->level = *rp - '0';
196 else if (*rp == 'o') {
197 inc->options |= FO_COMPRESS;
198 inc->algo = COMPRESS_LZO1X;
199 inc->level = 1; /* not used with LZO */
201 Dmsg2(200, "Compression alg=%d level=%d\n", inc->algo, inc->level);
204 inc->options |= FO_NOATIME;
207 inc->options |= FO_XATTR;
210 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
214 /* Skip past space(s) */
215 for ( ; *rp == ' '; rp++)
221 strcpy(inc->fname, rp);
224 /* Zap trailing slashes. */
226 while (p > inc->fname && IsPathSeparator(*p)) {
231 /* Check for wild cards */
233 for (p=inc->fname; *p; p++) {
234 if (*p == '*' || *p == '[' || *p == '?') {
239 #if defined(HAVE_WIN32)
240 /* Convert any \'s into /'s */
241 for (p=inc->fname; *p; p++) {
248 /* Chain this one on the end of the list */
249 if (!ff->included_files_list) {
250 /* First one, so set head */
251 ff->included_files_list = inc;
253 struct s_included_file *next;
254 /* Walk to end of list */
255 for (next=ff->included_files_list; next->next; next=next->next)
259 Dmsg4(100, "add_fname_to_include prefix=%d compres=%d alg= %d fname=%s\n",
260 prefixed, !!(inc->options & FO_COMPRESS), inc->algo, inc->fname);
264 * We add an exclude name to either the exclude path
265 * list or the exclude filename list.
267 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
270 struct s_excluded_file *exc, **list;
272 Dmsg1(20, "Add name to exclude: %s\n", fname);
274 if (first_path_separator(fname) != NULL) {
275 list = &ff->excluded_paths_list;
277 list = &ff->excluded_files_list;
282 exc = (struct s_excluded_file *)bmalloc(sizeof(struct s_excluded_file) + len + 1);
285 strcpy(exc->fname, fname);
286 #if defined(HAVE_WIN32)
287 /* Convert any \'s into /'s */
288 for (char *p=exc->fname; *p; p++) {
299 * Get next included file
301 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
303 struct s_included_file *inc;
306 inc = ff->included_files_list;
311 * copy inc_options for this file into the ff packet
314 ff->flags = inc->options;
315 ff->Compress_algo = inc->algo;
316 ff->Compress_level = inc->level;
322 * Walk through the included list to see if this
323 * file is included possibly with wild-cards.
326 int file_is_included(FF_PKT *ff, const char *file)
328 struct s_included_file *inc = ff->included_files_list;
331 for ( ; inc; inc=inc->next ) {
333 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
339 * No wild cards. We accept a match to the
340 * end of any component.
342 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
344 if (inc->len == len && strcmp(inc->fname, file) == 0) {
347 if (inc->len < len && IsPathSeparator(file[inc->len]) &&
348 strncmp(inc->fname, file, inc->len) == 0) {
351 if (inc->len == 1 && IsPathSeparator(inc->fname[0])) {
360 * This is the workhorse of excluded_file().
361 * Determine if the file is excluded or not.
364 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
367 Dmsg0(900, "exc is NULL\n");
369 for ( ; exc; exc=exc->next ) {
370 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
371 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
374 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
381 * Walk through the excluded lists to see if this
382 * file is excluded, or if it matches a component
383 * of an excluded directory.
386 int file_is_excluded(FF_PKT *ff, const char *file)
390 #if defined(HAVE_WIN32)
392 * ***NB*** this removes the drive from the exclude
395 if (file[1] == ':') {
400 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
404 /* Try each component */
405 for (p = file; *p; p++) {
406 /* Match from the beginning of a component only */
407 if ((p == file || (!IsPathSeparator(*p) && IsPathSeparator(p[-1])))
408 && file_in_excluded_list(ff->excluded_files_list, p)) {