]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: add blkid_probe_step_back()
authorKarel Zak <kzak@redhat.com>
Mon, 4 Feb 2013 10:28:09 +0000 (11:28 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 4 Feb 2013 10:28:09 +0000 (11:28 +0100)
It seems that blkid_do_probe() is too high-level solution for some
mkfs programs (for example ext4 mkfs supports "undo" so all write
operations has to be implemented by filesystem specific functions).

The new function blkid_probe_step_back() resets internal libblkid
buffers and move probing stuff one step back. It means that the
previously used probing function will be called again in the next
blkid_do_probe() call. This allows to modify on-disk data and check
for backup superblocks or alternative magic strings. Something like:

  while (blkid_do_probe(pr) == 0) {
    ... get SBMAGIC_OFFSET and SBMAGIC len ...
    ... use your private seek & write() ...

    blkid_probe_step_back(pr);
  }

References: https://bugzilla.redhat.com/show_bug.cgi?id=902512
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/blkid.h.in
libblkid/src/blkid.sym
libblkid/src/probe.c

index a41bd99d0c4c004a118d95055d3fca9aa3be7f8d..44f2aa7b6e89bc620e5241050a044fbc74af3a51 100644 (file)
@@ -414,6 +414,7 @@ extern int blkid_probe_has_value(blkid_probe pr, const char *name)
                        __ul_attribute__((warn_unused_result));
 
 extern int blkid_do_wipe(blkid_probe pr, int dryrun);
+extern int blkid_probe_step_back(blkid_probe pr);
 
 /*
  * Deprecated functions/macros
index 62f981f4c2997f038b6d911fd73b6119cf260de6..cf2a16f9444964ff430b54d8d1517a603b0c0f8e 100644 (file)
@@ -146,3 +146,10 @@ global:
        blkid_do_wipe;
 } BLKID_2.20;
 
+/*
+ * symbols since util-linux 2.23
+ */
+BLKID_2.23 {
+global:
+       blkid_probe_step_back;
+} BLKID_2.21;
index eabcf9010ba2f94887f20db3f7556e187248a9fd..f7f90761a2f702a1e9f884e5ddc2356a9455d52f 100644 (file)
@@ -948,7 +948,10 @@ int blkid_do_probe(blkid_probe pr)
  *  </programlisting>
  * </example>
  *
- * Returns: 0 on success, 1 when probing is done and -1 in case of error.
+ * See also blkid_probe_step_back() if you cannot use this build-in wipe
+ * function, but you want to use libblkid probing as a source for wiping.
+ *
+ * Returns: 0 on success, and -1 in case of error.
  */
 int blkid_do_wipe(blkid_probe pr, int dryrun)
 {
@@ -1006,30 +1009,94 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
                if (write_all(fd, buf, len))
                        return -1;
                fsync(fd);
+               return blkid_probe_step_back(pr);
+       }
 
-               blkid_probe_reset_buffer(pr);
+       return 0;
+}
 
-               if (chn->idx >= 0) {
-                       chn->idx--;
-                       DBG(DEBUG_LOWPROBE,
-                               printf("do_wipe: moving %s chain index to %d\n",
-                               chn->driver->name,
-                               chn->idx));
-               }
-               if (chn->idx == -1) {
-                       /* blkid_do_probe() goes to the next chain if the index
-                        * of the current chain is -1, so we have to set the
-                        * chain pointer to the previos chain.
-                        */
-                       size_t idx = chn->driver->id > 0 ?
-                                       chn->driver->id - 1 : 0;
-
-                       if (idx > 0)
-                               pr->cur_chain = &pr->chains[idx];
-                       else if (idx == 0)
-                               pr->cur_chain = NULL;
-               }
+/**
+ * blkid_probe_step_back():
+ * @pr: prober
+ *
+ * This function move pointer to the probing chain one step back -- it means
+ * that the previously used probing function will be called again in the next
+ * blkid_do_probe() call.
+ *
+ * This is necessary for example if you erase or modify on-disk superblock
+ * according to the current libblkid probing result.
+ *
+ * <example>
+ *  <title>wipe all superblock, but use libblkid only for probing</title>
+ *  <programlisting>
+ *      pr = blkid_new_probe_from_filename(devname);
+ *
+ *      blkid_probe_enable_superblocks(pr, 1);
+ *      blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
+ *
+ *     while (blkid_do_probe(pr) == 0) {
+ *             const char *ostr = NULL;
+ *             size_t len = 0;
+ *
+ *             // superblocks
+ *             if (blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &ostr, NULL) == 0)
+ *                     blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
+ *
+ *             // partition tables
+ *             if (len == 0 && blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &ostr, NULL) == 0)
+ *                     blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
+ *
+ *             if (!len || !str)
+ *                     continue;
+ *
+ *             // convert ostr to the real offset by off = strtoll(ostr, NULL, 10);
+ *              // use your stuff to errase @len bytes at the @off
+ *              ....
+ *
+ *             // retry the last probing to check for backup superblocks ..etc.
+ *              blkid_probe_step_back(pr);
+ *     }
+ *  </programlisting>
+ * </example>
+ *
+ * Returns: 0 on success, and -1 in case of error.
+ */
+int blkid_probe_step_back(blkid_probe pr)
+{
+       struct blkid_chain *chn;
+
+       if (!pr)
+               return -1;
+
+       chn = pr->cur_chain;
+       if (!chn)
+               return -1;
+
+       blkid_probe_reset_buffer(pr);
+
+       if (chn->idx >= 0) {
+               chn->idx--;
+               DBG(DEBUG_LOWPROBE,
+                       printf("step back: moving %s chain index to %d\n",
+                       chn->driver->name,
+                       chn->idx));
        }
+
+       if (chn->idx == -1) {
+               /* blkid_do_probe() goes to the next chain if the index
+                * of the current chain is -1, so we have to set the
+                * chain pointer to the previous chain.
+                */
+               size_t idx = chn->driver->id > 0 ? chn->driver->id - 1 : 0;
+
+               DBG(DEBUG_LOWPROBE, printf("step back: moving to previous chain\n"));
+
+               if (idx > 0)
+                       pr->cur_chain = &pr->chains[idx];
+               else if (idx == 0)
+                       pr->cur_chain = NULL;
+       }
+
        return 0;
 }