From 3d756fa1fde62b85c98e32d88e6a69fa45b58385 Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Wed, 14 Jul 2021 21:12:01 +0200 Subject: [PATCH] Allow to restore VSS Plugin files on Linux --- bacula/src/filed/restore.c | 15 +++++++++++++-- bacula/src/findlib/create_file.c | 26 +++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 26d40f2da..12714ed00 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -591,7 +591,7 @@ void do_restore(JCR *jcr) pm_strcpy(jcr->last_fname, attr->ofname); jcr->last_type = attr->type; jcr->unlock(); - Dmsg4(130, "Outfile=%s create_file stat=%d type=%ld rdev=%d\n", attr->ofname, stat, attr->type, attr->statp.st_rdev); + Dmsg4(100, "Outfile=%s create_file stat=%d type=%ld rdev=%d\n", attr->ofname, stat, attr->type, attr->statp.st_rdev); switch (stat) { case CF_ERROR: case CF_SKIP: @@ -756,6 +756,10 @@ void do_restore(JCR *jcr) rctx.flags |= FO_OFFSETS; } + if (rctx.full_stream & STREAM_BIT_DELTA) { + rctx.flags |= FO_DELTA; + } + if (rctx.stream == STREAM_GZIP_DATA || rctx.stream == STREAM_SPARSE_GZIP_DATA || rctx.stream == STREAM_WIN32_GZIP_DATA @@ -800,7 +804,13 @@ void do_restore(JCR *jcr) if (is_win32_stream(rctx.stream) && (win32decomp || !have_win32_api())) { set_portable_backup(&rctx.bfd); - rctx.flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */ + // Specific fix for VSS plugin, it is marked as Win32, but + // it's not a win32 data stream when Delta and Offset are on + if ((rctx.flags & FO_OFFSETS) && rctx.attr->delta_seq > 0) { + // noop + } else { + rctx.flags |= FO_WIN32DECOMP; /* "decompose" BackupWrite data */ + } } if (extract_data(rctx, bmsg->rbuf, bmsg->rbuflen) < 0) { @@ -1279,6 +1289,7 @@ bool sparse_data(JCR *jcr, BFILE *bfd, uint64_t *addr, char **data, uint32_t *le unser_uint64(faddr); if (*addr != faddr) { *addr = faddr; + Dmsg1(100, "Need to seek at %lld\n", faddr); if (blseek(bfd, (boffset_t)*addr, SEEK_SET) < 0) { berrno be; Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index a3aef68a9..7e8f187f2 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -114,6 +114,12 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) Dmsg2(400, "Replace=%c %d\n", (char)replace, replace); if (lstat(attr->ofname, &mstatp) == 0) { exists = true; + } + + /* The file already exists and we are not updating it, we need + * to choose if we skip the file or not based on the replace flag + */ + if (exists && attr->delta_seq == 0) { switch (replace) { case REPLACE_IFNEWER: /* Set attributes if we created this directory */ @@ -146,6 +152,12 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) break; } } + + if (!exists && attr->delta_seq > 0) { + Qmsg(jcr, M_SKIPPED, 0, _("File skipped. File must exists to apply a patch: %s\n"), attr->ofname); + return CF_SKIP; + } + switch (attr->type) { case FT_RAW: /* raw device to be written */ case FT_FIFO: /* FIFO to be written to */ @@ -161,9 +173,11 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) * restore data, or we may blow away a partition definition. */ if (exists && attr->type != FT_RAW && attr->type != FT_FIFO - && attr->stream != STREAM_UNIX_ATTRIBUTE_UPDATE) { + && attr->stream != STREAM_UNIX_ATTRIBUTE_UPDATE + && attr->delta_seq == 0) + { /* Get rid of old copy */ - Dmsg1(400, "unlink %s\n", attr->ofname); + Dmsg1(50, "unlink %s\n", attr->ofname); if (unlink(attr->ofname) == -1) { berrno be; Qmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"), @@ -211,12 +225,18 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) switch(attr->type) { case FT_REGE: case FT_REG: - Dmsg1(100, "Create=%s\n", attr->ofname); flags = O_WRONLY | O_CREAT | O_BINARY | O_EXCL; + /* Remove the O_EXCL flag if we will update an existing file */ + if (attr->delta_seq > 0) { + flags &= ~O_EXCL; + } + if (IS_CTG(attr->statp.st_mode)) { flags |= O_CTG; /* set contiguous bit if needed */ } + Dmsg3(50, "Create=%s flags=%lld delta=%d\n", attr->ofname, (uint64_t)flags, (int)attr->delta_seq); + if (is_bopen(bfd)) { Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid); bclose(bfd); -- 2.47.3