]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Fix #10020 #9757 Improve Volume Protection code and fix the unprotection code
authorEric Bollengier <eric@baculasystems.com>
Fri, 31 Mar 2023 15:03:24 +0000 (17:03 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 14 Sep 2023 11:57:01 +0000 (13:57 +0200)
31-Mar 13:55 zog8-sd JobId 12: Marking Volume "Test10018" as read-only. Retention set to 31-Mar-2023 13:55 (10 secs).

bacula/src/stored/block_util.c
bacula/src/stored/dircmd.c
bacula/src/stored/file_dev.c

index a1fc5eccd5133c881382eabe2adee3801101d27c..7a173b1ae11709525eefd64f48c953fb6cd6e2ab 100644 (file)
@@ -684,10 +684,11 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet)
       }
 
       if (dev->device->set_vol_read_only) {
+         btime_t now = time(NULL);
          uint32_t when = MAX(dev->device->min_volume_protection_time, dev->VolCatInfo.VolRetention);
          dev->VolCatInfo.UseProtect = 1;
          /* Set volume as immutable/read only */
-         if (dev->set_atime(dev->m_fd, dev->getVolCatName(), time(NULL) + when) < 0) {
+         if (dev->set_atime(dev->m_fd, dev->getVolCatName(), now + when) < 0) {
             Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s in atime retention, ERR=%s.\n"),
                  dev->getVolCatName(), dev->print_name(), dev->errmsg);
          }
@@ -697,12 +698,13 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet)
             Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s in read-only, ERR=%s.\n"),
                  dev->getVolCatName(), dev->print_name(), be.bstrerror());
          } else {
-            char buf[128];
-            edit_utime(when, buf, sizeof(buf));
-            if (!quiet) {
-               Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as read-only. Retention set to %s.\n"), buf,
-                    dev->getVolCatName());
-            }
+            char buf[128], buf2[128];
+            strip_trailing_junk(edit_utime(when, buf, sizeof(buf)));
+            bstrftime(buf2, sizeof(buf2), now+when);
+
+            Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as read-only. Retention set to %s (%s).\n"),
+                    dev->getVolCatName(), buf2, buf);
+
             dev->VolCatInfo.Protected = 1;
             events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr,
                             "Mark Volume \"%s\" as read-only. retention %s.", dev->getVolCatName(), buf);;
@@ -717,10 +719,8 @@ bool is_user_volume_size_reached(DCR *dcr, bool quiet)
             Jmsg(dcr->jcr, M_WARNING, 0, _("Failed to set the volume %s on device %s as immutable, ERR=%s.\n"),
                  dev->getVolCatName(), dev->print_name(), dev->errmsg);
          } else {
-            if (!quiet) {
-               Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as immutable\n"),
-                    dev->getVolCatName());
-            }
+            Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" as immutable\n"),
+                 dev->getVolCatName());
             events_send_msg(dcr->jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)dcr->jcr,
                             "Mark Volume \"%s\" as immutable", dev->getVolCatName());;
             dev->VolCatInfo.Protected = 1;
index cee028dd6d46ddf44166e99cfccc668a94840a48..3610cb30bf90184d5de3e00f9ac683bac8e09003 100644 (file)
@@ -1376,7 +1376,8 @@ static bool volumeprotect_cmd(JCR *jcr)
             /* Set volume as immutable/read only */
             pm_strcpy(tmp, "");
             uint32_t when = MAX(dev->device->min_volume_protection_time, retention);
