fdisk.c revision 18915
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/types.h> 28#include <sys/disklabel.h> 29#include <stdio.h> 30#include <string.h> 31#include <errno.h> 32#include <sys/stat.h> 33#include <sys/ioctl.h> 34#include <fcntl.h> 35#include <unistd.h> 36 37int iotest; 38 39#define LBUF 100 40static char lbuf[LBUF]; 41 42/* 43 * 44 * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 45 * 46 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 47 * Copyright (c) 1989 Robert. V. Baron 48 * Created. 49 */ 50 51#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 52#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 53#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 54 55#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 56 57#define SECSIZE 512 58 59const char *disk; 60const char *disks[] = 61{ 62 "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 63}; 64 65char *name; 66 67struct disklabel disklabel; /* disk parameters */ 68 69int cyls, sectors, heads, cylsecs, disksecs; 70 71struct mboot 72{ 73 unsigned char padding[2]; /* force the longs to be long alligned */ 74 unsigned char bootinst[DOSPARTOFF]; 75 struct dos_partition parts[4]; 76 unsigned short int signature; 77}; 78struct mboot mboot; 79 80#define ACTIVE 0x80 81#define BOOT_MAGIC 0xAA55 82 83int dos_cyls; 84int dos_heads; 85int dos_sectors; 86int dos_cylsecs; 87 88#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 89#define DOSCYL(c) (c & 0xff) 90static int partition = -1; 91 92 93static int a_flag = 0; /* set active partition */ 94static int i_flag = 0; /* replace partition data */ 95static int u_flag = 0; /* update partition data */ 96 97static unsigned char bootcode[] = { 980x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 990x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 1000xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 1010x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 1020x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 1030x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 1040x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 1050x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 1060xeb, 0xf4, 0xfb, 0xeb, 0xfe, 107'M', 'i', 's', 's', 'i', 'n', 'g', ' ', 108 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 109'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ', 110 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 111'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ', 112 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0, 113'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ', 114 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0, 115 116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 129}; 130 131struct part_type 132{ 133 unsigned char type; 134 char *name; 135}part_types[] = 136{ 137 {0x00, "unused"} 138 ,{0x01, "Primary DOS with 12 bit FAT"} 139 ,{0x02, "XENIX / filesystem"} 140 ,{0x03, "XENIX /usr filesystem"} 141 ,{0x04, "Primary DOS with 16 bit FAT"} 142 ,{0x05, "Extended DOS"} 143 ,{0x06, "Primary 'big' DOS (> 32MB)"} 144 ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"} 145 ,{0x08, "AIX filesystem"} 146 ,{0x09, "AIX boot partition or Coherent"} 147 ,{0x0A, "OS/2 Boot Manager or OPUS"} 148 ,{0x10, "OPUS"} 149 ,{0x40, "VENIX 286"} 150 ,{0x50, "DM"} 151 ,{0x51, "DM"} 152 ,{0x52, "CP/M or Microport SysV/AT"} 153 ,{0x56, "GB"} 154 ,{0x61, "Speed"} 155 ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 156 ,{0x64, "Novell Netware 2.xx"} 157 ,{0x65, "Novell Netware 3.xx"} 158 ,{0x75, "PCIX"} 159 ,{0x80, "Minix 1.1 ... 1.4a"} 160 ,{0x81, "Minix 1.4b ... 1.5.10"} 161 ,{0x82, "Linux swap"} 162 ,{0x83, "Linux filesystem"} 163 ,{0x93, "Amoeba filesystem"} 164 ,{0x94, "Amoeba bad block table"} 165 ,{0xA5, "FreeBSD/NetBSD/386BSD"} 166 ,{0xA7, "NEXTSTEP"} 167 ,{0xB7, "BSDI BSD/386 filesystem"} 168 ,{0xB8, "BSDI BSD/386 swap"} 169 ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 170 ,{0xE1, "Speed"} 171 ,{0xE3, "Speed"} 172 ,{0xE4, "Speed"} 173 ,{0xF1, "Speed"} 174 ,{0xF2, "DOS 3.3+ Secondary"} 175 ,{0xF4, "Speed"} 176 ,{0xFF, "BBT (Bad Blocks Table)"} 177}; 178 179static void print_s0(int which); 180static void print_part(int i); 181static void init_sector0(unsigned long start); 182static void change_part(int i); 183static void print_params(); 184static void change_active(int which); 185static void get_params_to_use(); 186static void dos(int sec, int size, unsigned char *c, unsigned char *s, 187 unsigned char *h); 188static int open_disk(int u_flag); 189static ssize_t read_disk(off_t sector, void *buf); 190static ssize_t write_disk(off_t sector, void *buf); 191static int get_params(); 192static int read_s0(); 193static int write_s0(); 194static int ok(char *str); 195static int decimal(char *str, int *num, int deflt); 196static char *get_type(int type); 197#if 0 198static int hex(char *str, int *num, int deflt); 199static int string(char *str, char **ans); 200#endif 201 202 203int 204main(int argc, char *argv[]) 205{ 206 int i; 207 208 name = *argv; 209 {register char *cp = name; 210 while (*cp) if (*cp++ == '/') name = cp; 211 } 212 213 for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 214 if (*token++ != '-' || !*token) 215 break; 216 else { register int flag; 217 for ( ; (flag = *token++) ; ) { 218 switch (flag) { 219 case '0': 220 partition = 0; 221 break; 222 case '1': 223 partition = 1; 224 break; 225 case '2': 226 partition = 2; 227 break; 228 case '3': 229 partition = 3; 230 break; 231 case 'a': 232 a_flag = 1; 233 break; 234 case 'i': 235 i_flag = 1; 236 case 'u': 237 u_flag = 1; 238 break; 239 default: 240 goto usage; 241 } 242 } 243 } 244 } 245 246 if (argc > 0) 247 { 248 static char realname[12]; 249 250 if(strncmp(argv[0], "/dev", 4) == 0) 251 disk = argv[0]; 252 else 253 { 254 snprintf(realname, 12, "/dev/r%s", argv[0]); 255 disk = realname; 256 } 257 258 if (open_disk(u_flag) < 0) 259 { 260 fprintf(stderr, "Cannot open disk %s (%s)\n", 261 disk, sys_errlist[errno]); 262 exit(1); 263 } 264 } 265 else 266 { 267 int i, rv = 0; 268 269 for(i = 0; disks[i]; i++) 270 { 271 disk = disks[i]; 272 rv = open_disk(u_flag); 273 if(rv != -2) break; 274 } 275 if(rv < 0) 276 { 277 fprintf(stderr, "Cannot open any disk (%s)\n", 278 sys_errlist[errno]); 279 exit(1); 280 } 281 } 282 283 printf("******* Working on device %s *******\n",disk); 284 if(u_flag) 285 { 286 get_params_to_use(); 287 } 288 else 289 { 290 print_params(); 291 } 292 293 if (read_s0()) 294 init_sector0(1); 295 296 printf("Warning: BIOS sector numbering starts with sector 1\n"); 297 printf("Information from DOS bootblock is:\n"); 298 if (partition == -1) 299 for (i = 0; i < NDOSPART; i++) 300 change_part(i); 301 else 302 change_part(partition); 303 304 if (u_flag || a_flag) 305 change_active(partition); 306 307 if (u_flag || a_flag) { 308 printf("\nWe haven't changed the partition table yet. "); 309 printf("This is your last chance.\n"); 310 print_s0(-1); 311 if (ok("Should we write new partition table?")) 312 write_s0(); 313 } 314 315 exit(0); 316 317usage: 318 printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n"); 319 return(1); 320} 321 322static void 323print_s0(int which) 324{ 325int i; 326 327 print_params(); 328 printf("Information from DOS bootblock is:\n"); 329 if (which == -1) 330 for (i = 0; i < NDOSPART; i++) 331 printf("%d: ", i), print_part(i); 332 else 333 print_part(which); 334} 335 336static struct dos_partition mtpart = { 0 }; 337 338static void 339print_part(int i) 340{ 341struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 342 343 344 if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 345 printf("<UNUSED>\n"); 346 return; 347 } 348 printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 349 printf(" start %ld, size %ld (%ld Meg), flag %x\n", 350 partp->dp_start, 351 partp->dp_size, partp->dp_size * 512 / (1024 * 1024), 352 partp->dp_flag); 353 printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 354 ,DPCYL(partp->dp_scyl, partp->dp_ssect) 355 ,DPSECT(partp->dp_ssect) 356 ,partp->dp_shd 357 ,DPCYL(partp->dp_ecyl, partp->dp_esect) 358 ,DPSECT(partp->dp_esect) 359 ,partp->dp_ehd); 360} 361 362static void 363init_sector0(unsigned long start) 364{ 365struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 366unsigned long size = disksecs - start; 367 368 memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 369 mboot.signature = BOOT_MAGIC; 370 371 partp->dp_typ = DOSPTYP_386BSD; 372 partp->dp_flag = ACTIVE; 373 partp->dp_start = start; 374 partp->dp_size = size; 375 376 dos(partp->dp_start, partp->dp_size, 377 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 378 dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 379 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 380} 381 382static void 383change_part(int i) 384{ 385struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 386 387 printf("The data for partition %d is:\n", i); 388 print_part(i); 389 390 if (u_flag && ok("Do you want to change it?")) { 391 int tmp; 392 393 if (i_flag) { 394 bzero((char *)partp, sizeof (struct dos_partition)); 395 if (i == 3) { 396 init_sector0(1); 397 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); 398 print_part(i); 399 } 400 } 401 402 do { 403 Decimal("sysid", partp->dp_typ, tmp); 404 Decimal("start", partp->dp_start, tmp); 405 Decimal("size", partp->dp_size, tmp); 406 407 if (ok("Explicitly specifiy beg/end address ?")) 408 { 409 int tsec,tcyl,thd; 410 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 411 thd = partp->dp_shd; 412 tsec = DPSECT(partp->dp_ssect); 413 Decimal("beginning cylinder", tcyl, tmp); 414 Decimal("beginning head", thd, tmp); 415 Decimal("beginning sector", tsec, tmp); 416 partp->dp_scyl = DOSCYL(tcyl); 417 partp->dp_ssect = DOSSECT(tsec,tcyl); 418 partp->dp_shd = thd; 419 420 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 421 thd = partp->dp_ehd; 422 tsec = DPSECT(partp->dp_esect); 423 Decimal("ending cylinder", tcyl, tmp); 424 Decimal("ending head", thd, tmp); 425 Decimal("ending sector", tsec, tmp); 426 partp->dp_ecyl = DOSCYL(tcyl); 427 partp->dp_esect = DOSSECT(tsec,tcyl); 428 partp->dp_ehd = thd; 429 } else { 430 dos(partp->dp_start, partp->dp_size, 431 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 432 dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 433 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 434 } 435 436 print_part(i); 437 } while (!ok("Are we happy with this entry?")); 438 } 439} 440 441static void 442print_params() 443{ 444 printf("parameters extracted from in-core disklabel are:\n"); 445 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 446 ,cyls,heads,sectors,cylsecs); 447 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 448 printf(" Figures below won't work with BIOS for partitions not in cyl 1\n"); 449 printf("parameters to be used for BIOS calculations are:\n"); 450 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 451 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 452} 453 454static void 455change_active(int which) 456{ 457int i; 458int active = 3, tmp; 459struct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 460 461 if (a_flag && which != -1) 462 active = which; 463 if (!ok("Do you want to change the active partition?")) 464 return; 465 do 466 Decimal("active partition", active, tmp); 467 while (!ok("Are you happy with this choice")); 468 for (i = 0; i < NDOSPART; i++) 469 partp[i].dp_flag = 0; 470 if (active >= 0 && active < NDOSPART) 471 partp[active].dp_flag = ACTIVE; 472} 473 474void 475get_params_to_use() 476{ 477 int tmp; 478 print_params(); 479 if (ok("Do you want to change our idea of what BIOS thinks ?")) 480 { 481 do 482 { 483 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 484 Decimal("BIOS's idea of #heads", dos_heads, tmp); 485 Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 486 dos_cylsecs = dos_heads * dos_sectors; 487 print_params(); 488 } 489 while(!ok("Are you happy with this choice")); 490 } 491} 492 493/***********************************************\ 494* Change real numbers into strange dos numbers * 495\***********************************************/ 496static void 497dos(sec, size, c, s, h) 498int sec, size; 499unsigned char *c, *s, *h; 500{ 501int cy; 502int hd; 503 504 if (sec == 0 && size == 0) { 505 *s = *c = *h = 0; 506 return; 507 } 508 509 cy = sec / ( dos_cylsecs ); 510 sec = sec - cy * ( dos_cylsecs ); 511 512 hd = sec / dos_sectors; 513 sec = (sec - hd * dos_sectors) + 1; 514 515 *h = hd; 516 *c = cy & 0xff; 517 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 518} 519 520int fd; 521 522 /* Getting device status */ 523 524static int 525open_disk(int u_flag) 526{ 527struct stat st; 528 529 if (stat(disk, &st) == -1) { 530 fprintf(stderr, "%s: Can't get file status of %s\n", 531 name, disk); 532 return -1; 533 } 534 if ( !(st.st_mode & S_IFCHR) ) 535 fprintf(stderr,"%s: Device %s is not character special\n", 536 name, disk); 537 if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 538 if(errno == ENXIO) 539 return -2; 540 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 541 return -1; 542 } 543 if (get_params(0) == -1) { 544 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 545 name, disk); 546 return -1; 547 } 548 return fd; 549} 550 551static ssize_t 552read_disk(off_t sector, void *buf) 553{ 554 lseek(fd,(sector * 512), 0); 555 return read(fd, buf, 512); 556} 557 558static ssize_t 559write_disk(off_t sector, void *buf) 560{ 561 lseek(fd,(sector * 512), 0); 562 return write(fd, buf, 512); 563} 564 565static int 566get_params() 567{ 568 569 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 570 fprintf(stderr, 571 "%s: Can't get disk parameters on %s; supplying dummy ones\n", 572 name, disk); 573 dos_cyls = cyls = 1; 574 dos_heads = heads = 1; 575 dos_sectors = sectors = 1; 576 dos_cylsecs = cylsecs = heads * sectors; 577 disksecs = cyls * heads * sectors; 578 return disksecs; 579 } 580 581 dos_cyls = cyls = disklabel.d_ncylinders; 582 dos_heads = heads = disklabel.d_ntracks; 583 dos_sectors = sectors = disklabel.d_nsectors; 584 dos_cylsecs = cylsecs = heads * sectors; 585 disksecs = cyls * heads * sectors; 586 587 return (disksecs); 588} 589 590 591static int 592read_s0() 593{ 594 if (read_disk(0, (char *) mboot.bootinst) == -1) { 595 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 596 return -1; 597 } 598 if (mboot.signature != BOOT_MAGIC) { 599 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 600 name); 601 /* So should we initialize things */ 602 return -1; 603 } 604 return 0; 605} 606 607static int 608write_s0() 609{ 610 int flag; 611 if (iotest) { 612 print_s0(-1); 613 return 0; 614 } 615 /* 616 * write enable label sector before write (if necessary), 617 * disable after writing. 618 * needed if the disklabel protected area also protects 619 * sector 0. (e.g. empty disk) 620 */ 621 flag = 1; 622#ifdef NOT_NOW 623 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 624 perror("ioctl DIOCWLABEL"); 625#endif 626 if (write_disk(0, (char *) mboot.bootinst) == -1) { 627 fprintf(stderr, "%s: Can't write fdisk partition table\n", 628 name); 629 return -1; 630 flag = 0; 631#ifdef NOT_NOW 632 (void) ioctl(fd, DIOCWLABEL, &flag); 633#endif 634 } 635 return(0); 636} 637 638 639static int 640ok(str) 641char *str; 642{ 643 printf("%s [n] ", str); 644 fgets(lbuf, LBUF, stdin); 645 lbuf[strlen(lbuf)-1] = 0; 646 647 if (*lbuf && 648 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 649 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 650 return 1; 651 else 652 return 0; 653} 654 655static int 656decimal(char *str, int *num, int deflt) 657{ 658int acc = 0, c; 659char *cp; 660 661 while (1) { 662 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 663 fgets(lbuf, LBUF, stdin); 664 lbuf[strlen(lbuf)-1] = 0; 665 666 if (!*lbuf) 667 return 0; 668 669 cp = lbuf; 670 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 671 if (!c) 672 return 0; 673 while ((c = *cp++)) { 674 if (c <= '9' && c >= '0') 675 acc = acc * 10 + c - '0'; 676 else 677 break; 678 } 679 if (c == ' ' || c == '\t') 680 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 681 if (!c) { 682 *num = acc; 683 return 1; 684 } else 685 printf("%s is an invalid decimal number. Try again\n", 686 lbuf); 687 } 688 689} 690 691#if 0 692static int 693hex(char *str, int *num, int deflt) 694{ 695int acc = 0, c; 696char *cp; 697 698 while (1) { 699 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 700 fgets(lbuf, LBUF, stdin); 701 lbuf[strlen(lbuf)-1] = 0; 702 703 if (!*lbuf) 704 return 0; 705 706 cp = lbuf; 707 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 708 if (!c) 709 return 0; 710 while ((c = *cp++)) { 711 if (c <= '9' && c >= '0') 712 acc = (acc << 4) + c - '0'; 713 else if (c <= 'f' && c >= 'a') 714 acc = (acc << 4) + c - 'a' + 10; 715 else if (c <= 'F' && c >= 'A') 716 acc = (acc << 4) + c - 'A' + 10; 717 else 718 break; 719 } 720 if (c == ' ' || c == '\t') 721 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 722 if (!c) { 723 *num = acc; 724 return 1; 725 } else 726 printf("%s is an invalid hex number. Try again\n", 727 lbuf); 728 } 729 730} 731 732static int 733string(char *str, char **ans) 734{ 735int c; 736char *cp = lbuf; 737 738 while (1) { 739 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 740 fgets(lbuf, LBUF, stdin); 741 lbuf[strlen(lbuf)-1] = 0; 742 743 if (!*lbuf) 744 return 0; 745 746 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 747 if (c == '"') { 748 c = *++cp; 749 *ans = cp; 750 while ((c = *cp) && c != '"') cp++; 751 } else { 752 *ans = cp; 753 while ((c = *cp) && c != ' ' && c != '\t') cp++; 754 } 755 756 if (c) 757 *cp = 0; 758 return 1; 759 } 760} 761#endif 762 763static char * 764get_type(int type) 765{ 766 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 767 int counter = 0; 768 struct part_type *ptr = part_types; 769 770 771 while(counter < numentries) 772 { 773 if(ptr->type == type) 774 { 775 return(ptr->name); 776 } 777 ptr++; 778 counter++; 779 } 780 return("unknown"); 781} 782