/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2015 Kern Sibbald
- Copyright (C) 2002-2014 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2017 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
Public License, v3.0 ("AGPLv3") and some additional permissions and
terms pursuant to its AGPLv3 Section 7.
- This notice must be preserved when any source code is
+ This notice must be preserved when any source code is
conveyed and/or propagated.
Bacula(R) is a registered trademark of Kern Sibbald.
*
* Kern Sibbald, July MMII
*
+ * Data verification added by Eric Bollengier
*/
#include "bacula.h"
/* Scan the fileset to know if we want to check checksums or st_size */
void scan_fileset();
+ /* Check the catalog to locate the file */
+ void check_accurate();
+
/* In cleanup, we reset the current file size to -1 */
void reset_size() {
size = -1;
*length -= OFFSET_FADDR_SIZE;
}
+void v_ctx::check_accurate()
+{
+ attr->fname = jcr->last_fname; /* struct stat is still valid, but not the fname */
+ if (accurate_check_file(jcr, attr, digest)) {
+ jcr->setJobStatus(JS_Differences);
+ }
+}
+
/*
* If extracting, close any previous stream
*/
/* Check the size if possible */
if (check_size && size >= 0) {
- if (attr->type == FT_REG && size != attr->statp.st_size) {
+ if (attr->type == FT_REG && size != (int64_t)attr->statp.st_size) {
Dmsg1(50, "Size comparison failed for %s\n", jcr->last_fname);
Jmsg(jcr, M_INFO, 0,
_(" st_size differs on \"%s\". Vol: %s File: %s\n"),
uint32_t VolSessionId, VolSessionTime, file_index;
char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
int stat;
+ int bget_ret = 0;
char *wbuf; /* write buffer */
uint32_t wsize; /* write size */
uint32_t rsize; /* read size */
- bool msg_encrypt = false;
- bool do_chksum;
+ bool msg_encrypt = false, do_check_accurate=false;
v_ctx vctx(jcr);
ATTR *attr = vctx.attr;
jcr->compress_buf_size = compress_buf_size;
}
- GetMsg *fdmsg = New(GetMsg(jcr, sd, rec_header, GETMSG_MAX_MSG_SIZE));
+ GetMsg *fdmsg;
+ fdmsg = New(GetMsg(jcr, sd, rec_header, GETMSG_MAX_MSG_SIZE));
+
fdmsg->start_read_sock();
- bmessage *bmsg = New(bmessage(GETMSG_MAX_MSG_SIZE));
+ bmessage *bmsg = fdmsg->new_msg(); /* get a message, to exchange with fdmsg */
/*
* Get a record from the Storage daemon
*/
- while (fdmsg->bget_msg(&bmsg) >= 0 && !job_canceled(jcr)) {
+ while ((bget_ret = fdmsg->bget_msg(&bmsg)) >= 0 && !job_canceled(jcr)) {
/* Remember previous stream type */
vctx.prev_stream = vctx.stream;
/*
* Now we expect the Stream Data
*/
- if (fdmsg->bget_msg(&bmsg) < 0) {
- Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
+ if ((bget_ret = fdmsg->bget_msg(&bmsg)) < 0) {
+ if (bget_ret != BNET_EXT_TERMINATE) {
+ Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
+ } else {
+ /* The error has been handled somewhere else, just quit */
+ }
goto bail_out;
}
if (size != ((uint32_t)bmsg->origlen)) {
if (!vctx.close_previous_stream()) {
goto bail_out;
}
+ if (do_check_accurate) {
+ vctx.check_accurate();
+ }
+ /* Next loop, we want to check the file (or we do it with the md5) */
+ do_check_accurate = true;
+
/*
* Unpack attributes and do sanity check them
*/
digest, digest_code, jcr->JobFiles);
} else if (jcr->getJobLevel() == L_VERIFY_DATA) {
-
/* Compare digest */
if (vctx.check_chksum && *digest) {
/* probably an empty file, we can create an empty crypto session */
Dmsg3(50, "Signature verification failed for %s %s != %s\n",
jcr->last_fname, digest, vctx.digest);
}
+ if (do_check_accurate) {
+ vctx.check_accurate();
+ do_check_accurate = false; /* Don't do it in the next loop */
+ }
}
/* Compute size and checksum for level=Data */
case STREAM_COMPRESSED_DATA:
case STREAM_SPARSE_COMPRESSED_DATA:
case STREAM_WIN32_COMPRESSED_DATA:
- do_chksum=true;
- if (!(attr->type == FT_RAW || attr->type == FT_FIFO || attr->type == FT_REG)) {
+ if (!(attr->type == FT_RAW || attr->type == FT_FIFO || attr->type == FT_REG || attr->type == FT_REGE)) {
break;
}
vctx.skip_sparse_header(&wbuf, &wsize);
}
- /* On Windows, the checksum is computed after the compression
- * On Unix, the checksum is computed before the compression
- */
- if (vctx.stream == STREAM_WIN32_GZIP_DATA
- || vctx.stream == STREAM_WIN32_DATA
- || vctx.stream == STREAM_WIN32_COMPRESSED_DATA
- || vctx.stream == STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA
- || vctx.stream == STREAM_ENCRYPTED_WIN32_GZIP_DATA)
- {
- do_chksum = false;
- vctx.update_checksum(wbuf, wsize);
- }
-
if (vctx.stream == STREAM_GZIP_DATA
|| vctx.stream == STREAM_SPARSE_GZIP_DATA
|| vctx.stream == STREAM_WIN32_GZIP_DATA
}
}
- /* Unix way to deal with checksums */
- if (do_chksum) {
- vctx.update_checksum(wbuf, wsize);
- }
+ vctx.update_checksum(wbuf, wsize);
if (vctx.stream == STREAM_WIN32_GZIP_DATA
|| vctx.stream == STREAM_WIN32_DATA
}
} /* end switch */
} /* end while bnet_get */
+ if (bget_ret == BNET_EXT_TERMINATE) {
+ goto bail_out;
+ }
if (!vctx.close_previous_stream()) {
goto bail_out;
}
+ /* Check the last file */
+ if (do_check_accurate) {
+ vctx.check_accurate();
+ }
+ if (!accurate_finish(jcr)) {
+ goto bail_out;
+ }
jcr->setJobStatus(JS_Terminated);
goto ok_out;
jcr->setJobStatus(JS_ErrorTerminated);
ok_out:
- Dmsg0(215, "wait BufferedMsg\n");
- fdmsg->wait_read_sock();
+ fdmsg->wait_read_sock(jcr->is_job_canceled());
delete bmsg;
free_GetMsg(fdmsg);
if (jcr->compress_buf) {