]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/accurate.c
Use RestoreObject type in Catalog
[bacula/bacula] / bacula / src / filed / accurate.c
index 90e7ff24d3138b99678a921e423b9e3387879bb2..404756aa6c20e16e42b1880c2848877abc97e145 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2011 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
 
    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.
 
    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.
 
    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.
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
@@ -40,6 +40,7 @@ typedef struct PrivateCurFile {
    char *fname;
    char *lstat;
    char *chksum;
    char *fname;
    char *lstat;
    char *chksum;
+   int32_t delta_seq;
    bool seen;
 } CurFile;
 
    bool seen;
 } CurFile;
 
@@ -100,7 +101,7 @@ static bool accurate_send_base_file_list(JCR *jcr)
    FF_PKT *ff_pkt;
    int stream = STREAM_UNIX_ATTRIBUTES;
 
    FF_PKT *ff_pkt;
    int stream = STREAM_UNIX_ATTRIBUTES;
 
-   if (!jcr->accurate || jcr->get_JobLevel() != L_FULL) {
+   if (!jcr->accurate || jcr->getJobLevel() != L_FULL) {
       return true;
    }
 
       return true;
    }
 
@@ -115,7 +116,7 @@ static bool accurate_send_base_file_list(JCR *jcr)
       if (elt->seen) {
          Dmsg2(dbglvl, "base file fname=%s seen=%i\n", elt->fname, elt->seen);
          /* TODO: skip the decode and use directly the lstat field */
       if (elt->seen) {
          Dmsg2(dbglvl, "base file fname=%s seen=%i\n", elt->fname, elt->seen);
          /* TODO: skip the decode and use directly the lstat field */
-         decode_stat(elt->lstat, &statc, &LinkFIc); /* decode catalog stat */  
+         decode_stat(elt->lstat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */  
          ff_pkt->fname = elt->fname;
          ff_pkt->statp = statc;
          encode_and_send_attributes(jcr, ff_pkt, stream);
          ff_pkt->fname = elt->fname;
          ff_pkt->statp = statc;
          encode_and_send_attributes(jcr, ff_pkt, stream);
@@ -157,7 +158,7 @@ static bool accurate_send_deleted_list(JCR *jcr)
       }
       Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
       /* TODO: skip the decode and use directly the lstat field */
       }
       Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
       /* TODO: skip the decode and use directly the lstat field */
-      decode_stat(elt->lstat, &statc, &LinkFIc); /* decode catalog stat */
+      decode_stat(elt->lstat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */
       ff_pkt->fname = elt->fname;
       ff_pkt->statp.st_mtime = statc.st_mtime;
       ff_pkt->statp.st_ctime = statc.st_ctime;
       ff_pkt->fname = elt->fname;
       ff_pkt->statp.st_mtime = statc.st_mtime;
       ff_pkt->statp.st_ctime = statc.st_ctime;
@@ -181,35 +182,43 @@ void accurate_free(JCR *jcr)
 /* Send the deleted or the base file list and cleanup  */
 bool accurate_finish(JCR *jcr)
 {
 /* Send the deleted or the base file list and cleanup  */
 bool accurate_finish(JCR *jcr)
 {
-   bool ret=true;
+   bool ret = true;
+
+   if (jcr->is_canceled() || jcr->is_incomplete()) {
+      accurate_free(jcr);
+      return ret;
+   }
    if (jcr->accurate) {
    if (jcr->accurate) {
-      if (jcr->get_JobLevel() == L_FULL) {
-         ret = accurate_send_base_file_list(jcr);
+      if (jcr->is_JobLevel(L_FULL)) {
+         if (!jcr->rerunning) {
+            ret = accurate_send_base_file_list(jcr);
+         }
       } else {
          ret = accurate_send_deleted_list(jcr);
       }
       } else {
          ret = accurate_send_deleted_list(jcr);
       }
-      
       accurate_free(jcr);
       accurate_free(jcr);
-      if (jcr->get_JobLevel() == L_FULL) {
-         Dmsg1(0, "Space saved with Base jobs: %lld MB\n"
-               jcr->base_size/(1024*1024));
+      if (jcr->is_JobLevel(L_FULL)) {
+         Jmsg(jcr, M_INFO, 0, _("Space saved with Base jobs: %lld MB\n")
+              jcr->base_size/(1024*1024));
       }
    }
    return ret;
 }
 
 static bool accurate_add_file(JCR *jcr, uint32_t len, 
       }
    }
    return ret;
 }
 
 static bool accurate_add_file(JCR *jcr, uint32_t len, 
-                              char *fname, char *lstat, char *chksum)
+                              char *fname, char *lstat, char *chksum,
+                              int32_t delta)
 {
    bool ret = true;
 {
    bool ret = true;
-   CurFile elt;
-   elt.seen = 0;
-
    CurFile *item;
    CurFile *item;
-   /* we store CurFile, fname and ctime/mtime in the same chunk */
-   item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+len+3);
-   memcpy(item, &elt, sizeof(CurFile));
 
 
+   /* we store CurFile, fname and ctime/mtime in the same chunk 
+    * we need one extra byte to handle an empty chksum
+    */
+   item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+len+1);
+   item->seen = 0;
+
+   /* TODO: see if we can optimize this part with memcpy instead of strcpy */
    item->fname  = (char *)item+sizeof(CurFile);
    strcpy(item->fname, fname);
 
    item->fname  = (char *)item+sizeof(CurFile);
    strcpy(item->fname, fname);
 
@@ -219,9 +228,12 @@ static bool accurate_add_file(JCR *jcr, uint32_t len,
    item->chksum = item->lstat+strlen(item->lstat)+1;
    strcpy(item->chksum, chksum);
 
    item->chksum = item->lstat+strlen(item->lstat)+1;
    strcpy(item->chksum, chksum);
 
+   item->delta_seq = delta;
+
    jcr->file_list->insert(item->fname, item); 
 
    jcr->file_list->insert(item->fname, item); 
 
-   Dmsg3(dbglvl, "add fname=<%s> lstat=%s chksum=%s\n", fname, lstat, chksum);
+   Dmsg4(dbglvl, "add fname=<%s> lstat=%s  delta_seq=%i chksum=%s\n", 
+         fname, lstat, delta, chksum);
    return ret;
 }
 
    return ret;
 }
 
@@ -242,10 +254,13 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
    struct stat statc;
    int32_t LinkFIc;
    bool stat = false;
    struct stat statc;
    int32_t LinkFIc;
    bool stat = false;
+   char *opts;
    char *fname;
    CurFile elt;
 
    char *fname;
    CurFile elt;
 
-   if (!jcr->accurate) {
+   ff_pkt->delta_seq = 0;
+
+   if (!jcr->accurate && !jcr->rerunning) {
       return true;
    }
 
       return true;
    }
 
@@ -263,18 +278,26 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
       goto bail_out;
    }
 
       goto bail_out;
    }
 
