From: Eric Bollengier Date: Tue, 17 May 2022 09:59:31 +0000 (+0200) Subject: Fix #9127 About incorrect handling of the new Accurate 'o' option with multiple incre... X-Git-Tag: Release-13.0.0~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db14169dd30732fb5d013764270f0d7ba8175335;p=thirdparty%2Fbacula.git Fix #9127 About incorrect handling of the new Accurate 'o' option with multiple incremental jobs. Add support for ACL updates --- diff --git a/bacula/src/filed/accurate.c b/bacula/src/filed/accurate.c index 09b437c80..8e0b7fdff 100644 --- a/bacula/src/filed/accurate.c +++ b/bacula/src/filed/accurate.c @@ -360,7 +360,7 @@ bail_out: */ 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; @@ -383,7 +383,6 @@ static int check_checksum_diff(JCR *jcr, FF_PKT *ff_pkt, CurFile *elt) if (!*elt->chksum && !jcr->rerunning) { Jmsg(jcr, M_WARNING, 0, _("Cannot verify checksum for %s\n"), ff_pkt->fname); - ret = -1; goto bail_out; } @@ -432,7 +431,6 @@ static int check_checksum_diff(JCR *jcr, FF_PKT *ff_pkt, CurFile *elt) 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, @@ -440,6 +438,9 @@ static int check_checksum_diff(JCR *jcr, FF_PKT *ff_pkt, CurFile *elt) elt->chksum, digest_buf); ret = 1; + + } else { + ret = 0; } free(digest_buf); } @@ -656,12 +657,15 @@ bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt) 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) { diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 9bb543529..1b21e6885 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -523,11 +523,17 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) } 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)) { @@ -553,6 +559,13 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) 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; } @@ -1215,7 +1228,8 @@ bool encode_and_send_attributes(bctx_t &bctx) 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()); diff --git a/bacula/src/filed/bacl_linux.c b/bacula/src/filed/bacl_linux.c index 0a3d93632..199822b76 100644 --- a/bacula/src/filed/bacl_linux.c +++ b/bacula/src/filed/bacl_linux.c @@ -170,8 +170,8 @@ bRC_BACL BACL_Linux::os_restore_acl (JCR *jcr, int stream, char *content, uint32 * * 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; diff --git a/bacula/src/filed/crypto.c b/bacula/src/filed/crypto.c index e9ec5f9ae..0f626192a 100644 --- a/bacula/src/filed/crypto.c +++ b/bacula/src/filed/crypto.c @@ -258,10 +258,11 @@ bool crypto_terminate_digests(bctx_t &bctx) 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); @@ -274,9 +275,15 @@ bool crypto_terminate_digests(bctx_t &bctx) 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 */ @@ -287,6 +294,7 @@ bool crypto_terminate_digests(bctx_t &bctx) sd->msglen = size; sd->send(); sd->signal(BNET_EOD); /* end of checksum */ + } /* Check if original file has a digest, and send it */ diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 5cfb4e701..57181bfc2 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -578,8 +578,13 @@ void do_restore(JCR *jcr) */ 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); } @@ -922,11 +927,13 @@ void do_restore(JCR *jcr) /* * 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)) { diff --git a/bacula/src/filed/restore.h b/bacula/src/filed/restore.h index 9de6795c8..0634396a5 100644 --- a/bacula/src/filed/restore.h +++ b/bacula/src/filed/restore.h @@ -58,6 +58,7 @@ struct r_ctx { 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 */ diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index 7915e6e06..7e67984f5 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -86,6 +86,8 @@ const char *stream_to_ascii(int stream) 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: diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index d2edcef3f..79ca579ab 100644 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -155,6 +155,8 @@ struct FF_PKT { 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 */ diff --git a/bacula/src/stored/record_util.c b/bacula/src/stored/record_util.c index c791e2b2d..1c91f4dae 100644 --- a/bacula/src/stored/record_util.c +++ b/bacula/src/stored/record_util.c @@ -89,6 +89,8 @@ const char *stream_to_ascii(char *buf, int stream, int fi) 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: