]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Allow to restore VSS Plugin files on Linux
authorEric Bollengier <eric@baculasystems.com>
Wed, 14 Jul 2021 19:12:01 +0000 (21:12 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:03 +0000 (09:03 +0100)
bacula/src/filed/restore.c
bacula/src/findlib/create_file.c

index 26d40f2da780d2534fa7b36accc9d3e633fb4b01..12714ed0033349ac9c276ac7ebeea1d6e8e754f5 100644 (file)
@@ -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"),
index a3aef68a9fb2e5c5f2e87a5f3efb9025712b8bc0..7e8f187f2093c7895f619a9e97c191c75d813a96 100644 (file)
@@ -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);