fdisk.c revision 1.11 1 /* $NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson 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.11 1995/10/04 23:11:19 ghudson 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 void
291 print_part(part)
292 int part;
293 {
294 struct dos_partition *partp;
295
296 partp = &mboot.parts[part];
297 if (!memcmp(partp, &mtpart, sizeof(struct dos_partition))) {
298 printf("<UNUSED>\n");
299 return;
300 }
301 printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ));
302 printf(" start %d, size %d (%d MB), flag %x\n",
303 partp->dp_start, partp->dp_size,
304 partp->dp_size * 512 / (1024 * 1024), partp->dp_flag);
305 printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
306 DPCYL(partp->dp_scyl, partp->dp_ssect),
307 partp->dp_shd, DPSECT(partp->dp_ssect));
308 printf("\tend: cylinder %4d, head %3d, sector %2d\n",
309 DPCYL(partp->dp_ecyl, partp->dp_esect),
310 partp->dp_ehd, DPSECT(partp->dp_esect));
311 }
312
313 void
314 init_sector0(start)
315 int start;
316 {
317 struct dos_partition *partp;
318
319 memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
320 mboot.signature = BOOT_MAGIC;
321
322 partp = &mboot.parts[3];
323 partp->dp_typ = DOSPTYP_386BSD;
324 partp->dp_flag = ACTIVE;
325 partp->dp_start = start;
326 partp->dp_size = disksectors - start;
327
328 dos(partp->dp_start,
329 &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
330 dos(partp->dp_start + partp->dp_size - 1,
331 &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
332 }
333
334 /* Prerequisite: the disklabel parameters and master boot record must
335 * have been read (i.e. dos_* and mboot are meaningful).
336 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
337 * dos_cylindersectors to be consistent with what the
338 * partition table is using, if we can find a geometry
339 * which is consistent with all partition table entries.
340 * We may get the number of cylinders slightly wrong (in
341 * the conservative direction). The idea is to be able
342 * to create a NetBSD partition on a disk we don't know
343 * the translated geometry of.
344 * This whole routine should be replaced with a kernel interface to get
345 * the BIOS geometry (which in turn requires modifications to the i386
346 * boot loader to pass in the BIOS geometry for each disk). */
347 void
348 intuit_translated_geometry()
349 {
350 int cylinders = -1, heads = -1, sectors = -1, i, j;
351 int c1, h1, s1, c2, h2, s2;
352 long a1, a2;
353 quad_t num, denom;
354
355 /* Try to deduce the number of heads from two different mappings. */
356 for (i = 0; i < NDOSPART * 2; i++) {
357 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
358 continue;
359 for (j = 0; j < 8; j++) {
360 if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
361 continue;
362 num = (quad_t)h1*(a2-s2) - h2*(a1-s1);
363 denom = (quad_t)c2*(a1-s1) - c1*(a2-s2);
364 if (denom != 0 && num % denom == 0) {
365 heads = num / denom;
366 break;
367 }
368 }
369 if (heads != -1)
370 break;
371 }
372
373 if (heads == -1)
374 return;
375
376 /* Now figure out the number of sectors from a single mapping. */
377 for (i = 0; i < NDOSPART * 2; i++) {
378 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
379 continue;
380 num = a1 - s1;
381 denom = c1 * heads + h1;
382 if (denom != 0 && num % denom == 0) {
383 sectors = num / denom;
384 break;
385 }
386 }
387
388 if (sectors == -1)
389 return;
390
391 /* Estimate the number of cylinders. */
392 cylinders = dos_cylinders * dos_cylindersectors / heads / sectors;
393
394 /* Now verify consistency with each of the partition table entries.
395 * Be willing to shove cylinders up a little bit to make things work,
396 * but translation mismatches are fatal. */
397 for (i = 0; i < NDOSPART * 2; i++) {
398 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
399 continue;
400 if (sectors * (c1 * heads + h1) + s1 != a1)
401 return;
402 if (c1 >= cylinders)
403 cylinders = c1 + 1;
404 }
405
406 /* Everything checks out. Reset the geometry to use for further
407 * calculations. */
408 dos_cylinders = cylinders;
409 dos_heads = heads;
410 dos_sectors = sectors;
411 dos_cylindersectors = heads * sectors;
412 }
413
414 /* For the purposes of intuit_translated_geometry(), treat the partition
415 * table as a list of eight mapping between (cylinder, head, sector)
416 * triplets and absolute sectors. Get the relevant geometry triplet and
417 * absolute sectors for a given entry, or return -1 if it isn't present.
418 * Note: for simplicity, the returned sector is 0-based. */
419 int
420 get_mapping(i, cylinder, head, sector, absolute)
421 int i, *cylinder, *head, *sector;
422 long *absolute;
423 {
424 struct dos_partition *part = &mboot.parts[i / 2];
425
426 if (part->dp_typ == 0)
427 return -1;
428 if (i % 2 == 0) {
429 *cylinder = DPCYL(part->dp_scyl, part->dp_ssect);
430 *head = part->dp_shd;
431 *sector = DPSECT(part->dp_ssect) - 1;
432 *absolute = part->dp_start;
433 } else {
434 *cylinder = DPCYL(part->dp_ecyl, part->dp_esect);
435 *head = part->dp_ehd;
436 *sector = DPSECT(part->dp_esect) - 1;
437 *absolute = part->dp_start + part->dp_size - 1;
438 }
439 return 0;
440 }
441
442 void
443 change_part(part)
444 int part;
445 {
446 struct dos_partition *partp;
447
448 partp = &mboot.parts[part];
449
450 printf("The data for partition %d is:\n", part);
451 print_part(part);
452
453 if (!u_flag || !yesno("Do you want to change it?"))
454 return;
455
456 if (i_flag) {
457 memset(partp, 0, sizeof(*partp));
458 if (part == 3) {
459 init_sector0(1);
460 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
461 print_part(part);
462 }
463 }
464
465 do {
466 {
467 int sysid, start, size;
468
469 sysid = partp->dp_typ,
470 start = partp->dp_start,
471 size = partp->dp_size;
472 decimal("sysid", &sysid);
473 decimal("start", &start);
474 decimal("size", &size);
475 partp->dp_typ = sysid;
476 partp->dp_start = start;
477 partp->dp_size = size;
478 }
479
480 if (yesno("Explicitly specify beg/end address?")) {
481 int tsector, tcylinder, thead;
482
483 tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect);
484 thead = partp->dp_shd;
485 tsector = DPSECT(partp->dp_ssect);
486 decimal("beginning cylinder", &tcylinder);
487 decimal("beginning head", &thead);
488 decimal("beginning sector", &tsector);
489 partp->dp_scyl = DOSCYL(tcylinder);
490 partp->dp_shd = thead;
491 partp->dp_ssect = DOSSECT(tsector, tcylinder);
492
493 tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect);
494 thead = partp->dp_ehd;
495 tsector = DPSECT(partp->dp_esect);
496 decimal("ending cylinder", &tcylinder);
497 decimal("ending head", &thead);
498 decimal("ending sector", &tsector);
499 partp->dp_ecyl = DOSCYL(tcylinder);
500 partp->dp_ehd = thead;
501 partp->dp_esect = DOSSECT(tsector, tcylinder);
502 } else {
503 dos(partp->dp_start,
504 &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
505 dos(partp->dp_start + partp->dp_size - 1,
506 &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
507 }
508
509 print_part(part);
510 } while (!yesno("Is this entry okay?"));
511 }
512
513 void
514 print_params()
515 {
516
517 printf("parameters extracted from in-core disklabel are:\n");
518 printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
519 cylinders, heads, sectors, cylindersectors);
520 if (dos_sectors > 63 || dos_cylinders > 1023 || dos_heads > 255)
521 printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
522 printf("parameters to be used for BIOS calculations are:\n");
523 printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
524 dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
525 }
526
527 void
528 change_active(which)
529 int which;
530 {
531 struct dos_partition *partp;
532 int part;
533 int active = 3;
534
535 partp = &mboot.parts[0];
536
537 if (a_flag && which != -1)
538 active = which;
539 else {
540 for (part = 0; part < NDOSPART; part++)
541 if (partp[part].dp_flag & ACTIVE)
542 active = part;
543 }
544 if (yesno("Do you want to change the active partition?")) {
545 do {
546 decimal("active partition", &active);
547 } while (!yesno("Are you happy with this choice?"));
548 }
549 for (part = 0; part < NDOSPART; part++)
550 partp[part].dp_flag &= ~ACTIVE;
551 partp[active].dp_flag |= ACTIVE;
552 }
553
554 void
555 get_params_to_use()
556 {
557
558 print_params();
559 if (yesno("Do you want to change our idea of what BIOS thinks?")) {
560 do {
561 decimal("BIOS's idea of #cylinders", &dos_cylinders);
562 decimal("BIOS's idea of #heads", &dos_heads);
563 decimal("BIOS's idea of #sectors", &dos_sectors);
564 dos_cylindersectors = dos_heads * dos_sectors;
565 print_params();
566 } while (!yesno("Are you happy with this choice?"));
567 }
568 }
569
570 /***********************************************\
571 * Change real numbers into strange dos numbers *
572 \***********************************************/
573 void
574 dos(sector, cylinderp, headp, sectorp)
575 int sector;
576 unsigned char *cylinderp, *headp, *sectorp;
577 {
578 int cylinder, head;
579
580 cylinder = sector / dos_cylindersectors;
581 sector -= cylinder * dos_cylindersectors;
582
583 head = sector / dos_sectors;
584 sector -= head * dos_sectors;
585
586 *cylinderp = DOSCYL(cylinder);
587 *headp = head;
588 *sectorp = DOSSECT(sector + 1, cylinder);
589 }
590
591 int fd;
592
593 int
594 open_disk(u_flag)
595 int u_flag;
596 {
597 struct stat st;
598
599 if ((fd = open(disk, u_flag ? O_RDWR : O_RDONLY)) == -1) {
600 warn("%s", disk);
601 return (-1);
602 }
603 if (fstat(fd, &st) == -1) {
604 close(fd);
605 warn("%s", disk);
606 return (-1);
607 }
608 if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) {
609 close(fd);
610 warnx("%s is not a character device or regular file", disk);
611 return (-1);
612 }
613 if (get_params() == -1) {
614 close(fd);
615 return (-1);
616 }
617 return (0);
618 }
619
620 int
621 read_disk(sector, buf)
622 int sector;
623 void *buf;
624 {
625
626 if (lseek(fd, (off_t)(sector * 512), 0) == -1)
627 return (-1);
628 return (read(fd, buf, 512));
629 }
630
631 int
632 write_disk(sector, buf)
633 int sector;
634 void *buf;
635 {
636
637 if (lseek(fd, (off_t)(sector * 512), 0) == -1)
638 return (-1);
639 return (write(fd, buf, 512));
640 }
641
642 int
643 get_params()
644 {
645
646 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
647 warn("DIOCGDINFO");
648 return (-1);
649 }
650
651 dos_cylinders = cylinders = disklabel.d_ncylinders;
652 dos_heads = heads = disklabel.d_ntracks;
653 dos_sectors = sectors = disklabel.d_nsectors;
654 dos_cylindersectors = cylindersectors = heads * sectors;
655 disksectors = cylinders * heads * sectors;
656
657 return (0);
658 }
659
660 int
661 read_s0()
662 {
663
664 if (read_disk(0, mboot.bootinst) == -1) {
665 warn("can't read fdisk partition table");
666 return (-1);
667 }
668 if (mboot.signature != BOOT_MAGIC) {
669 warn("invalid fdisk partition table found");
670 /* So should we initialize things? */
671 return (-1);
672 }
673 return (0);
674 }
675
676 int
677 write_s0()
678 {
679 int flag;
680
681 /*
682 * write enable label sector before write (if necessary),
683 * disable after writing.
684 * needed if the disklabel protected area also protects
685 * sector 0. (e.g. empty disk)
686 */
687 flag = 1;
688 if (ioctl(fd, DIOCWLABEL, &flag) < 0)
689 warn("DIOCWLABEL");
690 if (write_disk(0, mboot.bootinst) == -1) {
691 warn("can't write fdisk partition table");
692 return -1;
693 }
694 flag = 0;
695 if (ioctl(fd, DIOCWLABEL, &flag) < 0)
696 warn("DIOCWLABEL");
697 }
698
699 int
700 yesno(str)
701 char *str;
702 {
703 int ch, first;
704
705 printf("%s [n] ", str);
706
707 first = ch = getchar();
708 while (ch != '\n' && ch != EOF)
709 ch = getchar();
710 return (first == 'y' || first == 'Y');
711 }
712
713 void
714 decimal(str, num)
715 char *str;
716 int *num;
717 {
718 int acc = 0;
719 char *cp;
720
721 for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
722 printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
723
724 fgets(lbuf, LBUF, stdin);
725 lbuf[strlen(lbuf)-1] = '\0';
726 cp = lbuf;
727
728 cp += strspn(cp, " \t");
729 if (*cp == '\0')
730 return;
731
732 if (!isdigit(*cp))
733 continue;
734 acc = strtol(lbuf, &cp, 10);
735
736 cp += strspn(cp, " \t");
737 if (*cp != '\0')
738 continue;
739
740 *num = acc;
741 return;
742 }
743
744 }
745
746 int
747 type_match(key, item)
748 const void *key, *item;
749 {
750 const int *typep = key;
751 const struct part_type *ptr = item;
752
753 if (*typep < ptr->type)
754 return (-1);
755 if (*typep > ptr->type)
756 return (1);
757 return (0);
758 }
759
760 char *
761 get_type(type)
762 int type;
763 {
764 struct part_type *ptr;
765
766 ptr = bsearch(&type, part_types,
767 sizeof(part_types) / sizeof(struct part_type),
768 sizeof(struct part_type), type_match);
769 if (ptr == 0)
770 return ("unknown");
771 else
772 return (ptr->name);
773 }
774