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/script.c | 76 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 13 deletions(-) (limited to 'libfdisk/src/script.c') diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 66be4f08c..0a165aad4 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -7,13 +7,33 @@ /** * SECTION: script * @title: Script - * @short_description: text based sfdisk compatible description of partition table + * @short_description: complex way to create and dump partition table * - * The libfdisk scripts are based on original sfdisk script (dumps). Each + * This interface allows to compose in-memory partition table with all details, + * write all partition table description to human readable text file, read it + * from the file, and apply the script to on-disk label. + * + * The libfdisk scripts are based on original sfdisk script (dumps). Each * script has two parts: script headers and partition table entries - * (partitions). + * (partitions). The script is possible to dump in JSON too (read JSON is not + * implemented yet). * * For more details about script format see sfdisk man page. + * + * There are four ways how to build the script: + * + * - read the current on-disk partition table by fdisk_script_read_context()) + * - read it from text file by fdisk_script_read_file() + * - read it interactively from user by fdisk_script_read_line() and fdisk_script_set_fgets() + * - manually in code by fdisk_script_set_header() and fdisk_script_set_table() + * + * The read functions fdisk_script_read_context() and fdisk_script_read_file() + * creates always a new script partition table. The table (see + * fdisk_script_get_table()) is possible to modify by standard + * fdisk_table_...() functions and than apply by fdisk_apply_script(). + * + * Note that script API is fully non-interactive and forces libfdisk to not use + * standard dialog driven partitioning as we have in fdisk(8). */ /* script header (e.g. unit: sectors) */ @@ -76,12 +96,6 @@ struct fdisk_script *fdisk_new_script(struct fdisk_context *cxt) dp->cxt = cxt; fdisk_ref_context(cxt); - dp->table = fdisk_new_table(); - if (!dp->table) { - fdisk_unref_script(dp); - return NULL; - } - INIT_LIST_HEAD(&dp->headers); return dp; } @@ -317,11 +331,11 @@ int fdisk_script_set_header(struct fdisk_script *dp, * fdisk_script_get_table: * @dp: script * - * The table (container with partitions) is possible to create by - * fdisk_script_read_context() or fdisk_script_read_file(), otherwise - * this function returns NULL. + * The table represents partitions holded by the script. The table is possible to + * fill by fdisk_script_read_context() or fdisk_script_read_file(). All the "read" + * functions reset the table. See also fdisk_script_set_table(). * - * Returns: NULL or script. + * Returns: NULL or script table. */ struct fdisk_table *fdisk_script_get_table(struct fdisk_script *dp) { @@ -329,6 +343,40 @@ struct fdisk_table *fdisk_script_get_table(struct fdisk_script *dp) return dp ? dp->table : NULL; } +/** + * fdisk_script_set_table: + * @dp: script + * @tb: table + * + * Replaces table used by script and creates a new reference to @tb. This + * function allows to generate a new script table independently on the current + * context and without any file reading. + * + * This is useful for example to create partition table with the same basic + * settings (e.g. label-id, ...) but with different partitions -- just call + * fdisk_script_read_context() to get current settings and than + * fdisk_script_set_table() to set a different layout. + * + * If @tb is NULL than the current script table is unreferenced. + * + * Note that script read_ functions (e.g. fdisk_script_read_context()) create + * always a new script table. + * + * Returns: 0 on success, <0 on error + */ +int fdisk_script_set_table(struct fdisk_script *dp, struct fdisk_table *tb) +{ + if (!dp) + return -EINVAL; + + fdisk_ref_table(tb); + fdisk_unref_table(dp->table); + dp->table = tb; + + DBG(SCRIPT, ul_debugobj(dp, "table replaced")); + return 0; +} + static struct fdisk_label *script_get_label(struct fdisk_script *dp) { assert(dp); @@ -911,6 +959,7 @@ static int parse_line_nameval(struct fdisk_script *dp, char *s) assert(dp); assert(s); + assert(dp->table); DBG(SCRIPT, ul_debugobj(dp, " parse script line: '%s'", s)); @@ -1106,6 +1155,7 @@ static int parse_line_valcommas(struct fdisk_script *dp, char *s) assert(dp); assert(s); + assert(dp->table); pa = fdisk_new_partition(); if (!pa) -- cgit v1.2.3-55-g7522 From 73ec5e164c8e67bb2621c58fcccbdef54da8e1ca Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 10 Jun 2019 11:43:56 +0200 Subject: libfdisk: fix fdisk_script_get_table() Make sure we never return NULL and we reuse the table in code. Signed-off-by: Karel Zak --- libfdisk/src/script.c | 32 +++++++++++++++++++------------- libfdisk/src/table.c | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'libfdisk/src/script.c') diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 0a165aad4..dbbd53eaf 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -162,8 +162,9 @@ static void fdisk_reset_script(struct fdisk_script *dp) assert(dp); DBG(SCRIPT, ul_debugobj(dp, "reset")); - fdisk_unref_table(dp->table); - dp->table = NULL; + + if (dp->table) + fdisk_reset_table(dp->table); while (!list_empty(&dp->headers)) { struct fdisk_scriptheader *fi = list_entry(dp->headers.next, @@ -333,14 +334,22 @@ int fdisk_script_set_header(struct fdisk_script *dp, * * The table represents partitions holded by the script. The table is possible to * fill by fdisk_script_read_context() or fdisk_script_read_file(). All the "read" - * functions reset the table. See also fdisk_script_set_table(). + * functions remove old partitions from the table. See also fdisk_script_set_table(). * * Returns: NULL or script table. */ struct fdisk_table *fdisk_script_get_table(struct fdisk_script *dp) { assert(dp); - return dp ? dp->table : NULL; + + if (!dp->table) + /* + * Make sure user has access to the same table as script. If + * there is no table than create a new and reuse it later. + */ + dp->table = fdisk_new_table(); + + return dp->table; } /** @@ -448,7 +457,7 @@ int fdisk_script_read_context(struct fdisk_script *dp, struct fdisk_context *cxt if (!lb) return -EINVAL; - /* allocate and fill new table */ + /* allocate (if not yet) and fill table */ rc = fdisk_get_partitions(cxt, &dp->table); if (rc) return rc; @@ -590,7 +599,7 @@ static int write_file_json(struct fdisk_script *dp, FILE *f) } - if (!dp->table) { + if (!dp->table || fdisk_table_is_empty(dp->table)) { DBG(SCRIPT, ul_debugobj(dp, "script table empty")); goto done; } @@ -699,7 +708,7 @@ static int write_file_sfdisk(struct fdisk_script *dp, FILE *f) devname = fi->data; } - if (!dp->table) { + if (!dp->table || fdisk_table_is_empty(dp->table)) { DBG(SCRIPT, ul_debugobj(dp, "script table empty")); return 0; } @@ -1290,11 +1299,8 @@ static int fdisk_script_read_buffer(struct fdisk_script *dp, char *s) if (!s || !*s) return 0; /* nothing baby, ignore */ - if (!dp->table) { - dp->table = fdisk_new_table(); - if (!dp->table) - return -ENOMEM; - } + if (!dp->table && fdisk_script_get_table(dp) == NULL) + return -ENOMEM; /* parse header lines only if no partition specified yet */ if (fdisk_table_is_empty(dp->table) && is_header_line(s)) @@ -1619,7 +1625,7 @@ static int test_stdin(struct fdisk_test *ts, int argc, char *argv[]) printf(", , , \n"); do { struct fdisk_partition *pa; - size_t n = fdisk_table_get_nents(dp->table); + size_t n = dp->table ? fdisk_table_get_nents(dp->table) : 0; printf(" #%zu :\n", n + 1); rc = fdisk_script_read_line(dp, stdin, buf, sizeof(buf)); diff --git a/libfdisk/src/table.c b/libfdisk/src/table.c index 1f9d5a28a..8a3a935af 100644 --- a/libfdisk/src/table.c +++ b/libfdisk/src/table.c @@ -303,7 +303,7 @@ int fdisk_table_remove_partition(struct fdisk_table *tb, struct fdisk_partition * @tb: returns table * * This function adds partitions from disklabel to @table, it allocates a new - * table if if @table points to NULL. + * table if @table points to NULL. * * Returns: 0 on success, otherwise, a corresponding error. */ -- cgit v1.2.3-55-g7522 From f1424a94239f9149939b45ed9f19e8f77fb1847d Mon Sep 17 00:00:00 2001 From: Marcos Mello Date: Thu, 20 Jun 2019 08:22:25 -0300 Subject: libfdisk: fix typos --- libfdisk/src/alignment.c | 2 +- libfdisk/src/context.c | 8 ++++---- libfdisk/src/label.c | 8 ++++---- libfdisk/src/script.c | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'libfdisk/src/script.c') diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c index 426fa938c..4ae5ff08f 100644 --- a/libfdisk/src/alignment.c +++ b/libfdisk/src/alignment.c @@ -324,7 +324,7 @@ int fdisk_save_user_sector_size(struct fdisk_context *cxt, * * The smallest possible granularity for partitioning is physical sector size * (or minimal I/O size; the bigger number win). If the user's @grain size is - * too small than the smallest possible granularity is used. It means + * too small then the smallest possible granularity is used. It means * fdisk_save_user_grain(cxt, 512) forces libfdisk to use grain as small as * possible. * diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c index b62d2b101..3677648e9 100644 --- a/libfdisk/src/context.c +++ b/libfdisk/src/context.c @@ -17,7 +17,7 @@ * * The library distinguish between three types of partitioning objects. * - * on-disk lebel data + * on-disk label data * - disk label specific * - probed and read by disklabel drivers when assign device to the context * or when switch to another disk label type @@ -487,7 +487,7 @@ int fdisk_is_ptcollision(struct fdisk_context *cxt) * * * Note that the recommended way to list partitions is to use - * fdisk_get_partitions() and struct fdisk_table than ask disk driver for each + * fdisk_get_partitions() and struct fdisk_table then ask disk driver for each * individual partitions. * * Returns: maximal number of partitions for the current label. @@ -649,7 +649,7 @@ fail: * collisions and switch the current label driver to reflect the probing * result. * - * If in standard mode (!= non-listonly mode) than also detects for collisions. + * If in standard mode (!= non-listonly mode) then 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 @@ -711,7 +711,7 @@ int fdisk_assign_device_by_fd(struct fdisk_context *cxt, int fd, * @cxt: context * @nosync: disable fsync() * - * Close device and call fsync(). If the @cxt is nested context than the + * Close device and call fsync(). If the @cxt is nested context then the * request is redirected to the parent. * * Returns: 0 on success, < 0 on error. diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c index 68f73f143..a18cdeaff 100644 --- a/libfdisk/src/label.c +++ b/libfdisk/src/label.c @@ -247,7 +247,7 @@ const struct fdisk_field *fdisk_label_get_field_by_name( * fdisk_write_disklabel: * @cxt: fdisk context * - * This function wipes the device (if eanbled by fdisk_enable_wipe() and than + * This function wipes the device (if enabled by fdisk_enable_wipe()) and then * it writes in-memory changes to disk. Be careful! * * Returns: 0 on success, otherwise, a corresponding error. @@ -637,7 +637,7 @@ int fdisk_label_is_disabled(const struct fdisk_label *lb) * @ma: maximal number * * The function provides minimal and maximal geometry supported for the label, - * if no range defined by library than returns -ENOSYS. + * if no range defined by library then returns -ENOSYS. * * Since: 2.32 * @@ -662,7 +662,7 @@ int fdisk_label_get_geomrange_sectors(const struct fdisk_label *lb, * @ma: maximal number * * The function provides minimal and maximal geometry supported for the label, - * if no range defined by library than returns -ENOSYS. + * if no range defined by library then returns -ENOSYS. * * Since: 2.32 * @@ -687,7 +687,7 @@ int fdisk_label_get_geomrange_heads(const struct fdisk_label *lb, * @ma: maximal number * * The function provides minimal and maximal geometry supported for the label, - * if no range defined by library than returns -ENOSYS. + * if no range defined by library then returns -ENOSYS. * * Since: 2.32 * diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index dbbd53eaf..3db76c87b 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -30,7 +30,7 @@ * The read functions fdisk_script_read_context() and fdisk_script_read_file() * creates always a new script partition table. The table (see * fdisk_script_get_table()) is possible to modify by standard - * fdisk_table_...() functions and than apply by fdisk_apply_script(). + * fdisk_table_...() functions and then apply by fdisk_apply_script(). * * Note that script API is fully non-interactive and forces libfdisk to not use * standard dialog driven partitioning as we have in fdisk(8). @@ -345,7 +345,7 @@ struct fdisk_table *fdisk_script_get_table(struct fdisk_script *dp) if (!dp->table) /* * Make sure user has access to the same table as script. If - * there is no table than create a new and reuse it later. + * there is no table then create a new one and reuse it later. */ dp->table = fdisk_new_table(); @@ -363,10 +363,10 @@ struct fdisk_table *fdisk_script_get_table(struct fdisk_script *dp) * * This is useful for example to create partition table with the same basic * settings (e.g. label-id, ...) but with different partitions -- just call - * fdisk_script_read_context() to get current settings and than + * fdisk_script_read_context() to get current settings and then * fdisk_script_set_table() to set a different layout. * - * If @tb is NULL than the current script table is unreferenced. + * If @tb is NULL then the current script table is unreferenced. * * Note that script read_ functions (e.g. fdisk_script_read_context()) create * always a new script table. @@ -434,7 +434,7 @@ int fdisk_script_has_force_label(struct fdisk_script *dp) * @cxt: context * * Reads data from the @cxt context (on disk partition table) into the script. - * If the context is no specified than defaults to context used for fdisk_new_script(). + * If the context is not specified then defaults to context used for fdisk_new_script(). * * Return: 0 on success, <0 on error. */ -- cgit v1.2.3-55-g7522 From 08474fde6669d89f5b77653ba9d378fc16e19903 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 8 Aug 2019 10:34:27 +0200 Subject: libfdisk: (script) support shortcuts in the type= field The unnamed-field format supports partition type shortcuts: ",1MiB,L' but for named-field format it requires full type: (mbr) "size=1MiB,type=83" (gpt) "size=1MiB,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4" This patch implements type shortcuts also for named-field format: "size=1MiB,type=L" to make it more user-friendly and unified. Addresses: https://github.com/karelzak/util-linux/issues/837 Signed-off-by: Karel Zak --- disk-utils/sfdisk.8 | 3 ++- libfdisk/src/script.c | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'libfdisk/src/script.c') diff --git a/disk-utils/sfdisk.8 b/disk-utils/sfdisk.8 index ff54760ca..c7630bb37 100644 --- a/disk-utils/sfdisk.8 +++ b/disk-utils/sfdisk.8 @@ -462,7 +462,8 @@ GPT partition UUID. GPT partition name. .TP .BI type= code -A hexadecimal number (without 0x) for an MBR partition, or a GUID for a GPT partition. +A hexadecimal number (without 0x) for an MBR partition, a GUID for a GPT partition, +or a shortcut as for unnamed-fields format. For backward compatibility the \fBId=\fR field has the same meaning. .RE .RE diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 3db76c87b..a28983dba 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -61,6 +61,8 @@ struct fdisk_script { force_label : 1; /* label: specified */ }; +static struct fdisk_parttype *translate_type_shortcuts(struct fdisk_script *dp, char *str); + static void fdisk_script_free_header(struct fdisk_scriptheader *fi) { @@ -1054,8 +1056,11 @@ static int parse_line_nameval(struct fdisk_script *dp, char *s) rc = next_string(&p, &type); if (rc) break; - pa->type = fdisk_label_parse_parttype( - script_get_label(dp), type); + + pa->type = translate_type_shortcuts(dp, type); + if (!pa->type) + pa->type = fdisk_label_parse_parttype( + script_get_label(dp), type); free(type); if (!pa->type) { -- cgit v1.2.3-55-g7522