fdisk.c revision 1.12 1 /* $NetBSD: fdisk.c,v 1.12 1997/03/29 20:46:17 thorpej Exp $ */
2
3 /*
4 * Mach Operating System
5 * Copyright (c) 1992 Carnegie Mellon University
6 * All Rights Reserved.
7 *
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
27 */
28
29 #ifndef lint
30 static char rcsid[] = "$NetBSD: fdisk.c,v 1.12 1997/03/29 20:46:17 thorpej Exp $";
31 #endif /* not lint */
32
33 #include <sys/types.h>
34 #include <sys/disklabel.h>
35 #include <sys/ioctl.h>
36 #include <sys/stat.h>
37
38 #include <ctype.h>
39 #include <err.h>
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #define LBUF 100
47 static char lbuf[LBUF];
48
49 /*
50 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
51 * Copyright (c) 1989 Robert. V. Baron
52 * Created.
53 */
54
55 char *disk = "/dev/rwd0d";
56
57 struct disklabel disklabel; /* disk parameters */
58
59 int cylinders, sectors, heads, cylindersectors, disksectors;
60
61 struct mboot {
62 unsigned char padding[2]; /* force the longs to be long alligned */
63 unsigned char bootinst[DOSPARTOFF];
64 struct dos_partition parts[4];
65 unsigned short int signature;
66 };
67 struct mboot mboot;
68
69 #define ACTIVE 0x80
70 #define BOOT_MAGIC 0xAA55
71
72 int dos_cylinders;
73 int dos_heads;
74 int dos_sectors;
75 int dos_cylindersectors;
76
77 #define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
78 #define DOSCYL(c) ((c) & 0xff)
79 int partition = -1;
80
81 int a_flag; /* set active partition */
82 int i_flag; /* replace partition data */
83 int u_flag; /* update partition data */
84
85 unsigned char bootcode[] = {
86 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
87 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
88 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
89 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
90 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
91 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
92 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
93 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
94 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
95 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
96 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
97 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
98 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
99 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
100 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
101 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
102 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
103
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
117 };
118
119 struct part_type {
121 int type;
122 char *name;
123 } part_types[] = {
124 {0x00, "unused"},
125 {0x01, "Primary DOS with 12 bit FAT"},
126 {0x02, "XENIX / filesystem"},
127 {0x03, "XENIX /usr filesystem"},
128 {0x04, "Primary DOS with 16 bit FAT"},
129 {0x05, "Extended DOS"},
130 {0x06, "Primary 'big' DOS (> 32MB)"},
131 {0x07, "OS/2 HPFS, QNX or Advanced UNIX"},
132 {0x08, "AIX filesystem"},
133 {0x09, "AIX boot partition or Coherent"},
134 {0x0A, "OS/2 Boot Manager or OPUS"},
135 {0x10, "OPUS"},
136 {0x40, "VENIX 286"},
137 {0x50, "DM"},
138 {0x51, "DM"},
139 {0x52, "CP/M or Microport SysV/AT"},
140 {0x56, "GB"},
141 {0x61, "Speed"},
142 {0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"},
143 {0x64, "Novell Netware 2.xx"},
144 {0x65, "Novell Netware 3.xx"},
145 {0x75, "PCIX"},
146 {0x80, "Minix 1.1 ... 1.4a"},
147 {0x81, "Minix 1.4b ... 1.5.10"},
148 {0x82, "Linux swap"},
149 {0x83, "Linux filesystem"},
150 {0x93, "Amoeba filesystem"},
151 {0x94, "Amoeba bad block table"},
152 {0xA5, "NetBSD or 386BSD"},
153 {0xB7, "BSDI BSD/386 filesystem"},
154 {0xB8, "BSDI BSD/386 swap"},
155 {0xDB, "Concurrent CPM or C.DOS or CTOS"},
156 {0xE1, "Speed"},
157 {0xE3, "Speed"},
158 {0xE4, "Speed"},
159 {0xF1, "Speed"},
160 {0xF2, "DOS 3.3+ Secondary"},
161 {0xF4, "Speed"},
162 {0xFF, "BBT (Bad Blocks Table)"},
163 };
164
165 void usage __P((void));
166 void print_s0 __P((int));
167 void print_part __P((int));
168 void init_sector0 __P((int));
169 void intuit_translated_geometry __P((void));
170 int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t,
171 quad_t));
172 int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t));
173 void change_part __P((int));
174 void print_params __P((void));
175 void change_active __P((int));
176 void get_params_to_use __P((void));
177 void dos __P((int, unsigned char *, unsigned char *, unsigned char *));
178 int open_disk __P((int));
179 int read_disk __P((int, void *));
180 int write_disk __P((int, void *));
181 int get_params __P((void));
182 int read_s0 __P((void));
183 int write_s0 __P((void));
184 int yesno __P((char *));
185 void decimal __P((char *, int *));
186 int type_match __P((const void *, const void *));
187 char *get_type __P((int));
188
189 int
190 main(argc, argv)
191 int argc;
192 char *argv[];
193 {
194 int ch;
195 int part;
196
197 a_flag = i_flag = u_flag = 0;
198 while ((ch = getopt(argc, argv, "0123aiu")) != -1)
199 switch (ch) {
200 case '0':
201 partition = 0;
202 break;
203 case '1':
204 partition = 1;
205 break;
206 case '2':
207 partition = 2;
208 break;
209 case '3':
210 partition = 3;
211 break;
212 case 'a':
213 a_flag = 1;
214 break;
215 case 'i':
216 i_flag = 1;
217 case 'u':
218 u_flag = 1;
219 break;
220 default:
221 usage();
222 }
223 argc -= optind;
224 argv += optind;
225
226 if (argc > 0)
227 disk = argv[0];
228
229 if (open_disk(a_flag || i_flag || u_flag) < 0)
230 exit(1);
231
232 if (read_s0())
233 init_sector0(1);
234
235 intuit_translated_geometry();
236
237 printf("******* Working on device %s *******\n", disk);
238 if (u_flag)
239 get_params_to_use();
240 else
241 print_params();
242
243 printf("Warning: BIOS sector numbering starts with sector 1\n");
244 printf("Information from DOS bootblock is:\n");
245 if (partition == -1) {
246 for (part = 0; part < NDOSPART; part++)
247 change_part(part);
248 } else
249 change_part(partition);
250
251 if (u_flag || a_flag)
252 change_active(partition);
253
254 if (u_flag || a_flag) {
255 printf("\nWe haven't changed the partition table yet. ");
256 printf("This is your last chance.\n");
257 print_s0(-1);
258 if (yesno("Should we write new partition table?"))
259 write_s0();
260 }
261
262 exit(0);
263 }
264
265 void
266 usage()
267 {
268
269 (void)fprintf(stderr, "usage: fdisk [-aiu] [-0|-1|-2|-3] [device]\n");
270 exit(1);
271 }
272
273 void
274 print_s0(which)
275 int which;
276 {
277 int part;
278
279 print_params();
280 printf("Information from DOS bootblock is:\n");
281 if (which == -1) {
282 for (part = 0; part < NDOSPART; part++)
283 printf("%d: ", part), print_part(part);
284 } else
285 print_part(which);
286 }
287
288 static struct dos_partition mtpart = { 0 };
289
290 static inline unsigned short
291 getshort(p)
292 void *p;
293 {
294 unsigned char *cp = p;
295
296 return cp[0] | (cp[1] << 8);
297 }
298
299 static inline void
300 putshort(p, l)
301 void *p;
302 unsigned short l;
303 {
304 unsigned char *cp = p;
305
306 *cp++ = l;
307 *cp++ = l >> 8;
308 }
309
310 static inline unsigned long
311 getlong(p)
312 void *p;
313 {
314 unsigned char *cp = p;
315
316 return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
317 }
318
319 static inline void
320 putlong(p, l)
321 void *p;
322 unsigned long l;
323 {
324 unsigned char *cp = p;
325
326 *cp++ = l;
327 *cp++ = l >> 8;
328 *cp++ = l >> 16;
329 *cp++ = l >> 24;
330 }
331
332 void
333 print_part(part)
334 int part;
335 {
336 struct dos_partition *partp;
337
338 partp = &mboot.parts[part];
339 if (!memcmp(partp, &mtpart, sizeof(struct dos_partition))) {
340 printf("<UNUSED>\n");
341 return;
342 }
343 printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ));
344 printf(" start %d, size %d (%d MB), flag %x\n",
345 getlong(&partp->dp_start), getlong(&partp->dp_size),
346 getlong(&partp->dp_size) * 512 / (1024 * 1024), partp->dp_flag);
347 printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
348 DPCYL(partp->dp_scyl, partp->dp_ssect),
349 partp->dp_shd, DPSECT(partp->dp_ssect));
350 printf("\tend: cylinder %4d, head %3d, sector %2d\n",
351 DPCYL(partp->dp_ecyl, partp->dp_esect),
352 partp->dp_ehd, DPSECT(partp->dp_esect));
353 }
354
355 void
356 init_sector0(start)
357 int start;
358 {
359 struct dos_partition *partp;
360
361 memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
362 putshort(&mboot.signature, BOOT_MAGIC);
363
364 partp = &mboot.parts[3];
365 partp->dp_typ = DOSPTYP_386BSD;
366 partp->dp_flag = ACTIVE;
367 putlong(&partp->dp_start, start);
368 putlong(&partp->dp_size, disksectors - start);
369
370 dos(getlong(&partp->dp_start),
371 &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
372 dos(getlong(&partp->dp_start) + getlong(&partp->dp_size) - 1,
373 &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
374 }
375
376 /* Prerequisite: the disklabel parameters and master boot record must
377 * have been read (i.e. dos_* and mboot are meaningful).
378 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
379 * dos_cylindersectors to be consistent with what the
380 * partition table is using, if we can find a geometry
381 * which is consistent with all partition table entries.
382 * We may get the number of cylinders slightly wrong (in
383 * the conservative direction). The idea is to be able
384 * to create a NetBSD partition on a disk we don't know
385 * the translated geometry of.
386 * This whole routine should be replaced with a kernel interface to get
387 * the BIOS geometry (which in turn requires modifications to the i386
388 * boot loader to pass in the BIOS geometry for each disk). */
389 void
390 intuit_translated_geometry()
391 {
392 int cylinders = -1, heads = -1, sectors = -1, i, j;
393 int c1, h1, s1, c2, h2, s2;
394 long a1, a2;
395 quad_t num, denom;
396
397 /* Try to deduce the number of heads from two different mappings. */
398 for (i = 0; i < NDOSPART * 2; i++) {
399 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
400 continue;
401 for (j = 0; j < 8; j++) {
402 if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
403 continue;
404 num = (quad_t)h1*(a2-s2) - h2*(a1-s1);
405 denom = (quad_t)c2*(a1-s1) - c1*(a2-s2);
406 if (denom != 0 && num % denom == 0) {
407 heads = num / denom;
408 break;
409 }
410 }
411 if (heads != -1)
412 break;
413 }
414
415 if (heads == -1)
416 return;
417
418 /* Now figure out the number of sectors from a single mapping. */
419 for (i = 0; i < NDOSPART * 2; i++) {
420 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
421 continue;
422 num = a1 - s1;
423 denom = c1 * heads + h1;
424 if (denom != 0 && num % denom == 0) {
425 sectors = num / denom;
426 break;
427 }
428 }
429
430 if (sectors == -1)
431 return;
432
433 /* Estimate the number of cylinders. */
434 cylinders = dos_cylinders * dos_cylindersectors / heads / sectors;
435
436 /* Now verify consistency with each of the partition table entries.
437 * Be willing to shove cylinders up a little bit to make things work,
438 * but translation mismatches are fatal. */
439 for (i = 0; i < NDOSPART * 2; i++) {
440 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
441 continue;
442 if (sectors * (c1 * heads + h1) + s1 != a1)
443 return;
444 if (c1 >= cylinders)
445 cylinders = c1 + 1;
446 }
447
448 /* Everything checks out. Reset the geometry to use for further
449 * calculations. */
450 dos_cylinders = cylinders;
451 dos_heads = heads;
452 dos_sectors = sectors;
453 dos_cylindersectors = heads * sectors;
454 }
455
456 /* For the purposes of intuit_translated_geometry(), treat the partition
457 * table as a list of eight mapping between (cylinder, head, sector)
458 * triplets and absolute sectors. Get the relevant geometry triplet and
459 * absolute sectors for a given entry, or return -1 if it isn't present.
460 * Note: for simplicity, the returned sector is 0-based. */
461 int
462 get_mapping(i, cylinder, head, sector, absolute)
463 int i, *cylinder, *head, *sector;
464 long *absolute;
465 {
466 struct dos_partition *part = &mboot.parts[i / 2];
467
468 if (part->dp_typ == 0)
469 return -1;
470 if (i % 2 == 0) {
471 *cylinder = DPCYL(part->dp_scyl, part->dp_ssect);
472 *head = part->dp_shd;
473 *sector = DPSECT(part->dp_ssect) - 1;
474 *absolute = getlong(&part->dp_start);
475 } else {
476 *cylinder = DPCYL(part->dp_ecyl, part->dp_esect);
477 *head = part->dp_ehd;
478 *sector = DPSECT(part->dp_esect) - 1;
479 *absolute = getlong(&part->dp_start)
480 + getlong(&part->dp_size) - 1;
481 }
482 return 0;
483 }
484
485 void
486 change_part(part)
487 int part;
488 {
489 struct dos_partition *partp;
490
491 partp = &mboot.parts[part];
492
493 printf("The data for partition %d is:\n", part);
494 print_part(part);
495
496 if (!u_flag || !yesno("Do you want to change it?"))
497 return;
498
499 if (i_flag) {
500 memset(partp, 0, sizeof(*partp));
501 if (part == 3) {
502 init_sector0(1);
503 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
504 print_part(part);
505 }
506 }
507
508 do {
509 {
510 int sysid, start, size;
511
512 sysid = partp->dp_typ,
513 start = getlong(&partp->dp_start),
514 size = getlong(&partp->dp_size);
515 decimal("sysid", &sysid);
516 decimal("start", &start);
517 decimal("size", &size);
518 partp->dp_typ = sysid;
519 putlong(&partp->dp_start, start);
520 putlong(&partp->dp_size, size);
521 }
522
523 if (yesno("Explicitly specify beg/end address?")) {
524 int tsector, tcylinder, thead;
525
526 tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect);
527 thead = partp->dp_shd;
528 tsector = DPSECT(partp->dp_ssect);
529 decimal("beginning cylinder", &tcylinder);
530 decimal("beginning head", &thead);
531 decimal("beginning sector", &tsector);
532 partp->dp_scyl = DOSCYL(tcylinder);
533 partp->dp_shd = thead;
534 partp->dp_ssect = DOSSECT(tsector, tcylinder);
535
536 tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect);
537 thead = partp->dp_ehd;
538 tsector = DPSECT(partp->dp_esect);
539 decimal("ending cylinder", &tcylinder);
540 decimal("ending head", &thead);
541 decimal("ending sector", &tsector);
542 partp->dp_ecyl = DOSCYL(tcylinder);
543 partp->dp_ehd = thead;
544 partp->dp_esect = DOSSECT(tsector, tcylinder);
545 } else {
546 dos(getlong(&partp->dp_start),
547 &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
548 dos(getlong(&partp->dp_start)
549 + getlong(&partp->dp_size) - 1,
550 &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
551 }
552
553 print_part(part);
554 } while (!yesno("Is this entry okay?"));
555 }
556
557 void
558 print_params()
559 {
560
561 printf("parameters extracted from in-core disklabel are:\n");
562 printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
563 cylinders, heads, sectors, cylindersectors);
564 if (dos_sectors > 63 || dos_cylinders > 1023 || dos_heads > 255)
565 printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
566 printf("parameters to be used for BIOS calculations are:\n");
567 printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
568 dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
569 }
570
571 void
572 change_active(which)
573 int which;
574 {
575 struct dos_partition *partp;
576 int part;
577 int active = 3;
578
579 partp = &mboot.parts[0];
580
581 if (a_flag && which != -1)
582 active = which;
583 else {
584 for (part = 0; part < NDOSPART; part++)
585 if (partp[part].dp_flag & ACTIVE)
586 active = part;
587 }
588 if (yesno("Do you want to change the active partition?")) {
589 do {
590 decimal("active partition", &active);
591 } while (!yesno("Are you happy with this choice?"));
592 }
593 for (part = 0; part < NDOSPART; part++)
594 partp[part].dp_flag &= ~ACTIVE;
595 partp[active].dp_flag |= ACTIVE;
596 }
597
598 void
599 get_params_to_use()
600 {
601
602 print_params();
603 if (yesno("Do you want to change our idea of what BIOS thinks?")) {
604 do {
605 decimal("BIOS's idea of #cylinders", &dos_cylinders);
606 decimal("BIOS's idea of #heads", &dos_heads);
607 decimal("BIOS's idea of #sectors", &dos_sectors);
608 dos_cylindersectors = dos_heads * dos_sectors;
609 print_params();
610 } while (!yesno("Are you happy with this choice?"));
611 }
612 }
613
614 /***********************************************\
615 * Change real numbers into strange dos numbers *
616 \***********************************************/
617 void
618 dos(sector, cylinderp, headp, sectorp)
619 int sector;
620 unsigned char *cylinderp, *headp, *sectorp;
621 {
622 int cylinder, head;
623
624 cylinder = sector / dos_cylindersectors;
625 sector -= cylinder * dos_cylindersectors;
626
627 head = sector / dos_sectors;
628 sector -= head * dos_sectors;
629
630 *cylinderp = DOSCYL(cylinder);
631 *headp = head;
632 *sectorp = DOSSECT(sector + 1, cylinder);
633 }
634
635 int fd;
636
637 int
638 open_disk(u_flag)
639 int u_flag;
640 {
641 struct stat st;
642
643 if ((fd = open(disk, u_flag ? O_RDWR : O_RDONLY)) == -1) {
644 warn("%s", disk);
645 return (-1);
646 }
647 if (fstat(fd, &st) == -1) {
648 close(fd);
649 warn("%s", disk);
650 return (-1);
651 }
652 if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) {
653 close(fd);
654 warnx("%s is not a character device or regular file", disk);
655 return (-1);
656 }
657 if (get_params() == -1) {
658 close(fd);
659 return (-1);
660 }
661 return (0);
662 }
663
664 int
665 read_disk(sector, buf)
666 int sector;
667 void *buf;
668 {
669
670 if (lseek(fd, (off_t)(sector * 512), 0) == -1)
671 return (-1);
672 return (read(fd, buf, 512));
673 }
674
675 int
676 write_disk(sector, buf)
677 int sector;
678 void *buf;
679 {
680
681 if (lseek(fd, (off_t)(sector * 512), 0) == -1)
682 return (-1);
683 return (write(fd, buf, 512));
684 }
685
686 int
687 get_params()
688 {
689
690 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
691 warn("DIOCGDINFO");
692 return (-1);
693 }
694
695 dos_cylinders = cylinders = disklabel.d_ncylinders;
696 dos_heads = heads = disklabel.d_ntracks;
697 dos_sectors = sectors = disklabel.d_nsectors;
698 dos_cylindersectors = cylindersectors = heads * sectors;
699 disksectors = cylinders * heads * sectors;
700
701 return (0);
702 }
703
704 int
705 read_s0()
706 {
707
708 if (read_disk(0, mboot.bootinst) == -1) {
709 warn("can't read fdisk partition table");
710 return (-1);
711 }
712 if (getshort(&mboot.signature) != BOOT_MAGIC) {
713 warnx("invalid fdisk partition table found");
714 /* So should we initialize things? */
715 return (-1);
716 }
717 return (0);
718 }
719
720 int
721 write_s0()
722 {
723 int flag;
724
725 /*
726 * write enable label sector before write (if necessary),
727 * disable after writing.
728 * needed if the disklabel protected area also protects
729 * sector 0. (e.g. empty disk)
730 */
731 flag = 1;
732 if (ioctl(fd, DIOCWLABEL, &flag) < 0)
733 warn("DIOCWLABEL");
734 if (write_disk(0, mboot.bootinst) == -1) {
735 warn("can't write fdisk partition table");
736 return -1;
737 }
738 flag = 0;
739 if (ioctl(fd, DIOCWLABEL, &flag) < 0)
740 warn("DIOCWLABEL");
741 }
742
743 int
744 yesno(str)
745 char *str;
746 {
747 int ch, first;
748
749 printf("%s [n] ", str);
750
751 first = ch = getchar();
752 while (ch != '\n' && ch != EOF)
753 ch = getchar();
754 return (first == 'y' || first == 'Y');
755 }
756
757 void
758 decimal(str, num)
759 char *str;
760 int *num;
761 {
762 int acc = 0;
763 char *cp;
764
765 for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
766 printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
767
768 fgets(lbuf, LBUF, stdin);
769 lbuf[strlen(lbuf)-1] = '\0';
770 cp = lbuf;
771
772 cp += strspn(cp, " \t");
773 if (*cp == '\0')
774 return;
775
776 if (!isdigit(*cp))
777 continue;
778 acc = strtol(lbuf, &cp, 10);
779
780 cp += strspn(cp, " \t");
781 if (*cp != '\0')
782 continue;
783
784 *num = acc;
785 return;
786 }
787
788 }
789
790 int
791 type_match(key, item)
792 const void *key, *item;
793 {
794 const int *typep = key;
795 const struct part_type *ptr = item;
796
797 if (*typep < ptr->type)
798 return (-1);
799 if (*typep > ptr->type)
800 return (1);
801 return (0);
802 }
803
804 char *
805 get_type(type)
806 int type;
807 {
808 struct part_type *ptr;
809
810 ptr = bsearch(&type, part_types,
811 sizeof(part_types) / sizeof(struct part_type),
812 sizeof(struct part_type), type_match);
813 if (ptr == 0)
814 return ("unknown");
815 else
816 return (ptr->name);
817 }
818