]> 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
index 31cc8930f85fa0d92e2a24e7b97f18faa5388d0c..d4eb27c5f50d05d4ad6b63a0f481d071a7d56a1e 100644 (file)
@@ -1,37 +1,37 @@
-/*
- *   Parse a Bootstrap Records (used for restores)
- *
- *     Kern Sibbald, June MMII
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
+   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 two of the GNU General Public
-   License as published by the Free Software Foundation plus additions
-   that are listed in the file LICENSE.
+   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 General Public License
+   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 John Walker.
+   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)
+ *
+ *     Kern Sibbald, June MMII
+ *
+ *   Version $Id$
+ */
 
 
 #include "bacula.h"
@@ -52,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);
 
@@ -84,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}
-
 };
 
 /*
@@ -138,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;
@@ -167,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;
@@ -177,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;
@@ -211,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;
@@ -234,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 |
@@ -282,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)
 {
@@ -445,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)
 {
@@ -535,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)
 {
@@ -677,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)
 {
@@ -767,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);
@@ -801,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));
@@ -839,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;
 }