From 35ca51182782193f555fbdcb06bb10766550d017 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 30 Nov 2016 12:43:10 +0100 Subject: [PATCH] sfdisk: support empty label use-case By default sfdisk creates partition table when a first partition is specified, otherwise the device is not modified. This force users to create at least one partition. This commit allows to create empty label without partitions if "label: " header line is specified by script. The commit also modifies "New situation:" output to list label name and label identifier. Addresses: https://github.com/karelzak/util-linux/issues/374 Signed-off-by: Karel Zak --- disk-utils/fdisk-list.c | 23 +++++++++++++++-------- disk-utils/fdisk-list.h | 1 + disk-utils/sfdisk.8 | 18 +++++++++++++++++- disk-utils/sfdisk.c | 17 +++++++++++++++++ libfdisk/src/libfdisk.h.in | 1 + libfdisk/src/libfdisk.sym | 5 +++++ libfdisk/src/script.c | 20 +++++++++++++++++++- 7 files changed, 75 insertions(+), 10 deletions(-) diff --git a/disk-utils/fdisk-list.c b/disk-utils/fdisk-list.c index e6b2033..c9560f4 100644 --- a/disk-utils/fdisk-list.c +++ b/disk-utils/fdisk-list.c @@ -34,10 +34,23 @@ static int is_ide_cdrom_or_tape(char *device) return ret; } +void list_disk_identifier(struct fdisk_context *cxt) +{ + struct fdisk_label *lb = fdisk_get_label(cxt, NULL); + char *id = NULL; + + if (fdisk_has_label(cxt)) + fdisk_info(cxt, _("Disklabel type: %s"), + fdisk_label_get_name(lb)); + + if (!fdisk_is_details(cxt) && fdisk_get_disklabel_id(cxt, &id) == 0 && id) { + fdisk_info(cxt, _("Disk identifier: %s"), id); + free(id); + } +} void list_disk_geometry(struct fdisk_context *cxt) { - char *id = NULL; struct fdisk_label *lb = fdisk_get_label(cxt, NULL); uint64_t bytes = fdisk_get_nsectors(cxt) * fdisk_get_sector_size(cxt); char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE @@ -71,14 +84,8 @@ void list_disk_geometry(struct fdisk_context *cxt) if (fdisk_get_alignment_offset(cxt)) fdisk_info(cxt, _("Alignment offset: %lu bytes"), fdisk_get_alignment_offset(cxt)); - if (fdisk_has_label(cxt)) - fdisk_info(cxt, _("Disklabel type: %s"), - fdisk_label_get_name(lb)); - if (!fdisk_is_details(cxt) && fdisk_get_disklabel_id(cxt, &id) == 0 && id) { - fdisk_info(cxt, _("Disk identifier: %s"), id); - free(id); - } + list_disk_identifier(cxt); } void list_disklabel(struct fdisk_context *cxt) diff --git a/disk-utils/fdisk-list.h b/disk-utils/fdisk-list.h index eddab92..4ed5c25 100644 --- a/disk-utils/fdisk-list.h +++ b/disk-utils/fdisk-list.h @@ -2,6 +2,7 @@ #define UTIL_LINUX_FDISK_LIST_H extern void list_disklabel(struct fdisk_context *cxt); +extern void list_disk_identifier(struct fdisk_context *cxt); extern void list_disk_geometry(struct fdisk_context *cxt); extern void list_freespace(struct fdisk_context *cxt); diff --git a/disk-utils/sfdisk.8 b/disk-utils/sfdisk.8 index fcde872..efe4a86 100644 --- a/disk-utils/sfdisk.8 +++ b/disk-utils/sfdisk.8 @@ -212,7 +212,10 @@ Deprecated option. Only the sector unit is supported. .BR \-X , " \-\-label " \fItype Specify the disk label type (e.g. \fBdos\fR, \fBgpt\fR, ...). If this option is not given, then \fBsfdisk\fR defaults to the existing label, but if there -is no label on the device yet, then the type defaults to \fBdos\fR. +is no label on the device yet, then the type defaults to \fBdos\fR. The default +or the current label may be overwritten by the "label: " script header +line. The option \fB\-\-label\fR does not force \fBsfdisk\fR to create empty +disk label (see the \fBEMPTY DISK LABEL\fR section below). .TP .BR \-Y , " \-\-label\-nested " \fItype Force editing of a nested disk label. The primary disk label has to exist already. @@ -404,6 +407,19 @@ For backward compatibility the \fBId=\fR field has the same meaning. .RE .RE +.SH "EMPTY DISK LABEL" +.B sfdisk +does not create partition table without partitions by default. The lines with +partitions are expected in the script by default. The empty partition table has +to be explicitly requested by "label: " script header line without any +partitions lines. For example: +.RS +.sp +.B "echo 'label: gpt' | sfdisk /dev/sdb" +.sp +.RE +creates empty GPT partition table. Note that the \fB\-\-append\fR disables this feature. + .SH "BACKING UP THE PARTITION TABLE" It is recommended to save the layout of your devices. .B sfdisk diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c index 10307ad..2d65974 100644 --- a/disk-utils/sfdisk.c +++ b/disk-utils/sfdisk.c @@ -1766,8 +1766,25 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv) } } while (1); + /* create empty disk label if label, but no partition specified */ + if (rc == SFDISK_DONE_EOF && created == 0 + && fdisk_script_has_force_label(dp) == 1 + && fdisk_table_get_nents(tb) == 0 + && fdisk_script_get_header(dp, "label")) { + + int xrc = fdisk_apply_script_headers(sf->cxt, dp); + created = !xrc; + if (xrc) { + fdisk_warnx(sf->cxt, _( + "Failed to apply script headers, " + "disk label not created.")); + rc = SFDISK_DONE_ABORT; + } + } + if (!sf->quiet && rc != SFDISK_DONE_ABORT) { fdisk_info(sf->cxt, _("\nNew situation:")); + list_disk_identifier(sf->cxt); list_disklabel(sf->cxt); } diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in index 9154f5b..59cce19 100644 --- a/libfdisk/src/libfdisk.h.in +++ b/libfdisk/src/libfdisk.h.in @@ -642,6 +642,7 @@ const char *fdisk_script_get_header(struct fdisk_script *dp, const char *name); int fdisk_script_set_header(struct fdisk_script *dp, const char *name, const char *data); struct fdisk_table *fdisk_script_get_table(struct fdisk_script *dp); int fdisk_script_get_nlines(struct fdisk_script *dp); +int fdisk_script_has_force_label(struct fdisk_script *dp); int fdisk_script_set_userdata(struct fdisk_script *dp, void *data); void *fdisk_script_get_userdata(struct fdisk_script *dp); diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index 02cd7a8..d6d4ac5 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -274,3 +274,8 @@ FDISK_2.29 { fdisk_labelitem_is_number; fdisk_gpt_set_npartitions; } FDISK_2.28; + + +FDISK_2.30 { + fdisk_script_has_force_label; +} FDISK_2.29; diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index ae7e99a..0d1f260 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -36,7 +36,8 @@ struct fdisk_script { size_t nlines; struct fdisk_label *label; - unsigned int json : 1; /* JSON output */ + unsigned int json : 1, /* JSON output */ + force_label : 1; /* label: specified */ }; @@ -354,6 +355,22 @@ int fdisk_script_get_nlines(struct fdisk_script *dp) } /** + * fdisk_script_has_force_label: + * @dp: script + * + * Note that fdisk_script_set_header(dp, "label", name) does not modify + * force_label status. The label has to be specified by script. + * + * Returns: true if "label: " has been parsed. + */ +int fdisk_script_has_force_label(struct fdisk_script *dp) +{ + assert(dp); + return dp->force_label; +} + + +/** * fdisk_script_read_context: * @dp: script * @cxt: context @@ -706,6 +723,7 @@ static int parse_line_header(struct fdisk_script *dp, char *s) if (strcmp(name, "label") == 0) { if (dp->cxt && !fdisk_get_label(dp->cxt, value)) goto done; /* unknown label name */ + dp->force_label = 1; } else if (strcmp(name, "unit") == 0) { if (strcmp(value, "sectors") != 0) goto done; /* only "sectors" supported */ -- 2.10.2