1 | /*␊ |
2 | * Copyright (c) 2002, 2005 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * This file contains Original Code and/or Modifications of Original Code␊ |
7 | * as defined in and that are subject to the Apple Public Source License␊ |
8 | * Version 2.0 (the 'License'). You may not use this file except in␊ |
9 | * compliance with the License. Please obtain a copy of the License at␊ |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this␊ |
11 | * file.␊ |
12 | * ␊ |
13 | * The Original Code and all software distributed under the License are␊ |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.␊ |
18 | * Please see the License for the specific language governing rights and␊ |
19 | * limitations under the License.␊ |
20 | * ␊ |
21 | * @APPLE_LICENSE_HEADER_END@␊ |
22 | */␊ |
23 | ␊ |
24 | /*␊ |
25 | * Copyright (c) 1997 Tobias Weingartner␊ |
26 | * All rights reserved.␊ |
27 | *␊ |
28 | * Redistribution and use in source and binary forms, with or without␊ |
29 | * modification, are permitted provided that the following conditions␊ |
30 | * are met:␊ |
31 | * 1. Redistributions of source code must retain the above copyright␊ |
32 | * notice, this list of conditions and the following disclaimer.␊ |
33 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
34 | * notice, this list of conditions and the following disclaimer in the␊ |
35 | * documentation and/or other materials provided with the distribution.␊ |
36 | * 3. All advertising materials mentioning features or use of this software␊ |
37 | * must display the following acknowledgement:␊ |
38 | * This product includes software developed by Tobias Weingartner.␊ |
39 | * 4. The name of the author may not be used to endorse or promote products␊ |
40 | * derived from this software without specific prior written permission.␊ |
41 | *␊ |
42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR␊ |
43 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES␊ |
44 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.␊ |
45 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,␊ |
46 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT␊ |
47 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,␊ |
48 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY␊ |
49 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
50 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF␊ |
51 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
52 | */␊ |
53 | ␊ |
54 | #include <err.h>␊ |
55 | #include <util.h>␊ |
56 | #include <stdio.h>␊ |
57 | #include <unistd.h>␊ |
58 | #include <stdlib.h>␊ |
59 | #include <ctype.h>␊ |
60 | #include <memory.h>␊ |
61 | #include <sys/fcntl.h>␊ |
62 | #include <sys/ioctl.h>␊ |
63 | #include <sys/types.h>␊ |
64 | #include <sys/stat.h>␊ |
65 | #if 0␊ |
66 | #include <sys/dkio.h>␊ |
67 | #endif␊ |
68 | #include <machine/param.h>␊ |
69 | #include "disk.h"␊ |
70 | #include "misc.h"␊ |
71 | #include "mbr.h"␊ |
72 | #include "part.h"␊ |
73 | ␊ |
74 | ␊ |
75 | void␊ |
76 | MBR_init(disk, mbr)␊ |
77 | ␉disk_t *disk;␊ |
78 | ␉mbr_t *mbr;␊ |
79 | {␊ |
80 | ␉/* Fix up given mbr for this disk */␊ |
81 | ␉mbr->part[0].flag = 0;␊ |
82 | ␉mbr->part[1].flag = 0;␊ |
83 | ␉mbr->part[2].flag = 0;␊ |
84 | #if !defined(DOSPTYP_OPENBSD)␊ |
85 | ␉mbr->part[3].flag = 0;␊ |
86 | ␉mbr->signature = MBR_SIGNATURE;␊ |
87 | #else␊ |
88 | ␊ |
89 | ␉mbr->part[3].flag = DOSACTIVE;␊ |
90 | ␉mbr->signature = DOSMBR_SIGNATURE;␊ |
91 | ␊ |
92 | ␉/* Use whole disk, save for first head, on first cyl. */␊ |
93 | ␉mbr->part[3].id = DOSPTYP_OPENBSD;␊ |
94 | ␉mbr->part[3].scyl = 0;␊ |
95 | ␉mbr->part[3].shead = 1;␊ |
96 | ␉mbr->part[3].ssect = 1;␊ |
97 | ␊ |
98 | ␉/* Go right to the end */␊ |
99 | ␉mbr->part[3].ecyl = disk->real->cylinders - 1;␊ |
100 | ␉mbr->part[3].ehead = disk->real->heads - 1;␊ |
101 | ␉mbr->part[3].esect = disk->real->sectors;␊ |
102 | ␊ |
103 | ␉/* Fix up start/length fields */␊ |
104 | ␉PRT_fix_BN(disk, &mbr->part[3], 3);␊ |
105 | ␊ |
106 | #if defined(__powerpc__) || defined(__mips__)␊ |
107 | ␉/* Now fix up for the MS-DOS boot partition on PowerPC. */␊ |
108 | ␉mbr->part[0].flag = DOSACTIVE;␉/* Boot from dos part */␊ |
109 | ␉mbr->part[3].flag = 0;␊ |
110 | ␉mbr->part[3].ns += mbr->part[3].bs;␊ |
111 | ␉mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns;␊ |
112 | ␉mbr->part[3].ns -= mbr->part[3].bs;␊ |
113 | ␉PRT_fix_CHS(disk, &mbr->part[3], 3);␊ |
114 | ␉if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) {␊ |
115 | ␉␉/* align the partition on a cylinder boundary */␊ |
116 | ␉␉mbr->part[3].shead = 0;␊ |
117 | ␉␉mbr->part[3].ssect = 1;␊ |
118 | ␉␉mbr->part[3].scyl += 1;␊ |
119 | ␉}␊ |
120 | ␉/* Fix up start/length fields */␊ |
121 | ␉PRT_fix_BN(disk, &mbr->part[3], 3);␊ |
122 | #endif␊ |
123 | #endif␊ |
124 | }␊ |
125 | ␊ |
126 | void␊ |
127 | MBR_parse(disk, offset, reloff, mbr)␊ |
128 | ␉disk_t *disk;␊ |
129 | ␉off_t offset;␊ |
130 | ␉off_t reloff;␊ |
131 | ␉mbr_t *mbr;␊ |
132 | {␊ |
133 | ␉int i;␊ |
134 | ␉unsigned char *mbr_buf = mbr->buf;␊ |
135 | ␊ |
136 | ␉memcpy(mbr->code, mbr_buf, MBR_CODE_SIZE);␊ |
137 | ␉mbr->offset = offset;␊ |
138 | ␉mbr->reloffset = reloff;␊ |
139 | ␉mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]);␊ |
140 | ␊ |
141 | ␉for (i = 0; i < NDOSPART; i++)␊ |
142 | ␉␉PRT_parse(disk, &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i], ␊ |
143 | ␉␉ offset, reloff, &mbr->part[i], i);␊ |
144 | }␊ |
145 | ␊ |
146 | void␊ |
147 | MBR_make(mbr)␊ |
148 | ␉mbr_t *mbr;␊ |
149 | {␊ |
150 | ␉int i;␊ |
151 | ␉unsigned char *mbr_buf = mbr->buf;␊ |
152 | ␊ |
153 | ␉memcpy(mbr_buf, mbr->code, MBR_CODE_SIZE);␊ |
154 | ␉putshort(&mbr_buf[MBR_SIG_OFF], mbr->signature);␊ |
155 | ␊ |
156 | ␉for (i = 0; i < NDOSPART; i++)␊ |
157 | ␉␉PRT_make(&mbr->part[i], mbr->offset, mbr->reloffset, ␊ |
158 | ␉␉ &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i]);␊ |
159 | }␊ |
160 | ␊ |
161 | void␊ |
162 | MBR_print(mbr)␊ |
163 | ␉mbr_t *mbr;␊ |
164 | {␊ |
165 | ␉int i;␊ |
166 | ␊ |
167 | ␉/* Header */␊ |
168 | ␉printf("Signature: 0x%X\n",␊ |
169 | ␉ (int)mbr->signature);␊ |
170 | ␉PRT_print(0, NULL);␊ |
171 | ␊ |
172 | ␉/* Entries */␊ |
173 | ␉for (i = 0; i < NDOSPART; i++)␊ |
174 | ␉␉PRT_print(i, &mbr->part[i]);␊ |
175 | }␊ |
176 | ␊ |
177 | int␊ |
178 | MBR_read(disk, fd, where, mbr)␊ |
179 | ␉disk_t *disk;␊ |
180 | ␉int fd;␊ |
181 | ␉off_t where;␊ |
182 | ␉mbr_t *mbr;␊ |
183 | {␊ |
184 | ␉off_t off;␊ |
185 | ␉int len;␊ |
186 | ␉int size;␊ |
187 | ␉unsigned char *buf = mbr->buf;␊ |
188 | ␊ |
189 | ␉size = disk->real->sector_size;␊ |
190 | ␉where *= size;␊ |
191 | ␉off = lseek(fd, where, SEEK_SET);␊ |
192 | ␉if (off != where)␊ |
193 | ␉␉return (off);␊ |
194 | ␉len = read(fd, buf, size);␊ |
195 | ␉if (len != size)␊ |
196 | ␉␉return (len);␊ |
197 | ␉return (0);␊ |
198 | }␊ |
199 | ␊ |
200 | int␊ |
201 | MBR_write(disk, fd, mbr)␊ |
202 | ␉disk_t *disk;␊ |
203 | ␉int fd;␊ |
204 | ␉mbr_t *mbr;␊ |
205 | {␊ |
206 | ␉off_t off;␊ |
207 | ␉int len;␊ |
208 | ␉int size;␊ |
209 | ␉unsigned char *buf = mbr->buf;␊ |
210 | ␉off_t where;␊ |
211 | ␊ |
212 | ␉size = disk->real->sector_size;␊ |
213 | ␉where = mbr->offset * size;␊ |
214 | ␉off = lseek(fd, where, SEEK_SET);␊ |
215 | ␉if (off != where)␊ |
216 | ␉␉return (off);␊ |
217 | ␉len = write(fd, buf, size);␊ |
218 | ␉if (len != size)␊ |
219 | ␉␉return (len);␊ |
220 | #if defined(DIOCRLDINFO)␊ |
221 | ␉(void) ioctl(fd, DIOCRLDINFO, 0);␊ |
222 | #endif␊ |
223 | ␉return (0);␊ |
224 | }␊ |
225 | ␊ |
226 | void ␊ |
227 | MBR_pcopy(disk, mbr)␊ |
228 | ␉disk_t *disk;␊ |
229 | ␉mbr_t *mbr;␊ |
230 | {␊ |
231 | ␉/* ␊ |
232 | ␉ * Copy partition table from the disk indicated␊ |
233 | ␉ * to the supplied mbr structure ␊ |
234 | ␉ */␊ |
235 | ␊ |
236 | ␉int i, fd, offset = 0, reloff = 0;␊ |
237 | ␉mbr_t *mbrd;␊ |
238 | ␉␊ |
239 | ␉mbrd = MBR_alloc(NULL);␊ |
240 | ␉if (!mbr) errx(1, "out of memory");␊ |
241 | ␉fd = DISK_open(disk->name, O_RDONLY);␊ |
242 | ␉if (fd == -1) ␊ |
243 | ␉␉err(1, "Could not open %s", disk->name);␊ |
244 | ␉MBR_read(disk, fd, offset, mbrd);␊ |
245 | ␉DISK_close(fd);␊ |
246 | ␉MBR_parse(disk, offset, reloff, mbrd);␊ |
247 | ␉for (i = 0; i < NDOSPART; i++) {␊ |
248 | ␉␉PRT_parse(disk, &mbrd->buf[MBR_PART_OFF +␊ |
249 | ␉␉␉␉␉ MBR_PART_SIZE * i], ␊ |
250 | ␉␉␉ offset, reloff, &mbr->part[i], i);␊ |
251 | ␉␉PRT_print(i, &mbr->part[i]);␊ |
252 | ␉}␊ |
253 | ␉MBR_free(mbrd);␊ |
254 | }␊ |
255 | ␊ |
256 | ␊ |
257 | static int␊ |
258 | parse_number(char *str, int default_val, int base) {␊ |
259 | ␉if (str != NULL && *str != '\0') {␊ |
260 | ␉ default_val = strtol(str, NULL, base);␊ |
261 | ␉}␊ |
262 | ␉return default_val;␊ |
263 | }␊ |
264 | ␊ |
265 | static inline int␊ |
266 | null_arg(char *arg) {␊ |
267 | if (arg == NULL || *arg == 0)␊ |
268 | return 1;␊ |
269 | else␊ |
270 | return 0;␊ |
271 | }␊ |
272 | ␊ |
273 | /* Parse a partition spec into a partition structure.␊ |
274 | * Spec is of the form:␊ |
275 | * <start>,<size>,<id>,<bootable>[,<c,h,s>,<c,h,s>]␊ |
276 | * We require passing in the disk and mbr so we can␊ |
277 | * set reasonable defaults for values, e.g. "the whole disk"␊ |
278 | * or "starting after the last partition."␊ |
279 | */␊ |
280 | #define N_ARGS 10␊ |
281 | static int␊ |
282 | MBR_parse_one_spec(char *line, disk_t *disk, mbr_t *mbr, int pn)␊ |
283 | {␊ |
284 | int i;␊ |
285 | char *args[N_ARGS];␊ |
286 | prt_t *part = &mbr->part[pn];␊ |
287 | int next_start, next_size;␊ |
288 | ␊ |
289 | /* There are up to 10 arguments. */␊ |
290 | for (i=0; i<N_ARGS; i++) {␊ |
291 | char *arg;␊ |
292 | while (isspace(*line))␊ |
293 | line++;␊ |
294 | arg = strsep(&line, ",\n");␊ |
295 | if (arg == NULL || line == NULL) {␊ |
296 | break;␊ |
297 | }␊ |
298 | args[i] = arg;␊ |
299 | }␊ |
300 | for (; i<N_ARGS; i++) {␊ |
301 | args[i] = NULL;␊ |
302 | }␊ |
303 | /* Set reasonable defaults. */␊ |
304 | if (pn == 0) {␊ |
305 | next_start = 0;␊ |
306 | } else {␊ |
307 | next_start = mbr->part[pn-1].bs + mbr->part[pn-1].ns;␊ |
308 | }␊ |
309 | next_size = disk->real->size;␊ |
310 | for(i=0; i<pn; i++) {␊ |
311 | next_size -= mbr->part[i].ns;␊ |
312 | }␊ |
313 | ␊ |
314 | part->id = parse_number(args[2], 0xA8, 16);␊ |
315 | if (!null_arg(args[3]) && *args[3] == '*') {␊ |
316 | part->flag = 0x80;␊ |
317 | } else {␊ |
318 | part->flag = 0;␊ |
319 | }␊ |
320 | /* If you specify the start or end sector,␊ |
321 | you have to give both. */␊ |
322 | if ((null_arg(args[0]) && !null_arg(args[1])) ||␊ |
323 | (!null_arg(args[0]) && null_arg(args[1]))) {␊ |
324 | errx(1, "You must specify both start and size, or neither");␊ |
325 | return -1;␊ |
326 | }␊ |
327 | ␊ |
328 | /* If you specify one of the CHS args,␊ |
329 | you have to give them all. */␊ |
330 | if (!null_arg(args[4])) {␊ |
331 | for (i=5; i<10; i++) {␊ |
332 | if (null_arg(args[i])) {␊ |
333 | ␉errx(1, "Either all CHS arguments must be specified, or none");␊ |
334 | ␉return -1;␊ |
335 | }␊ |
336 | }␊ |
337 | ␊ |
338 | part->scyl = parse_number(args[4], 0, 10);␊ |
339 | part->shead = parse_number(args[5], 0, 10);␊ |
340 | part->ssect = parse_number(args[6], 0, 10);␉ ␊ |
341 | part->scyl = parse_number(args[7], 0, 10);␊ |
342 | part->shead = parse_number(args[8], 0, 10);␊ |
343 | part->ssect = parse_number(args[9], 0, 10);␉ ␊ |
344 | if (null_arg(args[0])) {␊ |
345 | PRT_fix_BN(disk, part, pn);␊ |
346 | }␊ |
347 | } else {␊ |
348 | /* See if they gave no CHS and no start/end */␊ |
349 | if (null_arg(args[0])) {␊ |
350 | errx(1, "You must specify either start sector and size or CHS");␊ |
351 | return -1;␊ |
352 | }␊ |
353 | }␊ |
354 | if (!null_arg(args[0])) {␊ |
355 | part->bs = parse_number(args[0], next_start, 10);␊ |
356 | part->ns = parse_number(args[1], next_size, 10);␊ |
357 | PRT_fix_CHS(disk, part, pn);␊ |
358 | }␊ |
359 | return 0;␊ |
360 | }␊ |
361 | ␊ |
362 | ␊ |
363 | typedef struct _mbr_chain {␊ |
364 | mbr_t mbr;␊ |
365 | struct _mbr_chain *next;␊ |
366 | } mbr_chain_t;␊ |
367 | ␊ |
368 | /* Parse some number of MBR spec lines.␊ |
369 | * Spec is of the form:␊ |
370 | * <start>,<size>,<id>,<bootable>[,<c,h,s>,<c,h,s>]␊ |
371 | * ␊ |
372 | */␊ |
373 | mbr_t *␊ |
374 | MBR_parse_spec(FILE *f, disk_t *disk)␊ |
375 | {␊ |
376 | int lineno;␊ |
377 | int offset, firstoffset;␊ |
378 | mbr_t *mbr, *head, *prev_mbr;␊ |
379 | ␊ |
380 | head = mbr = prev_mbr = NULL;␊ |
381 | firstoffset = 0;␊ |
382 | do {␊ |
383 | ␊ |
384 | offset = 0;␊ |
385 | for (lineno = 0; lineno < NDOSPART && !feof(f); lineno++) {␊ |
386 | char line[256];␊ |
387 | char *str;␊ |
388 | ␉prt_t *part;␊ |
389 | ␊ |
390 | ␉do {␊ |
391 | ␉ str = fgets(line, 256, f);␊ |
392 | ␉} while ((str != NULL) && (*str == '\0'));␊ |
393 | if (str == NULL) {␊ |
394 | break;␊ |
395 | }␊ |
396 | ␊ |
397 | ␉if (mbr == NULL) {␊ |
398 | ␉ mbr = MBR_alloc(prev_mbr);␊ |
399 | ␉␉if (!mbr) errx(1, "out of memory");␊ |
400 | ␉ if (head == NULL)␊ |
401 | ␉␉head = mbr;␊ |
402 | ␉}␊ |
403 | ␊ |
404 | ␉if (MBR_parse_one_spec(line, disk, mbr, lineno)) {␊ |
405 | ␉ /* MBR_parse_one_spec printed the error message. */␊ |
406 | ␉ return NULL;␊ |
407 | ␉}␊ |
408 | ␉part = &mbr->part[lineno];␊ |
409 | ␉if ((part->id == DOSPTYP_EXTEND) || (part->id == DOSPTYP_EXTENDL)) {␊ |
410 | ␉ offset = part->bs;␊ |
411 | ␉ if (firstoffset == 0) firstoffset = offset;␊ |
412 | ␉}␊ |
413 | }␊ |
414 | /* If fewer lines than partitions, zero out the rest of the partitions */␊ |
415 | if (mbr != NULL) {␊ |
416 | ␉for (; lineno < NDOSPART; lineno++) {␊ |
417 | ␉ bzero(&mbr->part[lineno], sizeof(prt_t));␊ |
418 | ␉}␊ |
419 | }␊ |
420 | prev_mbr = mbr;␊ |
421 | mbr = NULL;␊ |
422 | } while (offset >= 0 && !feof(f));␊ |
423 | ␊ |
424 | return head;␊ |
425 | }␊ |
426 | ␊ |
427 | void␊ |
428 | MBR_dump(mbr_t *mbr)␊ |
429 | {␊ |
430 | int i;␊ |
431 | prt_t *part;␊ |
432 | ␊ |
433 | for (i=0; i<NDOSPART; i++) {␊ |
434 | part = &mbr->part[i];␊ |
435 | printf("%d,%d,0x%02X,%c,%d,%d,%d,%d,%d,%d\n",␊ |
436 | ␉ part->bs,␊ |
437 | ␉ part->ns,␊ |
438 | ␉ part->id,␊ |
439 | ␉ (part->flag == 0x80) ? '*' : '-',␊ |
440 | ␉ part->scyl,␊ |
441 | ␉ part->shead,␊ |
442 | ␉ part->ssect,␊ |
443 | ␉ part->ecyl,␊ |
444 | ␉ part->ehead,␊ |
445 | ␉ part->esect);␊ |
446 | }␊ |
447 | }␊ |
448 | ␊ |
449 | mbr_t *␊ |
450 | MBR_alloc(mbr_t *parent)␊ |
451 | {␊ |
452 | mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));␊ |
453 | if (!mbr) return NULL;␊ |
454 | bzero(mbr, sizeof(mbr_t));␊ |
455 | if (parent) {␊ |
456 | parent->next = mbr;␊ |
457 | }␊ |
458 | mbr->signature = MBR_SIGNATURE;␊ |
459 | return mbr;␊ |
460 | }␊ |
461 | ␊ |
462 | void␊ |
463 | MBR_free(mbr_t *mbr)␊ |
464 | {␊ |
465 | mbr_t *tmp;␊ |
466 | while (mbr) {␊ |
467 | tmp = mbr->next;␊ |
468 | free(mbr);␊ |
469 | mbr = tmp;␊ |
470 | }␊ |
471 | }␊ |
472 | ␊ |
473 | /* Read and parse all the partition tables on the disk,␊ |
474 | * including extended partitions.␊ |
475 | */␊ |
476 | mbr_t *␊ |
477 | MBR_read_all(disk_t *disk)␊ |
478 | {␊ |
479 | mbr_t *mbr = NULL, *head = NULL;␊ |
480 | int i, fd, offset, firstoff;␊ |
481 | ␊ |
482 | fd = DISK_open(disk->name, O_RDONLY);␊ |
483 | if (fd == -1) ␊ |
484 | ␉␉err(1, "Could not open %s", disk->name);␊ |
485 | firstoff = offset = 0;␊ |
486 | do {␊ |
487 | mbr = MBR_alloc(mbr);␊ |
488 | ␉if (!mbr) errx(1, "out of memory");␊ |
489 | if (head == NULL) {␊ |
490 | head = mbr;␊ |
491 | }␊ |
492 | MBR_read(disk, fd, offset, mbr);␊ |
493 | MBR_parse(disk, offset, firstoff, mbr);␊ |
494 | if (mbr->signature != MBR_SIGNATURE) {␊ |
495 | /* The MBR signature is invalid. */␊ |
496 | break;␊ |
497 | } ␊ |
498 | offset = 0;␊ |
499 | for (i=0; i<NDOSPART; i++) {␊ |
500 | prt_t *part = &mbr->part[i];␊ |
501 | if ((part->id == DOSPTYP_EXTEND) || (part->id == DOSPTYP_EXTENDL)) {␊ |
502 | ␉offset = part->bs;␊ |
503 | ␉if (firstoff == 0) {␊ |
504 | ␉ firstoff = offset;␊ |
505 | ␉}␊ |
506 | }␊ |
507 | }␊ |
508 | } while (offset > 0);␊ |
509 | DISK_close(fd);␊ |
510 | ␊ |
511 | return head;␊ |
512 | }␊ |
513 | ␊ |
514 | ␊ |
515 | int␊ |
516 | MBR_write_all(disk_t *disk, mbr_t *mbr)␊ |
517 | {␊ |
518 | int result = 0;␊ |
519 | int fd;␊ |
520 | ␊ |
521 | fd = DISK_open(disk->name, O_RDWR);␊ |
522 | if (fd == -1) ␊ |
523 | ␉␉err(1, "Could not open %s", disk->name);␊ |
524 | while (mbr) {␊ |
525 | MBR_make(mbr);␊ |
526 | result = MBR_write(disk, fd, mbr);␊ |
527 | if (result)␊ |
528 | break;␊ |
529 | mbr = mbr->next;␊ |
530 | }␊ |
531 | DISK_close(fd);␊ |
532 | return result;␊ |
533 | }␊ |
534 | ␊ |
535 | void␊ |
536 | MBR_print_all(mbr_t *mbr) {␊ |
537 | while (mbr) {␊ |
538 | MBR_print(mbr);␊ |
539 | mbr = mbr->next;␊ |
540 | }␊ |
541 | }␊ |
542 | ␊ |
543 | void␊ |
544 | MBR_dump_all(mbr_t *mbr) {␊ |
545 | while (mbr) {␊ |
546 | MBR_dump(mbr);␊ |
547 | mbr = mbr->next;␊ |
548 | }␊ |
549 | }␊ |
550 | ␊ |
551 | void␊ |
552 | MBR_clear(mbr_t *mbr) {␊ |
553 | int i;␊ |
554 | if (mbr->next) {␊ |
555 | MBR_free(mbr->next);␊ |
556 | mbr->next = NULL;␊ |
557 | }␊ |
558 | for (i=0; i<4; i++) {␊ |
559 | bzero(&mbr->part[i], sizeof(mbr->part[i]));␊ |
560 | }␊ |
561 | bzero(&mbr->buf, sizeof(mbr->buf));␊ |
562 | }␊ |
563 | ␊ |
564 | |