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