1*5f7fe693Skrw /* $OpenBSD: user.c,v 1.85 2023/03/04 21:22:51 krw Exp $ */
2a1705421Sweingart
3a1705421Sweingart /*
4a1705421Sweingart * Copyright (c) 1997 Tobias Weingartner
5a1705421Sweingart *
610a68084Skrw * Permission to use, copy, modify, and distribute this software for any
710a68084Skrw * purpose with or without fee is hereby granted, provided that the above
810a68084Skrw * copyright notice and this permission notice appear in all copies.
9a1705421Sweingart *
1010a68084Skrw * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1110a68084Skrw * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1210a68084Skrw * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1310a68084Skrw * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1410a68084Skrw * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1510a68084Skrw * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1610a68084Skrw * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a1705421Sweingart */
18a1705421Sweingart
19a7568474Sderaadt #include <sys/types.h>
20a7568474Sderaadt #include <sys/disklabel.h>
21729290c0Skrw
227126966cSkrw #include <err.h>
23a1705421Sweingart #include <stdio.h>
24a1705421Sweingart #include <string.h>
25abc6f793Skrw
26a5472107Skrw #include "part.h"
27a1705421Sweingart #include "mbr.h"
28a5472107Skrw #include "misc.h"
29a1705421Sweingart #include "cmd.h"
30a5472107Skrw #include "user.h"
31fba7235cSkrw #include "gpt.h"
32cbfc0aa2Skrw #include "disk.h"
33a1705421Sweingart
3458c4c3e5Skrw struct cmd {
3558c4c3e5Skrw char *cmd_name;
369ba61043Skrw int cmd_valid;
37c5fb5a34Skrw int (*cmd_fcn)(const char *, struct mbr *);
3858c4c3e5Skrw char *cmd_help;
3958c4c3e5Skrw };
4058c4c3e5Skrw
41859be6c9Skrw const struct cmd cmd_table[] = {
429ba61043Skrw {"help", 2, Xhelp, "Display summary of available commands"},
439ba61043Skrw {"manual", 2, Xmanual, "Display fdisk man page"},
449ba61043Skrw {"reinit", 2, Xreinit, "Initialize the partition table"},
45fa72fed3Skrw {"setpid", 1, Xsetpid, "Set identifier of table entry"},
46fa72fed3Skrw {"edit", 1, Xedit, "Edit table entry"},
47fa72fed3Skrw {"flag", 1, Xflag, "Set flag value of table entry"},
48fa72fed3Skrw {"update", 0, Xupdate, "Update MBR bootcode"},
49fa72fed3Skrw {"select", 0, Xselect, "Select MBR extended table entry"},
50fa72fed3Skrw {"swap", 1, Xswap, "Swap two table entries"},
519ba61043Skrw {"print", 2, Xprint, "Print partition table"},
52fa72fed3Skrw {"write", 1, Xwrite, "Write partition table to disk"},
53fa72fed3Skrw {"exit", 1, Xexit, "Discard changes and exit edit level"},
54fa72fed3Skrw {"quit", 1, Xquit, "Save changes and exit edit level"},
559ba61043Skrw {"abort", 2, Xabort, "Discard changes and terminate fdisk"},
56a1705421Sweingart };
57a1705421Sweingart
589ba61043Skrw #define ANY_CMD(_i) (cmd_table[(_i)].cmd_valid > 1)
599ba61043Skrw #define GPT_CMD(_i) (cmd_table[(_i)].cmd_valid > 0)
609ba61043Skrw
618968bae4Sderaadt int modified;
628968bae4Sderaadt
639ba61043Skrw int ask_cmd(const struct mbr *, char **);
64543185b3Skrw
657126966cSkrw void
USER_edit(const uint64_t lba_self,const uint64_t lba_firstembr)660cd9e2afSkrw USER_edit(const uint64_t lba_self, const uint64_t lba_firstembr)
67a1705421Sweingart {
6853f0474fSkrw struct mbr mbr;
6963cabfdaSkrw char *args;
705765db39Skrw int i, st;
718c10a749Skrw static int editlevel;
72a1705421Sweingart
735765db39Skrw if (MBR_read(lba_self, lba_firstembr, &mbr))
74711fb9d5Skrw return;
75711fb9d5Skrw
76711fb9d5Skrw editlevel += 1;
77a1705421Sweingart
78afd1db78Skrw if (editlevel == 1)
793bbc645fSkrw GPT_read(ANYGPT);
8016530593Skrw
81111b5450Sderaadt printf("Enter 'help' for information\n");
82a1705421Sweingart
83711fb9d5Skrw for (;;) {
84ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE && editlevel > 1)
85711fb9d5Skrw break; /* 'reinit gpt'. Unwind recursion! */
86f43a9f23Skrw
87fa72fed3Skrw printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "",
88fa72fed3Skrw editlevel);
89fa72fed3Skrw fflush(stdout);
909ba61043Skrw i = ask_cmd(&mbr, &args);
9163cabfdaSkrw if (i == -1)
927126966cSkrw continue;
93a1705421Sweingart
94380d744dSkrw st = cmd_table[i].cmd_fcn(args ? args : "", &mbr);
95a1705421Sweingart
96711fb9d5Skrw if (st == CMD_EXIT) {
97711fb9d5Skrw if (modified)
98711fb9d5Skrw printf("Aborting changes to current MBR\n");
999d22187fSderaadt break;
100711fb9d5Skrw }
101711fb9d5Skrw if (st == CMD_QUIT) {
102711fb9d5Skrw if (modified && Xwrite(NULL, &mbr) == CMD_CONT)
103711fb9d5Skrw continue;
1049d22187fSderaadt break;
105711fb9d5Skrw }
1069d22187fSderaadt if (st == CMD_CLEAN)
1079d22187fSderaadt modified = 0;
1089d22187fSderaadt if (st == CMD_DIRTY)
1099d22187fSderaadt modified = 1;
110a1705421Sweingart }
1114b464610Sderaadt
1124b464610Sderaadt editlevel -= 1;
113a1705421Sweingart }
114a1705421Sweingart
1157126966cSkrw void
USER_print_disk(const int verbosity)116859be6c9Skrw USER_print_disk(const int verbosity)
117a1705421Sweingart {
11853f0474fSkrw struct mbr mbr;
1190cd9e2afSkrw uint64_t lba_self, lba_firstembr;
120*5f7fe693Skrw unsigned int i;
121a1705421Sweingart
1220cd9e2afSkrw lba_self = lba_firstembr = 0;
123a1705421Sweingart
124a1705421Sweingart do {
1255765db39Skrw if (MBR_read(lba_self, lba_firstembr, &mbr))
1269b35d4e1Skrw break;
1279ba61043Skrw if (lba_self == DOSBBSECTOR) {
1289ba61043Skrw if (MBR_valid_prt(&mbr) == 0) {
1299ba61043Skrw DISK_printgeometry("s");
1309ba61043Skrw printf("Offset: %d\tSignature: 0x%X.\t"
1319ba61043Skrw "No MBR or GPT.\n", DOSBBSECTOR,
1329ba61043Skrw (int)mbr.mbr_signature);
1339ba61043Skrw return;
1349ba61043Skrw }
135afd1db78Skrw if (GPT_read(ANYGPT)) {
1363bbc645fSkrw if (verbosity == VERBOSE) {
13714e81b27Skrw printf("Primary GPT:\nNot Found\n");
13814e81b27Skrw printf("\nSecondary GPT:\nNot Found\n");
13914e81b27Skrw }
14014e81b27Skrw } else if (verbosity == TERSE) {
14114e81b27Skrw GPT_print("s", verbosity);
14214e81b27Skrw return;
14314e81b27Skrw } else {
144fbf68f68Skrw printf("Primary GPT:\n");
1453bbc645fSkrw GPT_read(PRIMARYGPT);
146ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE)
14777db81deSkrw GPT_print("s", verbosity);
148fbf68f68Skrw else
149fbf68f68Skrw printf("\tNot Found\n");
15014e81b27Skrw printf("\nSecondary GPT:\n");
1513bbc645fSkrw GPT_read(SECONDARYGPT);
152ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE)
15377db81deSkrw GPT_print("s", verbosity);
154fbf68f68Skrw else
155fbf68f68Skrw printf("\tNot Found\n");
156fba7235cSkrw }
15714e81b27Skrw if (verbosity == VERBOSE)
15814e81b27Skrw printf("\nMBR:\n");
159fba7235cSkrw }
160a1705421Sweingart
1616c51fc53Skrw MBR_print(&mbr, "s");
162a1705421Sweingart
163*5f7fe693Skrw for (lba_self = i = 0; i < nitems(mbr.mbr_prt); i++)
164ee38fe33Skrw if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND ||
165ee38fe33Skrw mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) {
1660cd9e2afSkrw lba_self = mbr.mbr_prt[i].prt_bs;
1670cd9e2afSkrw if (lba_firstembr == 0)
1680cd9e2afSkrw lba_firstembr = lba_self;
169ca2e86e1Sprovos }
1700cd9e2afSkrw } while (lba_self);
171a1705421Sweingart }
172543185b3Skrw
173543185b3Skrw void
USER_help(const struct mbr * mbr)1749ba61043Skrw USER_help(const struct mbr *mbr)
17558c4c3e5Skrw {
176fa72fed3Skrw unsigned int i;
17758c4c3e5Skrw
17858c4c3e5Skrw for (i = 0; i < nitems(cmd_table); i++) {
1799ba61043Skrw if (gh.gh_sig == GPTSIGNATURE && GPT_CMD(i) == 0)
1809ba61043Skrw continue;
1819ba61043Skrw if (MBR_valid_prt(mbr) == 0 && ANY_CMD(i) == 0)
18258c4c3e5Skrw continue;
183fa72fed3Skrw printf("\t%s\t\t%s\n", cmd_table[i].cmd_name,
184fa72fed3Skrw cmd_table[i].cmd_help);
18558c4c3e5Skrw }
18658c4c3e5Skrw }
18758c4c3e5Skrw
18863cabfdaSkrw int
ask_cmd(const struct mbr * mbr,char ** arg)1899ba61043Skrw ask_cmd(const struct mbr *mbr, char **arg)
190543185b3Skrw {
19163400da5Skrw static char lbuf[LINEBUFSZ];
19263cabfdaSkrw char *cmd;
193ad6c5e72Skrw unsigned int i;
194543185b3Skrw
195380d744dSkrw string_from_line(lbuf, sizeof(lbuf), TRIMMED);
196543185b3Skrw
197380d744dSkrw *arg = lbuf;
19863cabfdaSkrw cmd = strsep(arg, WHITESPACE);
199543185b3Skrw
200380d744dSkrw if (*arg != NULL)
201380d744dSkrw *arg += strspn(*arg, WHITESPACE);
20263cabfdaSkrw
20363cabfdaSkrw if (strlen(cmd) == 0)
20463cabfdaSkrw return -1;
20563cabfdaSkrw if (strcmp(cmd, "?") == 0)
20663cabfdaSkrw cmd = "help";
20763cabfdaSkrw
20863cabfdaSkrw for (i = 0; i < nitems(cmd_table); i++) {
2099ba61043Skrw if (gh.gh_sig == GPTSIGNATURE && GPT_CMD(i) == 0)
2109ba61043Skrw continue;
2119ba61043Skrw if (MBR_valid_prt(mbr) == 0 && ANY_CMD(i) == 0)
21263cabfdaSkrw continue;
21363cabfdaSkrw if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name)
21463cabfdaSkrw return i;
21563cabfdaSkrw }
21663cabfdaSkrw
21763cabfdaSkrw printf("Invalid command '%s", cmd);
21863cabfdaSkrw if (*arg && strlen(*arg) > 0)
21963cabfdaSkrw printf(" %s", *arg);
22063cabfdaSkrw printf("'. Try 'help'.\n");
22163cabfdaSkrw
22263cabfdaSkrw return -1;
223543185b3Skrw }
224