*/
static int check_checksum_diff(JCR *jcr, FF_PKT *ff_pkt, CurFile *elt)
{
- int ret = 0;
+ int ret = -1;
int digest_stream = STREAM_NONE;
DIGEST *digest = NULL;
char *fname;
if (!*elt->chksum && !jcr->rerunning) {
Jmsg(jcr, M_WARNING, 0, _("Cannot verify checksum for %s\n"),
ff_pkt->fname);
- ret = -1;
goto bail_out;
}
digest_name = crypto_digest_name(digest);
bin_to_base64(digest_buf, BASE64_SIZE(size), md, size, true);
-
if (strcmp(digest_buf, elt->chksum)) {
Dmsg4(dbglvl,"%s %s chksum diff. Cat: %s File: %s\n",
fname,
elt->chksum,
digest_buf);
ret = 1;
+
+ } else {
+ ret = 0;
}
free(digest_buf);
}
if (ret == 1) {
// checksum has changed, backup file normally
stat = true;
- } else if (ret == -1){
+
+ } else if (ret == -1) {
stat = false;
goto bail_out;
+
} else {
/* Checksum hasn't changed, we can backup only meta */
ff_pkt->stat_update = true;
+ ff_pkt->accurate_chksum = elt.chksum; /* record the checksum to send it */
}
}
} else if (!only_changed && !stat) {
}
if (IS_FT_OBJECT(ff_pkt->type) || /* Meta data only for restore object */
- ff_pkt->type == FT_DELETED || /* Meta data only for deleted files */
- bctx.ff_pkt->stat_update) { /* Only metadata changed for file */
+ ff_pkt->type == FT_DELETED){ /* Meta data only for deleted files */
goto good_rtn;
}
+ /* If we have only to update attributes, we need to send the checksum to fill
+ * the catalog correctly for the next job
+ */
+ if (ff_pkt->stat_update) {
+ has_file_data = false;
+ }
+
/** Set up the encryption context and send the session data to the SD */
if (has_file_data && jcr->crypto.pki_encrypt) {
if (!crypto_session_send(jcr, sd)) {
do_read = true;
}
+ /* If we have only to update attributes, we need to send the checksum to fill
+ * the catalog correctly for the next job
+ */
+ if (ff_pkt->stat_update) {
+ do_read = false;
+ }
+
if (ff_pkt->cmd_plugin && !ff_pkt->no_read) {
do_read = true;
}
unstrip_path(ff_pkt);
}
- Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
+ char b[1024];
+ Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, asciidump(sd->msg, sd->msglen, b, sizeof(b)));
if (!stat && !jcr->is_job_canceled()) {
Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
sd->bstrerror());
*
* in/out - check API at bacl.h
*/
-bRC_BACL BACL_Linux::os_get_acl(JCR *jcr, BACL_type bacltype){
-
+bRC_BACL BACL_Linux::os_get_acl(JCR *jcr, BACL_type bacltype)
+{
acl_t acl;
acl_type_t acltype;
char *acltext;
sd->msglen = size;
sd->send();
sd->signal(BNET_EOD); /* end of checksum */
+
}
/** Terminate any digest and send it to Storage daemon */
- if (bctx.digest) {
+ if (bctx.digest || ff_pkt->stat_update) {
uint32_t size;
sd->fsend("%ld %d 0", jcr->JobFiles, bctx.digest_stream);
sd->msg = realloc_pool_memory(sd->msg, size);
}
- if (!crypto_digest_finalize(bctx.digest, (uint8_t *)sd->msg, &size)) {
- Jmsg(jcr, M_FATAL, 0, _("An error occurred finalizing signing the stream.\n"));
- return false;
+ if (ff_pkt->stat_update) {
+ /* The checksum comes from the accurate table and the format is in base64 */
+ size = base64_to_bin(sd->msg, sizeof_pool_memory(sd->msg), ff_pkt->accurate_chksum, strlen(ff_pkt->accurate_chksum));
+
+ } else {
+ if (!crypto_digest_finalize(bctx.digest, (uint8_t *)sd->msg, &size)) {
+ Jmsg(jcr, M_FATAL, 0, _("An error occurred finalizing signing the stream.\n"));
+ return false;
+ }
}
/* Keep the checksum if this file is a hardlink */
sd->msglen = size;
sd->send();
sd->signal(BNET_EOD); /* end of checksum */
+
}
/* Check if original file has a digest, and send it */
*/
jcr->num_files_examined++;
rctx.extract = false;
+ rctx.update_attr = false;
stat = CF_CORE; /* By default, let Bacula's core handle it */
+ if (rctx.stream == STREAM_UNIX_ATTRIBUTE_UPDATE) {
+ rctx.update_attr = true; /* Some operations are possible, like ACL update */
+ }
+
if (jcr->plugin) {
stat = plugin_create_file(jcr, attr, &rctx.bfd, jcr->replace);
}
/*
* Do not restore ACLs when
* a) The current file is not extracted
- * b) and it is not a directory (they are never "extracted")
- * c) and it is not a symlink (they are never "extracted")
- * d) or the file name is empty
+ * b) and it is not updated (only attributes)
+ * c) and it is not a directory (they are never "extracted")
+ * d) and it is not a symlink (they are never "extracted")
+ * e) or the file name is empty
*/
if ((!rctx.extract &&
+ !rctx.update_attr &&
jcr->last_type != FT_DIREND &&
jcr->last_type != FT_LNK) ||
(*jcr->last_fname == 0)) {
int32_t type; /* file type FT_ */
ATTR *attr; /* Pointer to attributes */
bool extract; /* set when extracting */
+ bool update_attr; /* set when we update attributes, but no data */
alist *delayed_streams; /* streams that should be restored as last */
worker *efs; /* Windows EFS worker thread */
int32_t count; /* Debug count */
switch (stream & STREAMMASK_TYPE) {
case STREAM_UNIX_ATTRIBUTES:
return _("Unix attributes");
+ case STREAM_UNIX_ATTRIBUTE_UPDATE:
+ return _("Unix attributes update");
case STREAM_FILE_DATA:
return _("File data");
case STREAM_MD5_DIGEST:
char *link; /* link if file linked */
char *plugin; /* Current Options{Plugin=} name */
+ char *accurate_chksum; /* keep the checksum from the accurate database */
+
/* Specific snapshot part */
char *volume_path; /* volume path */
char *snapshot_path; /* snapshot path */
stream &= STREAMMASK_TYPE;
/* Stream was negative => all are continuation items */
switch (stream) {
+ case STREAM_UNIX_ATTRIBUTE_UPDATE:
+ return _("contUATTRU");
case STREAM_UNIX_ATTRIBUTES:
return "contUATTR";
case STREAM_FILE_DATA: