]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/find.c
Implement new style filesets
[bacula/bacula] / bacula / src / findlib / find.c
1 /*
2  * Main routine for finding files on a file system.
3  *  The heart of the work is done in find_one.c
4  *
5  *  Kern E. Sibbald, MM
6  */
7 /*
8    Copyright (C) 2000-2003 Kern Sibbald and John Walker
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of
13    the License, or (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public
21    License along with this program; if not, write to the Free
22    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23    MA 02111-1307, USA.
24
25  */
26
27
28 #include "bacula.h"
29 #include "find.h"
30
31
32 int32_t name_max;              /* filename max length */
33 int32_t path_max;              /* path name max length */
34
35
36 /* ****FIXME**** debug until stable */
37 #undef bmalloc
38 #define bmalloc(x) sm_malloc(__FILE__, __LINE__, x)
39 static void set_options(FF_PKT *ff, const char *opts);
40
41
42 /* 
43  * Initialize the find files "global" variables
44  */
45 FF_PKT *init_find_files()
46 {
47   FF_PKT *ff;    
48
49   ff = (FF_PKT *)bmalloc(sizeof(FF_PKT));
50   memset(ff, 0, sizeof(FF_PKT));
51
52   ff->sys_fname = get_pool_memory(PM_FNAME);
53
54   init_include_exclude_files(ff);           /* init lists */
55
56    /* Get system path and filename maximum lengths */
57    path_max = pathconf(".", _PC_PATH_MAX);
58    if (path_max < 1024) {
59       path_max = 1024;
60    }
61
62    name_max = pathconf(".", _PC_NAME_MAX);
63    if (name_max < 1024) {
64       name_max = 1024;
65    }
66    path_max++;                        /* add for EOS */
67    name_max++;                        /* add for EOS */
68
69   Dmsg1(100, "init_find_files ff=%p\n", ff);
70   return ff;
71 }
72
73 /* 
74  * Set find_files options. For the moment, we only
75  * provide for full/incremental saves, and setting
76  * of save_time. For additional options, see above
77  */
78 void
79 set_find_options(FF_PKT *ff, int incremental, time_t save_time)
80 {
81   Dmsg0(100, "Enter set_find_options()\n");
82   ff->incremental = incremental;
83   ff->save_time = save_time;
84   Dmsg0(100, "Leave set_find_options()\n");
85 }
86
87 /* 
88  * Find all specified files (determined by calls to 
89  * name_add()
90  * This routine calls the (handle_file) subroutine with all
91  * sorts of good information for the final disposition of
92  * the file.
93  * 
94  * Call this subroutine with a callback subroutine as the first
95  * argument and a packet as the second argument, this packet
96  * will be passed back to the callback subroutine as the last
97  * argument.
98  *
99  * The callback subroutine gets called with:
100  *  arg1 -- the FF_PKT containing filename, link, stat, ftype, flags, etc
101  *  arg2 -- the user supplied packet
102  *
103  */
104 int
105 find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt), void *his_pkt) 
106 {
107    struct s_included_file *inc = NULL;
108
109    /* This is the old deprecated way */
110    while (!job_canceled(jcr) && (inc = get_next_included_file(ff, inc))) {
111       /* Copy options for this file */
112       bstrncpy(ff->VerifyOpts, inc->VerifyOpts, sizeof(ff->VerifyOpts)); 
113       Dmsg1(50, "find_files: file=%s\n", inc->fname);
114       if (!file_is_excluded(ff, inc->fname)) {
115          if (!find_one_file(jcr, ff, callback, his_pkt, inc->fname, (dev_t)-1, 1)) {
116             return 0;                  /* error return */
117          }
118       }
119    }
120
121    /* This is the new way */
122    findFILESET *fileset = ff->fileset;
123    if (fileset) {
124       int i, j;
125       for (i=0; i<fileset->include_list.size(); i++) {
126          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
127          /*
128           * By setting all options, we in effect or the global options
129           *   which is what we want.
130           */
131          for (j=0; j<incexe->opts_list.size(); j++) {
132             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
133             Dmsg1(400, "Find global options O %s\n", fo->opts);
134             set_options(ff, fo->opts);
135          }
136          for (j=0; j<incexe->name_list.size(); j++) {
137             Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
138             char *fname = (char *)incexe->name_list.get(j);
139             if (!find_one_file(jcr, ff, callback, his_pkt, fname, (dev_t)-1, 1)) {
140                return 0;                  /* error return */
141             }
142          }
143       }
144    }
145    return 1;
146 }
147
148 /*
149  * As an optimization, we should do this during
150  *  "compile" time in filed/job.c, and keep only a bit mask
151  *  and the Verify options.
152  */
153 static void set_options(FF_PKT *ff, const char *opts)
154 {
155    int j;
156    const char *p;
157
158    for (p=opts; *p; p++) {
159       switch (*p) {
160       case 'a':                 /* alway replace */
161       case '0':                 /* no option */
162          break;
163       case 'f':
164          ff->flags |= FO_MULTIFS;
165          break;
166       case 'h':                 /* no recursion */
167          ff->flags |= FO_NO_RECURSION;
168          break;
169       case 'M':                 /* MD5 */
170          ff->flags |= FO_MD5;
171          break;
172       case 'n':
173          ff->flags |= FO_NOREPLACE;
174          break;
175       case 'p':                 /* use portable data format */
176          ff->flags |= FO_PORTABLE;
177          break;
178       case 'r':                 /* read fifo */
179          ff->flags |= FO_READFIFO;
180          break;
181       case 'S':
182          ff->flags |= FO_SHA1;
183          break;
184       case 's':
185          ff->flags |= FO_SPARSE;
186          break;
187       case 'm':
188          ff->flags |= FO_MTIMEONLY;
189          break;
190       case 'k':
191          ff->flags |= FO_KEEPATIME;
192          break;
193       case 'V':                  /* verify options */
194          /* Copy Verify Options */
195          for (j=0; *p && *p != ':'; p++) {
196             ff->VerifyOpts[j] = *p;
197             if (j < (int)sizeof(ff->VerifyOpts) - 1) {
198                j++;
199             }
200          }
201          ff->VerifyOpts[j] = 0;
202          break;
203       case 'w':
204          ff->flags |= FO_IF_NEWER;
205          break;
206       case 'Z':                 /* gzip compression */
207          ff->flags |= FO_GZIP;
208          ff->GZIP_level = *++p - '0';
209          Dmsg1(200, "Compression level=%d\n", ff->GZIP_level);
210          break;
211       default:
212          Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p);
213          break;
214       }
215    }
216 }
217
218
219 /*
220  * Terminate find_files() and release
221  * all allocated memory   
222  */
223 int
224 term_find_files(FF_PKT *ff)
225 {
226   int hard_links;
227
228   term_include_exclude_files(ff);
229   free_pool_memory(ff->sys_fname);
230   hard_links = term_find_one(ff);
231   free(ff);
232   return hard_links;
233 }