xref: /openbsd-src/sbin/fdisk/user.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: user.c,v 1.52 2019/04/29 18:54:12 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 <fcntl.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include "part.h"
29 #include "mbr.h"
30 #include "misc.h"
31 #include "cmd.h"
32 #include "user.h"
33 #include "gpt.h"
34 #include "disk.h"
35 
36 /* Our command table */
37 struct cmd cmd_table[] = {
38 	{"help",   1, Xhelp,   "Command help list"},
39 	{"manual", 1, Xmanual, "Show entire OpenBSD man page for fdisk"},
40 	{"reinit", 1, Xreinit, "Re-initialize loaded MBR (to defaults)"},
41 	{"setpid", 1, Xsetpid, "Set the identifier of a given table entry"},
42 	{"disk",   0, Xdisk,   "Edit current drive stats"},
43 	{"edit",   1, Xedit,   "Edit given table entry"},
44 	{"flag",   1, Xflag,   "Flag given table entry as bootable"},
45 	{"update", 0, Xupdate, "Update machine code in loaded MBR"},
46 	{"select", 0, Xselect, "Select extended partition table entry MBR"},
47 	{"swap",   1, Xswap,   "Swap two partition entries"},
48 	{"print",  1, Xprint,  "Print loaded MBR partition table"},
49 	{"write",  1, Xwrite,  "Write loaded MBR to disk"},
50 	{"exit",   1, Xexit,   "Exit edit of current MBR, without saving changes"},
51 	{"quit",   1, Xquit,   "Quit edit of current MBR, saving current changes"},
52 	{"abort",  1, Xabort,  "Abort program without saving current changes"},
53 	{NULL,     0, NULL,    NULL}
54 };
55 
56 
57 int modified;
58 
59 void
60 USER_edit(off_t offset, off_t reloff)
61 {
62 	static int editlevel;
63 	struct dos_mbr dos_mbr;
64 	struct mbr mbr;
65 	char *cmd, *args;
66 	int i, st, error;
67 
68 	/* One level deeper */
69 	editlevel += 1;
70 
71 	/* Read MBR & partition */
72 	error = MBR_read(offset, &dos_mbr);
73 	if (error == -1)
74 		goto done;
75 
76 	/* Parse the sucker */
77 	MBR_parse(&dos_mbr, offset, reloff, &mbr);
78 
79 	if (editlevel == 1) {
80 		memset(&gh, 0, sizeof(gh));
81 		memset(&gp, 0, sizeof(gp));
82 		if (MBR_protective_mbr(&mbr) == 0)
83 			GPT_get_gpt(0);
84 	}
85 
86 	printf("Enter 'help' for information\n");
87 
88 	/* Edit cycle */
89 again:
90 	do {
91 		printf("%s%s: %d> ", disk.name, modified ? "*" : "", editlevel);
92 		fflush(stdout);
93 		ask_cmd(&cmd, &args);
94 
95 		if (cmd[0] == '\0')
96 			continue;
97 		for (i = 0; cmd_table[i].cmd != NULL; i++)
98 			if (strstr(cmd_table[i].cmd, cmd) == cmd_table[i].cmd)
99 				break;
100 
101 		/* Quick hack to put in '?' == 'help' */
102 		if (!strcmp(cmd, "?"))
103 			i = 0;
104 
105 		/* Check for valid command */
106 		if ((cmd_table[i].cmd == NULL) || (letoh64(gh.gh_sig) ==
107 		    GPTSIGNATURE && cmd_table[i].gpt == 0)) {
108 			printf("Invalid command '%s'.  Try 'help'.\n", cmd);
109 			continue;
110 		}
111 
112 		/* Call function */
113 		st = cmd_table[i].fcn(args, &mbr);
114 
115 		/* Update status */
116 		if (st == CMD_EXIT)
117 			break;
118 		if (st == CMD_SAVE)
119 			break;
120 		if (st == CMD_CLEAN)
121 			modified = 0;
122 		if (st == CMD_DIRTY)
123 			modified = 1;
124 	} while (1);
125 
126 	/* Write out MBR */
127 	if (modified) {
128 		if (st == CMD_SAVE) {
129 			if (Xwrite(NULL, &mbr) == CMD_CONT)
130 				goto again;
131 		} else
132 			printf("Aborting changes to current MBR.\n");
133 	}
134 
135 done:
136 	/* One level less */
137 	editlevel -= 1;
138 }
139 
140 void
141 USER_print_disk(int verbosity)
142 {
143 	off_t offset, firstoff;
144 	int i, error;
145 	struct dos_mbr dos_mbr;
146 	struct mbr mbr;
147 
148 	offset = firstoff = 0;
149 
150 	do {
151 		error = MBR_read(offset, &dos_mbr);
152 		if (error == -1)
153 			break;
154 		MBR_parse(&dos_mbr, offset, firstoff, &mbr);
155 		if (offset == 0) {
156 		       if (verbosity || MBR_protective_mbr(&mbr) == 0) {
157 				if (verbosity) {
158 					printf("Primary GPT:\n");
159 					GPT_get_gpt(1); /* Get Primary */
160 				}
161 				if (letoh64(gh.gh_sig) == GPTSIGNATURE)
162 					GPT_print("s", verbosity);
163 				else
164 					printf("\tNot Found\n");
165 				if (verbosity) {
166 					printf("\n");
167 					printf("Secondary GPT:\n");
168 					GPT_get_gpt(2); /* Get Secondary */
169 					if (letoh64(gh.gh_sig) == GPTSIGNATURE)
170 						GPT_print("s", verbosity);
171 					else
172 						printf("\tNot Found\n");
173 					printf("\nMBR:\n");
174 				} else
175 					break;
176 		       }
177 		}
178 
179 		MBR_print(&mbr, NULL);
180 
181 		/* Print out extended partitions too */
182 		for (offset = i = 0; i < 4; i++)
183 			if (mbr.part[i].id == DOSPTYP_EXTEND ||
184 			    mbr.part[i].id == DOSPTYP_EXTENDL) {
185 				offset = (off_t)mbr.part[i].bs;
186 				if (firstoff == 0)
187 					firstoff = offset;
188 			}
189 	} while (offset);
190 }
191