xref: /openbsd-src/sbin/fdisk/user.c (revision 5f7fe693f69a769e97d438ec6fd2d74ee8350f79)
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