summaryrefslogtreecommitdiffstats
path: root/libblkid/src/probe.c
diff options
context:
space:
mode:
authorKarel Zak2013-02-04 11:28:09 +0100
committerKarel Zak2013-02-04 11:28:09 +0100
commitcd0fe5c1659d4144610ffd76500002e98b873e0b (patch)
tree889cb6f7bd291fbc3b6eb0e690af826fa2288224 /libblkid/src/probe.c
parentnewgrp: more robust crypt() usage (diff)
downloadkernel-qcow2-util-linux-cd0fe5c1659d4144610ffd76500002e98b873e0b.tar.gz
kernel-qcow2-util-linux-cd0fe5c1659d4144610ffd76500002e98b873e0b.tar.xz
kernel-qcow2-util-linux-cd0fe5c1659d4144610ffd76500002e98b873e0b.zip
libblkid: add blkid_probe_step_back()
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>
Diffstat (limited to 'libblkid/src/probe.c')
-rw-r--r--libblkid/src/probe.c111
1 files changed, 89 insertions, 22 deletions
diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c
index eabcf9010..f7f90761a 100644
--- a/libblkid/src/probe.c
+++ b/libblkid/src/probe.c
@@ -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;
}