]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/verify.c
Allow plugin to skip restore if problem
[bacula/bacula] / bacula / src / filed / verify.c
index 6c3171f1204f1958b840b8b7b894f53c5a6b4694..f280c05b01f6ed82ed5bca20e73715b5e0b5cf56 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 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
+   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.
 
@@ -15,7 +15,7 @@
    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.
  *
  *    Kern Sibbald, October MM
  *
- *   Version $Id$
- *
  */
 
 #include "bacula.h"
 #include "filed.h"
 
+#ifdef HAVE_DARWIN_OS
+const bool have_darwin_os = true;
+#else
+const bool have_darwin_os = false;
+#endif
+
 static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool);
 static int read_digest(BFILE *bfd, DIGEST *digest, JCR *jcr);
 
@@ -120,21 +124,21 @@ static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
       berrno be;
       be.set_errno(ff_pkt->ff_errno);
       Jmsg(jcr, M_NOTSAVED, 1, _("     Could not access %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
-      jcr->Errors++;
+      jcr->JobErrors++;
       return 1;
    }
    case FT_NOFOLLOW: {
       berrno be;
       be.set_errno(ff_pkt->ff_errno);
       Jmsg(jcr, M_NOTSAVED, 1, _("     Could not follow link %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
-      jcr->Errors++;
+      jcr->JobErrors++;
       return 1;
    }
    case FT_NOSTAT: {
       berrno be;
       be.set_errno(ff_pkt->ff_errno);
       Jmsg(jcr, M_NOTSAVED, 1, _("     Could not stat %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
-      jcr->Errors++;
+      jcr->JobErrors++;
       return 1;
    }
    case FT_DIRNOCHG:
@@ -151,21 +155,23 @@ static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
    case FT_NOFSCHG:
       Jmsg(jcr, M_SKIPPED, 1, _("     File system change prohibited. Directory skipped: %s\n"), ff_pkt->fname);
       return 1;
+   case FT_RESTORE_FIRST:
+      return 1;                       /* silently skip */
    case FT_NOOPEN: {
       berrno be;
       be.set_errno(ff_pkt->ff_errno);
       Jmsg(jcr, M_NOTSAVED, 1, _("     Could not open directory %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
-      jcr->Errors++;
+      jcr->JobErrors++;
       return 1;
    }
    default:
       Jmsg(jcr, M_NOTSAVED, 0, _("     Unknown file type %d: %s\n"), ff_pkt->type, ff_pkt->fname);
-      jcr->Errors++;
+      jcr->JobErrors++;
       return 1;
    }
 
    /* Encode attributes and possibly extend them */
-   encode_stat(attribs, ff_pkt, 0);
+   encode_stat(attribs, &ff_pkt->statp, ff_pkt->LinkFI, 0);
    encode_attribsEx(jcr, attribsEx, ff_pkt);
 
    jcr->lock();
@@ -187,18 +193,18 @@ static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
    /* Send file attributes to Director (note different format than for Storage) */
    Dmsg2(400, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, ff_pkt->fname);
    if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
-      stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
-            STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname,
-            0, attribs, 0, ff_pkt->link, 0);
+      stat = dir->fsend("%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
+                        STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname,
+                        0, attribs, 0, ff_pkt->link, 0);
    } else if (ff_pkt->type == FT_DIREND || ff_pkt->type == FT_REPARSE) {
-         /* Here link is the canonical filename (i.e. with trailing slash) */
-         stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
-               STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link,
-               0, attribs, 0, 0);
+      /* Here link is the canonical filename (i.e. with trailing slash) */
+      stat = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles,
+                        STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link,
+                        0, attribs, 0, 0);
    } else {
-      stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
-            STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname,
-            0, attribs, 0, 0);
+      stat = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles,
+                        STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname,
+                        0, attribs, 0, 0);
    }
    Dmsg2(20, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
    if (!stat) {
@@ -247,7 +253,7 @@ static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
          size = sizeof(md);
          
          if (digest_file(jcr, ff_pkt, digest) != 0) {
-            jcr->Errors++;
+            jcr->JobErrors++;
             goto good_rtn;
          }
 
@@ -260,10 +266,10 @@ static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
 
             bin_to_base64(digest_buf, BASE64_SIZE(size), md, size, true);
             Dmsg3(400, "send inx=%d %s=%s\n", jcr->JobFiles, digest_name, digest_buf);
-            bnet_fsend(dir, "%d %d %s *%s-%d*", jcr->JobFiles, digest_stream, digest_buf,
+            dir->fsend("%d %d %s *%s-%d*", jcr->JobFiles, digest_stream, digest_buf,
                        digest_name, jcr->JobFiles);
             Dmsg3(20, "bfiled>bdird: %s len=%d: msg=%s\n", digest_name,
-            dir->msglen, dir->msg);
+                  dir->msglen, dir->msg);
 
             free(digest_buf);
          }
@@ -288,8 +294,9 @@ int digest_file(JCR *jcr, FF_PKT *ff_pkt, DIGEST *digest)
    Dmsg0(50, "=== digest_file\n");
    binit(&bfd);
 
-   if (ff_pkt->statp.st_size > 0 || ff_pkt->type == FT_RAW
-         || ff_pkt->type == FT_FIFO) {
+   if (ff_pkt->statp.st_size > 0 ||
+       ff_pkt->type == FT_RAW ||
+       ff_pkt->type == FT_FIFO) {
       int noatime = ff_pkt->flags & FO_NOATIME ? O_NOATIME : 0;
       if ((bopen(&bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0)) < 0) {
          ff_pkt->ff_errno = errno;
@@ -304,28 +311,27 @@ int digest_file(JCR *jcr, FF_PKT *ff_pkt, DIGEST *digest)
       bclose(&bfd);
    }
 
-#ifdef HAVE_DARWIN_OS
+   if (have_darwin_os) {
       /* Open resource fork if necessary */
-   if (ff_pkt->flags & FO_HFSPLUS && ff_pkt->hfsinfo.rsrclength > 0) {
-      if (bopen_rsrc(&bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
-         ff_pkt->ff_errno = errno;
-         berrno be;
-         Jmsg(jcr, M_ERROR, -1, _("     Cannot open resource fork for %s: ERR=%s.\n"),
-               ff_pkt->fname, be.bstrerror());
-         if (is_bopen(&ff_pkt->bfd)) {
-            bclose(&ff_pkt->bfd);
+      if (ff_pkt->flags & FO_HFSPLUS && ff_pkt->hfsinfo.rsrclength > 0) {
+         if (bopen_rsrc(&bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
+            ff_pkt->ff_errno = errno;
+            berrno be;
+            Jmsg(jcr, M_ERROR, -1, _("     Cannot open resource fork for %s: ERR=%s.\n"),
+                  ff_pkt->fname, be.bstrerror());
+            if (is_bopen(&ff_pkt->bfd)) {
+               bclose(&ff_pkt->bfd);
+            }
+            return 1;
          }
-         return 1;
+         read_digest(&bfd, digest, jcr);
+         bclose(&bfd);
       }
-      read_digest(&bfd, digest, jcr);
-      bclose(&bfd);
-   }
 
-   if (digest && ff_pkt->flags & FO_HFSPLUS) {
-      crypto_digest_update(digest, (uint8_t *)ff_pkt->hfsinfo.fndrinfo, 32);
+      if (digest && ff_pkt->flags & FO_HFSPLUS) {
+         crypto_digest_update(digest, (uint8_t *)ff_pkt->hfsinfo.fndrinfo, 32);
+      }
    }
-#endif
-
    return 0;
 }
 
@@ -333,16 +339,40 @@ int digest_file(JCR *jcr, FF_PKT *ff_pkt, DIGEST *digest)
  * Read message digest of bfd, updating digest
  * In case of errors we need the job control record and file name.
  */
-int read_digest(BFILE *bfd, DIGEST *digest, JCR *jcr)
+static int read_digest(BFILE *bfd, DIGEST *digest, JCR *jcr)
 {
    char buf[DEFAULT_NETWORK_BUFFER_SIZE];
    int64_t n;
+   int64_t bufsiz = (int64_t)sizeof(buf);
+   FF_PKT *ff_pkt = (FF_PKT *)jcr->ff;
+   uint64_t fileAddr = 0;             /* file address */
+
 
    Dmsg0(50, "=== read_digest\n");
-   while ((n=bread(bfd, buf, sizeof(buf))) > 0) {
+   while ((n=bread(bfd, buf, bufsiz)) > 0) {
+      /* Check for sparse blocks */
+      if (ff_pkt->flags & FO_SPARSE) {
+         bool allZeros = false;
+         if ((n == bufsiz &&
+              fileAddr+n < (uint64_t)ff_pkt->statp.st_size) ||
+             ((ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO) &&
+               (uint64_t)ff_pkt->statp.st_size == 0)) {
+            allZeros = is_buf_zero(buf, bufsiz);
+         }
+         fileAddr += n;               /* update file address */
+         /* Skip any block of all zeros */
+         if (allZeros) {
+            continue;                 /* skip block of zeros */
+         }
+      }
+      
       crypto_digest_update(digest, (uint8_t *)buf, n);
-      jcr->JobBytes += n;
-      jcr->ReadBytes += n;
+
+      /* Can be used by BaseJobs, update only for Verify jobs */
+      if (jcr->getJobLevel() != L_FULL) {
+         jcr->JobBytes += n;
+         jcr->ReadBytes += n;
+      }
    }
    if (n < 0) {
       berrno be;
@@ -350,7 +380,7 @@ int read_digest(BFILE *bfd, DIGEST *digest, JCR *jcr)
       Dmsg2(100, "Error reading file %s: ERR=%s\n", jcr->last_fname, be.bstrerror());
       Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
-      jcr->Errors++;
+      jcr->JobErrors++;
       return -1;
    }
    return 0;