xref: /openbsd-src/sbin/fdisk/user.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /*	$OpenBSD: user.c,v 1.79 2021/10/21 13:16:49 krw Exp $	*/
2 
3 /*
4  * Copyright (c) 1997 Tobias Weingartner
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/disklabel.h>
21 
22 #include <err.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "part.h"
27 #include "mbr.h"
28 #include "misc.h"
29 #include "cmd.h"
30 #include "user.h"
31 #include "gpt.h"
32 #include "disk.h"
33 
34 struct cmd {
35 	char	*cmd_name;
36 	int	 cmd_gpt;
37 	int	(*cmd_fcn)(char *, struct mbr *);
38 	char	*cmd_help;
39 };
40 
41 const struct cmd		cmd_table[] = {
42 	{"help",   1, Xhelp,   "Command help list"},
43 	{"manual", 1, Xmanual, "Show entire OpenBSD man page for fdisk"},
44 	{"reinit", 1, Xreinit, "Re-initialize loaded MBR (to defaults)"},
45 	{"setpid", 1, Xsetpid, "Set the identifier of a given table entry"},
46 	{"edit",   1, Xedit,   "Edit given table entry"},
47 	{"flag",   1, Xflag,   "Flag given table entry as bootable"},
48 	{"update", 0, Xupdate, "Update machine code in loaded MBR"},
49 	{"select", 0, Xselect, "Select extended partition table entry MBR"},
50 	{"swap",   1, Xswap,   "Swap two partition entries"},
51 	{"print",  1, Xprint,  "Print loaded MBR partition table"},
52 	{"write",  1, Xwrite,  "Write loaded MBR to disk"},
53 	{"exit",   1, Xexit,   "Exit edit of current MBR, without saving changes"},
54 	{"quit",   1, Xquit,   "Quit edit of current MBR, saving current changes"},
55 	{"abort",  1, Xabort,  "Abort program without saving current changes"},
56 };
57 
58 int			modified;
59 
60 int			ask_cmd(const int, char **);
61 
62 void
63 USER_edit(const uint64_t lba_self, const uint64_t lba_firstembr)
64 {
65 	struct mbr		 mbr;
66 	char			*args;
67 	int			 i, st;
68 	static int		 editlevel;
69 
70 	if (MBR_read(lba_self, lba_firstembr, &mbr))
71 		return;
72 
73 	editlevel += 1;
74 
75 	if (editlevel == 1)
76 		GPT_read(ANYGPT);
77 
78 	printf("Enter 'help' for information\n");
79 
80 	for (;;) {
81 		if (letoh64(gh.gh_sig) == GPTSIGNATURE && editlevel > 1)
82 			break;	/* 'reinit gpt'. Unwind recursion! */
83 
84 		i = ask_cmd(editlevel, &args);
85 		if (i == -1)
86 			continue;
87 
88 		st = cmd_table[i].cmd_fcn(args ? args : "", &mbr);
89 
90 		if (st == CMD_EXIT) {
91 			if (modified)
92 				printf("Aborting changes to current MBR\n");
93 			break;
94 		}
95 		if (st == CMD_QUIT) {
96 			if (modified && Xwrite(NULL, &mbr) == CMD_CONT)
97 				continue;
98 			break;
99 		}
100 		if (st == CMD_CLEAN)
101 			modified = 0;
102 		if (st == CMD_DIRTY)
103 			modified = 1;
104 	}
105 
106 	editlevel -= 1;
107 }
108 
109 void
110 USER_print_disk(const int verbosity)
111 {
112 	struct mbr		mbr;
113 	uint64_t		lba_self, lba_firstembr;
114 	int			i;
115 
116 	lba_self = lba_firstembr = 0;
117 
118 	do {
119 		if (MBR_read(lba_self, lba_firstembr, &mbr))
120 			break;
121 		if (lba_self == 0) {
122 			if (GPT_read(ANYGPT)) {
123 				if (verbosity == VERBOSE) {
124 					printf("Primary GPT:\nNot Found\n");
125 					printf("\nSecondary GPT:\nNot Found\n");
126 				}
127 			} else if (verbosity == TERSE) {
128 				GPT_print("s", verbosity);
129 				return;
130 			} else {
131 				printf("Primary GPT:\n");
132 				GPT_read(PRIMARYGPT);
133 				if (letoh64(gh.gh_sig) == GPTSIGNATURE)
134 					GPT_print("s", verbosity);
135 				else
136 					printf("\tNot Found\n");
137 				printf("\nSecondary GPT:\n");
138 				GPT_read(SECONDARYGPT);
139 				if (letoh64(gh.gh_sig) == GPTSIGNATURE)
140 					GPT_print("s", verbosity);
141 				else
142 					printf("\tNot Found\n");
143 			}
144 			if (verbosity == VERBOSE)
145 				printf("\nMBR:\n");
146 		}
147 
148 		MBR_print(&mbr, "s");
149 
150 		for (lba_self = i = 0; i < 4; i++)
151 			if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND ||
152 			    mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) {
153 				lba_self = mbr.mbr_prt[i].prt_bs;
154 				if (lba_firstembr == 0)
155 					lba_firstembr = lba_self;
156 			}
157 	} while (lba_self);
158 }
159 
160 void
161 USER_help(void)
162 {
163 	char			 help[80];
164 	char			*mbrstr;
165 	int			 i;
166 
167 	for (i = 0; i < nitems(cmd_table); i++) {
168 		strlcpy(help, cmd_table[i].cmd_help, sizeof(help));
169 		if (letoh64(gh.gh_sig) == GPTSIGNATURE) {
170 			if (cmd_table[i].cmd_gpt == 0)
171 				continue;
172 			mbrstr = strstr(help, "MBR");
173 			if (mbrstr)
174 				memcpy(mbrstr, "GPT", 3);
175 		}
176 		printf("\t%s\t\t%s\n", cmd_table[i].cmd_name, help);
177 	}
178 }
179 
180 int
181 ask_cmd(const int editlevel, char **arg)
182 {
183 	static char		 lbuf[100];
184 	char			*cmd;
185 	unsigned int		 i, gpt;
186 
187 	printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "", editlevel);
188 	fflush(stdout);
189 	string_from_line(lbuf, sizeof(lbuf), TRIMMED);
190 
191 	*arg = lbuf;
192 	cmd = strsep(arg, WHITESPACE);
193 
194 	if (*arg != NULL)
195 		*arg += strspn(*arg, WHITESPACE);
196 
197 	if (strlen(cmd) == 0)
198 		return -1;
199 	if (strcmp(cmd, "?") == 0)
200 		cmd = "help";
201 
202 	gpt = letoh64(gh.gh_sig) == GPTSIGNATURE;
203 	for (i = 0; i < nitems(cmd_table); i++) {
204 		if (gpt && cmd_table[i].cmd_gpt == 0)
205 			continue;
206 		if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name)
207 			return i;
208 	}
209 
210 	printf("Invalid command '%s", cmd);
211 	if (*arg && strlen(*arg) > 0)
212 		printf(" %s", *arg);
213 	printf("'. Try 'help'.\n");
214 
215 	return -1;
216 }
217