]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisks/fdisk-menu.c
fdisk: move remaining actions to menu callbacks
[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 */
329 if (IS_MENU_SEP(e))
330 printf("\n %s\n", _(e->title));
331 else
332 printf(" %c %s\n", e->key, _(e->title));
333 }
334 fputc('\n', stdout);
335
336 return 0;
337}
338
a410f8df
KZ
339/* Asks for command, verify the key and perform the command or
340 * returns the command key if no callback for the command is
341 * implemented.
342 *
a47fec81
KZ
343 * Note that this function might exchange the context pointer to
344 * switch to another (nested) context.
345 *
a410f8df
KZ
346 * Returns: <0 on error
347 * 0 on success (the command performed)
348 * >0 if no callback (then returns the key)
349 */
a47fec81 350int process_fdisk_menu(struct fdisk_context **cxt0)
a410f8df 351{
a47fec81 352 struct fdisk_context *cxt = *cxt0;
a410f8df
KZ
353 const struct menu_entry *ent;
354 const struct menu *menu;
355 int key, rc;
356 const char *prompt;
357 char buf[BUFSIZ];
358
359 if (fdisk_context_display_details(cxt))
360 prompt = _("Expert command (m for help): ");
361 else
362 prompt = _("Command (m for help): ");
363
364 fputc('\n',stdout);
365 rc = get_user_reply(cxt, prompt, buf, sizeof(buf));
366 if (rc)
367 return rc;
368
369 key = buf[0];
370 ent = get_fdisk_menu_entry(cxt, key, &menu);
371 if (!ent) {
372 fdisk_warnx(cxt, _("%c: unknown command"), key);
373 return -EINVAL;
374 }
375
a47fec81 376 rc = 0;
36050e70 377 DBG(FRONTEND, dbgprint("selected: key=%c, entry='%s'",
a410f8df 378 key, ent->title));
a410f8df
KZ
379
380 /* menu has implemented callback, use it */
27ddd4f1 381 if (menu->callback)
a47fec81
KZ
382 rc = menu->callback(cxt0, menu, ent);
383 else {
27ddd4f1
KZ
384 DBG(FRONTEND, dbgprint("no callback for key '%c'", key));
385 rc = -EINVAL;
a47fec81 386 }
a410f8df 387
a47fec81
KZ
388 DBG(FRONTEND, dbgprint("process menu done [rc=%d]", rc));
389 return rc;
a410f8df
KZ
390}
391
89309968
KZ
392/*
393 * Basic fdisk actions
394 */
395static int generic_menu_cb(struct fdisk_context **cxt0,
396 const struct menu *menu __attribute__((__unused__)),
397 const struct menu_entry *ent)
398{
399 struct fdisk_context *cxt = *cxt0;
400 int rc = 0;
27ddd4f1 401 size_t n;
89309968 402
27ddd4f1 403 /* actions shared between expert and normal mode */
89309968 404 switch (ent->key) {
89309968
KZ
405 case 'p':
406 list_disk_geometry(cxt);
407 rc = fdisk_list_disklabel(cxt);
408 break;
409 case 'q':
410 fdisk_free_context(cxt);
411 printf("\n");
412 exit(EXIT_SUCCESS);
27ddd4f1
KZ
413 case 'm':
414 rc = print_fdisk_menu(cxt);
415 break;
416 case 'w':
417 write_table(cxt);
89309968
KZ
418 break;
419 case 'v':
420 rc = fdisk_verify_disklabel(cxt);
421 break;
27ddd4f1
KZ
422 }
423
424 /* expert mode */
425 if (ent->expert) {
426 switch (ent->key) {
427 case 'd':
428 print_raw(cxt);
429 break;
430 case 'r':
431 rc = fdisk_context_enable_details(cxt, 0);
432 break;
433 }
434 return rc;
435 }
436
437 /* normal mode */
438 switch (ent->key) {
439 case 'd':
440 rc = fdisk_ask_partnum(cxt, &n, FALSE);
441 if (!rc)
442 rc = fdisk_delete_partition(cxt, n);
443 if (rc)
444 fdisk_warnx(cxt, _("Could not delete partition %d"), n + 1);
445 else
446 fdisk_info(cxt, _("Partition %d is deleted"), n + 1);
447 break;
448 case 'l':
449 list_partition_types(cxt);
450 break;
451 case 'n':
452 rc = fdisk_add_partition(cxt, NULL);
453 break;
454 case 't':
455 change_partition_type(cxt);
456 break;
457 case 'u':
458 fdisk_context_set_unit(cxt,
459 fdisk_context_use_cylinders(cxt) ? "sectors" :
460 "cylinders");
461 if (fdisk_context_use_cylinders(cxt))
462 fdisk_info(cxt, _("Changing display/entry units to cylinders (DEPRECATED!)."));
463 else
464 fdisk_info(cxt, _("Changing display/entry units to sectors."));
465 break;
466 case 'x':
467 fdisk_context_enable_details(cxt, 1);
468 break;
469 case 'r':
470 /* return from nested PT (e.g. BSD) */
471 if (cxt->parent) {
472 struct fdisk_context *tmp = cxt->parent;
473
474 fdisk_info(cxt, _("Leaving nested disk label."));
475 fdisk_free_context(cxt);
476 cxt = tmp;
477 }
478 break;
479 default:
480 fdisk_warnx(cxt, _("%c: unimplemented command"), ent->key);
89309968
KZ
481 break;
482 }
27ddd4f1 483
89309968
KZ
484 return rc;
485}
486
8e40a677 487
b9e94cd7
KZ
488/*
489 * This is fdisk frontend for GPT specific libfdisk functions that
490 * are not expported by generic libfdisk API.
491 */
a47fec81 492static int gpt_menu_cb(struct fdisk_context **cxt0,
b9e94cd7
KZ
493 const struct menu *menu __attribute__((__unused__)),
494 const struct menu_entry *ent)
495{
a47fec81 496 struct fdisk_context *cxt = *cxt0;
b9e94cd7
KZ
497 size_t n;
498 int rc;
499
500 assert(cxt);
501 assert(ent);
502 assert(fdisk_is_disklabel(cxt, GPT));
503
36050e70 504 DBG(FRONTEND, dbgprint("enter GPT menu"));
b9e94cd7 505
35b1f0a4
KZ
506 if (ent->key == 'i')
507 return fdisk_set_disklabel_id(cxt);
508
b9e94cd7
KZ
509 rc = fdisk_ask_partnum(cxt, &n, FALSE);
510 if (rc)
511 return rc;
512
513 switch(ent->key) {
514 case 'u':
515 rc = fdisk_gpt_partition_set_uuid(cxt, n);
516 break;
517 case 'n':
1054699c 518 rc = fdisk_gpt_partition_set_name(cxt, n);
b9e94cd7
KZ
519 break;
520 }
521 return rc;
522}
523
f02fecd1
KZ
524
525/*
526 * This is fdisk frontend for MBR specific libfdisk functions that
527 * are not expported by generic libfdisk API.
528 */
a47fec81 529static int dos_menu_cb(struct fdisk_context **cxt0,
f02fecd1
KZ
530 const struct menu *menu __attribute__((__unused__)),
531 const struct menu_entry *ent)
532{
a47fec81 533 struct fdisk_context *cxt = *cxt0;
f02fecd1
KZ
534 int rc = 0;
535
a47fec81
KZ
536 DBG(FRONTEND, dbgprint("enter DOS menu"));
537
f02fecd1
KZ
538 if (!ent->expert) {
539 switch (ent->key) {
540 case 'a':
541 {
542 size_t n;
543 rc = fdisk_ask_partnum(cxt, &n, FALSE);
544 if (!rc)
545 rc = fdisk_partition_toggle_flag(cxt, n, DOS_FLAG_ACTIVE);
546 break;
547 }
548 case 'b':
549 {
550 struct fdisk_context *bsd
551 = fdisk_new_nested_context(cxt, "bsd");
818d7924
KZ
552 if (!bsd)
553 return -ENOMEM;
554 if (!fdisk_dev_has_disklabel(bsd))
555 rc = fdisk_create_disklabel(bsd, "bsd");
a47fec81
KZ
556 if (rc)
557 fdisk_free_context(bsd);
27ddd4f1 558 else {
a47fec81 559 *cxt0 = cxt = bsd;
27ddd4f1
KZ
560 fdisk_info(cxt, _("Entering to nested BSD disk label"));
561 }
f02fecd1
KZ
562 break;
563 }
564 case 'c':
565 toggle_dos_compatibility_flag(cxt);
566 break;
567 }
568 return rc;
569 }
570
571 /* expert mode */
572 switch (ent->key) {
573 case 'b':
574 {
575 size_t n;
576 rc = fdisk_ask_partnum(cxt, &n, FALSE);
577 if (!rc)
f8ad3899 578 rc = fdisk_dos_move_begin(cxt, n);
f02fecd1
KZ
579 break;
580 }
581 case 'e':
582 rc = fdisk_dos_list_extended(cxt);
583 break;
584 case 'f':
f8ad3899 585 rc = fdisk_dos_fix_order(cxt);
f02fecd1
KZ
586 break;
587 case 'i':
588 rc = fdisk_set_disklabel_id(cxt);
589 break;
590 }
591 return rc;
592}
593
a47fec81 594static int sun_menu_cb(struct fdisk_context **cxt0,
9f280903
KZ
595 const struct menu *menu __attribute__((__unused__)),
596 const struct menu_entry *ent)
597{
a47fec81 598 struct fdisk_context *cxt = *cxt0;
9f280903
KZ
599 int rc = 0;
600
a47fec81
KZ
601 DBG(FRONTEND, dbgprint("enter SUN menu"));
602
9f280903
KZ
603 assert(cxt);
604 assert(ent);
605 assert(fdisk_is_disklabel(cxt, SUN));
606
607 DBG(FRONTEND, dbgprint("enter SUN menu"));
608
609 /* normal mode */
610 if (!ent->expert) {
611 size_t n;
612
613 rc = fdisk_ask_partnum(cxt, &n, FALSE);
614 if (rc)
615 return rc;
616 switch (ent->key) {
617 case 'a':
618 rc = fdisk_partition_toggle_flag(cxt, n, SUN_FLAG_RONLY);
619 break;
620 case 'c':
621 rc = fdisk_partition_toggle_flag(cxt, n, SUN_FLAG_UNMNT);
622 break;
623 }
624 return rc;
625 }
626
627 /* expert mode */
628 switch (ent->key) {
629 case 'a':
630 rc = fdisk_sun_set_alt_cyl(cxt);
631 break;
632 case 'e':
633 rc = fdisk_sun_set_xcyl(cxt);
634 break;
635 case 'i':
636 rc = fdisk_sun_set_ilfact(cxt);
637 break;
638 case 'o':
639 rc = fdisk_sun_set_rspeed(cxt);
640 break;
641 case 'y':
642 rc = fdisk_sun_set_pcylcount(cxt);
643 break;
644 }
645 return rc;
646}
647
aae727f2
KZ
648static int sgi_menu_cb(struct fdisk_context **cxt0,
649 const struct menu *menu __attribute__((__unused__)),
650 const struct menu_entry *ent)
651{
652 struct fdisk_context *cxt = *cxt0;
653 int rc = -EINVAL;
654 size_t n = 0;
655
656 DBG(FRONTEND, dbgprint("enter SGI menu"));
657
658 assert(cxt);
659 assert(ent);
660 assert(fdisk_is_disklabel(cxt, SGI));
661
662 if (ent->expert)
663 return rc;
664
665 switch (ent->key) {
666 case 'a':
667 rc = fdisk_ask_partnum(cxt, &n, FALSE);
668 if (!rc)
669 rc = fdisk_partition_toggle_flag(cxt, n, SGI_FLAG_BOOT);
670 break;
671 case 'b':
ac84272d 672 fdisk_sgi_set_bootfile(cxt);
aae727f2
KZ
673 break;
674 case 'c':
675 rc = fdisk_ask_partnum(cxt, &n, FALSE);
676 if (!rc)
677 rc = fdisk_partition_toggle_flag(cxt, n, SGI_FLAG_SWAP);
678 break;
679 case 'i':
ac84272d 680 rc = fdisk_sgi_create_info(cxt);
aae727f2
KZ
681 break;
682 }
683
684 return rc;
685}
686
b529ea2a
KZ
687/*
688 * This is fdisk frontend for BSD specific libfdisk functions that
689 * are not expported by generic libfdisk API.
690 */
691static int bsd_menu_cb(struct fdisk_context **cxt0,
692 const struct menu *menu __attribute__((__unused__)),
693 const struct menu_entry *ent)
694{
695 struct fdisk_context *cxt = *cxt0;
e563f055 696 int rc = 0, org;
b529ea2a
KZ
697
698 assert(cxt);
699 assert(ent);
22ddf547 700 assert(fdisk_is_disklabel(cxt, BSD));
b529ea2a
KZ
701
702 DBG(FRONTEND, dbgprint("enter BSD menu"));
703
704 switch(ent->key) {
705 case 'e':
706 rc = fdisk_bsd_edit_disklabel(cxt);
707 break;
708 case 'i':
709 rc = fdisk_bsd_write_bootstrap(cxt);
710 break;
711 case 's':
e563f055
KZ
712 org = fdisk_context_display_details(cxt);
713
714 fdisk_context_enable_details(cxt, 1);
715 fdisk_list_disklabel(cxt);
716 fdisk_context_enable_details(cxt, org);
b529ea2a
KZ
717 break;
718 case 'x':
719 rc = fdisk_bsd_link_partition(cxt);
720 break;
721 }
722 return rc;
723}
724
8e40a677 725/* C/H/S commands */
a47fec81 726static int geo_menu_cb(struct fdisk_context **cxt0,
8e40a677
KZ
727 const struct menu *menu __attribute__((__unused__)),
728 const struct menu_entry *ent)
729{
a47fec81 730 struct fdisk_context *cxt = *cxt0;
8e40a677
KZ
731 int rc = -EINVAL;
732 uintmax_t c = 0, h = 0, s = 0;
733
a47fec81
KZ
734 DBG(FRONTEND, dbgprint("enter GEO menu"));
735
8e40a677
KZ
736 assert(cxt);
737 assert(ent);
738
739 switch (ent->key) {
740 case 'c':
741 rc = fdisk_ask_number(cxt, 1, cxt->geom.cylinders,
742 1048576, _("Number of cylinders"), &c);
743 break;
744 case 'h':
745 rc = fdisk_ask_number(cxt, 1, cxt->geom.heads,
746 256, _("Number of heads"), &h);
747 break;
748 case 's':
749 rc = fdisk_ask_number(cxt, 1, cxt->geom.sectors,
750 63, _("Number of sectors"), &s);
751 break;
752 }
753
754 if (!rc)
755 fdisk_override_geometry(cxt, c, h, s);
756 return rc;
757}
758
b3ac22ef
KZ
759static int createlabel_menu_cb(struct fdisk_context **cxt0,
760 const struct menu *menu __attribute__((__unused__)),
761 const struct menu_entry *ent)
762{
763 struct fdisk_context *cxt = *cxt0;
764 int rc = -EINVAL;
765
766 DBG(FRONTEND, dbgprint("enter Create label menu"));
767
768 assert(cxt);
769 assert(ent);
770
aae727f2
KZ
771 if (ent->expert) {
772 switch (ent->key) {
773 case 'g':
774 /* Deprecated, use 'G' in main menu, just for backward
775 * compatibility only. */
776 rc = fdisk_create_disklabel(cxt, "sgi");
777 break;
778 }
779 return rc;
780 }
781
b3ac22ef
KZ
782 switch (ent->key) {
783 case 'g':
784 fdisk_create_disklabel(cxt, "gpt");
785 break;
786 case 'G':
787 fdisk_create_disklabel(cxt, "sgi");
788 break;
789 case 'o':
790 fdisk_create_disklabel(cxt, "dos");
791 break;
792 case 's':
793 fdisk_create_disklabel(cxt, "sun");
794 break;
795 }
796 return rc;
797}
798
161b0d1a
KZ
799#ifdef TEST_PROGRAM
800struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt) { return NULL; }
801struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt) { return NULL; }
802struct fdisk_label *fdisk_new_mac_label(struct fdisk_context *cxt) { return NULL; }
803struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt) { return NULL; }
804
805int main(int argc, char *argv[])
806{
807 struct fdisk_context *cxt;
808 int idx = 1;
809
810 fdisk_init_debug(0);
811 cxt = fdisk_new_context();
812
813 if (argc > idx && strcmp(argv[idx], "--expert") == 0) {
814 fdisk_context_enable_details(cxt, 1);
815 idx++;
816 }
817 fdisk_context_switch_label(cxt, argc > idx ? argv[idx] : "gpt");
818
819 print_fdisk_menu(cxt);
820 return 0;
821}
822#endif