]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisks/fdisk-menu.c
libfdisk: support nested MBR
[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"
9f280903 10#include "pt-sun.h"
f02fecd1
KZ
11#include "pt-mbr.h"
12
161b0d1a 13struct menu_entry {
7e937b77
KZ
14 const char key; /* command key */
15 const char *title; /* help string */
16 unsigned int normal : 1, /* normal mode */
17 expert : 1, /* expert mode */
18 hidden : 1; /* be sensitive for this key,
19 but don't print it in help */
161b0d1a 20
7e937b77
KZ
21 enum fdisk_labeltype label; /* only for this label */
22 enum fdisk_labeltype exclude; /* all labels except this */
161b0d1a
KZ
23};
24
25#define IS_MENU_SEP(e) ((e)->key == '-')
26#define IS_MENU_HID(e) ((e)->hidden)
27
28struct menu {
29 enum fdisk_labeltype label; /* only for this label */
30 enum fdisk_labeltype exclude; /* all labels except this */
31
a47fec81 32 int (*callback)(struct fdisk_context **,
a410f8df
KZ
33 const struct menu *,
34 const struct menu_entry *);
161b0d1a
KZ
35
36 struct menu_entry entries[]; /* NULL terminated array */
37};
38
39struct menu_context {
40 size_t menu_idx; /* the current menu */
41 size_t entry_idx; /* index with in the current menu */
42};
43
44#define MENU_CXT_EMPTY { 0, 0 }
8e40a677 45#define DECLARE_MENU_CB(x) \
a47fec81 46 static int x(struct fdisk_context **, \
8e40a677
KZ
47 const struct menu *, \
48 const struct menu_entry *)
161b0d1a 49
8e40a677 50DECLARE_MENU_CB(gpt_menu_cb);
9f280903 51DECLARE_MENU_CB(sun_menu_cb);
aae727f2 52DECLARE_MENU_CB(sgi_menu_cb);
8e40a677 53DECLARE_MENU_CB(geo_menu_cb);
f02fecd1 54DECLARE_MENU_CB(dos_menu_cb);
b529ea2a 55DECLARE_MENU_CB(bsd_menu_cb);
b3ac22ef 56DECLARE_MENU_CB(createlabel_menu_cb);
89309968 57DECLARE_MENU_CB(generic_menu_cb);
b9e94cd7 58
161b0d1a
KZ
59/*
60 * Menu entry macros:
61 * MENU_X* expert mode only
62 * MENU_B* both -- expert + normal mode
63 *
7e937b77
KZ
64 * *_E exclude this label
65 * *_H hidden
66 * *_L only for this label
161b0d1a
KZ
67 */
68
69/* separator */
70#define MENU_SEP(t) { .title = t, .key = '-', .normal = 1 }
71#define MENU_XSEP(t) { .title = t, .key = '-', .expert = 1 }
72#define MENU_BSEP(t) { .title = t, .key = '-', .expert = 1, .normal = 1 }
73
74/* entry */
75#define MENU_ENT(k, t) { .title = t, .key = k, .normal = 1 }
76#define MENU_ENT_E(k, t, l) { .title = t, .key = k, .normal = 1, .exclude = l }
7e937b77 77#define MENU_ENT_L(k, t, l) { .title = t, .key = k, .normal = 1, .label = l }
161b0d1a
KZ
78
79#define MENU_XENT(k, t) { .title = t, .key = k, .expert = 1 }
80#define MENU_XENT_H(k, t) { .title = t, .key = k, .expert = 1, .hidden = 1 }
81
82#define MENU_BENT(k, t) { .title = t, .key = k, .expert = 1, .normal = 1 }
27ddd4f1 83#define MENU_BENT_E(k, t, l) { .title = t, .key = k, .expert = 1, .normal = 1, .exclude = l }
161b0d1a
KZ
84
85
86/* Generic menu */
87struct menu menu_generic = {
89309968 88 .callback = generic_menu_cb,
161b0d1a 89 .entries = {
6ae5e1e0 90 MENU_BSEP(N_("Generic")),
161b0d1a
KZ
91 MENU_ENT ('d', N_("delete a partition")),
92 MENU_ENT ('l', N_("list known partition types")),
93 MENU_ENT ('n', N_("add a new partition")),
94 MENU_BENT ('p', N_("print the partition table")),
6ae5e1e0 95 MENU_ENT ('t', N_("change a partition type")),
27ddd4f1 96 MENU_BENT_E('v', N_("verify the partition table"), FDISK_DISKLABEL_BSD),
161b0d1a 97
e916600f
KZ
98 MENU_XENT('d', N_("print the raw data of the first sector from the device")),
99 MENU_XENT('D', N_("print the raw data of the disklabel from the device")),
6ae5e1e0 100
161b0d1a
KZ
101 MENU_SEP(N_("Misc")),
102 MENU_BENT ('m', N_("print this menu")),
103 MENU_ENT_E('u', N_("change display/entry units"), FDISK_DISKLABEL_GPT),
22ddf547 104 MENU_ENT_E('x', N_("extra functionality (experts only)"), FDISK_DISKLABEL_BSD),
161b0d1a 105
2a1a67df 106 MENU_BSEP(N_("Save & Exit")),
22ddf547
KZ
107 MENU_ENT_E('w', N_("write table to disk and exit"), FDISK_DISKLABEL_BSD),
108 MENU_ENT_L('w', N_("write table to disk"), FDISK_DISKLABEL_BSD),
161b0d1a
KZ
109 MENU_BENT ('q', N_("quit without saving changes")),
110 MENU_XENT ('r', N_("return to main menu")),
b5729667 111 MENU_ENT_L('r', N_("return to main menu"), FDISK_DISKLABEL_BSD),
161b0d1a
KZ
112
113 { 0, NULL }
114 }
115};
116
117struct menu menu_createlabel = {
b3ac22ef 118 .callback = createlabel_menu_cb,
22ddf547 119 .exclude = FDISK_DISKLABEL_BSD,
161b0d1a
KZ
120 .entries = {
121 MENU_SEP(N_("Create a new label")),
122 MENU_ENT('g', N_("create a new empty GPT partition table")),
123 MENU_ENT('G', N_("create a new empty SGI (IRIX) partition table")),
124 MENU_ENT('o', N_("create a new empty DOS partition table")),
125 MENU_ENT('s', N_("create a new empty Sun partition table")),
126
127 /* backward compatibility -- be sensitive to 'g', but don't
128 * print it in the expert menu */
129 MENU_XENT_H('g', N_("create an IRIX (SGI) partition table")),
130 { 0, NULL }
131 }
132};
133
be9ba6f3 134struct menu menu_geo = {
8e40a677 135 .callback = geo_menu_cb,
22ddf547 136 .exclude = FDISK_DISKLABEL_GPT | FDISK_DISKLABEL_BSD,
be9ba6f3
KZ
137 .entries = {
138 MENU_XSEP(N_("Geometry")),
139 MENU_XENT('c', N_("change number of cylinders")),
140 MENU_XENT('h', N_("change number of heads")),
141 MENU_XENT('s', N_("change number of sectors/track")),
142 { 0, NULL }
143 }
144};
145
161b0d1a 146struct menu menu_gpt = {
b9e94cd7 147 .callback = gpt_menu_cb,
161b0d1a
KZ
148 .label = FDISK_DISKLABEL_GPT,
149 .entries = {
150 MENU_XSEP(N_("GPT")),
35b1f0a4 151 MENU_XENT('i', N_("change disk GUID")),
161b0d1a 152 MENU_XENT('n', N_("change partition name")),
35b1f0a4
KZ
153 MENU_XENT('u', N_("change partition UUID")),
154
161b0d1a
KZ
155 { 0, NULL }
156 }
157};
158
2a1a67df 159struct menu menu_sun = {
9f280903 160 .callback = sun_menu_cb,
2a1a67df
KZ
161 .label = FDISK_DISKLABEL_SUN,
162 .entries = {
163 MENU_BSEP(N_("Sun")),
aaa43826 164 MENU_ENT('a', N_("toggle the read-only flag")),
2a1a67df
KZ
165 MENU_ENT('c', N_("toggle the mountable flag")),
166
167 MENU_XENT('a', N_("change number of alternate cylinders")),
2a1a67df 168 MENU_XENT('e', N_("change number of extra sectors per cylinder")),
2a1a67df
KZ
169 MENU_XENT('i', N_("change interleave factor")),
170 MENU_XENT('o', N_("change rotation speed (rpm)")),
2a1a67df
KZ
171 MENU_XENT('y', N_("change number of physical cylinders")),
172 { 0, NULL }
173 }
174};
175
6ae5e1e0 176struct menu menu_sgi = {
aae727f2 177 .callback = sgi_menu_cb,
6ae5e1e0
KZ
178 .label = FDISK_DISKLABEL_SGI,
179 .entries = {
180 MENU_SEP(N_("SGI")),
181 MENU_ENT('a', N_("select bootable partition")),
182 MENU_ENT('b', N_("edit bootfile entry")),
183 MENU_ENT('c', N_("select sgi swap partition")),
aae727f2 184 MENU_ENT('i', N_("create SGI info")),
6ae5e1e0
KZ
185 { 0, NULL }
186 }
187};
188
189struct menu menu_dos = {
f02fecd1 190 .callback = dos_menu_cb,
6ae5e1e0
KZ
191 .label = FDISK_DISKLABEL_DOS,
192 .entries = {
193 MENU_BSEP(N_("DOS (MBR)")),
194 MENU_ENT('a', N_("toggle a bootable flag")),
195 MENU_ENT('b', N_("edit nested BSD disklabel")),
196 MENU_ENT('c', N_("toggle the dos compatibility flag")),
197
198 MENU_XENT('b', N_("move beginning of data in a partition")),
be9ba6f3 199 MENU_XENT('e', N_("list extended partitions")),
6ae5e1e0 200 MENU_XENT('f', N_("fix partition order")),
6ae5e1e0 201 MENU_XENT('i', N_("change the disk identifier")),
6ae5e1e0
KZ
202 { 0, NULL }
203 }
204};
205
206struct menu menu_bsd = {
b529ea2a 207 .callback = bsd_menu_cb,
22ddf547 208 .label = FDISK_DISKLABEL_BSD,
6ae5e1e0
KZ
209 .entries = {
210 MENU_SEP(N_("BSD")),
211 MENU_ENT('e', N_("edit drive data")),
212 MENU_ENT('i', N_("install bootstrap")),
213 MENU_ENT('s', N_("show complete disklabel")),
6ae5e1e0 214 MENU_ENT('x', N_("link BSD partition to non-BSD partition")),
6ae5e1e0
KZ
215 { 0, NULL }
216 }
217};
218
161b0d1a 219static const struct menu *menus[] = {
6ae5e1e0
KZ
220 &menu_gpt,
221 &menu_sun,
222 &menu_sgi,
223 &menu_dos,
224 &menu_bsd,
be9ba6f3 225 &menu_geo,
161b0d1a
KZ
226 &menu_generic,
227 &menu_createlabel,
161b0d1a
KZ
228};
229
230static const struct menu_entry *next_menu_entry(
231 struct fdisk_context *cxt,
232 struct menu_context *mc)
233{
234 while (mc->menu_idx < ARRAY_SIZE(menus)) {
235 const struct menu *m = menus[mc->menu_idx];
236 const struct menu_entry *e = &(m->entries[mc->entry_idx]);
237
be9ba6f3 238 /* no more entries */
161b0d1a 239 if (e->title == NULL ||
be9ba6f3
KZ
240 /* menu wanted for specified labels only */
241 (m->label && cxt->label && !(m->label & cxt->label->id)) ||
242 /* menu excluded for specified labels */
243 (m->exclude && cxt->label && (m->exclude & cxt->label->id))) {
161b0d1a
KZ
244 mc->menu_idx++;
245 mc->entry_idx = 0;
246 continue;
247 }
248
7e937b77
KZ
249 /* excluded for the current label */
250 if ((e->exclude && cxt->label && e->exclude & cxt->label->id) ||
251 /* entry wanted for specified labels only */
252 (e->label && cxt->label && !(e->label & cxt->label->id)) ||
161b0d1a
KZ
253 /* exclude non-expert entries in expect mode */
254 (e->expert == 0 && fdisk_context_display_details(cxt)) ||
255 /* exclude non-normal entries in normal mode */
256 (e->normal == 0 && !fdisk_context_display_details(cxt))) {
257
258 mc->entry_idx++;
259 continue;
260 }
261 mc->entry_idx++;
262 return e;
263
264 }
265 return NULL;
266}
267
3b4f9f16
KZ
268/* returns @menu and menu entry for then @key */
269static const struct menu_entry *get_fdisk_menu_entry(
270 struct fdisk_context *cxt,
271 int key,
272 const struct menu **menu)
273{
274 struct menu_context mc = MENU_CXT_EMPTY;
275 const struct menu_entry *e;
276
277 while ((e = next_menu_entry(cxt, &mc))) {
278 if (IS_MENU_SEP(e) || e->key != key)
279 continue;
280
281 if (menu)
282 *menu = menus[mc.menu_idx];
283 return e;
284 }
285
286 return NULL;
287}
288
289static int menu_detect_collisions(struct fdisk_context *cxt)
290{
291 struct menu_context mc = MENU_CXT_EMPTY;
292 const struct menu_entry *e, *r;
293
294 while ((e = next_menu_entry(cxt, &mc))) {
295 if (IS_MENU_SEP(e))
296 continue;
297
298 r = get_fdisk_menu_entry(cxt, e->key, NULL);
299 if (!r) {
36050e70 300 DBG(FRONTEND, dbgprint("warning: not found "
3b4f9f16
KZ
301 "entry for %c", e->key));
302 return -1;
303 }
304 if (r != e) {
36050e70 305 DBG(FRONTEND, dbgprint("warning: duplicate key '%c'",
3b4f9f16 306 e->key));
818d7924
KZ
307 DBG(FRONTEND, dbgprint(" : %s", e->title));
308 DBG(FRONTEND, dbgprint(" : %s", r->title));
3b4f9f16
KZ
309 abort();
310 }
311 }
312
313 return 0;
314}
315
1f75d1ce 316static int print_fdisk_menu(struct fdisk_context *cxt)
161b0d1a
KZ
317{
318 struct menu_context mc = MENU_CXT_EMPTY;
319 const struct menu_entry *e;
320
36050e70 321 ON_DBG(FRONTEND, menu_detect_collisions(cxt));
3b4f9f16 322
161b0d1a 323 if (fdisk_context_display_details(cxt))
39f01b7b 324 printf(_("\nHelp (expert commands):\n"));
161b0d1a 325 else
39f01b7b 326 printf(_("\nHelp:\n"));
161b0d1a
KZ
327
328 while ((e = next_menu_entry(cxt, &mc))) {
329 if (IS_MENU_HID(e))
330 continue; /* hidden entry */
80a1712f
KZ
331 if (IS_MENU_SEP(e)) {
332 color_enable(UL_COLOR_BOLD);
161b0d1a 333 printf("\n %s\n", _(e->title));
80a1712f
KZ
334 color_disable();
335 } else
161b0d1a
KZ
336 printf(" %c %s\n", e->key, _(e->title));
337 }
338 fputc('\n', stdout);
339
340 return 0;
341}
342
a410f8df
KZ
343/* Asks for command, verify the key and perform the command or
344 * returns the command key if no callback for the command is
345 * implemented.
346 *
a47fec81
KZ
347 * Note that this function might exchange the context pointer to
348 * switch to another (nested) context.
349 *
a410f8df
KZ
350 * Returns: <0 on error
351 * 0 on success (the command performed)
352 * >0 if no callback (then returns the key)
353 */
a47fec81 354int process_fdisk_menu(struct fdisk_context **cxt0)
a410f8df 355{
a47fec81 356 struct fdisk_context *cxt = *cxt0;
a410f8df
KZ
357 const struct menu_entry *ent;
358 const struct menu *menu;
359 int key, rc;
360 const char *prompt;
361 char buf[BUFSIZ];
362
363 if (fdisk_context_display_details(cxt))
364 prompt = _("Expert command (m for help): ");
365 else
366 prompt = _("Command (m for help): ");
367
368 fputc('\n',stdout);
369 rc = get_user_reply(cxt, prompt, buf, sizeof(buf));
370 if (rc)
371 return rc;
372
373 key = buf[0];
374 ent = get_fdisk_menu_entry(cxt, key, &menu);
375 if (!ent) {
376 fdisk_warnx(cxt, _("%c: unknown command"), key);
377 return -EINVAL;
378 }
379
a47fec81 380 rc = 0;
36050e70 381 DBG(FRONTEND, dbgprint("selected: key=%c, entry='%s'",
a410f8df 382 key, ent->title));
a410f8df
KZ
383
384 /* menu has implemented callback, use it */
27ddd4f1 385 if (menu->callback)
a47fec81
KZ
386 rc = menu->callback(cxt0, menu, ent);
387 else {
27ddd4f1
KZ
388 DBG(FRONTEND, dbgprint("no callback for key '%c'", key));
389 rc = -EINVAL;
a47fec81 390 }
a410f8df 391
a47fec81
KZ
392 DBG(FRONTEND, dbgprint("process menu done [rc=%d]", rc));
393 return rc;
a410f8df
KZ
394}
395
89309968
KZ
396/*
397 * Basic fdisk actions
398 */
399static int generic_menu_cb(struct fdisk_context **cxt0,
400 const struct menu *menu __attribute__((__unused__)),
401 const struct menu_entry *ent)
402{
403 struct fdisk_context *cxt = *cxt0;
404 int rc = 0;
27ddd4f1 405 size_t n;
89309968 406
27ddd4f1 407 /* actions shared between expert and normal mode */
89309968 408 switch (ent->key) {
89309968
KZ
409 case 'p':
410 list_disk_geometry(cxt);
411 rc = fdisk_list_disklabel(cxt);
412 break;
df4bfa97
KZ
413 case 'w':
414 rc = fdisk_write_disklabel(cxt);
415 if (rc)
fd56121a 416 err(EXIT_FAILURE, _("failed to write disklabel"));
df4bfa97
KZ
417 if (cxt->parent)
418 break; /* nested PT, don't leave */
419 fdisk_info(cxt, _("The partition table has been altered."));
a57639e1
KZ
420 rc = fdisk_reread_partition_table(cxt);
421 if (!rc)
422 rc = fdisk_context_deassign_device(cxt);
423 /* fallthrough */
89309968
KZ
424 case 'q':
425 fdisk_free_context(cxt);
a57639e1
KZ
426 fputc('\n', stdout);
427 exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
27ddd4f1
KZ
428 case 'm':
429 rc = print_fdisk_menu(cxt);
430 break;
89309968
KZ
431 case 'v':
432 rc = fdisk_verify_disklabel(cxt);
433 break;
27ddd4f1
KZ
434 }
435
436 /* expert mode */
437 if (ent->expert) {
438 switch (ent->key) {
439 case 'd':
e916600f
KZ
440 dump_firstsector(cxt);
441 break;
442 case 'D':
443 dump_disklabel(cxt);
27ddd4f1
KZ
444 break;
445 case 'r':
446 rc = fdisk_context_enable_details(cxt, 0);
447 break;
448 }
449 return rc;
450 }
451
452 /* normal mode */
453 switch (ent->key) {
454 case 'd':
455 rc = fdisk_ask_partnum(cxt, &n, FALSE);
456 if (!rc)
457 rc = fdisk_delete_partition(cxt, n);
458 if (rc)
e39966c6 459 fdisk_warnx(cxt, _("Could not delete partition %d"), (int) n + 1);
27ddd4f1 460 else
e39966c6 461 fdisk_info(cxt, _("Partition %d has been deleted."), (int) n + 1);
27ddd4f1
KZ
462 break;
463 case 'l':
464 list_partition_types(cxt);
465 break;
466 case 'n':
467 rc = fdisk_add_partition(cxt, NULL);
468 break;
469 case 't':
470 change_partition_type(cxt);
471 break;
472 case 'u':
473 fdisk_context_set_unit(cxt,
474 fdisk_context_use_cylinders(cxt) ? "sectors" :
475 "cylinders");
476 if (fdisk_context_use_cylinders(cxt))
477 fdisk_info(cxt, _("Changing display/entry units to cylinders (DEPRECATED!)."));
478 else
479 fdisk_info(cxt, _("Changing display/entry units to sectors."));
480 break;
481 case 'x':
482 fdisk_context_enable_details(cxt, 1);
483 break;
484 case 'r':
485 /* return from nested PT (e.g. BSD) */
486 if (cxt->parent) {
b5729667 487 *cxt0 = cxt->parent;
27ddd4f1 488
fd56121a 489 fdisk_info(cxt, _("Leaving nested disklabel."));
27ddd4f1 490 fdisk_free_context(cxt);
b5729667 491 cxt = *cxt0;
27ddd4f1
KZ
492 }
493 break;
89309968 494 }
27ddd4f1 495
89309968
KZ
496 return rc;
497}
498
8e40a677 499
b9e94cd7
KZ
500/*
501 * This is fdisk frontend for GPT specific libfdisk functions that
502 * are not expported by generic libfdisk API.
503 */
a47fec81 504static int gpt_menu_cb(struct fdisk_context **cxt0,
b9e94cd7
KZ
505 const struct menu *menu __attribute__((__unused__)),
506 const struct menu_entry *ent)
507{
a47fec81 508 struct fdisk_context *cxt = *cxt0;
b9e94cd7
KZ
509 size_t n;
510 int rc;
511
512 assert(cxt);
513 assert(ent);
514 assert(fdisk_is_disklabel(cxt, GPT));
515
36050e70 516 DBG(FRONTEND, dbgprint("enter GPT menu"));
b9e94cd7 517
35b1f0a4
KZ
518 if (ent->key == 'i')
519 return fdisk_set_disklabel_id(cxt);
520
b9e94cd7
KZ
521 rc = fdisk_ask_partnum(cxt, &n, FALSE);
522 if (rc)
523 return rc;
524
525 switch(ent->key) {
526 case 'u':
527 rc = fdisk_gpt_partition_set_uuid(cxt, n);
528 break;
529 case 'n':
1054699c 530 rc = fdisk_gpt_partition_set_name(cxt, n);
b9e94cd7
KZ
531 break;
532 }
533 return rc;
534}
535
f02fecd1
KZ
536
537/*
538 * This is fdisk frontend for MBR specific libfdisk functions that
539 * are not expported by generic libfdisk API.
540 */
a47fec81 541static int dos_menu_cb(struct fdisk_context **cxt0,
f02fecd1
KZ
542 const struct menu *menu __attribute__((__unused__)),
543 const struct menu_entry *ent)
544{
a47fec81 545 struct fdisk_context *cxt = *cxt0;
f02fecd1
KZ
546 int rc = 0;
547
a47fec81
KZ
548 DBG(FRONTEND, dbgprint("enter DOS menu"));
549
f02fecd1
KZ
550 if (!ent->expert) {
551 switch (ent->key) {
552 case 'a':
553 {
554 size_t n;
555 rc = fdisk_ask_partnum(cxt, &n, FALSE);
556 if (!rc)
557 rc = fdisk_partition_toggle_flag(cxt, n, DOS_FLAG_ACTIVE);
558 break;
559 }
560 case 'b':
561 {
562 struct fdisk_context *bsd
563 = fdisk_new_nested_context(cxt, "bsd");
818d7924
KZ
564 if (!bsd)
565 return -ENOMEM;
566 if (!fdisk_dev_has_disklabel(bsd))
567 rc = fdisk_create_disklabel(bsd, "bsd");
a47fec81
KZ
568 if (rc)
569 fdisk_free_context(bsd);
27ddd4f1 570 else {
a47fec81 571 *cxt0 = cxt = bsd;
aaa43826 572 fdisk_info(cxt, _("Entering nested BSD disklabel."));
27ddd4f1 573 }
f02fecd1
KZ
574 break;
575 }
576 case 'c':
577 toggle_dos_compatibility_flag(cxt);
578 break;
579 }
580 return rc;
581 }
582
583 /* expert mode */
584 switch (ent->key) {
585 case 'b':
586 {
587 size_t n;
588 rc = fdisk_ask_partnum(cxt, &n, FALSE);
589 if (!rc)
f8ad3899 590 rc = fdisk_dos_move_begin(cxt, n);
f02fecd1
KZ
591 break;
592 }
593 case 'e':
594 rc = fdisk_dos_list_extended(cxt);
595 break;
596 case 'f':
f8ad3899 597 rc = fdisk_dos_fix_order(cxt);
f02fecd1
KZ
598 break;
599 case 'i':
600 rc = fdisk_set_disklabel_id(cxt);
601 break;
602 }
603 return rc;
604}
605
a47fec81 606static int sun_menu_cb(struct fdisk_context **cxt0,
9f280903
KZ
607 const struct menu *menu __attribute__((__unused__)),
608 const struct menu_entry *ent)
609{
a47fec81 610 struct fdisk_context *cxt = *cxt0;
9f280903
KZ
611 int rc = 0;
612
a47fec81
KZ
613 DBG(FRONTEND, dbgprint("enter SUN menu"));
614
9f280903
KZ
615 assert(cxt);
616 assert(ent);
617 assert(fdisk_is_disklabel(cxt, SUN));
618
619 DBG(FRONTEND, dbgprint("enter SUN menu"));
620
621 /* normal mode */
622 if (!ent->expert) {
623 size_t n;
624
625 rc = fdisk_ask_partnum(cxt, &n, FALSE);
626 if (rc)
627 return rc;
628 switch (ent->key) {
629 case 'a':
630 rc = fdisk_partition_toggle_flag(cxt, n, SUN_FLAG_RONLY);
631 break;
632 case 'c':
633 rc = fdisk_partition_toggle_flag(cxt, n, SUN_FLAG_UNMNT);
634 break;
635 }
636 return rc;
637 }
638
639 /* expert mode */
640 switch (ent->key) {
641 case 'a':
642 rc = fdisk_sun_set_alt_cyl(cxt);
643 break;
644 case 'e':
645 rc = fdisk_sun_set_xcyl(cxt);
646 break;
647 case 'i':
648 rc = fdisk_sun_set_ilfact(cxt);
649 break;
650 case 'o':
651 rc = fdisk_sun_set_rspeed(cxt);
652 break;
653 case 'y':
654 rc = fdisk_sun_set_pcylcount(cxt);
655 break;
656 }
657 return rc;
658}
659
aae727f2
KZ
660static int sgi_menu_cb(struct fdisk_context **cxt0,
661 const struct menu *menu __attribute__((__unused__)),
662 const struct menu_entry *ent)
663{
664 struct fdisk_context *cxt = *cxt0;
665 int rc = -EINVAL;
666 size_t n = 0;
667
668 DBG(FRONTEND, dbgprint("enter SGI menu"));
669
670 assert(cxt);
671 assert(ent);
672 assert(fdisk_is_disklabel(cxt, SGI));
673
674 if (ent->expert)
675 return rc;
676
677 switch (ent->key) {
678 case 'a':
679 rc = fdisk_ask_partnum(cxt, &n, FALSE);
680 if (!rc)
681 rc = fdisk_partition_toggle_flag(cxt, n, SGI_FLAG_BOOT);
682 break;
683 case 'b':
ac84272d 684 fdisk_sgi_set_bootfile(cxt);
aae727f2
KZ
685 break;
686 case 'c':
687 rc = fdisk_ask_partnum(cxt, &n, FALSE);
688 if (!rc)
689 rc = fdisk_partition_toggle_flag(cxt, n, SGI_FLAG_SWAP);
690 break;
691 case 'i':
ac84272d 692 rc = fdisk_sgi_create_info(cxt);
aae727f2
KZ
693 break;
694 }
695
696 return rc;
697}
698
b529ea2a
KZ
699/*
700 * This is fdisk frontend for BSD specific libfdisk functions that
701 * are not expported by generic libfdisk API.
702 */
703static int bsd_menu_cb(struct fdisk_context **cxt0,
704 const struct menu *menu __attribute__((__unused__)),
705 const struct menu_entry *ent)
706{
707 struct fdisk_context *cxt = *cxt0;
e563f055 708 int rc = 0, org;
b529ea2a
KZ
709
710 assert(cxt);
711 assert(ent);
22ddf547 712 assert(fdisk_is_disklabel(cxt, BSD));
b529ea2a
KZ
713
714 DBG(FRONTEND, dbgprint("enter BSD menu"));
715
716 switch(ent->key) {
717 case 'e':
718 rc = fdisk_bsd_edit_disklabel(cxt);
719 break;
720 case 'i':
721 rc = fdisk_bsd_write_bootstrap(cxt);
722 break;
723 case 's':
e563f055
KZ
724 org = fdisk_context_display_details(cxt);
725
726 fdisk_context_enable_details(cxt, 1);
727 fdisk_list_disklabel(cxt);
728 fdisk_context_enable_details(cxt, org);
b529ea2a
KZ
729 break;
730 case 'x':
731 rc = fdisk_bsd_link_partition(cxt);
732 break;
733 }
734 return rc;
735}
736
8e40a677 737/* C/H/S commands */
a47fec81 738static int geo_menu_cb(struct fdisk_context **cxt0,
8e40a677
KZ
739 const struct menu *menu __attribute__((__unused__)),
740 const struct menu_entry *ent)
741{
a47fec81 742 struct fdisk_context *cxt = *cxt0;
8e40a677
KZ
743 int rc = -EINVAL;
744 uintmax_t c = 0, h = 0, s = 0;
745
a47fec81
KZ
746 DBG(FRONTEND, dbgprint("enter GEO menu"));
747
8e40a677
KZ
748 assert(cxt);
749 assert(ent);
750
751 switch (ent->key) {
752 case 'c':
753 rc = fdisk_ask_number(cxt, 1, cxt->geom.cylinders,
754 1048576, _("Number of cylinders"), &c);
755 break;
756 case 'h':
757 rc = fdisk_ask_number(cxt, 1, cxt->geom.heads,
758 256, _("Number of heads"), &h);
759 break;
760 case 's':
761 rc = fdisk_ask_number(cxt, 1, cxt->geom.sectors,
762 63, _("Number of sectors"), &s);
763 break;
764 }
765
766 if (!rc)
767 fdisk_override_geometry(cxt, c, h, s);
768 return rc;
769}
770
b3ac22ef
KZ
771static int createlabel_menu_cb(struct fdisk_context **cxt0,
772 const struct menu *menu __attribute__((__unused__)),
773 const struct menu_entry *ent)
774{
775 struct fdisk_context *cxt = *cxt0;
776 int rc = -EINVAL;
777
778 DBG(FRONTEND, dbgprint("enter Create label menu"));
779
780 assert(cxt);
781 assert(ent);
782
aae727f2
KZ
783 if (ent->expert) {
784 switch (ent->key) {
785 case 'g':
786 /* Deprecated, use 'G' in main menu, just for backward
787 * compatibility only. */
788 rc = fdisk_create_disklabel(cxt, "sgi");
789 break;
790 }
791 return rc;
792 }
793
b3ac22ef
KZ
794 switch (ent->key) {
795 case 'g':
796 fdisk_create_disklabel(cxt, "gpt");
797 break;
798 case 'G':
799 fdisk_create_disklabel(cxt, "sgi");
800 break;
801 case 'o':
802 fdisk_create_disklabel(cxt, "dos");
803 break;
804 case 's':
805 fdisk_create_disklabel(cxt, "sun");
806 break;
807 }
808 return rc;
809}