+   ff_pkt->delta_seq = elt.delta_seq;
+
    if (elt.seen) { /* file has been seen ? */
       Dmsg1(dbglvl, "accurate %s (already seen)\n", fname);
       goto bail_out;
    }
 
    if (elt.seen) { /* file has been seen ? */
       Dmsg1(dbglvl, "accurate %s (already seen)\n", fname);
       goto bail_out;
    }
 
-   decode_stat(elt.lstat, &statc, &LinkFIc); /* decode catalog stat */
+   decode_stat(elt.lstat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */
+
+   if (!jcr->rerunning && (jcr->getJobLevel() == L_FULL)) {
+      opts = ff_pkt->BaseJobOpts;
+   } else {
+      opts = ff_pkt->AccurateOpts;
+   }
 
    /*
     * Loop over options supplied by user and verify the
     * fields he requests.
     */
 
    /*
     * Loop over options supplied by user and verify the
     * fields he requests.
     */
-   for (char *p=ff_pkt->AccurateOpts; !stat && *p; p++) {
+   for (char *p=opts; !stat && *p; p++) {
       char ed1[30], ed2[30];
       switch (*p) {
       case 'i':                /* compare INODEs */
       char ed1[30], ed2[30];
       switch (*p) {
       case 'i':                /* compare INODEs */
@@ -287,6 +310,9 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
          }
          break;
       case 'p':                /* permissions bits */
          }
          break;
       case 'p':                /* permissions bits */
+         /* TODO: If something change only in perm, user, group
+          * Backup only the attribute stream
+          */
          if (statc.st_mode != ff_pkt->statp.st_mode) {
             Dmsg3(dbglvl-1, "%s     st_mode  differ. Cat: %x File: %x\n",
                   fname,
          if (statc.st_mode != ff_pkt->statp.st_mode) {
             Dmsg3(dbglvl-1, "%s     st_mode  differ. Cat: %x File: %x\n",
                   fname,
@@ -354,21 +380,31 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
             stat = true;
          }
          break;
             stat = true;
          }
          break;
-
+      case 'A':                 /* Always backup a file */
+         stat = true;
+         break;
       /* TODO: cleanup and factorise this function with verify.c */
       case '5':                /* compare MD5 */
       /* TODO: cleanup and factorise this function with verify.c */
       case '5':                /* compare MD5 */
-      case '1':                 /* compare SHA1 */
+      case '1':                /* compare SHA1 */
         /*
           * The remainder of the function is all about getting the checksum.
           * First we initialise, then we read files, other streams and Finder Info.
           */
         /*
           * The remainder of the function is all about getting the checksum.
           * First we initialise, then we read files, other streams and Finder Info.
           */
-         if (!stat && *elt.chksum && ff_pkt->type != FT_LNKSAVED && 
+         if (!stat && ff_pkt->type != FT_LNKSAVED && 
              (S_ISREG(ff_pkt->statp.st_mode) && 
               ff_pkt->flags & (FO_MD5|FO_SHA1|FO_SHA256|FO_SHA512))) 
          {
              (S_ISREG(ff_pkt->statp.st_mode) && 
               ff_pkt->flags & (FO_MD5|FO_SHA1|FO_SHA256|FO_SHA512))) 
          {
+
+            if (!*elt.chksum && !jcr->rerunning) {
+               Jmsg(jcr, M_WARNING, 0, _("Cannot verify checksum for %s\n"),
+                    ff_pkt->fname);
+               stat = true;
+               break;
+            }
+
             /*
             /*
-             * Create our digest context. If this fails, the digest will be set to NULL
-             * and not used.
+             * Create our digest context. If this fails, the digest will be set
+             * to NULL and not used.
              */
             if (ff_pkt->flags & FO_MD5) {
                digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5);
              */
             if (ff_pkt->flags & FO_MD5) {
                digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5);
@@ -413,8 +449,9 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
                   bin_to_base64(digest_buf, BASE64_SIZE(size), md, size, true);
 
                   if (strcmp(digest_buf, elt.chksum)) {
                   bin_to_base64(digest_buf, BASE64_SIZE(size), md, size, true);
 
                   if (strcmp(digest_buf, elt.chksum)) {
-                     Dmsg3(dbglvl-1, "%s      chksum  diff. Cat: %s File: %s\n",
+                     Dmsg4(dbglvl,"%s      %s chksum  diff. Cat: %s File: %s\n",
                            fname,
                            fname,
+                           digest_name,
                            elt.chksum,
                            digest_buf);
                      stat = true;
                            elt.chksum,
                            digest_buf);
                      stat = true;
@@ -428,6 +465,7 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
 
          break;
       case ':':
 
          break;
       case ':':
+      case 'J':
       case 'C':
       default:
          break;
       case 'C':
       default:
          break;
@@ -437,7 +475,7 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
    /* In Incr/Diff accurate mode, we mark all files as seen
     * When in Full+Base mode, we mark only if the file match exactly
     */
    /* In Incr/Diff accurate mode, we mark all files as seen
     * When in Full+Base mode, we mark only if the file match exactly
     */
-   if (jcr->get_JobLevel() == L_FULL) {
+   if (jcr->getJobLevel() == L_FULL) {
       if (!stat) {               
          /* compute space saved with basefile */
          jcr->base_size += ff_pkt->statp.st_size;
       if (!stat) {               
          /* compute space saved with basefile */
          jcr->base_size += ff_pkt->statp.st_size;
@@ -460,6 +498,7 @@ int accurate_cmd(JCR *jcr)
    BSOCK *dir = jcr->dir_bsock;
    int lstat_pos, chksum_pos;
    int32_t nb;
    BSOCK *dir = jcr->dir_bsock;
    int lstat_pos, chksum_pos;
    int32_t nb;
+   uint16_t delta_seq;
 
    if (job_canceled(jcr)) {
       return true;
 
    if (job_canceled(jcr)) {
       return true;
@@ -475,7 +514,7 @@ int accurate_cmd(JCR *jcr)
 
    /*
     * buffer = sizeof(CurFile) + dirmsg
 
    /*
     * buffer = sizeof(CurFile) + dirmsg
-    * dirmsg = fname + \0 + lstat + \0 + checksum + \0
+    * dirmsg = fname + \0 + lstat + \0 + checksum + \0 + delta_seq + \0
     */
    /* get current files */
    while (dir->recv() >= 0) {
     */
    /* get current files */
    while (dir->recv() >= 0) {
@@ -485,12 +524,18 @@ int accurate_cmd(JCR *jcr)
 
          if (chksum_pos >= dir->msglen) {
             chksum_pos = lstat_pos - 1;    /* tweak: no checksum, point to the last \0 */
 
          if (chksum_pos >= dir->msglen) {
             chksum_pos = lstat_pos - 1;    /* tweak: no checksum, point to the last \0 */
-         } 
+            delta_seq = 0;
+         } else {
+            delta_seq = str_to_int32(dir->msg + 
+                                     chksum_pos + 
+                                     strlen(dir->msg + chksum_pos) + 1);
+         }
 
          accurate_add_file(jcr, dir->msglen, 
                            dir->msg,               /* Path */
                            dir->msg + lstat_pos,   /* LStat */
 
          accurate_add_file(jcr, dir->msglen, 
                            dir->msg,               /* Path */
                            dir->msg + lstat_pos,   /* LStat */
-                           dir->msg + chksum_pos); /* CheckSum */
+                           dir->msg + chksum_pos,  /* CheckSum */
+                           delta_seq);             /* Delta Sequence */
       }
    }
 
       }
    }