xref: /openbsd-src/sbin/fdisk/user.c (revision 25c4e8bd056e974b28f4a0ffd39d76c190a56013)
1 /*	$OpenBSD: user.c,v 1.83 2022/07/18 15:06:22 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)(const char *, struct mbr *);
38 	char	*cmd_help;
39 };
40 
41 const struct cmd		cmd_table[] = {
42 	{"help",   1, Xhelp,   "Display summary of available commands"},
43 	{"manual", 1, Xmanual, "Display fdisk man page"},
44 	{"reinit", 1, Xreinit, "Initialize the partition table"},
45 	{"setpid", 1, Xsetpid, "Set identifier of table entry"},
46 	{"edit",   1, Xedit,   "Edit table entry"},
47 	{"flag",   1, Xflag,   "Set flag value of table entry"},
48 	{"update", 0, Xupdate, "Update MBR bootcode"},
49 	{"select", 0, Xselect, "Select MBR extended table entry"},
50 	{"swap",   1, Xswap,   "Swap two table entries"},
51 	{"print",  1, Xprint,  "Print partition table"},
52 	{"write",  1, Xwrite,  "Write partition table to disk"},
53 	{"exit",   1, Xexit,   "Discard changes and exit edit level"},
54 	{"quit",   1, Xquit,   "Save changes and exit edit level"},
55 	{"abort",  1, Xabort,  "Discard changes and terminate fdisk"},
56 };
57 
58 int			modified;
59 
60 int			ask_cmd(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 (gh.gh_sig == GPTSIGNATURE && editlevel > 1)
82 			break;	/* 'reinit gpt'. Unwind recursion! */
83 
84 		printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "",
85 		    editlevel);
86 		fflush(stdout);
87 		i = ask_cmd(&args);
88 		if (i == -1)
89 			continue;
90 
91 		st = cmd_table[i].cmd_fcn(args ? args : "", &mbr);
92 
93 		if (st == CMD_EXIT) {
94 			if (modified)
95 				printf("Aborting changes to current MBR\n");
96 			break;
97 		}
98 		if (st == CMD_QUIT) {
99 			if (modified && Xwrite(NULL, &mbr) == CMD_CONT)
100 				continue;
101 			break;
102 		}
103 		if (st == CMD_CLEAN)
104 			modified = 0;
105 		if (st == CMD_DIRTY)
106 			modified = 1;
107 	}
108 
109 	editlevel -= 1;
110 }
111 
112 void
113 USER_print_disk(const int verbosity)
114 {
115 	struct mbr		mbr;
116 	uint64_t		lba_self, lba_firstembr;
117 	int			i;
118 
119 	lba_self = lba_firstembr = 0;
120 
121 	do {
122 		if (MBR_read(lba_self, lba_firstembr, &mbr))
123 			break;
124 		if (lba_self == 0) {
125 			if (GPT_read(ANYGPT)) {
126 				if (verbosity == VERBOSE) {
127 					printf("Primary GPT:\nNot Found\n");
128 					printf("\nSecondary GPT:\nNot Found\n");
129 				}
130 			} else if (verbosity == TERSE) {
131 				GPT_print("s", verbosity);
132 				return;
133 			} else {
134 				printf("Primary GPT:\n");
135 				GPT_read(PRIMARYGPT);
136 				if (gh.gh_sig == GPTSIGNATURE)
137 					GPT_print("s", verbosity);
138 				else
139 					printf("\tNot Found\n");
140 				printf("\nSecondary GPT:\n");
141 				GPT_read(SECONDARYGPT);
142 				if (gh.gh_sig == GPTSIGNATURE)
143 					GPT_print("s", verbosity);
144 				else
145 					printf("\tNot Found\n");
146 			}
147 			if (verbosity == VERBOSE)
148 				printf("\nMBR:\n");
149 		}
150 
151 		MBR_print(&mbr, "s");
152 
153 		for (lba_self = i = 0; i < 4; i++)
154 			if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND ||
155 			    mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) {
156 				lba_self = mbr.mbr_prt[i].prt_bs;
157 				if (lba_firstembr == 0)
158 					lba_firstembr = lba_self;
159 			}
160 	} while (lba_self);
161 }
162 
163 void
164 USER_help(void)
165 {
166 	unsigned int		i;
167 
168 	for (i = 0; i < nitems(cmd_table); i++) {
169 		if (gh.gh_sig == GPTSIGNATURE && cmd_table[i].cmd_gpt == 0)
170 				continue;
171 		printf("\t%s\t\t%s\n", cmd_table[i].cmd_name,
172 		    cmd_table[i].cmd_help);
173 	}
174 }
175 
176 int
177 ask_cmd(char **arg)
178 {
179 	static char		 lbuf[LINEBUFSZ];
180 	char			*cmd;
181 	unsigned int		 i;
182 
183 	string_from_line(lbuf, sizeof(lbuf), TRIMMED);
184 
185 	*arg = lbuf;
186 	cmd = strsep(arg, WHITESPACE);
187 
188 	if (*arg != NULL)
189 		*arg += strspn(*arg, WHITESPACE);
190 
191 	if (strlen(cmd) == 0)
192 		return -1;
193 	if (strcmp(cmd, "?") == 0)
194 		cmd = "help";
195 
196 	for (i = 0; i < nitems(cmd_table); i++) {
197 		if (gh.gh_sig == GPTSIGNATURE && cmd_table[i].cmd_gpt == 0)
198 			continue;
199 		if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name)
200 			return i;
201 	}
202 
203 	printf("Invalid command '%s", cmd);
204 	if (*arg && strlen(*arg) > 0)
205 		printf(" %s", *arg);
206 	printf("'. Try 'help'.\n");
207 
208 	return -1;
209 }
210