xref: /openbsd-src/sbin/fdisk/user.c (revision 3a3fbb3f2e2521ab7c4a56b7ff7462ebd9095ec5)
1 /*	$OpenBSD: user.c,v 1.17 2001/12/15 02:12:26 kjell Exp $	*/
2 
3 /*
4  * Copyright (c) 1997 Tobias Weingartner
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *    This product includes software developed by Tobias Weingartner.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <err.h>
34 #include <util.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <sys/fcntl.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/disklabel.h>
42 #include <machine/param.h>
43 #include "user.h"
44 #include "disk.h"
45 #include "misc.h"
46 #include "mbr.h"
47 #include "cmd.h"
48 
49 
50 /* Our command table */
51 static cmd_table_t cmd_table[] = {
52 	{"help",   Xhelp,	"Command help list"},
53 	{"manual", Xmanual,	"Show entire OpenBSD man page for fdisk"},
54 	{"reinit", Xreinit,	"Re-initialize loaded MBR (to defaults)"},
55 	{"setpid", Xsetpid,	"Set the identifier of a given table entry"},
56 	{"disk",   Xdisk,	"Edit current drive stats"},
57 	{"edit",   Xedit,	"Edit given table entry"},
58 	{"flag",   Xflag,	"Flag given table entry as bootable"},
59 	{"update", Xupdate,	"Update machine code in loaded MBR"},
60 	{"select", Xselect,	"Select extended partition table entry MBR"},
61 	{"print",  Xprint,	"Print loaded MBR partition table"},
62 	{"write",  Xwrite,	"Write loaded MBR to disk"},
63 	{"exit",   Xexit,	"Exit edit of current MBR, without saving changes"},
64 	{"quit",   Xquit,	"Quit edit of current MBR, saving current changes"},
65 	{"abort",  Xabort,	"Abort program without saving current changes"},
66 	{NULL,     NULL,	NULL}
67 };
68 
69 
70 int
71 USER_init(disk, tt, preserve)
72 	disk_t *disk;
73 	mbr_t *tt;
74 	int preserve;
75 {
76 	int fd, yn;
77 	char mbr_buf[DEV_BSIZE];
78 	char *msgp = "\nDo you wish to write new MBR?";
79 	char *msgk = "\nDo you wish to write new MBR and partition table?";
80 
81 	if (preserve)
82 		MBR_pcopy(disk, tt);
83 	else
84 		MBR_init(disk, tt);
85 
86 	/* Write sector 0 */
87 	printf("\a\n"
88 	   "\t-----------------------------------------------------\n"
89 	   "\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n"
90 	   "\t-----------------------------------------------------\n");
91 	if (preserve)
92 		yn = ask_yn(msgp);
93 	else
94 		yn = ask_yn(msgk);
95 
96 	if (yn) {
97 		fd = DISK_open(disk->name, O_RDWR);
98 		MBR_make(tt, mbr_buf);
99 		MBR_write(fd, (off_t)0, mbr_buf);
100 		DISK_close(fd);
101 	} else
102 		printf("MBR is unchanged\n");
103 
104 	return (0);
105 }
106 
107 int modified;
108 
109 int
110 USER_modify(disk, tt, offset, reloff)
111 	disk_t *disk;
112 	mbr_t *tt;
113 	off_t offset;
114 	off_t reloff;
115 {
116 	static int editlevel;
117 	char mbr_buf[DEV_BSIZE];
118 	mbr_t mbr;
119 	cmd_t cmd;
120 	int i, st, fd;
121 
122 	/* One level deeper */
123 	editlevel += 1;
124 
125 	/* Set up command table pointer */
126 	cmd.table = cmd_table;
127 
128 	/* Read MBR & partition */
129 	fd = DISK_open(disk->name, O_RDONLY);
130 	MBR_read(fd, offset, mbr_buf);
131 	DISK_close(fd);
132 
133 	/* Parse the sucker */
134 	MBR_parse(disk, mbr_buf, offset, reloff, &mbr);
135 
136 	printf("Enter 'help' for information\n");
137 
138 	/* Edit cycle */
139 	do {
140 again:
141 		printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel);
142 		fflush(stdout);
143 		ask_cmd(&cmd);
144 
145 		if (cmd.cmd[0] == '\0')
146 			goto again;
147 		for (i = 0; cmd_table[i].cmd != NULL; i++)
148 			if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd)
149 				break;
150 
151 		/* Quick hack to put in '?' == 'help' */
152 		if (!strcmp(cmd.cmd, "?"))
153 			i = 0;
154 
155 		/* Check for valid command */
156 		if (cmd_table[i].cmd == NULL) {
157 			printf("Invalid command '%s'.  Try 'help'.\n", cmd.cmd);
158 			continue;
159 		} else
160 			strcpy(cmd.cmd, cmd_table[i].cmd);
161 
162 		/* Call function */
163 		st = cmd_table[i].fcn(&cmd, disk, &mbr, tt, offset);
164 
165 		/* Update status */
166 		if (st == CMD_EXIT)
167 			break;
168 		if (st == CMD_SAVE)
169 			break;
170 		if (st == CMD_CLEAN)
171 			modified = 0;
172 		if (st == CMD_DIRTY)
173 			modified = 1;
174 	} while (1);
175 
176 	/* Write out MBR */
177 	if (modified) {
178 		if (st == CMD_SAVE) {
179 			printf("Writing current MBR to disk.\n");
180 			fd = DISK_open(disk->name, O_RDWR);
181 			MBR_make(&mbr, mbr_buf);
182 			MBR_write(fd, offset, mbr_buf);
183 			close(fd);
184 		} else
185 			printf("Aborting changes to current MBR.\n");
186 	}
187 
188 	/* One level less */
189 	editlevel -= 1;
190 
191 	return (0);
192 }
193 
194 int
195 USER_print_disk(disk)
196 	disk_t *disk;
197 {
198 	int fd, offset, firstoff, i;
199 	char mbr_buf[DEV_BSIZE];
200 	mbr_t mbr;
201 
202 	fd = DISK_open(disk->name, O_RDONLY);
203 	offset = firstoff = 0;
204 
205 	DISK_printmetrics(disk);
206 
207 	do {
208 		MBR_read(fd, (off_t)offset, mbr_buf);
209 		MBR_parse(disk, mbr_buf, offset, firstoff, &mbr);
210 
211 		printf("Offset: %d\t", (int)offset);
212 		MBR_print(&mbr);
213 
214 		/* Print out extended partitions too */
215 		for (offset = i = 0; i < 4; i++)
216 			if (mbr.part[i].id == DOSPTYP_EXTEND ||
217 			    mbr.part[i].id == DOSPTYP_EXTENDL) {
218 				offset = mbr.part[i].bs;
219 				if (firstoff == 0)
220 					firstoff = offset;
221 			}
222 	} while (offset);
223 
224 	return (DISK_close(fd));
225 }
226 
227