summarylogtreecommitdiffstats
path: root/0001-sfdisk-support-empty-label-use-case.patch
blob: 29ab44d9d7b94d2445e869a9860a8e07da6d4297 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
From 35ca51182782193f555fbdcb06bb10766550d017 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
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:
<name>" 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 <kzak@redhat.com>
---
 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: <name>" 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: <name>" 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: <name> 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: <name>" 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