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 */
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);
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 */
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 */
};
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.
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);
/* 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 */
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;
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);