]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/parse_bsr.c
Fix seg fault during cancel in SD
[bacula/bacula] / bacula / src / stored / parse_bsr.c
old mode 100755 (executable)
new mode 100644 (file)
index 1bd1fa3..d4eb27c
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version three of the GNU Affero General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of Kern Sibbald.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *   Parse a Bootstrap Records (used for restores)
  *
@@ -6,21 +33,6 @@
  *   Version $Id$
  */
 
-/*
-   Copyright (C) 2002-2006 Kern Sibbald
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-   the file LICENSE for additional details.
-
- */
-
 
 #include "bacula.h"
 #include "stored.h"
@@ -40,11 +52,14 @@ static BSR *store_findex(LEX *lc, BSR *bsr);
 static BSR *store_sessid(LEX *lc, BSR *bsr);
 static BSR *store_volfile(LEX *lc, BSR *bsr);
 static BSR *store_volblock(LEX *lc, BSR *bsr);
+static BSR *store_voladdr(LEX *lc, BSR *bsr);
 static BSR *store_sesstime(LEX *lc, BSR *bsr);
 static BSR *store_include(LEX *lc, BSR *bsr);
 static BSR *store_exclude(LEX *lc, BSR *bsr);
 static BSR *store_stream(LEX *lc, BSR *bsr);
 static BSR *store_slot(LEX *lc, BSR *bsr);
+static BSR *store_fileregex(LEX *lc, BSR *bsr);
+static BSR *store_nothing(LEX *lc, BSR *bsr);
 static bool is_fast_rejection_ok(BSR *bsr);
 static bool is_positioning_ok(BSR *bsr);
 
@@ -72,11 +87,13 @@ struct kw_items items[] = {
    {"exclude", store_exclude},
    {"volfile", store_volfile},
    {"volblock", store_volblock},
+   {"voladdr",  store_voladdr},
    {"stream",   store_stream},
    {"slot",     store_slot},
    {"device",   store_device},
+   {"fileregex", store_fileregex},
+   {"storage",  store_nothing},
    {NULL, NULL}
-
 };
 
 /*
@@ -126,28 +143,28 @@ BSR *parse_bsr(JCR *jcr, char *fname)
    BSR *root_bsr = new_bsr();
    BSR *bsr = root_bsr;
 
-   Dmsg1(200, "Enter parse_bsf %s\n", fname);
+   Dmsg1(300, "Enter parse_bsf %s\n", fname);
    if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
       berrno be;
       Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
-            fname, be.strerror());
+            fname, be.bstrerror());
    }
    lc->caller_ctx = (void *)jcr;
    while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
-      Dmsg1(200, "parse got token=%s\n", lex_tok_to_str(token));
+      Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
       if (token == T_EOL) {
          continue;
       }
       for (i=0; items[i].name; i++) {
          if (strcasecmp(items[i].name, lc->str) == 0) {
             token = lex_get_token(lc, T_ALL);
-            Dmsg1 (200, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
+            Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
             if (token != T_EQUALS) {
                scan_err1(lc, "expected an equals, got: %s", lc->str);
                bsr = NULL;
                break;
             }
-            Dmsg1(200, "calling handler for %s\n", items[i].name);
+            Dmsg1(300, "calling handler for %s\n", items[i].name);
             /* Call item handler */
             bsr = items[i].handler(lc, bsr);
             i = -1;
@@ -155,7 +172,7 @@ BSR *parse_bsr(JCR *jcr, char *fname)
          }
       }
       if (i >= 0) {
-         Dmsg1(200, "Keyword = %s\n", lc->str);
+         Dmsg1(300, "Keyword = %s\n", lc->str);
          scan_err1(lc, "Keyword %s not found", lc->str);
          bsr = NULL;
          break;
@@ -165,7 +182,7 @@ BSR *parse_bsr(JCR *jcr, char *fname)
       }
    }
    lc = lex_close_file(lc);
