fdisk_set_last_lba
fdisk_set_size_unit
fdisk_set_unit
+fdisk_set_vfs
FDISK_SINGULAR
fdisk_unref_context
fdisk_use_cylinders
{
int fd;
- if ((fd = open(path, O_RDONLY)) < 0) {
+ if ((fd = ul_vfs_open(cxt->vfs, path, O_RDONLY, 0)) < 0) {
fdisk_warn(cxt, _("cannot open %s"), path);
return -errno;
}
- if (ul_read_all(fd, ptr, size) != size) {
+ if (ul_vfs_read_all(cxt->vfs, fd, ptr, size) != size) {
fdisk_warn(cxt, _("cannot read %s"), path);
- close(fd);
+ ul_vfs_close(cxt->vfs, fd);
return -errno;
}
fdisk_info(cxt, _("The bootstrap file %s successfully loaded."), path);
- close (fd);
+ ul_vfs_close(cxt->vfs, fd);
return 0;
}
#if defined (__alpha__)
alpha_bootblock_checksum(l->bsdbuffer);
#endif
- if (lseek(cxt->dev_fd, (off_t) sector * DEFAULT_SECTOR_SIZE, SEEK_SET) == -1) {
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, (off_t) sector * DEFAULT_SECTOR_SIZE, SEEK_SET) == -1) {
fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path);
rc = -errno;
goto done;
}
- if (ul_write_all(cxt->dev_fd, l->bsdbuffer, BSD_BBSIZE)) {
+ if (ul_vfs_write_all(cxt->vfs, cxt->dev_fd, l->bsdbuffer, BSD_BBSIZE)) {
fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path);
rc = -errno;
goto done;
* partition. Note that DOS uses native sector size. */
offset = dos_partition_get_start(l->dos_part) * cxt->sector_size;
- if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1)
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET) == -1)
return -1;
- if (ul_read_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer)) < 0)
+ if (ul_vfs_read_all(cxt->vfs, cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer)) < 0)
return errno ? -errno : -1;
/* The offset to begin of the disk label. Note that BSD uses
/* Write the checksum to the end of the first sector. */
alpha_bootblock_checksum(l->bsdbuffer);
#endif
- if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1) {
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET) == -1) {
fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path);
return -errno;
}
- if (ul_write_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer))) {
+ if (ul_vfs_write_all(cxt->vfs, cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer))) {
fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path);
return -errno;
}
cxt->user_geom = parent->user_geom;
cxt->user_log_sector = parent->user_log_sector;
cxt->user_pyh_sector = parent->user_pyh_sector;
+ cxt->vfs = parent->vfs;
/* parent <--> nested independent setting, initialize for new nested
* contexts only */
cxt->protect_bootbits = enable ? 1 : 0;
return 0;
}
+
+/**
+ * fdisk_set_vfs:
+ * @cxt: fdisk context
+ * @ops: VFS operations or NULL to reset to defaults
+ *
+ * Sets custom I/O operations for the context. This allows replacing
+ * standard read/write/lseek/etc. with custom implementations
+ * (e.g., fiber-aware I/O).
+ *
+ * The @ops struct is copied into a private allocation owned by the
+ * context. The caller sets ops->size to sizeof(struct ul_vfs_ops) to
+ * enable forward/backward compatibility. NULL function pointers fall
+ * back to standard syscalls. Passing @ops as NULL frees the private
+ * copy and resets the context to default (direct syscall) I/O.
+ *
+ * Note: fdisk_set_vfs() should be called before fdisk_assign_device().
+ *
+ * Since: 2.43
+ *
+ * Returns: 0 on success, or <0 in case of error.
+ */
+int fdisk_set_vfs(struct fdisk_context *cxt, const struct ul_vfs_ops *ops)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ if (!ops) {
+ free(cxt->vfs);
+ cxt->vfs = NULL;
+ return 0;
+ }
+ if (!cxt->vfs) {
+ cxt->vfs = calloc(1, sizeof(*cxt->vfs));
+ if (!cxt->vfs)
+ return -ENOMEM;
+ }
+ ul_vfs_init(cxt->vfs, ops);
+ return 0;
+}
+
/**
* fdisk_disable_dialogs
* @cxt: fdisk context
} else {
/* we close device only in primary context */
if (cxt->dev_fd > -1 && cxt->is_priv)
- close(cxt->dev_fd);
+ ul_vfs_close(cxt->vfs, cxt->dev_fd);
DBG_OBJ(CXT, cxt, ul_debug(" freeing firstsector"));
free(cxt->firstsector);
+ free(cxt->vfs);
+ cxt->vfs = NULL;
}
free(cxt->dev_path);
flags |= (O_RDWR | O_EXCL);
errno = 0;
- fd = open(fname,flags);
+ fd = ul_vfs_open(cxt->vfs, fname, flags, 0);
if (fd < 0 && errno == EBUSY && (flags & O_EXCL)) {
flags &= ~O_EXCL;
errno = 0;
- fd = open(fname, flags);
+ fd = ul_vfs_open(cxt->vfs, fname, flags, 0);
}
if (fd < 0) {
rc = fdisk_assign_fd(cxt, fd, fname, readonly, 1, flags & O_EXCL);
if (rc)
- close(fd);
+ ul_vfs_close(cxt->vfs, fd);
return rc;
}
DBG_OBJ(CXT, cxt, ul_debug("de-assigning device %s", cxt->dev_path));
if (cxt->readonly && cxt->is_priv)
- close(cxt->dev_fd);
+ ul_vfs_close(cxt->vfs, cxt->dev_fd);
else {
- if (fsync(cxt->dev_fd)) {
+ if (ul_vfs_fsync(cxt->vfs, cxt->dev_fd)) {
fdisk_warn(cxt, _("%s: fsync device failed"),
cxt->dev_path);
return -errno;
}
- if (cxt->is_priv && close(cxt->dev_fd)) {
+ if (cxt->is_priv && ul_vfs_close(cxt->vfs, cxt->dev_fd)) {
fdisk_warn(cxt, _("%s: close device failed"),
cxt->dev_path);
return -errno;
{
off_t offset = (off_t) secno * cxt->sector_size;
- return lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1 ? -errno : 0;
+ return ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET) == (off_t) -1 ? -errno : 0;
}
static int read_sector(struct fdisk_context *cxt, fdisk_sector_t secno,
if (rc < 0)
return rc;
- r = read(cxt->dev_fd, buf, cxt->sector_size);
+ r = ul_vfs_read(cxt->vfs, cxt->dev_fd, buf, cxt->sector_size);
if (r == (ssize_t) cxt->sector_size)
return 0;
if (r < 0)
DBG(LABEL, ul_debug("DOS: writing to sector %ju", (uintmax_t) secno));
- if (write(cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size)
+ if (ul_vfs_write(cxt->vfs, cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size)
return -errno;
return 0;
}
#include "c.h"
#include "libfdisk.h"
+#include "vfs.h"
#include "list.h"
#include "debug.h"
struct fdisk_context *parent; /* for nested PT */
struct fdisk_script *script; /* what we want to follow */
+
+ struct ul_vfs_ops *vfs; /* pluggable I/O ops (owned, or NULL) */
};
/* table */
{
off_t offset = lba * cxt->sector_size;
- if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
return -1;
- return (size_t)read(cxt->dev_fd, buffer, bytes) != bytes;
+ return (size_t)ul_vfs_read(cxt->vfs, cxt->dev_fd, buffer, bytes) != bytes;
}
offset = (off_t) le64_to_cpu(header->partition_entry_lba) *
cxt->sector_size;
- if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
+ if (offset != ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET))
goto fail;
- ssz = read(cxt->dev_fd, ret, sz);
+ ssz = ul_vfs_read(cxt->vfs, cxt->dev_fd, ret, sz);
if (ssz < 0 || (size_t) ssz != sz)
goto fail;
static int gpt_read(struct fdisk_context *cxt, off_t offset, void *buf, size_t count)
{
- if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
+ if (offset != ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET))
return -errno;
- if (ul_read_all(cxt->dev_fd, buf, count))
+ if (ul_vfs_read_all(cxt->vfs, cxt->dev_fd, buf, count))
return -errno;
DBG(GPT, ul_debug(" read OK [offset=%zu, size=%zu]",
static int gpt_write(struct fdisk_context *cxt, off_t offset, void *buf, size_t count)
{
- if (offset != lseek(cxt->dev_fd, offset, SEEK_SET))
+ if (offset != ul_vfs_lseek(cxt->vfs, cxt->dev_fd, offset, SEEK_SET))
return -errno;
- if (ul_write_all(cxt->dev_fd, buf, count))
+ if (ul_vfs_write_all(cxt->vfs, cxt->dev_fd, buf, count))
return -errno;
- if (fsync(cxt->dev_fd) != 0)
+ if (ul_vfs_fsync(cxt->vfs, cxt->dev_fd) != 0)
return -errno;
DBG(GPT, ul_debug(" write OK [offset=%zu, size=%zu]",
dev_t fdisk_get_devno(struct fdisk_context *cxt);
const char *fdisk_get_devmodel(struct fdisk_context *cxt);
+#ifndef UL_VFS_OPS_DEFINED
+#define UL_VFS_OPS_DEFINED
+
+struct ul_vfs_ops {
+ size_t size;
+
+ ssize_t (*vfs_read)(int fd, void *buf, size_t count);
+ ssize_t (*vfs_write)(int fd, const void *buf, size_t count);
+ int (*vfs_open)(const char *pathname, int flags, mode_t mode);
+ int (*vfs_close)(int fd);
+ off_t (*vfs_lseek)(int fd, off_t offset, int whence);
+ int (*vfs_fsync)(int fd);
+
+ FILE *(*vfs_fopen)(const char *pathname, const char *mode);
+};
+
+#endif /* UL_VFS_OPS_DEFINED */
+
+extern int fdisk_set_vfs(struct fdisk_context *cxt, const struct ul_vfs_ops *ops);
unsigned int fdisk_get_geom_heads(struct fdisk_context *cxt);
fdisk_sector_t fdisk_get_geom_sectors(struct fdisk_context *cxt);
fdisk_script_disable_devnames;
fdisk_script_has_devnames;
fdisk_get_recommended_labelname;
+ fdisk_set_vfs;
} FDISK_2_42;
assert(sgi_pt_checksum(sgilabel) == 0);
- if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0)
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, 0, SEEK_SET) < 0)
goto err;
- if (ul_write_all(cxt->dev_fd, sgilabel, DEFAULT_SECTOR_SIZE))
+ if (ul_vfs_write_all(cxt->vfs, cxt->dev_fd, sgilabel, DEFAULT_SECTOR_SIZE))
goto err;
if (!strncmp((char *) sgilabel->volume[0].name, "sgilabel", 8)) {
/*
int infostartblock
= be32_to_cpu(sgilabel->volume[0].block_num);
- if (lseek(cxt->dev_fd, (off_t) infostartblock *
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, (off_t) infostartblock *
DEFAULT_SECTOR_SIZE, SEEK_SET) < 0)
goto err;
info = sgi_new_info();
if (!info)
goto err;
- if (ul_write_all(cxt->dev_fd, info, sizeof(*info)))
+ if (ul_vfs_write_all(cxt->vfs, cxt->dev_fd, info, sizeof(*info)))
goto err;
}
sunlabel->csum = 0;
sunlabel->csum = sun_pt_checksum(sunlabel);
- if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0)
+ if (ul_vfs_lseek(cxt->vfs, cxt->dev_fd, 0, SEEK_SET) < 0)
return -errno;
- if (ul_write_all(cxt->dev_fd, sunlabel, sz) != 0)
+ if (ul_vfs_write_all(cxt->vfs, cxt->dev_fd, sunlabel, sz) != 0)
return -errno;
return 0;
DBG_OBJ(CXT, cxt, ul_debug("reading: offset=%ju, size=%zu",
start, size));
- r = lseek(cxt->dev_fd, start, SEEK_SET);
+ r = ul_vfs_lseek(cxt->vfs, cxt->dev_fd, start, SEEK_SET);
if (r == -1)
{
DBG_OBJ(CXT, cxt, ul_debug("failed to seek to offset %ju: %m", start));
}
errno = 0;
- r = read(cxt->dev_fd, buf, size);
+ r = ul_vfs_read(cxt->vfs, cxt->dev_fd, buf, size);
if (r < 0 || (size_t)r != size) {
if (!errno)
errno = EINVAL; /* probably too small file/device */
if (!pr)
return -ENOMEM;
+ if (cxt->vfs)
+ blkid_probe_set_vfs(pr, cxt->vfs);
+
list_for_each(p, &cxt->wipes) {
struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
blkid_loff_t start = (blkid_loff_t) wp->start * cxt->sector_size,
pr = blkid_new_probe();
if (!pr)
return -ENOMEM;
+
+ if (cxt->vfs)
+ blkid_probe_set_vfs(pr, cxt->vfs);
+
rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0);
if (rc)
return rc;