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