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@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 { 120 int type; 121 char *name; 122 } part_types[] = { 123 {0x00, "unused"}, 124 {0x01, "Primary DOS with 12 bit FAT"}, 125 {0x02, "XENIX / filesystem"}, 126 {0x03, "XENIX /usr filesystem"}, 127 {0x04, "Primary DOS with 16 bit FAT"}, 128 {0x05, "Extended DOS"}, 129 {0x06, "Primary 'big' DOS (> 32MB)"}, 130 {0x07, "OS/2 HPFS, QNX or Advanced UNIX"}, 131 {0x08, "AIX filesystem"}, 132 {0x09, "AIX boot partition or Coherent"}, 133 {0x0A, "OS/2 Boot Manager or OPUS"}, 134 {0x10, "OPUS"}, 135 {0x40, "VENIX 286"}, 136 {0x50, "DM"}, 137 {0x51, "DM"}, 138 {0x52, "CP/M or Microport SysV/AT"}, 139 {0x56, "GB"}, 140 {0x61, "Speed"}, 141 {0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}, 142 {0x64, "Novell Netware 2.xx"}, 143 {0x65, "Novell Netware 3.xx"}, 144 {0x75, "PCIX"}, 145 {0x80, "Minix 1.1 ... 1.4a"}, 146 {0x81, "Minix 1.4b ... 1.5.10"}, 147 {0x82, "Linux swap"}, 148 {0x83, "Linux filesystem"}, 149 {0x93, "Amoeba filesystem"}, 150 {0x94, "Amoeba bad block table"}, 151 {0xA5, "NetBSD or 386BSD"}, 152 {0xB7, "BSDI BSD/386 filesystem"}, 153 {0xB8, "BSDI BSD/386 swap"}, 154 {0xDB, "Concurrent CPM or C.DOS or CTOS"}, 155 {0xE1, "Speed"}, 156 {0xE3, "Speed"}, 157 {0xE4, "Speed"}, 158 {0xF1, "Speed"}, 159 {0xF2, "DOS 3.3+ Secondary"}, 160 {0xF4, "Speed"}, 161 {0xFF, "BBT (Bad Blocks Table)"}, 162 }; 163 164 void usage __P((void)); 165 void print_s0 __P((int)); 166 void print_part __P((int)); 167 void init_sector0 __P((int)); 168 void intuit_translated_geometry __P((void)); 169 int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, 170 quad_t)); 171 int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t)); 172 void change_part __P((int)); 173 void print_params __P((void)); 174 void change_active __P((int)); 175 void get_params_to_use __P((void)); 176 void dos __P((int, unsigned char *, unsigned char *, unsigned char *)); 177 int open_disk __P((int)); 178 int read_disk __P((int, void *)); 179 int write_disk __P((int, void *)); 180 int get_params __P((void)); 181 int read_s0 __P((void)); 182 int write_s0 __P((void)); 183 int yesno __P((char *)); 184 void decimal __P((char *, int *)); 185 int type_match __P((const void *, const void *)); 186 char *get_type __P((int)); 187 188 int 189 main(argc, argv) 190 int argc; 191 char *argv[]; 192 { 193 int ch; 194 int part; 195 196 a_flag = i_flag = u_flag = 0; 197 while ((ch = getopt(argc, argv, "0123aiu")) != -1) 198 switch (ch) { 199 case '0': 200 partition = 0; 201 break; 202 case '1': 203 partition = 1; 204 break; 205 case '2': 206 partition = 2; 207 break; 208 case '3': 209 partition = 3; 210 break; 211 case 'a': 212 a_flag = 1; 213 break; 214 case 'i': 215 i_flag = 1; 216 case 'u': 217 u_flag = 1; 218 break; 219 default: 220 usage(); 221 } 222 argc -= optind; 223 argv += optind; 224 225 if (argc > 0) 226 disk = argv[0]; 227 228 if (open_disk(a_flag || i_flag || u_flag) < 0) 229 exit(1); 230 231 if (read_s0()) 232 init_sector0(1); 233 234 intuit_translated_geometry(); 235 236 printf("******* Working on device %s *******\n", disk); 237 if (u_flag) 238 get_params_to_use(); 239 else 240 print_params(); 241 242 printf("Warning: BIOS sector numbering starts with sector 1\n"); 243 printf("Information from DOS bootblock is:\n"); 244 if (partition == -1) { 245 for (part = 0; part < NDOSPART; part++) 246 change_part(part); 247 } else 248 change_part(partition); 249 250 if (u_flag || a_flag) 251 change_active(partition); 252 253 if (u_flag || a_flag) { 254 printf("\nWe haven't changed the partition table yet. "); 255 printf("This is your last chance.\n"); 256 print_s0(-1); 257 if (yesno("Should we write new partition table?")) 258 write_s0(); 259 } 260 261 exit(0); 262 } 263 264 void 265 usage() 266 { 267 268 (void)fprintf(stderr, "usage: fdisk [-aiu] [-0|-1|-2|-3] [device]\n"); 269 exit(1); 270 } 271 272 void 273 print_s0(which) 274 int which; 275 { 276 int part; 277 278 print_params(); 279 printf("Information from DOS bootblock is:\n"); 280 if (which == -1) { 281 for (part = 0; part < NDOSPART; part++) 282 printf("%d: ", part), print_part(part); 283 } else 284 print_part(which); 285 } 286 287 static struct dos_partition mtpart = { 0 }; 288 289 void 290 print_part(part) 291 int part; 292 { 293 struct dos_partition *partp; 294 295 partp = &mboot.parts[part]; 296 if (!memcmp(partp, &mtpart, sizeof(struct dos_partition))) { 297 printf("<UNUSED>\n"); 298 return; 299 } 300 printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 301 printf(" start %d, size %d (%d MB), flag %x\n", 302 partp->dp_start, partp->dp_size, 303 partp->dp_size * 512 / (1024 * 1024), partp->dp_flag); 304 printf("\tbeg: cylinder %4d, head %3d, sector %2d\n", 305 DPCYL(partp->dp_scyl, partp->dp_ssect), 306 partp->dp_shd, DPSECT(partp->dp_ssect)); 307 printf("\tend: cylinder %4d, head %3d, sector %2d\n", 308 DPCYL(partp->dp_ecyl, partp->dp_esect), 309 partp->dp_ehd, DPSECT(partp->dp_esect)); 310 } 311 312 void 313 init_sector0(start) 314 int start; 315 { 316 struct dos_partition *partp; 317 318 memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 319 mboot.signature = BOOT_MAGIC; 320 321 partp = &mboot.parts[3]; 322 partp->dp_typ = DOSPTYP_386BSD; 323 partp->dp_flag = ACTIVE; 324 partp->dp_start = start; 325 partp->dp_size = disksectors - start; 326 327 dos(partp->dp_start, 328 &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect); 329 dos(partp->dp_start + partp->dp_size - 1, 330 &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect); 331 } 332 333 /* Prerequisite: the disklabel parameters and master boot record must 334 * have been read (i.e. dos_* and mboot are meaningful). 335 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and 336 * dos_cylindersectors to be consistent with what the 337 * partition table is using, if we can find a geometry 338 * which is consistent with all partition table entries. 339 * We may get the number of cylinders slightly wrong (in 340 * the conservative direction). The idea is to be able 341 * to create a NetBSD partition on a disk we don't know 342 * the translated geometry of. 343 * This whole routine should be replaced with a kernel interface to get 344 * the BIOS geometry (which in turn requires modifications to the i386 345 * boot loader to pass in the BIOS geometry for each disk). */ 346 void 347 intuit_translated_geometry() 348 { 349 int cylinders = -1, heads = -1, sectors = -1, i, j; 350 int c1, h1, s1, c2, h2, s2; 351 long a1, a2; 352 quad_t num, denom; 353 354 /* Try to deduce the number of heads from two different mappings. */ 355 for (i = 0; i < NDOSPART * 2; i++) { 356 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) 357 continue; 358 for (j = 0; j < 8; j++) { 359 if (get_mapping(j, &c2, &h2, &s2, &a2) < 0) 360 continue; 361 num = (quad_t)h1*(a2-s2) - h2*(a1-s1); 362 denom = (quad_t)c2*(a1-s1) - c1*(a2-s2); 363 if (denom != 0 && num % denom == 0) { 364 heads = num / denom; 365 break; 366 } 367 } 368 if (heads != -1) 369 break; 370 } 371 372 if (heads == -1) 373 return; 374 375 /* Now figure out the number of sectors from a single mapping. */ 376 for (i = 0; i < NDOSPART * 2; i++) { 377 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) 378 continue; 379 num = a1 - s1; 380 denom = c1 * heads + h1; 381 if (denom != 0 && num % denom == 0) { 382 sectors = num / denom; 383 break; 384 } 385 } 386 387 if (sectors == -1) 388 return; 389 390 /* Estimate the number of cylinders. */ 391 cylinders = dos_cylinders * dos_cylindersectors / heads / sectors; 392 393 /* Now verify consistency with each of the partition table entries. 394 * Be willing to shove cylinders up a little bit to make things work, 395 * but translation mismatches are fatal. */ 396 for (i = 0; i < NDOSPART * 2; i++) { 397 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) 398 continue; 399 if (sectors * (c1 * heads + h1) + s1 != a1) 400 return; 401 if (c1 >= cylinders) 402 cylinders = c1 + 1; 403 } 404 405 /* Everything checks out. Reset the geometry to use for further 406 * calculations. */ 407 dos_cylinders = cylinders; 408 dos_heads = heads; 409 dos_sectors = sectors; 410 dos_cylindersectors = heads * sectors; 411 } 412 413 /* For the purposes of intuit_translated_geometry(), treat the partition 414 * table as a list of eight mapping between (cylinder, head, sector) 415 * triplets and absolute sectors. Get the relevant geometry triplet and 416 * absolute sectors for a given entry, or return -1 if it isn't present. 417 * Note: for simplicity, the returned sector is 0-based. */ 418 int 419 get_mapping(i, cylinder, head, sector, absolute) 420 int i, *cylinder, *head, *sector; 421 long *absolute; 422 { 423 struct dos_partition *part = &mboot.parts[i / 2]; 424 425 if (part->dp_typ == 0) 426 return -1; 427 if (i % 2 == 0) { 428 *cylinder = DPCYL(part->dp_scyl, part->dp_ssect); 429 *head = part->dp_shd; 430 *sector = DPSECT(part->dp_ssect) - 1; 431 *absolute = part->dp_start; 432 } else { 433 *cylinder = DPCYL(part->dp_ecyl, part->dp_esect); 434 *head = part->dp_ehd; 435 *sector = DPSECT(part->dp_esect) - 1; 436 *absolute = part->dp_start + part->dp_size - 1; 437 } 438 return 0; 439 } 440 441 void 442 change_part(part) 443 int part; 444 { 445 struct dos_partition *partp; 446 447 partp = &mboot.parts[part]; 448 449 printf("The data for partition %d is:\n", part); 450 print_part(part); 451 452 if (!u_flag || !yesno("Do you want to change it?")) 453 return; 454 455 if (i_flag) { 456 memset(partp, 0, sizeof(*partp)); 457 if (part == 3) { 458 init_sector0(1); 459 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); 460 print_part(part); 461 } 462 } 463 464 do { 465 { 466 int sysid, start, size; 467 468 sysid = partp->dp_typ, 469 start = partp->dp_start, 470 size = partp->dp_size; 471 decimal("sysid", &sysid); 472 decimal("start", &start); 473 decimal("size", &size); 474 partp->dp_typ = sysid; 475 partp->dp_start = start; 476 partp->dp_size = size; 477 } 478 479 if (yesno("Explicitly specify beg/end address?")) { 480 int tsector, tcylinder, thead; 481 482 tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect); 483 thead = partp->dp_shd; 484 tsector = DPSECT(partp->dp_ssect); 485 decimal("beginning cylinder", &tcylinder); 486 decimal("beginning head", &thead); 487 decimal("beginning sector", &tsector); 488 partp->dp_scyl = DOSCYL(tcylinder); 489 partp->dp_shd = thead; 490 partp->dp_ssect = DOSSECT(tsector, tcylinder); 491 492 tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect); 493 thead = partp->dp_ehd; 494 tsector = DPSECT(partp->dp_esect); 495 decimal("ending cylinder", &tcylinder); 496 decimal("ending head", &thead); 497 decimal("ending sector", &tsector); 498 partp->dp_ecyl = DOSCYL(tcylinder); 499 partp->dp_ehd = thead; 500 partp->dp_esect = DOSSECT(tsector, tcylinder); 501 } else { 502 dos(partp->dp_start, 503 &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect); 504 dos(partp->dp_start + partp->dp_size - 1, 505 &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect); 506 } 507 508 print_part(part); 509 } while (!yesno("Is this entry okay?")); 510 } 511 512 void 513 print_params() 514 { 515 516 printf("parameters extracted from in-core disklabel are:\n"); 517 printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n", 518 cylinders, heads, sectors, cylindersectors); 519 if (dos_sectors > 63 || dos_cylinders > 1023 || dos_heads > 255) 520 printf("Figures below won't work with BIOS for partitions not in cylinder 1\n"); 521 printf("parameters to be used for BIOS calculations are:\n"); 522 printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n", 523 dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors); 524 } 525 526 void 527 change_active(which) 528 int which; 529 { 530 struct dos_partition *partp; 531 int part; 532 int active = 3; 533 534 partp = &mboot.parts[0]; 535 536 if (a_flag && which != -1) 537 active = which; 538 else { 539 for (part = 0; part < NDOSPART; part++) 540 if (partp[part].dp_flag & ACTIVE) 541 active = part; 542 } 543 if (yesno("Do you want to change the active partition?")) { 544 do { 545 decimal("active partition", &active); 546 } while (!yesno("Are you happy with this choice?")); 547 } 548 for (part = 0; part < NDOSPART; part++) 549 partp[part].dp_flag &= ~ACTIVE; 550 partp[active].dp_flag |= ACTIVE; 551 } 552 553 void 554 get_params_to_use() 555 { 556 557 print_params(); 558 if (yesno("Do you want to change our idea of what BIOS thinks?")) { 559 do { 560 decimal("BIOS's idea of #cylinders", &dos_cylinders); 561 decimal("BIOS's idea of #heads", &dos_heads); 562 decimal("BIOS's idea of #sectors", &dos_sectors); 563 dos_cylindersectors = dos_heads * dos_sectors; 564 print_params(); 565 } while (!yesno("Are you happy with this choice?")); 566 } 567 } 568 569 /***********************************************\ 570 * Change real numbers into strange dos numbers * 571 \***********************************************/ 572 void 573 dos(sector, cylinderp, headp, sectorp) 574 int sector; 575 unsigned char *cylinderp, *headp, *sectorp; 576 { 577 int cylinder, head; 578 579 cylinder = sector / dos_cylindersectors; 580 sector -= cylinder * dos_cylindersectors; 581 582 head = sector / dos_sectors; 583 sector -= head * dos_sectors; 584 585 *cylinderp = DOSCYL(cylinder); 586 *headp = head; 587 *sectorp = DOSSECT(sector + 1, cylinder); 588 } 589 590 int fd; 591 592 int 593 open_disk(u_flag) 594 int u_flag; 595 { 596 struct stat st; 597 598 if ((fd = open(disk, u_flag ? O_RDWR : O_RDONLY)) == -1) { 599 warn("%s", disk); 600 return (-1); 601 } 602 if (fstat(fd, &st) == -1) { 603 close(fd); 604 warn("%s", disk); 605 return (-1); 606 } 607 if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) { 608 close(fd); 609 warnx("%s is not a character device or regular file", disk); 610 return (-1); 611 } 612 if (get_params() == -1) { 613 close(fd); 614 return (-1); 615 } 616 return (0); 617 } 618 619 int 620 read_disk(sector, buf) 621 int sector; 622 void *buf; 623 { 624 625 if (lseek(fd, (off_t)(sector * 512), 0) == -1) 626 return (-1); 627 return (read(fd, buf, 512)); 628 } 629 630 int 631 write_disk(sector, buf) 632 int sector; 633 void *buf; 634 { 635 636 if (lseek(fd, (off_t)(sector * 512), 0) == -1) 637 return (-1); 638 return (write(fd, buf, 512)); 639 } 640 641 int 642 get_params() 643 { 644 645 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 646 warn("DIOCGDINFO"); 647 return (-1); 648 } 649 650 dos_cylinders = cylinders = disklabel.d_ncylinders; 651 dos_heads = heads = disklabel.d_ntracks; 652 dos_sectors = sectors = disklabel.d_nsectors; 653 dos_cylindersectors = cylindersectors = heads * sectors; 654 disksectors = cylinders * heads * sectors; 655 656 return (0); 657 } 658 659 int 660 read_s0() 661 { 662 663 if (read_disk(0, mboot.bootinst) == -1) { 664 warn("can't read fdisk partition table"); 665 return (-1); 666 } 667 if (mboot.signature != BOOT_MAGIC) { 668 warn("invalid fdisk partition table found"); 669 /* So should we initialize things? */ 670 return (-1); 671 } 672 return (0); 673 } 674 675 int 676 write_s0() 677 { 678 int flag; 679 680 /* 681 * write enable label sector before write (if necessary), 682 * disable after writing. 683 * needed if the disklabel protected area also protects 684 * sector 0. (e.g. empty disk) 685 */ 686 flag = 1; 687 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 688 warn("DIOCWLABEL"); 689 if (write_disk(0, mboot.bootinst) == -1) { 690 warn("can't write fdisk partition table"); 691 return -1; 692 } 693 flag = 0; 694 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 695 warn("DIOCWLABEL"); 696 } 697 698 int 699 yesno(str) 700 char *str; 701 { 702 int ch, first; 703 704 printf("%s [n] ", str); 705 706 first = ch = getchar(); 707 while (ch != '\n' && ch != EOF) 708 ch = getchar(); 709 return (first == 'y' || first == 'Y'); 710 } 711 712 void 713 decimal(str, num) 714 char *str; 715 int *num; 716 { 717 int acc = 0; 718 char *cp; 719 720 for (;; printf("%s is not a valid decimal number.\n", lbuf)) { 721 printf("Supply a decimal value for \"%s\" [%d] ", str, *num); 722 723 fgets(lbuf, LBUF, stdin); 724 lbuf[strlen(lbuf)-1] = '\0'; 725 cp = lbuf; 726 727 cp += strspn(cp, " \t"); 728 if (*cp == '\0') 729 return; 730 731 if (!isdigit(*cp)) 732 continue; 733 acc = strtol(lbuf, &cp, 10); 734 735 cp += strspn(cp, " \t"); 736 if (*cp != '\0') 737 continue; 738 739 *num = acc; 740 return; 741 } 742 743 } 744 745 int 746 type_match(key, item) 747 const void *key, *item; 748 { 749 const int *typep = key; 750 const struct part_type *ptr = item; 751 752 if (*typep < ptr->type) 753 return (-1); 754 if (*typep > ptr->type) 755 return (1); 756 return (0); 757 } 758 759 char * 760 get_type(type) 761 int type; 762 { 763 struct part_type *ptr; 764 765 ptr = bsearch(&type, part_types, 766 sizeof(part_types) / sizeof(struct part_type), 767 sizeof(struct part_type), type_match); 768 if (ptr == 0) 769 return ("unknown"); 770 else 771 return (ptr->name); 772 } 773