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 two of the GNU 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 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
48 #include <sys/types.h>
50 #ifndef FNM_LEADING_DIR
51 #define FNM_LEADING_DIR 0
54 /* Fold case in fnmatch() on Win32 */
56 static const int fnmode = FNM_CASEFOLD;
58 static const int fnmode = 0;
63 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
67 match_files(JCR *jcr, FF_PKT *ff, int file_save(JCR *, FF_PKT *ff_pkt, bool))
69 ff->file_save = file_save;
71 struct s_included_file *inc = NULL;
73 /* This is the old deprecated way */
74 while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
75 /* Copy options for this file */
76 bstrncat(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts));
77 Dmsg1(100, "find_files: file=%s\n", inc->fname);
78 if (!file_is_excluded(ff, inc->fname)) {
79 if (find_one_file(jcr, ff, file_save, inc->fname, (dev_t)-1, 1) ==0) {
80 return 0; /* error return */
89 * Done doing filename matching, release all
92 void term_include_exclude_files(FF_PKT *ff)
94 struct s_included_file *inc, *next_inc;
95 struct s_excluded_file *exc, *next_exc;
97 for (inc=ff->included_files_list; inc; ) {
102 ff->included_files_list = NULL;
104 for (exc=ff->excluded_files_list; exc; ) {
105 next_exc = exc->next;
109 ff->excluded_files_list = NULL;
111 for (exc=ff->excluded_paths_list; exc; ) {
112 next_exc = exc->next;
116 ff->excluded_paths_list = NULL;
120 * Add a filename to list of included files
122 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
125 struct s_included_file *inc;
131 inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
133 inc->VerifyOpts[0] = 'V';
134 inc->VerifyOpts[1] = ':';
135 inc->VerifyOpts[2] = 0;
137 /* prefixed = preceded with options */
139 for (rp=fname; *rp && *rp != ' '; rp++) {
141 case 'a': /* alway replace */
142 case '0': /* no option */
145 inc->options |= FO_MULTIFS;
147 case 'h': /* no recursion */
148 inc->options |= FO_NO_RECURSION;
151 inc->options |= FO_MD5;
154 inc->options |= FO_NOREPLACE;
156 case 'p': /* use portable data format */
157 inc->options |= FO_PORTABLE;
159 case 'r': /* read fifo */
160 inc->options |= FO_READFIFO;
163 inc->options |= FO_SHA1;
166 inc->options |= FO_SPARSE;
169 inc->options |= FO_MTIMEONLY;
172 inc->options |= FO_KEEPATIME;
174 case 'V': /* verify options */
175 /* Copy Verify Options */
176 for (j=0; *rp && *rp != ':'; rp++) {
177 inc->VerifyOpts[j] = *rp;
178 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
182 inc->VerifyOpts[j] = 0;
185 inc->options |= FO_IF_NEWER;
188 inc->options |= FO_ACL;
190 case 'Z': /* gzip compression */
191 inc->options |= FO_GZIP;
192 inc->level = *++rp - '0';
193 Dmsg1(200, "Compression level=%d\n", inc->level);
196 inc->options |= FO_NOATIME;
199 inc->options |= FO_XATTR;
202 Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
206 /* Skip past space(s) */
207 for ( ; *rp == ' '; rp++)
213 strcpy(inc->fname, rp);
216 /* Zap trailing slashes. */
218 while (p > inc->fname && IsPathSeparator(*p)) {
223 /* Check for wild cards */
225 for (p=inc->fname; *p; p++) {
226 if (*p == '*' || *p == '[' || *p == '?') {
231 #if defined(HAVE_WIN32)
232 /* Convert any \'s into /'s */
233 for (p=inc->fname; *p; p++) {
240 /* Chain this one on the end of the list */
241 if (!ff->included_files_list) {
242 /* First one, so set head */
243 ff->included_files_list = inc;
245 struct s_included_file *next;
246 /* Walk to end of list */
247 for (next=ff->included_files_list; next->next; next=next->next)
251 Dmsg3(100, "add_fname_to_include prefix=%d gzip=%d fname=%s\n",
252 prefixed, !!(inc->options & FO_GZIP), inc->fname);
256 * We add an exclude name to either the exclude path
257 * list or the exclude filename list.
259 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
262 struct s_excluded_file *exc, **list;
264 Dmsg1(20, "Add name to exclude: %s\n", fname);
266 if (first_path_separator(fname) != NULL) {
267 list = &ff->excluded_paths_list;
269 list = &ff->excluded_files_list;
274 exc = (struct s_excluded_file *)bmalloc(sizeof(struct s_excluded_file) + len + 1);
277 strcpy(exc->fname, fname);
278 #if defined(HAVE_WIN32)
279 /* Convert any \'s into /'s */
280 for (char *p=exc->fname; *p; p++) {
291 * Get next included file
293 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
295 struct s_included_file *inc;
298 inc = ff->included_files_list;
303 * copy inc_options for this file into the ff packet
306 ff->flags = inc->options;
307 ff->GZIP_level = inc->level;
313 * Walk through the included list to see if this
314 * file is included possibly with wild-cards.
317 int file_is_included(FF_PKT *ff, const char *file)
319 struct s_included_file *inc = ff->included_files_list;
322 for ( ; inc; inc=inc->next ) {
324 if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
330 * No wild cards. We accept a match to the
331 * end of any component.
333 Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
335 if (inc->len == len && strcmp(inc->fname, file) == 0) {
338 if (inc->len < len && IsPathSeparator(file[inc->len]) &&
339 strncmp(inc->fname, file, inc->len) == 0) {
342 if (inc->len == 1 && IsPathSeparator(inc->fname[0])) {
351 * This is the workhorse of excluded_file().
352 * Determine if the file is excluded or not.
355 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
358 Dmsg0(900, "exc is NULL\n");
360 for ( ; exc; exc=exc->next ) {
361 if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
362 Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
365 Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
372 * Walk through the excluded lists to see if this
373 * file is excluded, or if it matches a component
374 * of an excluded directory.
377 int file_is_excluded(FF_PKT *ff, const char *file)
381 #if defined(HAVE_WIN32)
383 * ***NB*** this removes the drive from the exclude
386 if (file[1] == ':') {
391 if (file_in_excluded_list(ff->excluded_paths_list, file)) {
395 /* Try each component */
396 for (p = file; *p; p++) {
397 /* Match from the beginning of a component only */
398 if ((p == file || (!IsPathSeparator(*p) && IsPathSeparator(p[-1])))
399 && file_in_excluded_list(ff->excluded_files_list, p)) {