-            if (dev->set_atime(-1, volume, time(NULL) + when) < 0) {
+            btime_t now = time(NULL);
+            if (dev->set_atime(-1, volume, now + when) < 0) {
                berrno be;
                Mmsg(tmp, _(" Failed to set the volume %s on device %s in atime retention, ERR=%s.\n"),
                     volume, dev->print_name(), be.bstrerror());
@@ -1387,11 +1388,13 @@ static bool volumeprotect_cmd(JCR *jcr)
                dir->fsend(_("3900 Failed to set the volume %s on device %s in read-only, ERR=%s.%s\n"),
                           volume, dev->print_name(), be.bstrerror(), tmp.c_str());
             } else {
-               char buf[128];
-               dir->fsend(_("3000 Marking volume \"%s\" as read-only. Retention set to %s.\n"),
-                          volume, edit_utime(when, buf, sizeof(buf)));
+               char buf[128], buf2[128];
+               dir->fsend(_("3000 Marking volume \"%s\" as read-only. Retention set to %s (%s).\n"),
+                          volume,
+                          bstrftime(buf2, sizeof(buf2), now+when),
+                          strip_trailing_junk(edit_utime(when, buf, sizeof(buf))));
                events_send_msg(jcr, "SJ0003", EVENTS_TYPE_VOLUME, me->hdr.name, (intptr_t)jcr,
-                               "Mark volume \"%s\" as read-only, retention %s", volume, buf);
+                               "Mark volume \"%s\" as read-only, retention %s (%s)", volume, buf2, buf);
             }
          } else {
             dir->fsend(_("3900 Device %s not configured for ReadOnly or Immutable\n"), dev->device->hdr.name);
index c6845461e4940c32de8e0659fa9c4bc0a96ea49a..6026d8b8ea437e50b58374bfaaa86f7d0a37b359 100644 (file)
@@ -199,27 +199,47 @@ bool file_dev::open_device(DCR *dcr, int omode)
    /* Use system open() */
    if ((m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC|append, 0640)) < 0) {
       /* Open may fail if we want to write to the Immutable volume */
-      if (errno == EPERM && check_for_immutable(getVolCatName())) {
-         /* Volume has immutable flag set, we need to clear it */
-         if (!check_volume_protection_time(getVolCatName())) {
-            /* Volume cannot be reused yet */
-            MmsgD1(dbglvl, errmsg, _("Cannot open Volume %s for writing/truncating, "
-                     "because Minimum Volume Protection Time hasn't expired yet\n"),
-                  getVolCatName());
-         } else {
-            /* Flag can be cleared, volume can probably be reused */
-            if (clear_immutable(getVolCatName(), &errmsg)) {
-               /* It should be now possible to open the device with desired mode */
-               if ((m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC|append, 0640)) < 0) {
+      if (errno == EACCES && use_protect()) {
+         bool immutable = check_for_immutable(getVolCatName());
+         bool readonly = check_for_read_only(-1, getVolCatName());
+         Dmsg3(DT_VOLUME|40, "volume=%s immutable=%d readonly=%d\n", getVolCatName(), immutable, readonly);
+         if (immutable || readonly) {
+            /* Volume has immutable flag set, we need to clear it */
+            if (!check_volume_protection_time(getVolCatName())) {
+               /* Volume cannot be reused yet */
+               MmsgD1(dbglvl, errmsg, _("Cannot open Volume %s for writing/truncating, "
+                                        "because Minimum Volume Protection Time hasn't expired yet\n"),
+                      getVolCatName());
+            } else {
+               bool tryopen = false;
+               /* Flag can be cleared, volume can probably be reused */
+               if (immutable && clear_immutable(getVolCatName(), &errmsg)) {
+                  tryopen = true;
+               }
+               if (readonly && set_writable(-1, getVolCatName())) {
+                  tryopen = true;
+               }
+               if (tryopen) { /* It should be now possible to open the device with desired mode */
+                  if ((m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC|append, 0640)) < 0) {
+                     berrno be;
+                     dev_errno = errno;
+                     MmsgD3(40, errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"),
+                            archive_name.c_str(), mode_to_str(omode), be.bstrerror());
+                  } // else open is ok
+
+               } else {         // Cannot clear the flags
                   berrno be;
-                  dev_errno = errno;
-                  MmsgD3(40, errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"),
-                         archive_name.c_str(), mode_to_str(omode), be.bstrerror());
+                  MmsgD2(40, errmsg, _("Could not clear volume protection on %s ERR=%s\n"),
+                         getVolCatName(), be.bstrerror());
                }
             }
+         } else {               // not immutable or readonly, other issue
+            berrno be;
+            dev_errno = errno;
+            MmsgD3(40, errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"),
+                   archive_name.c_str(), mode_to_str(omode), be.bstrerror());
          }
-      } else {
-         /* Volume is not immutable, that should succeed */
+      } else {               // Not a permission issue on this device
          berrno be;
          dev_errno = errno;
          MmsgD3(40, errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"),