-   Dmsg0(200, "Leave parse_bsf()\n");
+   Dmsg0(300, "Leave parse_bsf()\n");
    if (!bsr) {
       free_bsr(root_bsr);
       root_bsr = NULL;
@@ -199,17 +216,17 @@ static bool is_positioning_ok(BSR *bsr)
 {
    /*
     * Every bsr should have a volfile entry and a volblock entry
+    * or a VolAddr
     *   if we are going to use positioning
     */
    for ( ; bsr; bsr=bsr->next) {
-      if (!bsr->volfile || !bsr->volblock) {
+      if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
          return false;
       }
    }
    return true;
 }
 
-
 static BSR *store_vol(LEX *lc, BSR *bsr)
 {
    int token;
@@ -222,6 +239,7 @@ static BSR *store_vol(LEX *lc, BSR *bsr)
    }
    if (bsr->volume) {
       bsr->next = new_bsr();
+      bsr->next->prev = bsr;
       bsr = bsr->next;
    }
    /* This may actually be more than one volume separated by a |
@@ -270,6 +288,17 @@ static BSR *store_mediatype(LEX *lc, BSR *bsr)
    return bsr;
 }
 
+static BSR *store_nothing(LEX *lc, BSR *bsr)
+{
+   int token;
+
+   token = lex_get_token(lc, T_STRING);
+   if (token == T_ERROR) {
+      return NULL;
+   }
+   return bsr;
+}
+
 /* Shove the Device name in each Volume in the current bsr */
 static BSR *store_device(LEX *lc, BSR *bsr)
 {
@@ -433,6 +462,32 @@ static BSR *store_count(LEX *lc, BSR *bsr)
    return bsr;
 }
 
+static BSR *store_fileregex(LEX *lc, BSR *bsr)
+{
+   int token;
+   int rc;
+   token = lex_get_token(lc, T_STRING);
+   if (token == T_ERROR) {
+      return NULL;
+   }
+
+   if (bsr->fileregex) free(bsr->fileregex);
+   bsr->fileregex = bstrdup(lc->str);
+
+   if (bsr->fileregex_re == NULL)
+      bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
+
+   rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
+   if (rc != 0) {
+      char prbuf[500];
+      regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
+      Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
+            bsr->fileregex, prbuf);
+      return NULL;
+   }
+   return bsr;
+}
 
 static BSR *store_jobtype(LEX *lc, BSR *bsr)
 {
@@ -523,6 +578,40 @@ static BSR *store_volblock(LEX *lc, BSR *bsr)
    return bsr;
 }
 
+/*
+ * Routine to handle Volume start/end address
+ */
+static BSR *store_voladdr(LEX *lc, BSR *bsr)
+{
+   int token;
+   BSR_VOLADDR *voladdr;
+
+   for (;;) {
+      token = lex_get_token(lc, T_PINT64_RANGE);
+      if (token == T_ERROR) {
+         return NULL;
+      }
+      voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
+      memset(voladdr, 0, sizeof(BSR_VOLADDR));
+      voladdr->saddr = lc->pint64_val;
+      voladdr->eaddr = lc->pint64_val2;
+      /* Add it to the end of the chain */
+      if (!bsr->voladdr) {
+         bsr->voladdr = voladdr;
+      } else {
+         /* Add to end of chain */
+         BSR_VOLADDR *bs = bsr->voladdr;
+         for ( ;bs->next; bs=bs->next)
+            {  }
+         bs->next = voladdr;
+      }
+      token = lex_get_token(lc, T_ALL);
+      if (token != T_COMMA) {
+         break;
+      }
+   }
+   return bsr;
+}
 
 static BSR *store_sessid(LEX *lc, BSR *bsr)
 {
@@ -665,6 +754,13 @@ void dump_volblock(BSR_VOLBLOCK *volblock)
    }
 }
 
