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