From: Eric Bollengier Date: Wed, 13 Apr 2011 09:31:44 +0000 (+0200) Subject: Fix #1612 about checksum for hardlinks X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=53599625a64f9b7a6881811afac02af3f148797d;p=bacula%2Fbacula Fix #1612 about checksum for hardlinks --- diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 562621d4d3..ab842c3280 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -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); diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 86710941fd..804eeaec2b 100644 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -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 */ diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 64a5ec0dd8..b2d7f98810 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -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; diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h index 71076c6b9d..b738b21d6d 100644 --- a/bacula/src/findlib/protos.h +++ b/bacula/src/findlib/protos.h @@ -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);