]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix #1612 about checksum for hardlinks
authorEric Bollengier <eric@eb.homelinux.org>
Wed, 13 Apr 2011 09:31:44 +0000 (11:31 +0200)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:44:33 +0000 (14:44 +0200)
bacula/src/filed/backup.c
bacula/src/findlib/find.h
bacula/src/findlib/find_one.c
bacula/src/findlib/protos.h

index 562621d4d3a0c2b10f2e3802f504ac252b95f1c8..ab842c32808b26f44440f72ac3a84786a78fd93e 100644 (file)
@@ -741,11 +741,29 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
          goto bail_out;
       }
 
+      /* Keep the checksum if this file is a hardlink */
+      if (ff_pkt->linked) {
+         ff_pkt_set_link_digest(ff_pkt, digest_stream, sd->msg, size);
+      }
+
       sd->msglen = size;
       sd->send();
       sd->signal(BNET_EOD);              /* end of checksum */
    }
 
+   /* Check if original file has a digest, and send it */
+   if (ff_pkt->type == FT_LNKSAVED && ff_pkt->digest) {
+      Dmsg2(300, "Link %s digest %d\n", ff_pkt->fname, ff_pkt->digest_len);
+      sd->fsend("%ld %d 0", jcr->JobFiles, ff_pkt->digest_stream);
+
+      sd->msg = check_pool_memory_size(sd->msg, ff_pkt->digest_len);
+      memcpy(sd->msg, ff_pkt->digest, ff_pkt->digest_len);
+      sd->msglen = ff_pkt->digest_len;
+      sd->send();
+
+      sd->signal(BNET_EOD);              /* end of hardlink record */
+   }
+
 good_rtn:
    rtnstat = jcr->is_canceled() ? 0 : 1; /* good return if not canceled */
 
@@ -1199,7 +1217,7 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream)
    switch (ff_pkt->type) {
    case FT_LNK:
    case FT_LNKSAVED:
-      Dmsg2(300, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link);
+      Dmsg3(300, "Link %d %s to %s\n", jcr->JobFiles, ff_pkt->fname, ff_pkt->link);
       stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c%u%c", jcr->JobFiles,
                        ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 
                        ff_pkt->link, 0, attribsEx, 0, ff_pkt->delta_seq, 0);
index 86710941fd43a00569538748d8c285c3278bf093..804eeaec2b236c558a6943ff391e5374e7a245d9 100644 (file)
@@ -165,7 +165,10 @@ struct FF_PKT {
    POOLMEM *sys_fname;                /* system filename */
    POOLMEM *fname_save;               /* save when stripping path */
    POOLMEM *link_save;                /* save when stripping path */
+   char *digest;                      /* set to file digest when the file is a hardlink */
    struct stat statp;                 /* stat packet */
+   uint32_t digest_len;               /* set to the digest len when the file is a hardlink*/
+   int32_t digest_stream;             /* set to digest type when the file is hardlink */
    int32_t FileIndex;                 /* FileIndex of this file */
    int32_t LinkFI;                    /* FileIndex of main hard linked file */
    int32_t delta_seq;                 /* Delta Sequence number */
index 64a5ec0dd872c5faedae1e015f290a9c9787c6e2..b2d7f988104192bf6b601d63498ae56c396527f9 100644 (file)
@@ -59,6 +59,9 @@ struct f_link {
     dev_t dev;                        /* device */
     ino_t ino;                        /* inode with device is unique */
     uint32_t FileIndex;               /* Bacula FileIndex of this file */
+    int32_t digest_stream;            /* Digest type if needed */
+    uint32_t digest_len;              /* Digest len if needed */
+    char *digest;                     /* Checksum of the file if needed */
     char name[1];                     /* The name */
 };
 
@@ -326,6 +329,22 @@ static bool have_ignoredir(FF_PKT *ff_pkt)
    return false;
 }
 
+/* 
+ * When the current file is a hardlink, the backup code can compute
+ * the checksum and store it into the link_t structure.
+ */
+void
+ff_pkt_set_link_digest(FF_PKT *ff_pkt,
+                       int32_t digest_stream, const char *digest, uint32_t len)
+{
+   if (ff_pkt->linked && !ff_pkt->linked->digest) {     /* is a hardlink */
+      ff_pkt->linked->digest = (char *) bmalloc(len);
+      memcpy(ff_pkt->linked->digest, digest, len);
+      ff_pkt->linked->digest_len = len;
+      ff_pkt->linked->digest_stream = digest_stream;
+   }
+}
+
 /*
  * Find a single file.
  * handle_file is the callback for handling the file.
@@ -473,6 +492,9 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt,
              ff_pkt->type = FT_LNKSAVED;       /* Handle link, file already saved */
              ff_pkt->LinkFI = lp->FileIndex;
              ff_pkt->linked = 0;
+             ff_pkt->digest = lp->digest;
+             ff_pkt->digest_stream = lp->digest_stream;
+             ff_pkt->digest_len = lp->digest_len;
              rtn_stat = handle_file(jcr, ff_pkt, top_level);
              Dmsg3(400, "FT_LNKSAVED FI=%d LinkFI=%d file=%s\n", 
                 ff_pkt->FileIndex, lp->FileIndex, lp->name);
@@ -482,6 +504,9 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt,
       /* File not previously dumped. Chain it into our list. */
       len = strlen(fname) + 1;
       lp = (struct f_link *)bmalloc(sizeof(struct f_link) + len);
+      lp->digest = NULL;                /* set later */
+      lp->digest_stream = 0;            /* set later */
+      lp->digest_len = 0;               /* set later */
       lp->ino = ff_pkt->statp.st_ino;
       lp->dev = ff_pkt->statp.st_dev;
       lp->FileIndex = 0;                  /* set later */
@@ -808,16 +833,19 @@ int term_find_one(FF_PKT *ff)
 
    for (i =0 ; i < LINK_HASHTABLE_SIZE; i ++) {
    /* Free up list of hard linked files */
-       lp = ff->linkhash[i];
-       while (lp) {
-      lc = lp;
-      lp = lp->next;
-      if (lc) {
-         free(lc);
-         count++;
+      lp = ff->linkhash[i];
+      while (lp) {
+         lc = lp;
+         lp = lp->next;
+         if (lc) {
+            if (lc->digest) {
+               free(lc->digest);
+            }
+            free(lc);
+            count++;
+         }
       }
-   }
-       ff->linkhash[i] = NULL;
+      ff->linkhash[i] = NULL;
    }
    free(ff->linkhash);
    ff->linkhash = NULL;
index 71076c6b9d7eb23d8ba05e56f966cfa40d13d622..b738b21d6d3496dec911b0e90b038e6b6da6a3da 100644 (file)
@@ -70,6 +70,8 @@ int   find_one_file(JCR *jcr, FF_PKT *ff,
 int   term_find_one(FF_PKT *ff);
 bool  has_file_changed(JCR *jcr, FF_PKT *ff_pkt);
 bool check_changes(JCR *jcr, FF_PKT *ff_pkt);
+void ff_pkt_set_link_digest(FF_PKT *ff_pkt, 
+                            int32_t digest_stream, const char *digest, uint32_t len);
 
 /* From get_priv.c */
 int enable_backup_privileges(JCR *jcr, int ignore_errors);