Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.h"
3 : #include "../../bu.h"
4 : #include "../../cstat.h"
5 : #include "../../conffile.h"
6 : #include "../../fsops.h"
7 : #include "../../lock.h"
8 : #include "../../log.h"
9 : #include "../../strlist.h"
10 : #include "../bu_get.h"
11 : #include "../sdirs.h"
12 : #include "cstat.h"
13 :
14 : #ifndef UTEST
15 : static
16 : #endif
17 19 : int cstat_permitted(struct cstat *cstat,
18 : struct conf **monitor_cconfs, struct conf **cconfs)
19 : {
20 : struct strlist *rclient;
21 : const char *monitorconf_cname;
22 :
23 19 : monitorconf_cname=get_string(monitor_cconfs[OPT_CNAME]);
24 19 : if(!monitorconf_cname)
25 : return 0;
26 :
27 : // Allow clients to look at themselves.
28 4 : if(!strcmp(cstat->name, monitorconf_cname))
29 : return 1;
30 :
31 : // Do not allow clients using the super_client option to see more
32 : // than the client that it is pretending to be.
33 3 : if(get_string(monitor_cconfs[OPT_SUPER_CLIENT]))
34 : return 0;
35 :
36 : // If we are listed in this restore_client list, or super_client list.
37 6 : for(rclient=get_strlist(cconfs[OPT_RESTORE_CLIENTS]);
38 2 : rclient; rclient=rclient->next)
39 3 : if(!strcmp(get_string(monitor_cconfs[OPT_CNAME]), rclient->path))
40 : return 1;
41 2 : for(rclient=get_strlist(cconfs[OPT_SUPER_CLIENTS]);
42 0 : rclient; rclient=rclient->next)
43 0 : if(!strcmp(get_string(monitor_cconfs[OPT_CNAME]), rclient->path))
44 : return 1;
45 : return 0;
46 : }
47 :
48 15 : static int cstat_set_sdirs_protocol_known(struct cstat *cstat,
49 : struct conf **cconfs)
50 : {
51 15 : struct sdirs *sdirs=NULL;
52 :
53 15 : if(!(sdirs=sdirs_alloc()))
54 : return -1;
55 15 : if(sdirs_init_from_confs(sdirs, cconfs))
56 : {
57 0 : sdirs_free(&sdirs);
58 : return -1;
59 : }
60 15 : cstat->sdirs=sdirs;
61 : return 0;
62 : }
63 :
64 : static int cstat_set_sdirs(struct cstat *cstat, struct conf **cconfs)
65 : {
66 15 : sdirs_free((struct sdirs **)&cstat->sdirs);
67 :
68 15 : return cstat_set_sdirs_protocol_known(cstat, cconfs);
69 : }
70 :
71 15 : static int set_cstat_from_conf(struct cstat *cstat,
72 : struct conf **monitor_cconfs, struct conf **cconfs)
73 : {
74 15 : struct strlist *s=NULL;
75 : // Make sure the permitted flag is set appropriately.
76 15 : cstat->permitted=cstat_permitted(cstat, monitor_cconfs, cconfs);
77 :
78 15 : if(cstat_set_sdirs(cstat, cconfs))
79 : return -1;
80 15 : strlists_free(&cstat->labels);
81 21 : for(s=get_strlist(cconfs[OPT_LABEL]); s; s=s->next)
82 6 : if(strlist_add_sorted(&cstat->labels, s->path, s->flag))
83 : return -1;
84 : return 0;
85 : }
86 :
87 : #ifndef UTEST
88 : static
89 : #endif
90 24 : int cstat_get_client_names(struct cstat **clist, const char *clientconfdir)
91 : {
92 24 : int i=0;
93 24 : int n=0;
94 24 : int ret=-1;
95 : struct cstat *c;
96 : struct cstat *cnew;
97 24 : struct dirent **dir=NULL;
98 :
99 24 : if((n=scandir(clientconfdir, &dir, filter_dot, NULL))<0)
100 : {
101 1 : logp("scandir failed for %s in %s: %s\n",
102 1 : clientconfdir, __func__, strerror(errno));
103 1 : goto end;
104 : }
105 75 : for(i=0; i<n; i++)
106 : {
107 75 : if(!cname_valid(dir[i]->d_name))
108 2 : continue;
109 175 : for(c=*clist; c; c=c->next)
110 : {
111 119 : if(!c->name) continue;
112 119 : if(!strcmp(dir[i]->d_name, c->name))
113 : break;
114 : }
115 73 : if(c) continue;
116 :
117 : // We do not have this client yet. Add it.
118 56 : if(!(cnew=cstat_alloc())
119 56 : || cstat_init(cnew, dir[i]->d_name, clientconfdir))
120 : goto end;
121 56 : cstat_add_to_list(clist, cnew);
122 : }
123 :
124 : ret=0;
125 : end:
126 24 : if(dir)
127 : {
128 75 : for(i=0; i<n; i++)
129 75 : free(dir[i]);
130 23 : free(dir);
131 : }
132 24 : return ret;
133 : }
134 :
135 : static void cstat_free_w(struct cstat **cstat)
136 : {
137 8 : sdirs_free((struct sdirs **)&(*cstat)->sdirs);
138 8 : cstat_free(cstat);
139 : }
140 :
141 : #ifndef UTEST
142 : static
143 : #endif
144 8 : void cstat_remove(struct cstat **clist, struct cstat **cstat)
145 : {
146 : struct cstat *c;
147 8 : if(!cstat || !*cstat) return;
148 8 : if(*clist==*cstat)
149 : {
150 4 : *clist=(*clist)->next;
151 4 : if(*clist) (*clist)->prev=NULL;
152 4 : cstat_free_w(cstat);
153 4 : *cstat=*clist;
154 4 : return;
155 : }
156 10 : for(c=*clist; c; c=c->next)
157 : {
158 7 : if(c->next!=*cstat)
159 3 : continue;
160 4 : c->next=(*cstat)->next;
161 4 : if(c->next)
162 3 : c->next->prev=(*cstat)->prev;
163 4 : cstat_free_w(cstat);
164 4 : *cstat=*clist;
165 4 : return;
166 : }
167 : }
168 :
169 : // Returns -1 on error, otherwise the number of clients that were reloaded.
170 : #ifndef UTEST
171 : static
172 : #endif
173 12 : int cstat_reload_from_client_confs(struct cstat **clist,
174 : struct conf **monitor_cconfs,
175 : struct conf **globalcs, struct conf **cconfs)
176 : {
177 : struct cstat *c;
178 : struct stat statp;
179 : static time_t global_mtime=0;
180 12 : time_t global_mtime_new=0;
181 : const char *globalconffile;
182 12 : int reloaded=0;
183 :
184 12 : globalconffile=get_string(globalcs[OPT_CONFFILE]);
185 :
186 12 : if(stat(globalconffile, &statp)
187 11 : || !S_ISREG(statp.st_mode))
188 : {
189 1 : logp("Could not stat main conf file %s: %s\n",
190 1 : globalconffile, strerror(errno));
191 1 : return -1;
192 : }
193 11 : global_mtime_new=statp.st_mtime;
194 :
195 : // FIX THIS: If '. included' conf files have changed, this code will
196 : // not detect them. I guess that conf.c should make a list of them.
197 : while(1)
198 : {
199 41 : for(c=*clist; c; c=c->next)
200 : {
201 : // Look at the client conf files to see if they have
202 : // changed, and reload bits and pieces if they have.
203 :
204 31 : if(!c->conffile) continue;
205 62 : if(stat(c->conffile, &statp)
206 28 : || !S_ISREG(statp.st_mode))
207 : {
208 3 : cstat_remove(clist, &c);
209 3 : break; // Go to the beginning of the list.
210 : }
211 28 : if(statp.st_mtime==c->conf_mtime
212 12 : && global_mtime_new==global_mtime)
213 : {
214 : // The conf files have not changed - no need to
215 : // do anything.
216 12 : continue;
217 : }
218 16 : c->conf_mtime=statp.st_mtime;
219 :
220 16 : confs_free_content(cconfs);
221 16 : if(set_string(cconfs[OPT_CNAME], c->name))
222 : return -1;
223 16 : if(conf_load_clientconfdir(globalcs, cconfs))
224 : {
225 : // If the file has junk in it, we will keep
226 : // trying to reload it after removal.
227 : // So, just deny permission to view it.
228 1 : c->permitted=0;
229 1 : continue;
230 : }
231 :
232 15 : if(set_cstat_from_conf(c, monitor_cconfs, cconfs))
233 : return -1;
234 15 : reloaded++;
235 : }
236 : // Only stop if the end of the list was not reached.
237 13 : if(!c) break;
238 : }
239 11 : if(global_mtime!=global_mtime_new)
240 3 : global_mtime=global_mtime_new;
241 : return reloaded;
242 : }
243 :
244 19 : void cstat_set_run_status(struct cstat *cstat, enum run_status run_status)
245 : {
246 19 : if(!cstat->permitted)
247 : return;
248 18 : cstat->run_status=run_status;
249 : }
250 :
251 : // Return -1 on error, or the number of reloaded clients.
252 : #ifndef UTEST
253 : static
254 : #endif
255 5 : int reload_from_clientdir(struct cstat **clist)
256 : {
257 5 : int reloaded=0;
258 : struct cstat *c;
259 18 : for(c=*clist; c; c=c->next)
260 : {
261 : struct stat statp;
262 : struct sdirs *sdirs;
263 :
264 25 : if(!c->permitted) continue;
265 :
266 3 : sdirs=(struct sdirs *)c->sdirs;
267 3 : if(!sdirs || !sdirs->client) continue;
268 6 : if(stat(sdirs->client, &statp))
269 1 : continue;
270 :
271 2 : if(statp.st_mtime==c->clientdir_mtime)
272 : {
273 : // clientdir has not changed - no need to do anything.
274 1 : continue;
275 : }
276 1 : c->clientdir_mtime=statp.st_mtime;
277 :
278 1 : bu_list_free(&c->bu);
279 : // FIX THIS: should probably not load everything each time.
280 : // if(bu_get_current(sdirs, &c->bu))
281 : // goto error;
282 1 : if(bu_get_list_with_working(sdirs, &c->bu))
283 : goto error;
284 1 : reloaded++;
285 : }
286 : return reloaded;
287 : error:
288 0 : return -1;
289 : }
290 :
291 2 : int cstat_load_data_from_disk(struct cstat **clist,
292 : struct conf **monitor_cconfs,
293 : struct conf **globalcs, struct conf **cconfs)
294 : {
295 2 : if(!globalcs) return -1;
296 2 : return cstat_get_client_names(clist,
297 2 : get_string(globalcs[OPT_CLIENTCONFDIR]))
298 2 : || cstat_reload_from_client_confs(clist,
299 : monitor_cconfs, globalcs, cconfs)<0
300 4 : || reload_from_clientdir(clist)<0;
301 : }
302 :
303 21 : int cstat_set_backup_list(struct cstat *cstat)
304 : {
305 21 : struct bu *bu=NULL;
306 :
307 : // Free any previous list.
308 21 : bu_list_free(&cstat->bu);
309 :
310 21 : if(!cstat->permitted) return 0;
311 :
312 20 : if(bu_get_list_with_working((struct sdirs *)cstat->sdirs, &bu))
313 : {
314 : //logp("error when looking up current backups\n");
315 : return 0;
316 : }
317 :
318 : // Find the end of the list just loaded, so we can traverse
319 : // it backwards later.
320 43 : while(bu && bu->next) bu=bu->next;
321 :
322 19 : cstat->bu=bu;
323 19 : return 0;
324 : }
|