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