]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisks/fdisk-menu.c
fdisk: add bsd, dos and sgi menus
[thirdparty/util-linux.git] / fdisks / fdisk-menu.c
CommitLineData
161b0d1a
KZ
1
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <ctype.h>
6#include <stdint.h>
7
8#include "c.h"
9#include "fdisk.h"
10
11struct menu_entry {
12 const char key;
13 const char *title;
14 unsigned int normal : 1,
15 expert : 1,
16 hidden : 1;
17
18 enum fdisk_labeltype exclude;
19};
20
21#define IS_MENU_SEP(e) ((e)->key == '-')
22#define IS_MENU_HID(e) ((e)->hidden)
23
24struct menu {
25 enum fdisk_labeltype label; /* only for this label */
26 enum fdisk_labeltype exclude; /* all labels except this */
27
28 int (*callback)(struct fdisk_context *, struct menu *, int);
29
30 struct menu_entry entries[]; /* NULL terminated array */
31};
32
33struct menu_context {
34 size_t menu_idx; /* the current menu */
35 size_t entry_idx; /* index with in the current menu */
36};
37
38#define MENU_CXT_EMPTY { 0, 0 }
39
40/*
41 * Menu entry macros:
42 * MENU_X* expert mode only
43 * MENU_B* both -- expert + normal mode
44 *
45 * *_E exclude
46 * *_H hidden
47 */
48
49/* separator */
50#define MENU_SEP(t) { .title = t, .key = '-', .normal = 1 }
51#define MENU_XSEP(t) { .title = t, .key = '-', .expert = 1 }
52#define MENU_BSEP(t) { .title = t, .key = '-', .expert = 1, .normal = 1 }
53
54/* entry */
55#define MENU_ENT(k, t) { .title = t, .key = k, .normal = 1 }
56#define MENU_ENT_E(k, t, l) { .title = t, .key = k, .normal = 1, .exclude = l }
57
58#define MENU_XENT(k, t) { .title = t, .key = k, .expert = 1 }
59#define MENU_XENT_H(k, t) { .title = t, .key = k, .expert = 1, .hidden = 1 }
60
61#define MENU_BENT(k, t) { .title = t, .key = k, .expert = 1, .normal = 1 }
62
63
64/* Generic menu */
65struct menu menu_generic = {
66/* .callback = generic_menu_cb,*/
67 .entries = {
6ae5e1e0 68 MENU_BSEP(N_("Generic")),
161b0d1a
KZ
69 MENU_ENT ('d', N_("delete a partition")),
70 MENU_ENT ('l', N_("list known partition types")),
71 MENU_ENT ('n', N_("add a new partition")),
72 MENU_BENT ('p', N_("print the partition table")),
6ae5e1e0 73 MENU_ENT ('t', N_("change a partition type")),
161b0d1a
KZ
74 MENU_ENT ('v', N_("verify the partition table")),
75
6ae5e1e0
KZ
76 MENU_XENT('d', N_("print the raw data of the first sector")),
77
161b0d1a
KZ
78 MENU_SEP(N_("Misc")),
79 MENU_BENT ('m', N_("print this menu")),
80 MENU_ENT_E('u', N_("change display/entry units"), FDISK_DISKLABEL_GPT),
81 MENU_ENT ('x', N_("extra functionality (experts only)")),
82
2a1a67df 83 MENU_BSEP(N_("Save & Exit")),
161b0d1a
KZ
84 MENU_ENT_E('w', N_("write table to disk and exit"), FDISK_DISKLABEL_OSF),
85 MENU_BENT ('q', N_("quit without saving changes")),
86 MENU_XENT ('r', N_("return to main menu")),
87
88 { 0, NULL }
89 }
90};
91
92struct menu menu_createlabel = {
93/* .callback = createlabel_menu_cb, */
94 .exclude = FDISK_DISKLABEL_OSF,
95 .entries = {
96 MENU_SEP(N_("Create a new label")),
97 MENU_ENT('g', N_("create a new empty GPT partition table")),
98 MENU_ENT('G', N_("create a new empty SGI (IRIX) partition table")),
99 MENU_ENT('o', N_("create a new empty DOS partition table")),
100 MENU_ENT('s', N_("create a new empty Sun partition table")),
101
102 /* backward compatibility -- be sensitive to 'g', but don't
103 * print it in the expert menu */
104 MENU_XENT_H('g', N_("create an IRIX (SGI) partition table")),
105 { 0, NULL }
106 }
107};
108
109struct menu menu_gpt = {
110/* .callback = gpt_menu_cb, */
111 .label = FDISK_DISKLABEL_GPT,
112 .entries = {
113 MENU_XSEP(N_("GPT")),
114 MENU_XENT('u', N_("change partition UUID")),
115 MENU_XENT('n', N_("change partition name")),
116 { 0, NULL }
117 }
118};
119
2a1a67df
KZ
120struct menu menu_sun = {
121/* .callback = sun_menu_cb, */
122 .label = FDISK_DISKLABEL_SUN,
123 .entries = {
124 MENU_BSEP(N_("Sun")),
125 MENU_ENT('a', N_("toggle a read only flag")),
126 MENU_ENT('c', N_("toggle the mountable flag")),
127
128 MENU_XENT('a', N_("change number of alternate cylinders")),
129 MENU_XENT('c', N_("change number of cylinders")),
130 MENU_XENT('e', N_("change number of extra sectors per cylinder")),
131 MENU_XENT('h', N_("change number of heads")),
132 MENU_XENT('i', N_("change interleave factor")),
133 MENU_XENT('o', N_("change rotation speed (rpm)")),
134 MENU_XENT('s', N_("change number of sectors/track")),
135 MENU_XENT('y', N_("change number of physical cylinders")),
136 { 0, NULL }
137 }
138};
139
6ae5e1e0
KZ
140struct menu menu_sgi = {
141/* .callback = sgi_menu_cb, */
142 .label = FDISK_DISKLABEL_SGI,
143 .entries = {
144 MENU_SEP(N_("SGI")),
145 MENU_ENT('a', N_("select bootable partition")),
146 MENU_ENT('b', N_("edit bootfile entry")),
147 MENU_ENT('c', N_("select sgi swap partition")),
148 { 0, NULL }
149 }
150};
151
152struct menu menu_dos = {
153/* .callback = dos_menu_cb, */
154 .label = FDISK_DISKLABEL_DOS,
155 .entries = {
156 MENU_BSEP(N_("DOS (MBR)")),
157 MENU_ENT('a', N_("toggle a bootable flag")),
158 MENU_ENT('b', N_("edit nested BSD disklabel")),
159 MENU_ENT('c', N_("toggle the dos compatibility flag")),
160
161 MENU_XENT('b', N_("move beginning of data in a partition")),
162 MENU_XENT('c', N_("change number of cylinders")), MENU_XENT('e', N_("list extended partitions")),
163 MENU_XENT('f', N_("fix partition order")),
164 MENU_XENT('h', N_("change number of heads")),
165 MENU_XENT('i', N_("change the disk identifier")),
166 MENU_XENT('s', N_("change number of sectors/track")),
167 { 0, NULL }
168 }
169};
170
171struct menu menu_bsd = {
172/* .callback = bsd_menu_cb, */
173 .label = FDISK_DISKLABEL_OSF,
174 .entries = {
175 MENU_SEP(N_("BSD")),
176 MENU_ENT('e', N_("edit drive data")),
177 MENU_ENT('i', N_("install bootstrap")),
178 MENU_ENT('s', N_("show complete disklabel")),
179 MENU_ENT('w', N_("write disklabel to disk")),
180#if !defined (__alpha__)
181 MENU_ENT('x', N_("link BSD partition to non-BSD partition")),
182#endif
183 { 0, NULL }
184 }
185};
186
161b0d1a 187static const struct menu *menus[] = {
6ae5e1e0
KZ
188 &menu_gpt,
189 &menu_sun,
190 &menu_sgi,
191 &menu_dos,
192 &menu_bsd,
161b0d1a
KZ
193 &menu_generic,
194 &menu_createlabel,
161b0d1a
KZ
195};
196
197static const struct menu_entry *next_menu_entry(
198 struct fdisk_context *cxt,
199 struct menu_context *mc)
200{
201 while (mc->menu_idx < ARRAY_SIZE(menus)) {
202 const struct menu *m = menus[mc->menu_idx];
203 const struct menu_entry *e = &(m->entries[mc->entry_idx]);
204
205 /* move to the next submenu if there is no more entries */
206 if (e->title == NULL ||
207 (m->label && cxt->label && !(m->label & cxt->label->id))) {
208 mc->menu_idx++;
209 mc->entry_idx = 0;
210 continue;
211 }
212
213 /* is the entry excluded for the current label? */
214 if ((e->exclude && cxt->label &&
215 e->exclude & cxt->label->id) ||
216 /* exclude non-expert entries in expect mode */
217 (e->expert == 0 && fdisk_context_display_details(cxt)) ||
218 /* exclude non-normal entries in normal mode */
219 (e->normal == 0 && !fdisk_context_display_details(cxt))) {
220
221 mc->entry_idx++;
222 continue;
223 }
224 mc->entry_idx++;
225 return e;
226
227 }
228 return NULL;
229}
230
3b4f9f16
KZ
231/* returns @menu and menu entry for then @key */
232static const struct menu_entry *get_fdisk_menu_entry(
233 struct fdisk_context *cxt,
234 int key,
235 const struct menu **menu)
236{
237 struct menu_context mc = MENU_CXT_EMPTY;
238 const struct menu_entry *e;
239
240 while ((e = next_menu_entry(cxt, &mc))) {
241 if (IS_MENU_SEP(e) || e->key != key)
242 continue;
243
244 if (menu)
245 *menu = menus[mc.menu_idx];
246 return e;
247 }
248
249 return NULL;
250}
251
252static int menu_detect_collisions(struct fdisk_context *cxt)
253{
254 struct menu_context mc = MENU_CXT_EMPTY;
255 const struct menu_entry *e, *r;
256
257 while ((e = next_menu_entry(cxt, &mc))) {
258 if (IS_MENU_SEP(e))
259 continue;
260
261 r = get_fdisk_menu_entry(cxt, e->key, NULL);
262 if (!r) {
263 DBG(CONTEXT, dbgprint("warning: not found "
264 "entry for %c", e->key));
265 return -1;
266 }
267 if (r != e) {
268 DBG(CONTEXT, dbgprint("warning: duplicate key '%c'",
269 e->key));
270 DBG(CONTEXT, dbgprint(" %s", e->title));
271 DBG(CONTEXT, dbgprint(" %s", r->title));
272 abort();
273 }
274 }
275
276 return 0;
277}
278
161b0d1a
KZ
279static int print_fdisk_menu(struct fdisk_context *cxt)
280{
281 struct menu_context mc = MENU_CXT_EMPTY;
282 const struct menu_entry *e;
283
3b4f9f16
KZ
284 ON_DBG(CONTEXT, menu_detect_collisions(cxt));
285
161b0d1a
KZ
286 if (fdisk_context_display_details(cxt))
287 printf(_("\nExpert commands:\n"));
288 else
289 printf(_("\nCommands:\n"));
290
291 while ((e = next_menu_entry(cxt, &mc))) {
292 if (IS_MENU_HID(e))
293 continue; /* hidden entry */
294 if (IS_MENU_SEP(e))
295 printf("\n %s\n", _(e->title));
296 else
297 printf(" %c %s\n", e->key, _(e->title));
298 }
299 fputc('\n', stdout);
300
301 return 0;
302}
303
304#ifdef TEST_PROGRAM
305struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt) { return NULL; }
306struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt) { return NULL; }
307struct fdisk_label *fdisk_new_mac_label(struct fdisk_context *cxt) { return NULL; }
308struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt) { return NULL; }
309
310int main(int argc, char *argv[])
311{
312 struct fdisk_context *cxt;
313 int idx = 1;
314
315 fdisk_init_debug(0);
316 cxt = fdisk_new_context();
317
318 if (argc > idx && strcmp(argv[idx], "--expert") == 0) {
319 fdisk_context_enable_details(cxt, 1);
320 idx++;
321 }
322 fdisk_context_switch_label(cxt, argc > idx ? argv[idx] : "gpt");
323
324 print_fdisk_menu(cxt);
325 return 0;
326}
327#endif