]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/parse_bsr.c
4cd7cba3d79d090c3744a6cbcfd1c6dbc88c06cd
[bacula/bacula] / bacula / src / stored / parse_bsr.c
1 /*     
2  *   Parse a Bootstrap Records (used for restores) 
3  *  
4  *     Kern Sibbald, June MMII
5  *
6  *   Version $Id$
7  */
8
9 /*
10    Copyright (C) 2002 Kern Sibbald and John Walker
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    MA 02111-1307, USA.
25
26  */
27
28
29 #include "bacula.h"
30 #include "stored.h"
31
32 typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
33
34 static BSR *store_vol(LEX *lc, BSR *bsr);
35 static BSR *store_client(LEX *lc, BSR *bsr);
36 static BSR *store_job(LEX *lc, BSR *bsr);
37 static BSR *store_jobid(LEX *lc, BSR *bsr);
38 static BSR *store_jobtype(LEX *lc, BSR *bsr);
39 static BSR *store_joblevel(LEX *lc, BSR *bsr);
40 static BSR *store_findex(LEX *lc, BSR *bsr);
41 static BSR *store_sessid(LEX *lc, BSR *bsr);
42 static BSR *store_volfile(LEX *lc, BSR *bsr);
43 static BSR *store_sesstime(LEX *lc, BSR *bsr);
44 static BSR *store_include(LEX *lc, BSR *bsr);
45 static BSR *store_exclude(LEX *lc, BSR *bsr);
46 static BSR *store_stream(LEX *lc, BSR *bsr);
47 static BSR *store_slot(LEX *lc, BSR *bsr);
48
49 struct kw_items {
50    char *name;
51    ITEM_HANDLER *handler;
52 };
53
54 struct kw_items items[] = {
55    {"volume", store_vol},
56    {"client", store_client},
57    {"job", store_job},
58    {"jobid", store_jobid},
59    {"fileindex", store_findex},
60    {"jobtype", store_jobtype},
61    {"joblevel", store_joblevel},
62    {"volsessionid", store_sessid},
63    {"volsessiontime", store_sesstime},
64    {"include", store_include},
65    {"exclude", store_exclude},
66    {"volfile", store_volfile},
67    {"stream",  store_stream},
68    {"slot",    store_slot},
69    {NULL, NULL}
70
71 };
72
73 static BSR *new_bsr() 
74 {
75    BSR *bsr = (BSR *)malloc(sizeof(BSR));
76    memset(bsr, 0, sizeof(BSR));
77    return bsr;
78 }
79
80 /*
81  * Format a scanner error message 
82  */
83 static void s_err(char *file, int line, LEX *lc, char *msg, ...)
84 {
85    JCR *jcr = (JCR *)(lc->caller_ctx);
86    va_list arg_ptr;
87    char buf[MAXSTRING];
88
89    va_start(arg_ptr, msg);
90    bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
91    va_end(arg_ptr);
92      
93    if (jcr) {
94       Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n\
95             : Line %d, col %d of file %s\n%s\n"),
96          buf, lc->line_no, lc->col_no, lc->fname, lc->line);
97    } else {
98       e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n\
99             : Line %d, col %d of file %s\n%s\n"),
100          buf, lc->line_no, lc->col_no, lc->fname, lc->line);
101    }
102 }
103
104
105 /*********************************************************************
106  *
107  *      Parse Bootstrap file
108  *
109  */
110 BSR *parse_bsr(JCR *jcr, char *cf)
111 {
112    LEX *lc = NULL;
113    int token, i;
114    BSR *root_bsr = new_bsr();
115    BSR *bsr = root_bsr;
116
117    Dmsg1(200, "Enter parse_bsf %s\n", cf);
118    lc = lex_open_file(lc, cf, s_err);
119    lc->caller_ctx = (void *)jcr;
120    while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
121       Dmsg1(200, "parse got token=%s\n", lex_tok_to_str(token));
122       if (token == T_EOL) {
123          continue;
124       }
125       for (i=0; items[i].name; i++) {
126          if (strcasecmp(items[i].name, lc->str) == 0) {
127             token = lex_get_token(lc, T_ALL);
128             Dmsg1 (200, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
129             if (token != T_EQUALS) {
130                scan_err1(lc, "expected an equals, got: %s", lc->str);
131                bsr = NULL;
132                break;
133             }
134             Dmsg1(200, "calling handler for %s\n", items[i].name);
135             /* Call item handler */
136             bsr = items[i].handler(lc, bsr);
137             i = -1;
138             break;
139          }
140       }
141       if (i >= 0) {
142          Dmsg1(200, "Keyword = %s\n", lc->str);
143          scan_err1(lc, "Keyword %s not found", lc->str);
144          bsr = NULL;
145          break;
146       }
147       if (!bsr) {
148          break;
149       }
150    }
151    lc = lex_close_file(lc);
152    Dmsg0(200, "Leave parse_bsf()\n");
153    if (!bsr) {
154       free_bsr(root_bsr);
155       root_bsr = NULL;
156    }
157    return root_bsr;
158 }
159
160 static BSR *store_vol(LEX *lc, BSR *bsr)
161 {
162    int token;
163     
164    token = lex_get_token(lc, T_NAME);
165    if (token == T_ERROR) {
166       return NULL;
167    }
168    if (bsr->VolumeName) {
169       bsr->next = new_bsr();
170       bsr = bsr->next;
171    }
172    bsr->VolumeName = bstrdup(lc->str);
173    scan_to_eol(lc);
174    return bsr;
175 }
176
177 static BSR *store_client(LEX *lc, BSR *bsr)
178 {
179    int token;
180    BSR_CLIENT *client;
181     
182    for (;;) {
183       token = lex_get_token(lc, T_NAME);
184       if (token == T_ERROR) {
185          return NULL;
186       }
187       client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
188       memset(client, 0, sizeof(BSR_CLIENT));
189       strcpy(client->ClientName, lc->str);
190       /* Add it to the end of the client chain */
191       if (!bsr->client) {
192          bsr->client = client;
193       } else {
194          BSR_CLIENT *bc = bsr->client;
195          for ( ;bc->next; bc=bc->next)  
196             { }
197          bc->next = client;
198       }
199       token = lex_get_token(lc, T_ALL);
200       if (token != T_COMMA) {
201          break;
202       }
203    }
204    return bsr;
205 }
206
207 static BSR *store_job(LEX *lc, BSR *bsr)
208 {
209    int token;
210    BSR_JOB *job;
211     
212    for (;;) {
213       token = lex_get_token(lc, T_NAME);
214       if (token == T_ERROR) {
215          return NULL;
216       }
217       job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
218       memset(job, 0, sizeof(BSR_JOB));
219       strcpy(job->Job, lc->str);
220       /* Add it to the end of the client chain */
221       if (!bsr->job) {
222          bsr->job = job;
223       } else {
224          /* Add to end of chain */
225          BSR_JOB *bc = bsr->job;
226          for ( ;bc->next; bc=bc->next)
227             { }
228          bc->next = job;
229       }
230       token = lex_get_token(lc, T_ALL);
231       if (token != T_COMMA) {
232          break;
233       }
234    }
235    return bsr;
236 }
237
238 static BSR *store_findex(LEX *lc, BSR *bsr)
239 {
240    int token;
241    BSR_FINDEX *findex;
242
243    for (;;) {
244       token = lex_get_token(lc, T_PINT32_RANGE);
245       if (token == T_ERROR) {
246          return NULL;
247       }
248       findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
249       memset(findex, 0, sizeof(BSR_FINDEX));
250       findex->findex = lc->pint32_val;
251       findex->findex2 = lc->pint32_val2;
252       /* Add it to the end of the chain */
253       if (!bsr->FileIndex) {
254          bsr->FileIndex = findex;
255       } else {
256          /* Add to end of chain */
257          BSR_FINDEX *bs = bsr->FileIndex;
258          for ( ;bs->next; bs=bs->next)
259             {  }
260          bs->next = findex;
261       }
262       token = lex_get_token(lc, T_ALL);
263       if (token != T_COMMA) {
264          break;
265       }
266    }
267    return bsr;
268 }
269
270
271 static BSR *store_jobid(LEX *lc, BSR *bsr)
272 {
273    int token;
274    BSR_JOBID *jobid;
275
276    for (;;) {
277       token = lex_get_token(lc, T_PINT32_RANGE);
278       if (token == T_ERROR) {
279          return NULL;
280       }
281       jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
282       memset(jobid, 0, sizeof(BSR_JOBID));
283       jobid->JobId = lc->pint32_val;
284       jobid->JobId2 = lc->pint32_val2;
285       /* Add it to the end of the chain */
286       if (!bsr->JobId) {
287          bsr->JobId = jobid;
288       } else {
289          /* Add to end of chain */
290          BSR_JOBID *bs = bsr->JobId;
291          for ( ;bs->next; bs=bs->next)
292             {  }
293          bs->next = jobid;
294       }
295       token = lex_get_token(lc, T_ALL);
296       if (token != T_COMMA) {
297          break;
298       }
299    }
300    return bsr;
301 }
302
303 static BSR *store_jobtype(LEX *lc, BSR *bsr)
304 {
305    /* *****FIXME****** */
306    Dmsg0(-1, "JobType not yet implemented\n");
307    return bsr;
308 }
309
310
311 static BSR *store_joblevel(LEX *lc, BSR *bsr)
312 {
313    /* *****FIXME****** */
314    Dmsg0(-1, "JobLevel not yet implemented\n");
315    return bsr;
316 }
317
318
319
320
321 /*
322  * Routine to handle Volume start/end file   
323  */
324 static BSR *store_volfile(LEX *lc, BSR *bsr)
325 {
326    int token;
327    BSR_VOLFILE *volfile;
328
329    for (;;) {
330       token = lex_get_token(lc, T_PINT32_RANGE);
331       if (token == T_ERROR) {
332          return NULL;
333       }
334       volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
335       memset(volfile, 0, sizeof(BSR_VOLFILE));
336       volfile->sfile = lc->pint32_val;
337       volfile->efile = lc->pint32_val2;
338       /* Add it to the end of the chain */
339       if (!bsr->volfile) {
340          bsr->volfile = volfile;
341       } else {
342          /* Add to end of chain */
343          BSR_VOLFILE *bs = bsr->volfile;
344          for ( ;bs->next; bs=bs->next)
345             {  }
346          bs->next = volfile;
347       }
348       token = lex_get_token(lc, T_ALL);
349       if (token != T_COMMA) {
350          break;
351       }
352    }
353    return bsr;
354 }
355
356
357
358 static BSR *store_sessid(LEX *lc, BSR *bsr)
359 {
360    int token;
361    BSR_SESSID *sid;
362
363    for (;;) {
364       token = lex_get_token(lc, T_PINT32_RANGE);
365       if (token == T_ERROR) {
366          return NULL;
367       }
368       sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
369       memset(sid, 0, sizeof(BSR_SESSID));
370       sid->sessid = lc->pint32_val;
371       sid->sessid2 = lc->pint32_val2;
372       /* Add it to the end of the chain */
373       if (!bsr->sessid) {
374          bsr->sessid = sid;
375       } else {
376          /* Add to end of chain */
377          BSR_SESSID *bs = bsr->sessid;
378          for ( ;bs->next; bs=bs->next)
379             {  }
380          bs->next = sid;
381       }
382       token = lex_get_token(lc, T_ALL);
383       if (token != T_COMMA) {
384          break;
385       }
386    }
387    return bsr;
388 }
389
390 static BSR *store_sesstime(LEX *lc, BSR *bsr)
391 {
392    int token;
393    BSR_SESSTIME *stime;
394
395    for (;;) {
396       token = lex_get_token(lc, T_PINT32);
397       if (token == T_ERROR) {
398          return NULL;
399       }
400       stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
401       memset(stime, 0, sizeof(BSR_SESSTIME));
402       stime->sesstime = lc->pint32_val;
403       /* Add it to the end of the chain */
404       if (!bsr->sesstime) {
405          bsr->sesstime = stime;
406       } else {
407          /* Add to end of chain */
408          BSR_SESSTIME *bs = bsr->sesstime;
409          for ( ;bs->next; bs=bs->next)
410             { }
411          bs->next = stime;
412       }
413       token = lex_get_token(lc, T_ALL);
414       if (token != T_COMMA) {
415          break;
416       }
417    }
418    return bsr;
419 }
420
421
422 static BSR *store_stream(LEX *lc, BSR *bsr)
423 {
424    int token;
425    BSR_STREAM *stream;
426
427    for (;;) {
428       token = lex_get_token(lc, T_INT32);
429       if (token == T_ERROR) {
430          return NULL;
431       }
432       stream = (BSR_STREAM *)malloc(sizeof(BSR_STREAM));
433       memset(stream, 0, sizeof(BSR_STREAM));
434       stream->stream = lc->int32_val;
435       /* Add it to the end of the chain */
436       if (!bsr->stream) {
437          bsr->stream = stream;
438       } else {
439          /* Add to end of chain */
440          BSR_STREAM *bs = bsr->stream;
441          for ( ;bs->next; bs=bs->next)
442             { }
443          bs->next = stream;
444       }
445       token = lex_get_token(lc, T_ALL);
446       if (token != T_COMMA) {
447          break;
448       }
449    }
450    return bsr;
451 }
452
453 static BSR *store_slot(LEX *lc, BSR *bsr)
454 {
455    int token;
456
457    token = lex_get_token(lc, T_PINT32);
458    if (token == T_ERROR) {
459       return NULL;
460    }
461    bsr->Slot = lc->pint32_val;
462    scan_to_eol(lc);
463    return bsr;
464 }
465
466 static BSR *store_include(LEX *lc, BSR *bsr)
467 {
468    scan_to_eol(lc);
469    return bsr;
470 }
471
472 static BSR *store_exclude(LEX *lc, BSR *bsr)
473 {
474    scan_to_eol(lc);
475    return bsr;
476 }
477
478 void dump_volfile(BSR_VOLFILE *volfile)
479 {
480    if (volfile) {
481       Dmsg2(-1, "VolFile     : %u-%u\n", volfile->sfile, volfile->efile);
482       dump_volfile(volfile->next);
483    }
484 }
485
486 void dump_findex(BSR_FINDEX *FileIndex)
487 {
488    if (FileIndex) {
489       if (FileIndex->findex == FileIndex->findex2) {
490          Dmsg1(-1, "FileIndex   : %u\n", FileIndex->findex);
491       } else {
492          Dmsg2(-1, "FileIndex   : %u-%u\n", FileIndex->findex, FileIndex->findex2);
493       }
494       dump_findex(FileIndex->next);
495    }
496 }
497
498 void dump_jobid(BSR_JOBID *jobid)
499 {
500    if (jobid) {
501       if (jobid->JobId == jobid->JobId2) {
502          Dmsg1(-1, "JobId       : %u\n", jobid->JobId);
503       } else {
504          Dmsg2(-1, "JobId       : %u-%u\n", jobid->JobId, jobid->JobId2);
505       }
506       dump_jobid(jobid->next);
507    }
508 }
509
510 void dump_sessid(BSR_SESSID *sessid)
511 {
512    if (sessid) {
513       if (sessid->sessid == sessid->sessid2) {
514          Dmsg1(-1, "SessId      : %u\n", sessid->sessid);
515       } else {
516          Dmsg2(-1, "SessId      : %u-%u\n", sessid->sessid, sessid->sessid2);
517       }
518       dump_sessid(sessid->next);
519    }
520 }
521
522
523 void dump_client(BSR_CLIENT *client)
524 {
525    if (client) {
526       Dmsg1(-1, "Client      : %s\n", client->ClientName);
527       dump_client(client->next);
528    }
529 }
530
531 void dump_job(BSR_JOB *job)
532 {
533    if (job) {
534       Dmsg1(-1, "Job          : %s\n", job->Job);
535       dump_job(job->next);
536    }
537 }
538
539 void dump_sesstime(BSR_SESSTIME *sesstime)
540 {
541    if (sesstime) {
542       Dmsg1(-1, "SessTime    : %u\n", sesstime->sesstime);
543       dump_sesstime(sesstime->next);
544    }
545 }
546
547
548
549
550
551 void dump_bsr(BSR *bsr)
552 {
553    if (!bsr) {
554       Dmsg0(-1, "BSR is NULL\n");
555       return;
556    }
557    Dmsg2(-1,   
558 "Next        : 0x%x\n"
559 "VolumeName  : %s\n",
560                  bsr->next,
561                  bsr->VolumeName ? bsr->VolumeName : "*None*");
562    dump_sessid(bsr->sessid);
563    dump_sesstime(bsr->sesstime);
564    dump_volfile(bsr->volfile);
565    dump_client(bsr->client);
566    dump_jobid(bsr->JobId);
567    dump_job(bsr->job);
568    dump_findex(bsr->FileIndex);
569    if (bsr->next) {
570       Dmsg0(-1, "\n");
571       dump_bsr(bsr->next);
572    }
573 }
574
575
576
577 /*********************************************************************
578  *
579  *      Free bsr resources
580  */
581
582 static void free_bsr_item(BSR *bsr)
583 {
584    if (bsr) {
585       free_bsr_item(bsr->next);
586       free(bsr);
587    }
588 }
589
590 void free_bsr(BSR *bsr)
591 {
592    if (!bsr) {
593       return;
594    }
595    free_bsr_item((BSR *)bsr->client);
596    free_bsr_item((BSR *)bsr->sessid);
597    free_bsr_item((BSR *)bsr->sesstime);
598    free_bsr_item((BSR *)bsr->volfile);
599    free_bsr_item((BSR *)bsr->JobId);
600    free_bsr_item((BSR *)bsr->job);
601    free_bsr_item((BSR *)bsr->FileIndex);
602    free_bsr_item((BSR *)bsr->JobType);
603    free_bsr_item((BSR *)bsr->JobLevel);
604    if (bsr->VolumeName) {
605       free(bsr->VolumeName);
606    }
607    free_bsr(bsr->next);
608    free(bsr);
609 }
610
611 /*****************************************************************
612  * Routines for handling volumes     
613  */
614 VOL_LIST *new_vol()
615 {
616    VOL_LIST *vol;
617    vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
618    memset(vol, 0, sizeof(VOL_LIST));
619    return vol;
620 }
621
622 /* 
623  * Add current volume to end of list, only if the Volume
624  * is not already in the list.
625  *
626  *   returns: 1 if volume added
627  *            0 if volume already in list
628  */
629 int add_vol(JCR *jcr, VOL_LIST *vol)
630 {
631    VOL_LIST *next = jcr->VolList;
632
633    if (!next) {                       /* list empty ? */
634       jcr->VolList = vol;             /* yes, add volume */
635    } else {
636       for ( ; next->next; next=next->next) {
637          if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
638             return 0;                 /* already in list */
639          }
640       }
641       if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
642          return 0;                    /* already in list */
643       }
644       next->next = vol;               /* add volume */
645    }
646    return 1;
647 }
648
649 void free_vol_list(JCR *jcr)
650 {
651    VOL_LIST *next = jcr->VolList;
652    VOL_LIST *tmp;
653
654    for ( ; next; ) {
655       tmp = next->next;
656       free(next);
657       next = tmp;
658    }
659 }
660
661 void create_vol_list(JCR *jcr)
662 {
663    char *p, *n;
664    VOL_LIST *vol;
665
666    /* 
667     * Build a list of volume to be processed
668     */
669    jcr->NumVolumes = 0;
670    jcr->CurVolume = 1;
671    if (jcr->bsr) {
672       BSR *bsr = jcr->bsr;
673       strcpy(jcr->VolumeName, bsr->VolumeName); /* setup first volume */
674       for ( ; bsr; bsr=bsr->next) {
675          vol = new_vol();
676          strcpy(vol->VolumeName, bsr->VolumeName);
677          if (add_vol(jcr, vol)) {
678             jcr->NumVolumes++;
679             Dmsg1(400, "Added volume %s\n", vol->VolumeName);
680          } else {
681             Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
682             free((char *)vol);
683          }
684       }
685    } else {
686       /* This is the old way -- deprecated */ 
687       for (p = jcr->VolumeName; p && *p; ) {
688          n = strchr(p, '|');             /* volume name separator */
689          if (n) {
690             *n++ = 0;                    /* Terminate name */
691          }
692          vol = new_vol();
693          strcpy(vol->VolumeName, p);
694          if (add_vol(jcr, vol)) {
695             jcr->NumVolumes++;
696          } else {
697             free((char *)vol);
698          }
699          p = n;
700       }
701    }
702 }