]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: add blkid_probe_{set,get}_hint()
authorKarel Zak <kzak@redhat.com>
Tue, 3 Nov 2020 16:06:09 +0000 (17:06 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 3 Nov 2020 16:12:20 +0000 (17:12 +0100)
Add new API for additional probing hints (offsets). The idea is that
probing function can optionally use the hint to detect superblock or
partition table if on unusual place where the library does not expects (etc.)

The hints use strings as identifiers (e.g. "last-medium-session") to
make it extendable and prober specific (if necessary). The function
blkid_probe_set_hint() always add a new hint, so you can specify more
offsets with the same (hint) name.

The function blkid_probe_get_hint() is not public. For now it returns
the first hint only.

Addresses: https://github.com/karelzak/util-linux/issues/1161
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/docs/libblkid-sections.txt
libblkid/src/blkid.h.in
libblkid/src/blkidP.h
libblkid/src/libblkid.sym
libblkid/src/probe.c

index 8163d2d82b7dfa12facb64191e40fcacdcbfadbe..0f18d929cbc7aee2a9ed06e3b4a988e870ffc12d 100644 (file)
@@ -58,6 +58,7 @@ blkid_probe_hide_range
 blkid_probe_is_wholedisk
 blkid_probe_reset_buffers
 blkid_probe_set_device
+blkid_probe_set_hint
 blkid_probe_set_sectorsize
 blkid_probe_step_back
 blkid_reset_probe
index 7328d0e30687da39ca49163593adc7cceb2256ca..6550ed7a6d390bd11bdada8d1a2ebc791a854f62 100644 (file)
@@ -255,6 +255,9 @@ extern blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
 extern int blkid_probe_get_fd(blkid_probe pr)
                        __ul_attribute__((nonnull));
 
+extern int blkid_probe_set_hint(blkid_probe pr, const char *name, uint64_t value)
+                       __ul_attribute__((nonnull));
+
 /*
  * superblocks probing
  */
index fe3736f744ad8ff72755596a09bafdd209a99c66..c3b10562164967c00e73bbeed27df773b8951ca4 100644 (file)
@@ -183,6 +183,15 @@ struct blkid_bufinfo {
        struct list_head        bufs;   /* list of buffers */
 };
 
+/*
+ * Probing hint
+ */
+struct blkid_hint {
+       char                    *name;
+       uint64_t                value;
+       struct list_head        hints;
+};
+
 /*
  * Low-level probing control struct
  */
@@ -205,6 +214,7 @@ struct blkid_struct_probe
        struct blkid_chain      *wipe_chain;    /* superblock, partition, ... */
 
        struct list_head        buffers;        /* list of buffers */
+       struct list_head        hints;
 
        struct blkid_chain      chains[BLKID_NCHAINS];  /* array of chains */
        struct blkid_chain      *cur_chain;             /* current chain */
@@ -521,6 +531,10 @@ extern int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
 extern void blkid_probe_use_wiper(blkid_probe pr, uint64_t off, uint64_t size)
                        __attribute__((nonnull));
 
+extern int blkid_probe_get_hint(blkid_probe pr, const char *name, uint64_t *value)
+                       __attribute__((nonnull(1,2)))
+                       __attribute__((warn_unused_result));
+
 /* filter bitmap macros */
 #define blkid_bmp_wordsize             (8 * sizeof(unsigned long))
 #define blkid_bmp_idx_bit(item)                (1UL << ((item) % blkid_bmp_wordsize))
index 50a976b9be4bbbf68c243e31cf35e82fc96248e9..4eb4c18e0e984286481e9da628f56c3ea0660d02 100644 (file)
@@ -178,3 +178,7 @@ BLKID_2_31 {
 BLKID_2_36 {
        blkid_topology_get_dax;
 } BLKID_2_31;
+
+BLKID_2_37 {
+       blkid_probe_set_hint;
+} BLKID_2_36;
index 8f5f59da3bcc76a53848cc7aeaed1f2a1a6f932c..7a7c902f0db331691eda12176843ed443d8296c5 100644 (file)
@@ -121,6 +121,7 @@ static const struct blkid_chaindrv *chains_drvs[] = {
 };
 
 static void blkid_probe_reset_values(blkid_probe pr);
+static void blkid_probe_reset_hints(blkid_probe pr);
 
 /**
  * blkid_new_probe:
@@ -147,6 +148,7 @@ blkid_probe blkid_new_probe(void)
        }
        INIT_LIST_HEAD(&pr->buffers);
        INIT_LIST_HEAD(&pr->values);
+       INIT_LIST_HEAD(&pr->hints);
        return pr;
 }
 
@@ -248,6 +250,7 @@ void blkid_free_probe(blkid_probe pr)
                close(pr->fd);
        blkid_probe_reset_buffers(pr);
        blkid_probe_reset_values(pr);
+       blkid_probe_reset_hints(pr);
        blkid_free_probe(pr->disk_probe);
 
        DBG(LOWPROBE, ul_debug("free probe"));
@@ -403,6 +406,7 @@ void blkid_reset_probe(blkid_probe pr)
        int i;
 
        blkid_probe_reset_values(pr);
+       blkid_probe_reset_hints(pr);
        blkid_probe_set_wiper(pr, 0, 0);
 
        pr->cur_chain = NULL;
@@ -757,6 +761,7 @@ int blkid_probe_hide_range(blkid_probe pr, uint64_t off, uint64_t len)
        return rc;
 }
 
+
 static void blkid_probe_reset_values(blkid_probe pr)
 {
        if (list_empty(&pr->values))
@@ -2031,3 +2036,98 @@ void blkid_probe_use_wiper(blkid_probe pr, uint64_t off, uint64_t size)
                blkid_probe_chain_reset_values(pr, chn);
        }
 }
+
+/**
+ * blkid_probe_set_hint
+ * @pr: probe
+ * @name: hint name or NAME=value
+ * @value: offset or another number
+ *
+ * Sets extra hint for low-level prober. If the hint is set by NAME=value
+ * notation than @value is ignored. The functions blkid_probe_set_device()
+ * and blkid_reset_probe() resets all hints.
+ *
+ * The hints are optional way how to force libblkid probing functions to check
+ * for example another location.
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_set_hint(blkid_probe pr, const char *name, uint64_t value)
+{
+       struct blkid_hint *hint = NULL;
+       char *n = NULL, *v = NULL;
+
+       if (strchr(name, '=')) {
+               char *end = NULL;
+
+               if (blkid_parse_tag_string(name, &n, &v) != 0)
+                       goto done;
+
+               errno = 0;
+               value = strtoumax(v, &end, 10);
+
+               if (errno || v == end || (end && *end))
+                       goto done;
+       } else {
+               n = strdup(name);
+               if (!n)
+                       goto done;
+       }
+
+       /* allocate info and space for data by one malloc call */
+       hint = malloc(sizeof(*hint));
+       if (!hint)
+               goto done;
+
+       INIT_LIST_HEAD(&hint->hints);
+       hint->name = n;
+       hint->value = value;
+       n = NULL;
+       list_add_tail(&hint->hints, &pr->hints);
+
+       DBG(LOWPROBE,
+               ul_debug("new hint '%s' is %"PRIu64"", hint->name, hint->value));
+done:
+       free(n);
+       free(v);
+       if (!hint)
+               return errno ? -errno : -EINVAL;
+       return 0;
+}
+
+int blkid_probe_get_hint(blkid_probe pr, const char *name, uint64_t *value)
+{
+       struct list_head *p;
+
+       if (list_empty(&pr->hints))
+               return -EINVAL;
+
+       list_for_each(p, &pr->hints) {
+               struct blkid_hint *h = list_entry(p, struct blkid_hint, hints);
+
+               if (h->name && strcmp(name, h->name) == 0) {
+                       if (value)
+                               *value = h->value;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static void blkid_probe_reset_hints(blkid_probe pr)
+{
+       if (list_empty(&pr->hints))
+               return;
+
+       DBG(LOWPROBE, ul_debug("resetting hints"));
+
+       while (!list_empty(&pr->hints)) {
+               struct blkid_hint *h = list_entry(pr->hints.next,
+                                               struct blkid_hint, hints);
+               list_del(&h->hints);
+               free(h->name);
+               free(h);
+       }
+
+       INIT_LIST_HEAD(&pr->hints);
+}