/* $OpenBSD: user.c,v 1.85 2023/03/04 21:22:51 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "part.h" #include "mbr.h" #include "misc.h" #include "cmd.h" #include "user.h" #include "gpt.h" #include "disk.h" struct cmd { char *cmd_name; int cmd_valid; int (*cmd_fcn)(const char *, struct mbr *); char *cmd_help; }; const struct cmd cmd_table[] = { {"help", 2, Xhelp, "Display summary of available commands"}, {"manual", 2, Xmanual, "Display fdisk man page"}, {"reinit", 2, Xreinit, "Initialize the partition table"}, {"setpid", 1, Xsetpid, "Set identifier of table entry"}, {"edit", 1, Xedit, "Edit table entry"}, {"flag", 1, Xflag, "Set flag value of table entry"}, {"update", 0, Xupdate, "Update MBR bootcode"}, {"select", 0, Xselect, "Select MBR extended table entry"}, {"swap", 1, Xswap, "Swap two table entries"}, {"print", 2, Xprint, "Print partition table"}, {"write", 1, Xwrite, "Write partition table to disk"}, {"exit", 1, Xexit, "Discard changes and exit edit level"}, {"quit", 1, Xquit, "Save changes and exit edit level"}, {"abort", 2, Xabort, "Discard changes and terminate fdisk"}, }; #define ANY_CMD(_i) (cmd_table[(_i)].cmd_valid > 1) #define GPT_CMD(_i) (cmd_table[(_i)].cmd_valid > 0) int modified; int ask_cmd(const struct mbr *, char **); void USER_edit(const uint64_t lba_self, const uint64_t lba_firstembr) { struct mbr mbr; char *args; int i, st; static int editlevel; if (MBR_read(lba_self, lba_firstembr, &mbr)) return; editlevel += 1; if (editlevel == 1) GPT_read(ANYGPT); printf("Enter 'help' for information\n"); for (;;) { if (gh.gh_sig == GPTSIGNATURE && editlevel > 1) break; /* 'reinit gpt'. Unwind recursion! */ printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "", editlevel); fflush(stdout); i = ask_cmd(&mbr, &args); if (i == -1) continue; st = cmd_table[i].cmd_fcn(args ? args : "", &mbr); if (st == CMD_EXIT) { if (modified) printf("Aborting changes to current MBR\n"); break; } if (st == CMD_QUIT) { if (modified && Xwrite(NULL, &mbr) == CMD_CONT) continue; break; } if (st == CMD_CLEAN) modified = 0; if (st == CMD_DIRTY) modified = 1; } editlevel -= 1; } void USER_print_disk(const int verbosity) { struct mbr mbr; uint64_t lba_self, lba_firstembr; unsigned int i; lba_self = lba_firstembr = 0; do { if (MBR_read(lba_self, lba_firstembr, &mbr)) break; if (lba_self == DOSBBSECTOR) { if (MBR_valid_prt(&mbr) == 0) { DISK_printgeometry("s"); printf("Offset: %d\tSignature: 0x%X.\t" "No MBR or GPT.\n", DOSBBSECTOR, (int)mbr.mbr_signature); return; } if (GPT_read(ANYGPT)) { if (verbosity == VERBOSE) { printf("Primary GPT:\nNot Found\n"); printf("\nSecondary GPT:\nNot Found\n"); } } else if (verbosity == TERSE) { GPT_print("s", verbosity); return; } else { printf("Primary GPT:\n"); GPT_read(PRIMARYGPT); if (gh.gh_sig == GPTSIGNATURE) GPT_print("s", verbosity); else printf("\tNot Found\n"); printf("\nSecondary GPT:\n"); GPT_read(SECONDARYGPT); if (gh.gh_sig == GPTSIGNATURE) GPT_print("s", verbosity); else printf("\tNot Found\n"); } if (verbosity == VERBOSE) printf("\nMBR:\n"); } MBR_print(&mbr, "s"); for (lba_self = i = 0; i < nitems(mbr.mbr_prt); i++) if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND || mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) { lba_self = mbr.mbr_prt[i].prt_bs; if (lba_firstembr == 0) lba_firstembr = lba_self; } } while (lba_self); } void USER_help(const struct mbr *mbr) { unsigned int i; for (i = 0; i < nitems(cmd_table); i++) { if (gh.gh_sig == GPTSIGNATURE && GPT_CMD(i) == 0) continue; if (MBR_valid_prt(mbr) == 0 && ANY_CMD(i) == 0) continue; printf("\t%s\t\t%s\n", cmd_table[i].cmd_name, cmd_table[i].cmd_help); } } int ask_cmd(const struct mbr *mbr, char **arg) { static char lbuf[LINEBUFSZ]; char *cmd; unsigned int i; string_from_line(lbuf, sizeof(lbuf), TRIMMED); *arg = lbuf; cmd = strsep(arg, WHITESPACE); if (*arg != NULL) *arg += strspn(*arg, WHITESPACE); if (strlen(cmd) == 0) return -1; if (strcmp(cmd, "?") == 0) cmd = "help"; for (i = 0; i < nitems(cmd_table); i++) { if (gh.gh_sig == GPTSIGNATURE && GPT_CMD(i) == 0) continue; if (MBR_valid_prt(mbr) == 0 && ANY_CMD(i) == 0) continue; if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name) return i; } printf("Invalid command '%s", cmd); if (*arg && strlen(*arg) > 0) printf(" %s", *arg); printf("'. Try 'help'.\n"); return -1; }