]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/match.c
- Use different share mode when opening files on WinMe/98/95 since
[bacula/bacula] / bacula / src / findlib / match.c
1 /*
2  *  Routines used to keep and match include and exclude
3  *   filename/pathname patterns.
4  *
5  *  Note, this file is used for the old style include and
6  *   excludes, so is deprecated. The new style code is  
7  *   found in find.c
8  *
9  *   Kern E. Sibbald, December MMI
10  *
11  */
12 /*
13    Copyright (C) 2001-2004 Kern Sibbald and John Walker
14
15    This program is free software; you can redistribute it and/or
16    modify it under the terms of the GNU General Public License as
17    published by the Free Software Foundation; either version 2 of
18    the License, or (at your option) any later version.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23    General Public License for more details.
24
25    You should have received a copy of the GNU General Public
26    License along with this program; if not, write to the Free
27    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28    MA 02111-1307, USA.
29
30  */
31
32 #include "bacula.h"
33 #include "find.h"
34
35 #include <pwd.h>
36 #include <grp.h>
37 #include <sys/types.h>
38
39 #ifndef FNM_LEADING_DIR
40 #define FNM_LEADING_DIR 0
41 #endif
42
43 /* Fold case in fnmatch() on Win32 */
44 #ifdef WIN32
45 static const int fnmode = FNM_CASEFOLD;
46 #else
47 static const int fnmode = 0;
48 #endif
49
50
51 #undef bmalloc
52 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
53
54 extern const int win32_client;
55        
56 /*
57  * Initialize structures for filename matching
58  */
59 void init_include_exclude_files(FF_PKT *ff)
60 {
61 }
62
63 /*
64  * Done doing filename matching, release all 
65  *  resources used.
66  */
67 void term_include_exclude_files(FF_PKT *ff)
68 {
69    struct s_included_file *inc, *next_inc;
70    struct s_excluded_file *exc, *next_exc;
71
72    for (inc=ff->included_files_list; inc; ) {
73       next_inc = inc->next;
74       free(inc);
75       inc = next_inc;
76    }
77
78    for (exc=ff->excluded_files_list; exc; ) {
79       next_exc = exc->next;
80       free(exc);
81       exc = next_exc;
82    }
83
84    for (exc=ff->excluded_paths_list; exc; ) {
85       next_exc = exc->next;
86       free(exc);
87       exc = next_exc;
88    }
89    
90 }
91
92 /*
93  * Add a filename to list of included files
94  */
95 void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
96 {
97    int len, j;
98    struct s_included_file *inc;
99    char *p;
100    const char *rp;
101
102    len = strlen(fname);
103
104    inc =(struct s_included_file *)bmalloc(sizeof(struct s_included_file) + len + 1);
105    inc->options = 0;
106    inc->VerifyOpts[0] = 'V'; 
107    inc->VerifyOpts[1] = ':';
108    inc->VerifyOpts[2] = 0;
109
110    /* prefixed = preceded with options */
111    if (prefixed) {
112       for (rp=fname; *rp && *rp != ' '; rp++) {
113          switch (*rp) {
114          case 'a':                 /* alway replace */
115          case '0':                 /* no option */
116             break;
117          case 'f':
118             inc->options |= FO_MULTIFS;
119             break;
120          case 'h':                 /* no recursion */
121             inc->options |= FO_NO_RECURSION;
122             break;
123          case 'M':                 /* MD5 */
124             inc->options |= FO_MD5;
125             break;
126          case 'n':
127             inc->options |= FO_NOREPLACE;
128             break;
129          case 'p':                 /* use portable data format */
130             inc->options |= FO_PORTABLE;
131             break;
132          case 'r':                 /* read fifo */
133             inc->options |= FO_READFIFO;
134             break;
135          case 'S':
136             inc->options |= FO_SHA1;
137             break;
138          case 's':
139             inc->options |= FO_SPARSE;
140             break;
141          case 'm':
142             inc->options |= FO_MTIMEONLY;
143             break;
144          case 'k':
145             inc->options |= FO_KEEPATIME;
146             break;
147          case 'V':                  /* verify options */
148             /* Copy Verify Options */
149             for (j=0; *rp && *rp != ':'; rp++) {
150                inc->VerifyOpts[j] = *rp;
151                if (j < (int)sizeof(inc->VerifyOpts) - 1) {
152                   j++;
153                }
154             }
155             inc->VerifyOpts[j] = 0;
156             break;
157          case 'w':
158             inc->options |= FO_IF_NEWER;
159             break;
160          case 'A':
161             inc->options |= FO_ACL;
162             break;
163          case 'Z':                 /* gzip compression */
164             inc->options |= FO_GZIP;
165             inc->level = *++rp - '0';
166             Dmsg1(200, "Compression level=%d\n", inc->level);
167             break;
168          default:
169             Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *rp);
170             break;
171          }
172       }
173       /* Skip past space(s) */
174       for ( ; *rp == ' '; rp++)
175          {}
176    } else {
177       rp = fname;
178    }
179
180    strcpy(inc->fname, rp);                
181    p = inc->fname;
182    len = strlen(p);
183    /* Zap trailing slashes.  */
184    p += len - 1;
185    while (p > inc->fname && *p == '/') {
186       *p-- = 0;
187       len--;
188    }
189    inc->len = len;
190    /* Check for wild cards */
191    inc->pattern = 0;
192    for (p=inc->fname; *p; p++) {
193       if (*p == '*' || *p == '[' || *p == '?') {
194          inc->pattern = 1;
195          break;
196       }
197    }
198 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
199    /* Convert any \'s into /'s */
200    for (p=inc->fname; *p; p++) {
201       if (*p == '\\') {
202          *p = '/';
203       }
204    }
205 #endif
206    inc->next = NULL;
207    /* Chain this one on the end of the list */
208    if (!ff->included_files_list) {
209       /* First one, so set head */
210       ff->included_files_list = inc;
211    } else {
212       struct s_included_file *next;
213       /* Walk to end of list */
214       for (next=ff->included_files_list; next->next; next=next->next)
215          { }
216       next->next = inc;
217    }  
218    Dmsg1(50, "add_fname_to_include fname=%s\n", inc->fname);
219 }
220
221 /*
222  * We add an exclude name to either the exclude path
223  *  list or the exclude filename list.
224  */
225 void add_fname_to_exclude_list(FF_PKT *ff, const char *fname)
226 {
227    int len;
228    struct s_excluded_file *exc, **list;
229
230    Dmsg1(20, "Add name to exclude: %s\n", fname);
231
232 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
233    if (strchr(fname, '/') || strchr(fname, '\\')) {
234 #else
235    if (strchr(fname, '/')) {
236 #endif
237       list = &ff->excluded_paths_list;
238    } else {
239       list = &ff->excluded_files_list;
240    }
241   
242    len = strlen(fname);
243
244    exc = (struct s_excluded_file *)bmalloc(sizeof(struct s_excluded_file) + len + 1);
245    exc->next = *list;
246    exc->len = len;
247    strcpy(exc->fname, fname);                 
248 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
249    /* Convert any \'s into /'s */
250    for (char *p=exc->fname; *p; p++) {
251       if (*p == '\\') {
252          *p = '/';
253       }
254    }
255 #endif
256    *list = exc;
257 }
258
259
260 /*
261  * Get next included file
262  */
263 struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_file *ainc)
264 {
265    struct s_included_file *inc;
266
267    if (ainc == NULL) { 
268       inc = ff->included_files_list;
269    } else {
270       inc = ainc->next;
271    }
272    /*
273     * copy inc_options for this file into the ff packet
274     */
275    if (inc) {
276       ff->flags = inc->options;
277       ff->GZIP_level = inc->level;
278    }
279    return inc;
280 }
281
282 /*
283  * Walk through the included list to see if this
284  *  file is included possibly with wild-cards.
285  */
286
287 int file_is_included(FF_PKT *ff, const char *file)
288 {
289    struct s_included_file *inc = ff->included_files_list;
290    int len;
291
292    for ( ; inc; inc=inc->next ) {
293       if (inc->pattern) {
294          if (fnmatch(inc->fname, file, fnmode|FNM_LEADING_DIR) == 0) {
295             return 1;
296          }
297          continue;
298       }                             
299       /*
300        * No wild cards. We accept a match to the
301        *  end of any component.
302        */
303       Dmsg2(900, "pat=%s file=%s\n", inc->fname, file);
304       len = strlen(file);
305       if (inc->len == len && strcmp(inc->fname, file) == 0) {
306          return 1;
307       }
308       if (inc->len < len && file[inc->len] == '/' && 
309           strncmp(inc->fname, file, inc->len) == 0) {
310          return 1;
311       }
312       if (inc->len == 1 && inc->fname[0] == '/') {
313          return 1;
314       }
315    }
316    return 0;
317 }
318
319
320 /*
321  * This is the workhorse of excluded_file().
322  * Determine if the file is excluded or not.
323  */
324 static int
325 file_in_excluded_list(struct s_excluded_file *exc, const char *file)
326 {
327    if (exc == NULL) {
328       Dmsg0(900, "exc is NULL\n");
329    }
330    for ( ; exc; exc=exc->next ) {
331       if (fnmatch(exc->fname, file, fnmode|FNM_PATHNAME) == 0) {
332          Dmsg2(900, "Match exc pat=%s: file=%s:\n", exc->fname, file);
333          return 1;
334       }
335       Dmsg2(900, "No match exc pat=%s: file=%s:\n", exc->fname, file);
336    }
337    return 0;
338 }
339
340
341 /*
342  * Walk through the excluded lists to see if this
343  *  file is excluded, or if it matches a component
344  *  of an excluded directory.
345  */
346
347 int file_is_excluded(FF_PKT *ff, const char *file)
348 {
349    const char *p;
350
351    /* 
352     *  ***NB*** this removes the drive from the exclude
353     *  rule.  Why?????
354     */
355    if (win32_client && file[1] == ':') {
356       file += 2;
357    }
358
359    if (file_in_excluded_list(ff->excluded_paths_list, file)) {
360       return 1;
361    }
362
363    /* Try each component */
364    for (p = file; *p; p++) {
365       /* Match from the beginning of a component only */
366       if ((p == file || (*p != '/' && *(p-1) == '/'))
367            && file_in_excluded_list(ff->excluded_files_list, p)) {
368          return 1;   
369       }
370    }
371    return 0;
372 }