fdisk.c revision 145765
1/* 2 * Mach Operating System 3 * Copyright (c) 1992 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the 9 * software, derivative works or modified versions, and any portions 10 * thereof, and that both notices appear in supporting documentation. 11 * 12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15 * 16 * Carnegie Mellon requests users of this software to return to 17 * 18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19 * School of Computer Science 20 * Carnegie Mellon University 21 * Pittsburgh PA 15213-3890 22 * 23 * any improvements or extensions that they make and grant Carnegie Mellon 24 * the rights to redistribute these changes. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sbin/fdisk_pc98/fdisk.c 145765 2005-05-01 10:08:35Z nyan $"); 29 30#include <sys/disk.h> 31#include <sys/disklabel.h> 32#include <sys/diskpc98.h> 33#include <sys/param.h> 34#include <sys/stat.h> 35#include <sys/mount.h> 36#include <ctype.h> 37#include <fcntl.h> 38#include <err.h> 39#include <errno.h> 40#include <paths.h> 41#include <regex.h> 42#include <stdint.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47 48int iotest; 49 50#define LBUF 100 51static char lbuf[LBUF]; 52 53/* 54 * 55 * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 56 * 57 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 58 * Copyright (c) 1989 Robert. V. Baron 59 * Created. 60 */ 61 62#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 63#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 64 65#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 66 67#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 68#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 69static int secsize = 0; /* the sensed sector size */ 70 71static char *disk; 72 73static int cyls, sectors, heads, cylsecs, disksecs; 74 75struct mboot { 76 unsigned char padding[2]; /* force the longs to be long aligned */ 77 unsigned char bootinst[510]; 78 unsigned short int signature; 79 struct pc98_partition parts[8]; 80 unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; 81}; 82 83static struct mboot mboot; 84static int fd, fdw; 85 86#define ACTIVE 0x80 87 88static uint dos_cyls; 89static uint dos_heads; 90static uint dos_sectors; 91static uint dos_cylsecs; 92 93#define MAX_ARGS 10 94 95typedef struct cmd { 96 char cmd; 97 int n_args; 98 struct arg { 99 char argtype; 100 int arg_val; 101 } args[MAX_ARGS]; 102} CMD; 103 104static int B_flag = 0; /* replace boot code */ 105static int a_flag = 0; /* set active partition */ 106static int i_flag = 0; /* replace partition data */ 107static int u_flag = 0; /* update partition data */ 108static int s_flag = 0; /* Print a summary and exit */ 109static int t_flag = 0; /* test only */ 110static char *f_flag = NULL; /* Read config info from file */ 111static int v_flag = 0; /* Be verbose */ 112 113static struct part_type 114{ 115 unsigned char type; 116 const char *name; 117} part_types[] = { 118 {0x00, "unused"} 119 ,{0x01, "Primary DOS with 12 bit FAT"} 120 ,{0x11, "MSDOS"} 121 ,{0x20, "MSDOS"} 122 ,{0x21, "MSDOS"} 123 ,{0x22, "MSDOS"} 124 ,{0x23, "MSDOS"} 125 ,{0x02, "XENIX / file system"} 126 ,{0x03, "XENIX /usr file system"} 127 ,{0x04, "PC-UX"} 128 ,{0x05, "Extended DOS"} 129 ,{0x06, "Primary 'big' DOS (> 32MB)"} 130 ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"} 131 ,{0x08, "AIX file system"} 132 ,{0x09, "AIX boot partition or Coherent"} 133 ,{0x0A, "OS/2 Boot Manager or OPUS"} 134 ,{0x10, "OPUS"} 135 ,{0x14, "FreeBSD/NetBSD/386BSD"} 136 ,{0x94, "FreeBSD/NetBSD/386BSD"} 137 ,{0x40, "VENIX 286"} 138 ,{0x50, "DM"} 139 ,{0x51, "DM"} 140 ,{0x52, "CP/M or Microport SysV/AT"} 141 ,{0x56, "GB"} 142 ,{0x61, "Speed"} 143 ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 144 ,{0x64, "Novell Netware 2.xx"} 145 ,{0x65, "Novell Netware 3.xx"} 146 ,{0x75, "PCIX"} 147 ,{0x40, "Minix"} 148}; 149 150static void print_s0(int which); 151static void print_part(int i); 152static void init_sector0(unsigned long start); 153static void init_boot(void); 154static void change_part(int i); 155static void print_params(void); 156static void change_active(int which); 157static void change_code(void); 158static void get_params_to_use(void); 159static char *get_rootdisk(void); 160static void dos(u_int32_t start, u_int32_t size, struct pc98_partition *partp); 161static int open_disk(int flag); 162static ssize_t read_disk(off_t sector, void *buf); 163static ssize_t write_disk(off_t sector, void *buf); 164static int get_params(void); 165static int read_s0(void); 166static int write_s0(void); 167static int ok(const char *str); 168static int decimal(const char *str, int *num, int deflt); 169static const char *get_type(int type); 170static void usage(void); 171static int string(const char *str, char **ans); 172 173int 174main(int argc, char *argv[]) 175{ 176 struct stat sb; 177 int c, i; 178 int partition = -1; 179 struct pc98_partition *partp; 180 181 while ((c = getopt(argc, argv, "Ba:f:istuv12345678")) != -1) 182 switch (c) { 183 case 'B': 184 B_flag = 1; 185 break; 186 case 'a': 187 a_flag = 1; 188 break; 189 case 'f': 190 f_flag = optarg; 191 break; 192 case 'i': 193 i_flag = 1; 194 break; 195 case 's': 196 s_flag = 1; 197 break; 198 case 't': 199 t_flag = 1; 200 break; 201 case 'u': 202 u_flag = 1; 203 break; 204 case 'v': 205 v_flag = 1; 206 break; 207 case '1': 208 case '2': 209 case '3': 210 case '4': 211 case '5': 212 case '6': 213 case '7': 214 case '8': 215 partition = c - '0'; 216 break; 217 default: 218 usage(); 219 } 220 if (f_flag || i_flag) 221 u_flag = 1; 222 if (t_flag) 223 v_flag = 1; 224 argc -= optind; 225 argv += optind; 226 227 if (argc == 0) { 228 disk = get_rootdisk(); 229 } else { 230 if (stat(argv[0], &sb) == 0) { 231 /* OK, full pathname given */ 232 disk = argv[0]; 233 } else if (errno == ENOENT && argv[0][0] != '/') { 234 /* Try prepending "/dev" */ 235 asprintf(&disk, "%s%s", _PATH_DEV, argv[0]); 236 if (disk == NULL) 237 errx(1, "out of memory"); 238 } else { 239 /* other stat error, let it fail below */ 240 disk = argv[0]; 241 } 242 } 243 if (open_disk(u_flag) < 0) 244 err(1, "cannot open disk %s", disk); 245 246 if (s_flag) { 247 if (read_s0()) 248 err(1, "read_s0"); 249 printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 250 dos_sectors); 251 printf("Part %11s %11s SID\n", "Start", "Size"); 252 for (i = 0; i < NDOSPART; i++) { 253 partp = ((struct pc98_partition *) &mboot.parts) + i; 254 if (partp->dp_sid == 0) 255 continue; 256 printf("%4d: %11u %11u 0x%02x\n", i + 1, 257 partp->dp_scyl * cylsecs, 258 (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs, 259 partp->dp_sid); 260 } 261 exit(0); 262 } 263 264 printf("******* Working on device %s *******\n",disk); 265 266 if (f_flag) { 267 if (v_flag) 268 print_s0(-1); 269 if (!t_flag) 270 write_s0(); 271 } else { 272 if(u_flag) 273 get_params_to_use(); 274 else 275 print_params(); 276 277 if (read_s0()) 278 init_sector0(dos_sectors); 279 280 printf("Media sector size is %d\n", secsize); 281 printf("Warning: BIOS sector numbering starts with sector 1\n"); 282 printf("Information from DOS bootblock is:\n"); 283 if (partition == -1) 284 for (i = 1; i <= NDOSPART; i++) 285 change_part(i); 286 else 287 change_part(partition); 288 289 if (u_flag || a_flag) 290 change_active(partition); 291 292 if (B_flag) 293 change_code(); 294 295 if (u_flag || a_flag || B_flag) { 296 if (!t_flag) { 297 printf("\nWe haven't changed the partition table yet. "); 298 printf("This is your last chance.\n"); 299 } 300 print_s0(-1); 301 if (!t_flag) { 302 if (ok("Should we write new partition table?")) 303 write_s0(); 304 } else { 305 printf("\n-t flag specified -- partition table not written.\n"); 306 } 307 } 308 } 309 310 exit(0); 311} 312 313static void 314usage() 315{ 316 fprintf(stderr, "%s%s", 317 "usage: fdisk [-Baistu] [-12345678] [disk]\n", 318 " fdisk -f configfile [-itv] [disk]\n"); 319 exit(1); 320} 321 322static void 323print_s0(int which) 324{ 325 int i; 326 327 print_params(); 328 printf("Information from DOS bootblock is:\n"); 329 if (which == -1) 330 for (i = 1; i <= NDOSPART; i++) 331 printf("%d: ", i), print_part(i); 332 else 333 print_part(which); 334} 335 336static struct pc98_partition mtpart; 337 338static void 339print_part(int i) 340{ 341 struct pc98_partition *partp; 342 u_int64_t part_sz, part_mb; 343 344 partp = ((struct pc98_partition *) &mboot.parts) + i - 1; 345 346 if (!bcmp(partp, &mtpart, sizeof (struct pc98_partition))) { 347 printf("<UNUSED>\n"); 348 return; 349 } 350 /* 351 * Be careful not to overflow. 352 */ 353 part_sz = (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs; 354 part_mb = part_sz * secsize; 355 part_mb /= (1024 * 1024); 356 printf("sysmid %d (%#04x),(%s)\n", partp->dp_mid, partp->dp_mid, 357 get_type(partp->dp_mid)); 358 printf(" start %lu, size %lu (%ju Meg), sid %d\n", 359 (u_long)(partp->dp_scyl * cylsecs), (u_long)part_sz, 360 (uintmax_t)part_mb, partp->dp_sid); 361 printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n" 362 ,partp->dp_scyl 363 ,partp->dp_shd 364 ,partp->dp_ssect 365 ,partp->dp_ecyl 366 ,partp->dp_ehd 367 ,partp->dp_esect); 368 printf ("\tsystem Name %.16s\n", partp->dp_name); 369} 370 371 372static void 373init_boot(void) 374{ 375 376 mboot.signature = DOSMAGIC; 377} 378 379 380static void 381init_sector0(unsigned long start) 382{ 383 struct pc98_partition *partp = 384 (struct pc98_partition *)(&mboot.parts[0]); 385 386 init_boot(); 387 388 partp->dp_mid = DOSMID_386BSD; 389 partp->dp_sid = DOSSID_386BSD; 390 391 dos(start, disksecs - start, partp); 392} 393 394static void 395change_part(int i) 396{ 397 struct pc98_partition *partp = 398 ((struct pc98_partition *) &mboot.parts) + i - 1; 399 400 printf("The data for partition %d is:\n", i); 401 print_part(i); 402 403 if (u_flag && ok("Do you want to change it?")) { 404 int tmp; 405 406 if (i_flag) { 407 bzero((char *)partp, sizeof (struct pc98_partition)); 408 if (i == 1) { 409 init_sector0(1); 410 printf("\nThe static data for the slice 1 has been reinitialized to:\n"); 411 print_part(i); 412 } 413 } 414 415 do { 416 int x_start = partp->dp_scyl * cylsecs ; 417 int x_size = (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs; 418 Decimal("sysmid", partp->dp_mid, tmp); 419 Decimal("syssid", partp->dp_sid, tmp); 420 String ("system name", partp->dp_name, 16); 421 Decimal("start", x_start, tmp); 422 Decimal("size", x_size, tmp); 423 424 if (ok("Explicitly specify beg/end address ?")) 425 { 426 int tsec,tcyl,thd; 427 tcyl = partp->dp_scyl; 428 thd = partp->dp_shd; 429 tsec = partp->dp_ssect; 430 Decimal("beginning cylinder", tcyl, tmp); 431 Decimal("beginning head", thd, tmp); 432 Decimal("beginning sector", tsec, tmp); 433 partp->dp_scyl = tcyl; 434 partp->dp_ssect = tsec; 435 partp->dp_shd = thd; 436 partp->dp_ipl_cyl = partp->dp_scyl; 437 partp->dp_ipl_sct = partp->dp_ssect; 438 partp->dp_ipl_head = partp->dp_shd; 439 440 tcyl = partp->dp_ecyl; 441 thd = partp->dp_ehd; 442 tsec = partp->dp_esect; 443 Decimal("ending cylinder", tcyl, tmp); 444 Decimal("ending head", thd, tmp); 445 Decimal("ending sector", tsec, tmp); 446 partp->dp_ecyl = tcyl; 447 partp->dp_esect = tsec; 448 partp->dp_ehd = thd; 449 } else 450 dos(x_start, x_size, partp); 451 452 print_part(i); 453 } while (!ok("Are we happy with this entry?")); 454 } 455} 456 457static void 458print_params() 459{ 460 printf("parameters extracted from in-core disklabel are:\n"); 461 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 462 ,cyls,heads,sectors,cylsecs); 463 if (dos_cyls > 65535 || dos_heads > 255 || dos_sectors > 255) 464 printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 465 printf("parameters to be used for BIOS calculations are:\n"); 466 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 467 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 468} 469 470static void 471change_active(int which) 472{ 473 struct pc98_partition *partp = &mboot.parts[0]; 474 int active, i, new, tmp; 475 476 active = -1; 477 for (i = 0; i < NDOSPART; i++) { 478 if ((partp[i].dp_sid & ACTIVE) == 0) 479 continue; 480 printf("Partition %d is marked active\n", i + 1); 481 if (active == -1) 482 active = i + 1; 483 } 484 if (a_flag && which != -1) 485 active = which; 486 else if (active == -1) 487 active = 1; 488 489 if (!ok("Do you want to change the active partition?")) 490 return; 491setactive: 492 do { 493 new = active; 494 Decimal("active partition", new, tmp); 495 if (new < 1 || new > 8) { 496 printf("Active partition number must be in range 1-8." 497 " Try again.\n"); 498 goto setactive; 499 } 500 active = new; 501 } while (!ok("Are you happy with this choice")); 502 if (active > 0 && active <= 8) 503 partp[active-1].dp_sid |= ACTIVE; 504} 505 506static void 507change_code() 508{ 509 if (ok("Do you want to change the boot code?")) 510 init_boot(); 511} 512 513void 514get_params_to_use() 515{ 516 int tmp; 517 print_params(); 518 if (ok("Do you want to change our idea of what BIOS thinks ?")) 519 { 520 do 521 { 522 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 523 Decimal("BIOS's idea of #heads", dos_heads, tmp); 524 Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 525 dos_cylsecs = dos_heads * dos_sectors; 526 print_params(); 527 } 528 while(!ok("Are you happy with this choice")); 529 } 530} 531 532 533/***********************************************\ 534* Change real numbers into strange dos numbers * 535\***********************************************/ 536static void 537dos(u_int32_t start, u_int32_t size, struct pc98_partition *partp) 538{ 539 u_int32_t end; 540 541 if (partp->dp_mid == 0 && partp->dp_sid == 0 && 542 start == 0 && size == 0) { 543 memcpy(partp, &mtpart, sizeof(*partp)); 544 return; 545 } 546 547 /* Start c/h/s. */ 548 partp->dp_scyl = partp->dp_ipl_cyl = start / dos_cylsecs; 549 partp->dp_shd = partp->dp_ipl_head = start % dos_cylsecs / dos_sectors; 550 partp->dp_ssect = partp->dp_ipl_sct = start % dos_sectors; 551 552 /* End c/h/s. */ 553 end = start + size - cylsecs; 554 partp->dp_ecyl = end / dos_cylsecs; 555 partp->dp_ehd = end % dos_cylsecs / dos_sectors; 556 partp->dp_esect = end % dos_sectors; 557} 558 559static int 560open_disk(int flag) 561{ 562 struct stat st; 563 int rwmode, p; 564 char *s; 565 566 fdw = -1; 567 if (stat(disk, &st) == -1) { 568 if (errno == ENOENT) 569 return -2; 570 warnx("can't get file status of %s", disk); 571 return -1; 572 } 573 if ( !(st.st_mode & S_IFCHR) ) 574 warnx("device %s is not character special", disk); 575 rwmode = a_flag || B_flag || flag ? O_RDWR : O_RDONLY; 576 fd = open(disk, rwmode); 577 if (fd == -1 && errno == ENXIO) 578 return -2; 579 if (fd == -1 && errno == EPERM && rwmode == O_RDWR) { 580 fd = open(disk, O_RDONLY); 581 if (fd == -1) 582 return -3; 583 for (p = 0; p < NDOSPART; p++) { 584 asprintf(&s, "%ss%d", disk, p + 1); 585 fdw = open(s, rwmode); 586 free(s); 587 if (fdw == -1) 588 continue; 589 break; 590 } 591 if (fdw == -1) 592 return -4; 593 } 594 if (fd == -1) { 595 warnx("can't open device %s", disk); 596 return -1; 597 } 598 if (get_params() == -1) { 599 warnx("can't get disk parameters on %s", disk); 600 return -1; 601 } 602 return fd; 603} 604 605static ssize_t 606read_disk(off_t sector, void *buf) 607{ 608 609 lseek(fd, (sector * 512), 0); 610 return read(fd, buf, 611 secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2); 612} 613 614static ssize_t 615write_disk(off_t sector, void *buf) 616{ 617 618 if (fdw != -1) { 619 return ioctl(fdw, DIOCSPC98, buf); 620 } else { 621 lseek(fd, (sector * 512), 0); 622 /* write out in the size that the read_disk found worked */ 623 return write(fd, buf, 624 secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2); 625 } 626} 627 628static int 629get_params() 630{ 631 int error; 632 u_int u; 633 off_t o; 634 635 error = ioctl(fd, DIOCGFWSECTORS, &u); 636 if (error == 0) 637 sectors = dos_sectors = u; 638 else 639 sectors = dos_sectors = 17; 640 641 error = ioctl(fd, DIOCGFWHEADS, &u); 642 if (error == 0) 643 heads = dos_heads = u; 644 else 645 heads = dos_heads = 8; 646 647 dos_cylsecs = cylsecs = heads * sectors; 648 disksecs = cyls * heads * sectors; 649 650 error = ioctl(fd, DIOCGSECTORSIZE, &u); 651 if (error != 0 || u == 0) 652 u = 512; 653 secsize = u; 654 655 error = ioctl(fd, DIOCGMEDIASIZE, &o); 656 if (error == 0) { 657 disksecs = o / u; 658 cyls = dos_cyls = o / (u * dos_heads * dos_sectors); 659 } 660 661 return (disksecs); 662} 663 664 665static int 666read_s0() 667{ 668 669 if (read_disk(0, (char *) mboot.bootinst) == -1) { 670 warnx("can't read fdisk partition table"); 671 return -1; 672 } 673 if (mboot.signature != DOSMAGIC) { 674 warnx("invalid fdisk partition table found"); 675 /* So should we initialize things */ 676 return -1; 677 } 678 679 return 0; 680} 681 682static int 683write_s0() 684{ 685 686 if (iotest) { 687 print_s0(-1); 688 return 0; 689 } 690 691 /* 692 * write enable label sector before write (if necessary), 693 * disable after writing. 694 * needed if the disklabel protected area also protects 695 * sector 0. (e.g. empty disk) 696 */ 697 if (write_disk(0, (char *) mboot.bootinst) == -1) { 698 warn("can't write fdisk partition table"); 699 return -1; 700 } 701 702 return(0); 703} 704 705 706static int 707ok(const char *str) 708{ 709 printf("%s [n] ", str); 710 fflush(stdout); 711 if (fgets(lbuf, LBUF, stdin) == NULL) 712 exit(1); 713 lbuf[strlen(lbuf)-1] = 0; 714 715 if (*lbuf && 716 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 717 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 718 return 1; 719 else 720 return 0; 721} 722 723static int 724decimal(const char *str, int *num, int deflt) 725{ 726 int acc = 0, c; 727 char *cp; 728 729 while (1) { 730 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 731 fflush(stdout); 732 if (fgets(lbuf, LBUF, stdin) == NULL) 733 exit(1); 734 lbuf[strlen(lbuf)-1] = 0; 735 736 if (!*lbuf) 737 return 0; 738 739 cp = lbuf; 740 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 741 if (!c) 742 return 0; 743 while ((c = *cp++)) { 744 if (c <= '9' && c >= '0') 745 acc = acc * 10 + c - '0'; 746 else 747 break; 748 } 749 if (c == ' ' || c == '\t') 750 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 751 if (!c) { 752 *num = acc; 753 return 1; 754 } else 755 printf("%s is an invalid decimal number. Try again.\n", 756 lbuf); 757 } 758 759} 760 761static int 762string(const char *str, char **ans) 763{ 764 int i, c; 765 char *cp = lbuf; 766 767 while (1) { 768 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 769 fgets(lbuf, LBUF, stdin); 770 lbuf[strlen(lbuf)-1] = 0; 771 772 if (!*lbuf) 773 return 0; 774 775 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 776 if (c == '"') { 777 c = *++cp; 778 *ans = cp; 779 while ((c = *cp) && c != '"') cp++; 780 } else { 781 *ans = cp; 782 while ((c = *cp) && c != ' ' && c != '\t') cp++; 783 } 784 785 for (i = strlen(*ans); i < 16; i++) 786 (*ans)[i] = ' '; 787 (*ans)[16] = 0; 788 789 return 1; 790 } 791} 792 793static const char * 794get_type(int type) 795{ 796 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 797 int counter = 0; 798 struct part_type *ptr = part_types; 799 800 801 while(counter < numentries) { 802 if(ptr->type == (type & 0x7f)) 803 return(ptr->name); 804 ptr++; 805 counter++; 806 } 807 return("unknown"); 808} 809 810/* 811 * Try figuring out the root device's canonical disk name. 812 * The following choices are considered: 813 * /dev/ad0s1a => /dev/ad0 814 * /dev/da0a => /dev/da0 815 * /dev/vinum/root => /dev/vinum/root 816 */ 817static char * 818get_rootdisk(void) 819{ 820 struct statfs rootfs; 821 regex_t re; 822#define NMATCHES 2 823 regmatch_t rm[NMATCHES]; 824 char *s; 825 int rv; 826 827 if (statfs("/", &rootfs) == -1) 828 err(1, "statfs(\"/\")"); 829 830 if ((rv = regcomp(&re, "^(/dev/[a-z]+[0-9]+)([sp][0-9]+)?[a-h]?$", 831 REG_EXTENDED)) != 0) 832 errx(1, "regcomp() failed (%d)", rv); 833 if ((rv = regexec(&re, rootfs.f_mntfromname, NMATCHES, rm, 0)) != 0) 834 errx(1, 835"mounted root fs resource doesn't match expectations (regexec returned %d)", 836 rv); 837 if ((s = malloc(rm[1].rm_eo - rm[1].rm_so + 1)) == NULL) 838 errx(1, "out of memory"); 839 memcpy(s, rootfs.f_mntfromname + rm[1].rm_so, 840 rm[1].rm_eo - rm[1].rm_so); 841 s[rm[1].rm_eo - rm[1].rm_so] = 0; 842 843 return s; 844} 845