]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: add blkid_probe_open_device()
authorKarel Zak <kzak@redhat.com>
Tue, 30 Jun 2026 13:18:25 +0000 (15:18 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 9 Jul 2026 10:18:04 +0000 (12:18 +0200)
Add a convenience function that opens a device and assigns it to
the probe, using VFS operations if previously set. This enables
the composable pattern:

  blkid_new_probe()
  → blkid_probe_set_vfs()
  → blkid_probe_open_device()

Refactor blkid_new_probe_from_filename() to use it internally.

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

index 75b2b3a320f744334379325cd42c69e91bed4eb2..9a4ae2a54b3cb143fefbb2ec99b70a143a1d43c9 100644 (file)
@@ -61,6 +61,7 @@ blkid_probe_reset_buffers
 blkid_probe_reset_hints
 blkid_probe_set_device
 blkid_probe_set_hint
+blkid_probe_open_device
 blkid_probe_set_sectorsize
 blkid_probe_set_vfs
 blkid_probe_step_back
index adfd3c3a6313efdcca40edcbc2253f72d504c0c6..ee85ef015eafee574ea84a07ca581897da5ded1e 100644 (file)
@@ -262,6 +262,10 @@ struct ul_vfs_ops {
 extern int blkid_probe_set_vfs(blkid_probe pr, const struct ul_vfs_ops *ops)
                        __ul_attribute__((nonnull(1)));
 
+extern int blkid_probe_open_device(blkid_probe pr, const char *filename,
+                       int flags)
+                       __ul_attribute__((nonnull));
+
 extern dev_t blkid_probe_get_devno(blkid_probe pr)
                        __ul_attribute__((nonnull));
 
index cf520d9b71a42ac371b89708fafbf901b3e1dbea..55c4e23ac2d9346c80c20b3cff402c7d8aeaebe7 100644 (file)
@@ -194,5 +194,6 @@ BLKID_2_40 {
 
 BLKID_2_43 {
     blkid_evaluate_tag2;
+    blkid_probe_open_device;
     blkid_probe_set_vfs;
 } BLKID_2_40;
index 6fa8ba563c76f10ceaa33ca3546f1666db973975..7f4c2791db36f3195efc63ccde97729188eeb712 100644 (file)
@@ -205,60 +205,82 @@ blkid_probe blkid_clone_probe(blkid_probe parent)
        return pr;
 }
 
-
-
 /**
- * blkid_new_probe_from_filename:
+ * blkid_probe_open_device:
+ * @pr: probe
  * @filename: device or regular file
+ * @flags: open(2) flags or 0 for default (O_RDONLY|O_CLOEXEC|O_NONBLOCK)
  *
- * This function is same as call open(filename), blkid_new_probe() and
- * blkid_probe_set_device(pr, fd, 0, 0).
+ * Opens the @filename and assigns it to the probe. This is equivalent to
+ * calling open() and blkid_probe_set_device(), but uses VFS operations
+ * if previously set by blkid_probe_set_vfs().
+ *
+ * This allows probe setup before the device is opened:
+ *
+ *   blkid_new_probe() → blkid_probe_set_vfs() → blkid_probe_open_device()
  *
  * The @filename is closed by blkid_free_probe() or by the
  * blkid_probe_set_device() call.
  *
- * Returns: a pointer to the newly allocated probe struct or NULL in case of
- * error.
+ * Since: 2.43
+ *
+ * Returns: 0 on success, or <0 in case of error.
  */
-blkid_probe blkid_new_probe_from_filename(const char *filename)
+int blkid_probe_open_device(blkid_probe pr, const char *filename, int flags)
 {
        int fd;
-       blkid_probe pr = NULL;
        struct stat sb;
 
-       /*
-        * Check for hidden device-mapper devices (LVM internals, etc.)
-        * before open() to avoid bumping the kernel open count.  A racing
-        * DM_DEVICE_REMOVE would otherwise see EBUSY.
-        *
-        * Use sysfs_devno_is_dm_hidden() rather than _dm_private() so that
-        * Stratis devices remain accessible to tools like mkfs.xfs that
-        * need to probe device geometry.
-        */
        if (stat(filename, &sb) == 0 && S_ISBLK(sb.st_mode) &&
            sysfs_devno_is_dm_hidden(sb.st_rdev, NULL)) {
                DBG(LOWPROBE, ul_debug("ignore hidden device mapper device"));
                errno = EINVAL;
-               return NULL;
+               return -EINVAL;
        }
 
-       fd = open(filename, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
+       if (!flags)
+               flags = O_RDONLY | O_CLOEXEC | O_NONBLOCK;
+
+       fd = ul_vfs_open(pr->vfs, filename, flags, 0);
        if (fd < 0)
-               return NULL;
+               return -errno;
+
+       if (blkid_probe_set_device(pr, fd, 0, 0)) {
+               ul_vfs_close(pr->vfs, fd);
+               return -errno ? -errno : -EINVAL;
+       }
+
+       pr->flags |= BLKID_FL_PRIVATE_FD;
+       return 0;
+}
+
+/**
+ * blkid_new_probe_from_filename:
+ * @filename: device or regular file
+ *
+ * This function is same as call open(filename), blkid_new_probe() and
+ * blkid_probe_set_device(pr, fd, 0, 0).
+ *
+ * The @filename is closed by blkid_free_probe() or by the
+ * blkid_probe_set_device() call.
+ *
+ * Returns: a pointer to the newly allocated probe struct or NULL in case of
+ * error.
+ */
+blkid_probe blkid_new_probe_from_filename(const char *filename)
+{
+       blkid_probe pr;
 
        pr = blkid_new_probe();
        if (!pr)
-               goto err;
+               return NULL;
 
-       if (blkid_probe_set_device(pr, fd, 0, 0))
-               goto err;
+       if (blkid_probe_open_device(pr, filename, 0)) {
+               blkid_free_probe(pr);
+               return NULL;
+       }
 
-       pr->flags |= BLKID_FL_PRIVATE_FD;
        return pr;
-err:
-       close(fd);
-       blkid_free_probe(pr);
-       return NULL;
 }
 
 /**