From bfdca6d7287bedb8c40c9750fc3523544bbf5022 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 7 Jun 2019 12:20:53 +0200 Subject: libfdisk: add fdisk_script_set_table() This small change improves possibility to modify by script described PT and use script API in another tools as primary way to create partitions. All you need is to compose script by fdisk_script_set_header() and fdisk_script_set_table() and than apply by fdisk_apply_script(). Requested-by: Lennart Poettering Signed-off-by: Karel Zak --- libfdisk/src/libfdisk.sym | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libfdisk/src/libfdisk.sym') diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index 8f80d7964..8ce943acc 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -303,3 +303,7 @@ FDISK_2.33 { fdisk_get_devmodel; fdisk_get_devno; } FDISK_2.32; + +FDISK_2.35 { + fdisk_script_set_table; +} FDISK_2.33; -- cgit v1.2.3-55-g7522 From 7571ec08a15d54ad05e4b619ccef5a6f10ce30bc Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 18 Jun 2019 13:30:42 +0200 Subject: libfdisk: add fdisk_assign_device_by_fd() It's possible that caller has the device already opened for some other task, so let's reuse the file descriptor. Requested-by: Lennart Poettering Signed-off-by: Karel Zak --- libfdisk/docs/libfdisk-sections.txt | 1 + libfdisk/src/context.c | 142 ++++++++++++++++++++++++------------ libfdisk/src/fdiskP.h | 1 + libfdisk/src/libfdisk.h.in | 2 + libfdisk/src/libfdisk.sym | 1 + 5 files changed, 99 insertions(+), 48 deletions(-) (limited to 'libfdisk/src/libfdisk.sym') diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt index d0d362f60..f148da527 100644 --- a/libfdisk/docs/libfdisk-sections.txt +++ b/libfdisk/docs/libfdisk-sections.txt @@ -291,6 +291,7 @@ fdisk_unref_table context fdisk_context fdisk_assign_device +fdisk_assign_device_by_fd fdisk_deassign_device fdisk_reassign_device fdisk_device_is_used diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c index 1171f28a8..b62d2b101 100644 --- a/libfdisk/src/context.c +++ b/libfdisk/src/context.c @@ -541,7 +541,7 @@ static void reset_context(struct fdisk_context *cxt) free(cxt->firstsector); } else { /* we close device only in primary context */ - if (cxt->dev_fd > -1) + if (cxt->dev_fd > -1 && cxt->private_fd) close(cxt->dev_fd); free(cxt->firstsector); } @@ -559,6 +559,7 @@ static void reset_context(struct fdisk_context *cxt) memset(&cxt->dev_st, 0, sizeof(cxt->dev_st)); cxt->dev_fd = -1; + cxt->private_fd = 0; cxt->firstsector = NULL; cxt->firstsector_bufsz = 0; @@ -572,39 +573,12 @@ static void reset_context(struct fdisk_context *cxt) fdisk_free_wipe_areas(cxt); } -/** - * fdisk_assign_device: - * @cxt: context - * @fname: path to the device to be handled - * @readonly: how to open the device - * - * Open the device, discovery topology, geometry, detect disklabel, check for - * collisions and switch the current label driver to reflect the probing - * result. - * - * If in standard mode (!= non-listonly mode) than also detects for collisions. - * The result is accessible by fdisk_get_collision() and - * fdisk_is_ptcollision(). The collision (e.g. old obsolete PT) may be removed - * by fdisk_enable_wipe(). Note that new PT and old PT may be on different - * locations. - * - * Note that this function resets all generic setting in context. - * - * If the @cxt is nested context (necessary for example to edit BSD or PMBR) - * then the device is assigned to the parental context and necessary properties - * are copied to the @cxt. The change is propagated in child->parent direction - * only. It's impossible to use a different device for primary and nested - * contexts. - * - * Returns: 0 on success, < 0 on error. - */ -int fdisk_assign_device(struct fdisk_context *cxt, - const char *fname, int readonly) +/* fdisk_assign_device() body */ +static int fdisk_assign_fd(struct fdisk_context *cxt, int fd, + const char *fname, int readonly, int privfd) { - int fd; - - DBG(CXT, ul_debugobj(cxt, "assigning device %s", fname)); assert(cxt); + assert(fd >= 0); /* redirect request to parent */ if (cxt->parent) { @@ -615,7 +589,7 @@ int fdisk_assign_device(struct fdisk_context *cxt, * unwanted extra warnings. */ fdisk_enable_listonly(cxt->parent, fdisk_is_listonly(cxt)); - rc = fdisk_assign_device(cxt->parent, fname, readonly); + rc = fdisk_assign_fd(cxt->parent, fd, fname, readonly, privfd); fdisk_enable_listonly(cxt->parent, org); if (!rc) @@ -627,16 +601,13 @@ int fdisk_assign_device(struct fdisk_context *cxt, reset_context(cxt); - fd = open(fname, (readonly ? O_RDONLY : O_RDWR ) | O_CLOEXEC); - if (fd < 0) - goto fail; - if (fstat(fd, &cxt->dev_st) != 0) goto fail; cxt->readonly = readonly; cxt->dev_fd = fd; - cxt->dev_path = strdup(fname); + cxt->private_fd = privfd; + cxt->dev_path = fname ? strdup(fname) : NULL; if (!cxt->dev_path) goto fail; @@ -649,7 +620,6 @@ int fdisk_assign_device(struct fdisk_context *cxt, goto fail; fdisk_probe_labels(cxt); - fdisk_apply_label_device_properties(cxt); /* warn about obsolete stuff on the device if we aren't in @@ -664,13 +634,78 @@ int fdisk_assign_device(struct fdisk_context *cxt, fail: { int rc = -errno; - if (fd >= 0) - close(fd); DBG(CXT, ul_debugobj(cxt, "failed to assign device [rc=%d]", rc)); return rc; } } +/** + * fdisk_assign_device: + * @cxt: context + * @fname: path to the device to be handled + * @readonly: how to open the device + * + * Open the device, discovery topology, geometry, detect disklabel, check for + * collisions and switch the current label driver to reflect the probing + * result. + * + * If in standard mode (!= non-listonly mode) than also detects for collisions. + * The result is accessible by fdisk_get_collision() and + * fdisk_is_ptcollision(). The collision (e.g. old obsolete PT) may be removed + * by fdisk_enable_wipe(). Note that new PT and old PT may be on different + * locations. + * + * Note that this function resets all generic setting in context. + * + * If the @cxt is nested context (necessary for example to edit BSD or PMBR) + * then the device is assigned to the parental context and necessary properties + * are copied to the @cxt. The change is propagated in child->parent direction + * only. It's impossible to use a different device for primary and nested + * contexts. + * + * Returns: 0 on success, < 0 on error. + */ +int fdisk_assign_device(struct fdisk_context *cxt, + const char *fname, int readonly) +{ + int fd, rc; + + DBG(CXT, ul_debugobj(cxt, "assigning device %s", fname)); + assert(cxt); + + fd = open(fname, (readonly ? O_RDONLY : O_RDWR ) | O_CLOEXEC); + if (fd < 0) { + int rc = -errno; + DBG(CXT, ul_debugobj(cxt, "failed to assign device [rc=%d]", rc)); + return rc; + } + + rc = fdisk_assign_fd(cxt, fd, fname, readonly, 1); + if (rc) + close(fd); + return rc; +} + +/** + * fdisk_assign_device_by_fd: + * @cxt: context + * @fd: device file descriptor + * @fname: path to the device (used for dialogs, debugging, partition names, ...) + * @readonly: how to use the device + * + * Like fdisk_assign_device(), but caller is responsible to open and close the + * device. The library only fsync() the device on fdisk_deassign_device(). + * + * The device has to be open O_RDWR on @readonly=0. + * + * Returns: 0 on success, < 0 on error. + */ +int fdisk_assign_device_by_fd(struct fdisk_context *cxt, int fd, + const char *fname, int readonly) +{ + return fdisk_assign_fd(cxt, fd, fname, readonly, 0); +} + /** * fdisk_deassign_device: * @cxt: context @@ -696,15 +731,19 @@ int fdisk_deassign_device(struct fdisk_context *cxt, int nosync) DBG(CXT, ul_debugobj(cxt, "de-assigning device %s", cxt->dev_path)); - if (cxt->readonly) + if (cxt->readonly && cxt->private_fd) close(cxt->dev_fd); else { - if (fsync(cxt->dev_fd) || close(cxt->dev_fd)) { + if (fsync(cxt->dev_fd)) { + fdisk_warn(cxt, _("%s: fsync device failed"), + cxt->dev_path); + return -errno; + } + if (cxt->private_fd && close(cxt->dev_fd)) { fdisk_warn(cxt, _("%s: close device failed"), cxt->dev_path); return -errno; } - if (!nosync) { fdisk_info(cxt, _("Syncing disks.")); sync(); @@ -713,7 +752,6 @@ int fdisk_deassign_device(struct fdisk_context *cxt, int nosync) free(cxt->dev_path); cxt->dev_path = NULL; - cxt->dev_fd = -1; return 0; @@ -733,7 +771,7 @@ int fdisk_deassign_device(struct fdisk_context *cxt, int nosync) int fdisk_reassign_device(struct fdisk_context *cxt) { char *devname; - int rdonly, rc; + int rdonly, rc, fd, privfd; assert(cxt); assert(cxt->dev_fd >= 0); @@ -745,11 +783,19 @@ int fdisk_reassign_device(struct fdisk_context *cxt) return -ENOMEM; rdonly = cxt->readonly; + fd = cxt->dev_fd; + privfd = cxt->private_fd; fdisk_deassign_device(cxt, 1); - rc = fdisk_assign_device(cxt, devname, rdonly); - free(devname); + if (privfd) + /* reopen and assign */ + rc = fdisk_assign_device(cxt, devname, rdonly); + else + /* assign only */ + rc = fdisk_assign_fd(cxt, fd, devname, rdonly, privfd); + + free(devname); return rc; } diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 19c1c7953..fefebae2a 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -389,6 +389,7 @@ struct fdisk_context { pt_collision : 1, /* another PT detected by libblkid */ no_disalogs : 1, /* disable dialog-driven partititoning */ dev_model_probed : 1, /* tried to read from sys */ + private_fd : 1, /* open by libfdisk */ listonly : 1; /* list partition, nothing else */ char *collision; /* name of already existing FS/PT */ diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in index 69c6fd820..0669c0a7c 100644 --- a/libfdisk/src/libfdisk.h.in +++ b/libfdisk/src/libfdisk.h.in @@ -195,6 +195,8 @@ int fdisk_is_labeltype(struct fdisk_context *cxt, enum fdisk_labeltype id); int fdisk_assign_device(struct fdisk_context *cxt, const char *fname, int readonly); +int fdisk_assign_device_by_fd(struct fdisk_context *cxt, int fd, + const char *fname, int readonly); int fdisk_deassign_device(struct fdisk_context *cxt, int nosync); int fdisk_reassign_device(struct fdisk_context *cxt); diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index 8ce943acc..96fcadd71 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -306,4 +306,5 @@ FDISK_2.33 { FDISK_2.35 { fdisk_script_set_table; + fdisk_assign_device_by_fd; } FDISK_2.33; -- cgit v1.2.3-55-g7522