1 | /*␊ |
2 | * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * ␊ |
5 | * This file contains Original Code and/or Modifications of Original Code␊ |
6 | * as defined in and that are subject to the Apple Public Source License␊ |
7 | * Version 2.0 (the 'License'). You may not use this file except in␊ |
8 | * compliance with the License. Please obtain a copy of the License at␊ |
9 | * http://www.opensource.apple.com/apsl/ and read it before using this␊ |
10 | * file.␊ |
11 | * ␊ |
12 | * The Original Code and all software distributed under the License are␊ |
13 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
16 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.␊ |
17 | * Please see the License for the specific language governing rights and␊ |
18 | * limitations under the License.␊ |
19 | * ␊ |
20 | * Copyright (c) 1997 Tobias Weingartner␊ |
21 | * All rights reserved.␊ |
22 | *␊ |
23 | * Redistribution and use in source and binary forms, with or without␊ |
24 | * modification, are permitted provided that the following conditions␊ |
25 | * are met:␊ |
26 | * 1. Redistributions of source code must retain the above copyright␊ |
27 | * notice, this list of conditions and the following disclaimer.␊ |
28 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
29 | * notice, this list of conditions and the following disclaimer in the␊ |
30 | * documentation and/or other materials provided with the distribution.␊ |
31 | * 3. All advertising materials mentioning features or use of this software␊ |
32 | * must display the following acknowledgement:␊ |
33 | * This product includes software developed by Tobias Weingartner.␊ |
34 | * 4. The name of the author may not be used to endorse or promote products␊ |
35 | * derived from this software without specific prior written permission.␊ |
36 | *␊ |
37 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR␊ |
38 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES␊ |
39 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.␊ |
40 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,␊ |
41 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT␊ |
42 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,␊ |
43 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY␊ |
44 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
45 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF␊ |
46 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
47 | */␊ |
48 | ␊ |
49 | #include <err.h>␊ |
50 | #include <util.h>␊ |
51 | #include <stdio.h>␊ |
52 | #include <unistd.h>␊ |
53 | #include <string.h>␊ |
54 | #include <sys/fcntl.h>␊ |
55 | #include <sys/types.h>␊ |
56 | #include <sys/stat.h>␊ |
57 | #include <machine/param.h>␊ |
58 | #include "user.h"␊ |
59 | #include "disk.h"␊ |
60 | #include "misc.h"␊ |
61 | #include "mbr.h"␊ |
62 | #include "cmd.h"␊ |
63 | ␊ |
64 | ␊ |
65 | /* Our command table */␊ |
66 | static cmd_table_t cmd_table[] = {␊ |
67 | ␉{"help", Xhelp,␉"Command help list"},␊ |
68 | ␉{"manual", Xmanual,␉"Show entire man page for fdisk"},␊ |
69 | ␉{"reinit", Xreinit,␉"Re-initialize loaded MBR (to defaults)"},␊ |
70 | ␉{"auto", Xauto, "Auto-partition the disk with a partition style"},␊ |
71 | ␉{"setpid", Xsetpid,␉"Set the identifier of a given table entry"},␊ |
72 | ␉{"disk", Xdisk,␉"Edit current drive stats"},␊ |
73 | ␉{"edit", Xedit,␉"Edit given table entry"},␊ |
74 | ␉{"erase", Xerase, "Erase current MBR"},␊ |
75 | ␉{"flag", Xflag,␉"Flag given table entry as bootable"},␊ |
76 | ␉{"update", Xupdate,␉"Update machine code in loaded MBR"},␊ |
77 | ␉{"select", Xselect,␉"Select extended partition table entry MBR"},␊ |
78 | ␉{"print", Xprint,␉"Print loaded MBR partition table"},␊ |
79 | ␉{"write", Xwrite,␉"Write loaded MBR to disk"},␊ |
80 | ␉{"exit", Xexit,␉"Exit edit of current MBR, without saving changes"},␊ |
81 | ␉{"quit", Xquit,␉"Quit edit of current MBR, saving current changes"},␊ |
82 | ␉{"abort", Xabort,␉"Abort program without saving current changes"},␊ |
83 | ␉{NULL, NULL,␉NULL}␊ |
84 | };␊ |
85 | ␊ |
86 | ␊ |
87 | int␊ |
88 | USER_write(disk, tt, preserve, force)␊ |
89 | ␉disk_t *disk;␊ |
90 | ␉mbr_t *tt; /* Template MBR to write */␊ |
91 | ␉int preserve; /* Preserve partition table and just write boot code */␊ |
92 | ␉int force; /* Don't ask any questions */␊ |
93 | {␊ |
94 | ␉int fd, yn;␊ |
95 | ␉char *msgp = "\nDo you wish to write new MBR?";␊ |
96 | ␉char *msgk = "\nDo you wish to write new MBR and partition table?";␊ |
97 | ␊ |
98 | ␉/* Write sector 0 */␊ |
99 | ␉if (force) {␊ |
100 | ␉ yn = 1;␊ |
101 | ␉} else {␊ |
102 | ␉ printf("\a\n"␊ |
103 | ␉␉ "\t-----------------------------------------------------\n"␊ |
104 | ␉␉ "\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n"␊ |
105 | ␉␉ "\t-----------------------------------------------------\n");␊ |
106 | ␉ if (preserve)␊ |
107 | ␉ yn = ask_yn(msgp, 0);␊ |
108 | ␉ else␊ |
109 | ␉ yn = ask_yn(msgk, 0);␊ |
110 | ␉}␊ |
111 | ␊ |
112 | ␉if (yn) {␊ |
113 | ␉ if (preserve) {␊ |
114 | ␉ int shared;␊ |
115 | ␉ /* Only write the first one, if there's more than one in an extended partition chain */␊ |
116 | ␉ /* Since we're updating boot code, we don't require exclusive access */␊ |
117 | ␉ fd = DISK_openshared(disk->name, O_RDWR, &shared);␊ |
118 | ␉ MBR_make(tt);␊ |
119 | ␉ MBR_write(disk, fd, tt);␊ |
120 | ␉ DISK_close(fd);␊ |
121 | ␉ } else {␊ |
122 | ␉ MBR_write_all(disk, tt);␊ |
123 | ␉ }␊ |
124 | ␉} else {␊ |
125 | ␉ printf("MBR is unchanged\n");␊ |
126 | ␉}␊ |
127 | ␊ |
128 | ␉return (0);␊ |
129 | }␊ |
130 | ␊ |
131 | ␊ |
132 | int␊ |
133 | USER_modify(disk, tt, offset, reloff)␊ |
134 | ␉disk_t *disk;␊ |
135 | ␉mbr_t *tt;␊ |
136 | ␉off_t offset;␊ |
137 | ␉off_t reloff;␊ |
138 | {␊ |
139 | ␉static int editlevel;␊ |
140 | ␉mbr_t *mbr;␊ |
141 | ␉cmd_t cmd;␊ |
142 | ␉int i, st, fd;␊ |
143 | ␉int modified = 0;␉␊ |
144 | ␊ |
145 | ␉/* One level deeper */␊ |
146 | ␉editlevel += 1;␊ |
147 | ␊ |
148 | ␉/* Set up command table pointer */␊ |
149 | ␉cmd.table = cmd_table;␊ |
150 | ␊ |
151 | ␉/* Read MBR & partition */␊ |
152 | ␉mbr = MBR_alloc(NULL);␊ |
153 | ␉fd = DISK_open(disk->name, O_RDONLY);␊ |
154 | ␉MBR_read(disk, fd, offset, mbr);␊ |
155 | ␉DISK_close(fd);␊ |
156 | ␊ |
157 | ␉/* Parse the sucker */␊ |
158 | ␉MBR_parse(disk, offset, reloff, mbr);␊ |
159 | ␊ |
160 | ␉if (mbr->signature != MBR_SIGNATURE) {␊ |
161 | ␉ int yn = ask_yn("The signature for this MBR is invalid.\nWould you like to initialize the partition table?", 1);␊ |
162 | ␉ if (yn) {␊ |
163 | ␉ strcpy(cmd.cmd, "erase");␊ |
164 | ␉ cmd.args[0] = '\0';␊ |
165 | ␉ st = Xerase(&cmd, disk, mbr, tt, offset);␊ |
166 | ␉ modified = 1;␊ |
167 | ␉ }␊ |
168 | ␉}␊ |
169 | ␊ |
170 | ␉printf("Enter 'help' for information\n");␊ |
171 | ␊ |
172 | ␉/* Edit cycle */␊ |
173 | ␉do {␊ |
174 | again:␊ |
175 | ␉␉printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel);␊ |
176 | ␉␉fflush(stdout);␊ |
177 | ␉␉ask_cmd(&cmd);␊ |
178 | ␊ |
179 | ␉␉if (cmd.cmd[0] == '\0')␊ |
180 | ␉␉␉goto again;␊ |
181 | ␉␉for (i = 0; cmd_table[i].cmd != NULL; i++)␊ |
182 | ␉␉␉if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd)␊ |
183 | ␉␉␉␉break;␊ |
184 | ␊ |
185 | ␉␉/* Quick hack to put in '?' == 'help' */␊ |
186 | ␉␉if (!strcmp(cmd.cmd, "?"))␊ |
187 | ␉␉␉i = 0;␊ |
188 | ␊ |
189 | ␉␉/* Check for valid command */␊ |
190 | ␉␉if (cmd_table[i].cmd == NULL) {␊ |
191 | ␉␉␉printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd);␊ |
192 | ␉␉␉continue;␊ |
193 | ␉␉} else␊ |
194 | ␉␉␉strcpy(cmd.cmd, cmd_table[i].cmd);␊ |
195 | ␊ |
196 | ␉␉/* Call function */␊ |
197 | ␉␉st = cmd_table[i].fcn(&cmd, disk, mbr, tt, offset);␊ |
198 | ␊ |
199 | ␉␉/* Update status */␊ |
200 | ␉␉if (st == CMD_EXIT)␊ |
201 | ␉␉␉break;␊ |
202 | ␉␉if (st == CMD_SAVE)␊ |
203 | ␉␉␉break;␊ |
204 | ␉␉if (st == CMD_CLEAN)␊ |
205 | ␉␉␉modified = 0;␊ |
206 | ␉␉if (st == CMD_DIRTY)␊ |
207 | ␉␉␉modified = 1;␊ |
208 | ␉} while (1);␊ |
209 | ␊ |
210 | ␉/* Write out MBR */␊ |
211 | ␉if (modified) {␊ |
212 | ␉␉if (st == CMD_SAVE) {␊ |
213 | ␉␉ ␉int shared = 0;␊ |
214 | ␉␉␉printf("Writing current MBR to disk.\n");␊ |
215 | ␉␉␉fd = DISK_openshared(disk->name, O_RDWR, &shared);␊ |
216 | ␉␉␉if(shared) {␊ |
217 | ␉␉␉ if(!ask_yn("Device could not be accessed exclusively.\nA reboot will be needed for changes to take effect. OK?", 0)) {␊ |
218 | ␉␉␉ close(fd);␊ |
219 | ␉␉␉ goto again;␊ |
220 | ␉␉␉ }␊ |
221 | ␉␉␉}␊ |
222 | ␊ |
223 | ␉␉␉MBR_make(mbr);␊ |
224 | ␉␉␉MBR_write(disk, fd, mbr);␊ |
225 | ␉␉␉close(fd);␊ |
226 | ␉␉} else {␊ |
227 | ␉ int yn = ask_yn("MBR was modified; really quit without saving?", 0);␊ |
228 | ␉␉␉if (yn) {␊ |
229 | ␉␉␉␉printf("Aborting changes to current MBR.\n");␊ |
230 | ␉␉␉} else {␊ |
231 | ␉␉␉␉goto again;␊ |
232 | ␉␉␉}␊ |
233 | ␉␉}␊ |
234 | ␉}␊ |
235 | ␊ |
236 | ␉/* One level less */␊ |
237 | ␉editlevel -= 1;␊ |
238 | ␊ |
239 | ␉MBR_free(mbr);␊ |
240 | ␉␊ |
241 | ␉return (0);␊ |
242 | }␊ |
243 | ␊ |
244 | int␊ |
245 | USER_print_disk(disk, do_dump)␊ |
246 | ␉disk_t *disk;␊ |
247 | ␉int do_dump;␊ |
248 | {␊ |
249 | ␉int fd, offset, firstoff;␊ |
250 | ␉mbr_t *mbr;␊ |
251 | ␊ |
252 | ␉fd = DISK_open(disk->name, O_RDONLY);␊ |
253 | ␉offset = firstoff = 0;␊ |
254 | ␊ |
255 | ␉if (!do_dump)␊ |
256 | ␉ DISK_printmetrics(disk);␊ |
257 | ␊ |
258 | ␉mbr = MBR_read_all(disk);␊ |
259 | ␉if (do_dump)␊ |
260 | ␉ MBR_dump_all(mbr);␊ |
261 | ␉else␊ |
262 | ␉ MBR_print_all(mbr);␊ |
263 | ␉MBR_free(mbr);␊ |
264 | ␊ |
265 | ␉return (DISK_close(fd));␊ |
266 | }␊ |
267 | ␊ |
268 | ␊ |
269 | ␊ |
270 | |