+void dump_voladdr(BSR_VOLADDR *voladdr)
+{
+   if (voladdr) {
+      Pmsg2(-1, _("VolAddr    : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
+      dump_voladdr(voladdr->next);
+   }
+}
 
 void dump_findex(BSR_FINDEX *FileIndex)
 {
@@ -739,9 +835,6 @@ void dump_sesstime(BSR_SESSTIME *sesstime)
 }
 
 
-
-
-
 void dump_bsr(BSR *bsr, bool recurse)
 {
    int save_debug = debug_level;
@@ -758,6 +851,7 @@ void dump_bsr(BSR *bsr, bool recurse)
    dump_sesstime(bsr->sesstime);
    dump_volfile(bsr->volfile);
    dump_volblock(bsr->volblock);
+   dump_voladdr(bsr->voladdr);
    dump_client(bsr->client);
    dump_jobid(bsr->JobId);
    dump_job(bsr->job);
@@ -792,30 +886,63 @@ static void free_bsr_item(BSR *bsr)
    }
 }
 
-void free_bsr(BSR *bsr)
+/*
+ * Remove a single item from the bsr tree
+ */
+void remove_bsr(BSR *bsr)
 {
-   if (!bsr) {
-      return;
-   }
    free_bsr_item((BSR *)bsr->volume);
    free_bsr_item((BSR *)bsr->client);
    free_bsr_item((BSR *)bsr->sessid);
    free_bsr_item((BSR *)bsr->sesstime);
    free_bsr_item((BSR *)bsr->volfile);
    free_bsr_item((BSR *)bsr->volblock);
+   free_bsr_item((BSR *)bsr->voladdr);
    free_bsr_item((BSR *)bsr->JobId);
    free_bsr_item((BSR *)bsr->job);
    free_bsr_item((BSR *)bsr->FileIndex);
    free_bsr_item((BSR *)bsr->JobType);
    free_bsr_item((BSR *)bsr->JobLevel);
-   free_bsr(bsr->next);
+   if (bsr->fileregex) {
+      bfree(bsr->fileregex);
+   }
+   if (bsr->fileregex_re) {
+      regfree(bsr->fileregex_re);
+      free(bsr->fileregex_re);
+   }
+   if (bsr->attr) {
+      free_attr(bsr->attr);
+   }
+   if (bsr->next) {
+      bsr->next->prev = bsr->prev;
+   }
+   if (bsr->prev) {
+      bsr->prev->next = bsr->next;
+   }
    free(bsr);
 }
 
+/*
+ * Free all bsrs in chain
+ */
+void free_bsr(BSR *bsr)
+{
+   BSR *next_bsr;
+
+   if (!bsr) {
+      return;
+   }
+   next_bsr = bsr->next;
+   /* Remove (free) current bsr */
+   remove_bsr(bsr);
+   /* Now get the next one */
+   free_bsr(next_bsr);
+}
+
 /*****************************************************************
  * Routines for handling volumes
  */
-VOL_LIST *new_restore_volume()
+static VOL_LIST *new_restore_volume()
 {
    VOL_LIST *vol;
    vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
@@ -830,41 +957,48 @@ VOL_LIST *new_restore_volume()
  *   returns: 1 if volume added
  *            0 if volume already in list
  */
-int add_restore_volume(JCR *jcr, VOL_LIST *vol)
+static bool add_restore_volume(JCR *jcr, VOL_LIST *vol)
 {
    VOL_LIST *next = jcr->VolList;
 
+   /* Add volume to volume manager's read list */
+   add_read_volume(jcr, vol->VolumeName);
+
    if (!next) {                       /* list empty ? */
       jcr->VolList = vol;             /* yes, add volume */
    } else {
+      /* Loop through all but last */
       for ( ; next->next; next=next->next) {
          if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
+            /* Save smallest start file */
             if (vol->start_file < next->start_file) {
                next->start_file = vol->start_file;
             }
-            return 0;                 /* already in list */
+            return false;              /* already in list */
          }
       }
+      /* Check last volume in list */
       if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
          if (vol->start_file < next->start_file) {
             next->start_file = vol->start_file;
          }
-         return 0;                    /* already in list */
+         return false;                /* already in list */
       }
       next->next = vol;               /* add volume */
    }
-   return 1;
+   return true;
 }
 
 void free_restore_volume_list(JCR *jcr)
 {
-   VOL_LIST *next = jcr->VolList;
+   VOL_LIST *vol = jcr->VolList;
    VOL_LIST *tmp;
 
-   for ( ; next; ) {
-      tmp = next->next;
-      free(next);
-      next = tmp;
+   for ( ; vol; ) {
+      tmp = vol->next;
+      remove_read_volume(jcr, vol->VolumeName);
+      free(vol);
+      vol = tmp;
    }
    jcr->VolList = NULL;
 }
@@ -881,8 +1015,8 @@ void create_restore_volume_list(JCR *jcr)
    /*
     * Build a list of volumes to be processed
     */
-   jcr->NumVolumes = 0;
-   jcr->CurVolume = 0;
+   jcr->NumReadVolumes = 0;
+   jcr->CurReadVolume = 0;
    if (jcr->bsr) {
       BSR *bsr = jcr->bsr;
       if (!bsr->volume || !bsr->volume->VolumeName) {
@@ -908,7 +1042,7 @@ void create_restore_volume_list(JCR *jcr)
             vol->Slot = bsrvol->Slot;
             vol->start_file = sfile;
             if (add_restore_volume(jcr, vol)) {
-               jcr->NumVolumes++;
+               jcr->NumReadVolumes++;
                Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
                   vol->MediaType);
             } else {
@@ -929,7 +1063,7 @@ void create_restore_volume_list(JCR *jcr)
          bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
          bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
          if (add_restore_volume(jcr, vol)) {
-            jcr->NumVolumes++;
+            jcr->NumReadVolumes++;
          } else {
             free((char *)vol);
          }