From: Karel Zak Date: Tue, 30 Jun 2026 12:47:19 +0000 (+0200) Subject: libblkid: use VFS I/O operations in probe X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e9a31287dddadd66907252fe45d03c0f919f3b4;p=thirdparty%2Futil-linux.git libblkid: use VFS I/O operations in probe Replace all direct I/O syscalls in the probe path with ul_vfs_* dispatch functions that route through the pluggable VFS layer when set, falling back to real syscalls otherwise. Add ul_vfs_copy() to include/vfs.h for cloning VFS ops structs. Changed call sites: - read_buffer(): lseek + read - is_sector_readable(): lseek + read, changed signature to take blkid_probe instead of bare fd - blkid_probe_set_device(): close - blkid_do_wipe(): lseek + write_all + fsync - blkid_free_probe(): close + free(pr->vfs) - blkid_clone_probe(): allocate private VFS copy via ul_vfs_copy() Addresses: https://github.com/util-linux/util-linux/issues/4308 Signed-off-by: Karel Zak --- diff --git a/include/vfs.h b/include/vfs.h index 9dfab596f..97479ec0a 100644 --- a/include/vfs.h +++ b/include/vfs.h @@ -5,6 +5,7 @@ #ifndef UTIL_LINUX_VFS_H #define UTIL_LINUX_VFS_H +#include #include #include #include @@ -37,6 +38,19 @@ static inline void ul_vfs_init(struct ul_vfs_ops *dst, dst->size = sizeof(*dst); } +static inline struct ul_vfs_ops *ul_vfs_copy(const struct ul_vfs_ops *src) +{ + struct ul_vfs_ops *dst; + + if (!src) + return NULL; + dst = malloc(sizeof(*dst)); + if (!dst) + return NULL; + memcpy(dst, src, sizeof(*dst)); + return dst; +} + static inline ssize_t ul_vfs_read(const struct ul_vfs_ops *vfs, int fd, void *buf, size_t count) { diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c index 3464a3736..6fa8ba563 100644 --- a/libblkid/src/probe.c +++ b/libblkid/src/probe.c @@ -194,6 +194,14 @@ blkid_probe blkid_clone_probe(blkid_probe parent) pr->flags &= ~BLKID_FL_PRIVATE_FD; + if (parent->vfs) { + pr->vfs = ul_vfs_copy(parent->vfs); + if (!pr->vfs) { + blkid_free_probe(pr); + return NULL; + } + } + return pr; } @@ -277,13 +285,14 @@ void blkid_free_probe(blkid_probe pr) } if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0) - close(pr->fd); + ul_vfs_close(pr->vfs, 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")); + free(pr->vfs); free(pr); } @@ -578,7 +587,7 @@ static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint ssize_t ret; struct blkid_bufinfo *bf = NULL; - if (lseek(pr->fd, real_off, SEEK_SET) == (off_t) -1) { + if (ul_vfs_lseek(pr->vfs, pr->fd, real_off, SEEK_SET) == (off_t) -1) { errno = 0; return NULL; } @@ -611,7 +620,7 @@ static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint DBG(LOWPROBE, ul_debug("\tread: off=%"PRIu64" len=%"PRIu64"", real_off, len)); - ret = read(pr->fd, bf->data, len); + ret = ul_vfs_read(pr->vfs, pr->fd, bf->data, len); if (ret != (ssize_t) len) { DBG(LOWPROBE, ul_debug("\tread failed: %m")); remove_buffer(bf); @@ -967,15 +976,15 @@ int blkdid_probe_is_opal_locked(blkid_probe pr) #ifdef CDROM_GET_CAPABILITY -static int is_sector_readable(int fd, uint64_t sector) +static int is_sector_readable(blkid_probe pr, uint64_t sector) { char buf[512]; ssize_t sz; - if (lseek(fd, sector * 512, SEEK_SET) == (off_t) -1) + if (ul_vfs_lseek(pr->vfs, pr->fd, sector * 512, SEEK_SET) == (off_t) -1) goto failed; - sz = read(fd, buf, sizeof(buf)); + sz = ul_vfs_read(pr->vfs, pr->fd, buf, sizeof(buf)); if (sz != (ssize_t) sizeof(buf)) goto failed; @@ -1002,7 +1011,7 @@ static void cdrom_size_correction(blkid_probe pr, uint64_t last_written) nsectors = (last_written+1) << 2; for (n = nsectors - 12; n < nsectors; n++) { - if (!is_sector_readable(pr->fd, n)) + if (!is_sector_readable(pr, n)) goto failed; } @@ -1073,7 +1082,7 @@ int blkid_probe_set_device(blkid_probe pr, int fd, blkid_probe_reset_buffers(pr); if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0) - close(pr->fd); + ul_vfs_close(pr->vfs, pr->fd); if (pr->disk_probe) { blkid_free_probe(pr->disk_probe); @@ -1614,7 +1623,7 @@ int blkid_do_wipe(blkid_probe pr, int dryrun) "do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n", offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not")); - if (lseek(fd, offset, SEEK_SET) == (off_t) -1) + if (ul_vfs_lseek(pr->vfs, fd, offset, SEEK_SET) == (off_t) -1) return BLKID_PROBE_ERROR; if (!dryrun && len) { @@ -1622,9 +1631,9 @@ int blkid_do_wipe(blkid_probe pr, int dryrun) memset(buf, 0, len); /* wipen on device */ - if (ul_write_all(fd, buf, len)) + if (ul_vfs_write_all(pr->vfs, fd, buf, len)) return BLKID_PROBE_ERROR; - if (fsync(fd) != 0) + if (ul_vfs_fsync(pr->vfs, fd) != 0) return BLKID_PROBE_ERROR; } else { #ifdef HAVE_LINUX_BLKZONED_H diff --git a/libblkid/src/topology/md.c b/libblkid/src/topology/md.c index b9e7d792f..4d9c01884 100644 --- a/libblkid/src/topology/md.c +++ b/libblkid/src/topology/md.c @@ -97,7 +97,7 @@ static int probe_md_tp(blkid_probe pr, if (!diskpath) goto nothing; - fd = open(diskpath, O_RDONLY|O_CLOEXEC); + fd = ul_vfs_open(pr->vfs, diskpath, O_RDONLY|O_CLOEXEC, 0); free(diskpath); if (fd == -1) @@ -110,7 +110,7 @@ static int probe_md_tp(blkid_probe pr, goto nothing; if (fd >= 0 && fd != pr->fd) { - close(fd); + ul_vfs_close(pr->vfs, fd); fd = -1; }