|
|
1.1 ! root 1: /* ! 2: * fdisk.c ! 3: * ! 4: * Last hacked: 07/06/92, COHERENT 386 ! 5: * ! 6: * cc -o fdisk fdisk.c -f ! 7: * Change partitioning IBM-AT (or other type) hard disk. ! 8: * Usage: /etc/fdisk [ -crvxB ] [ -b bootb ] [ device ... ] ! 9: * Options: ! 10: * -B Invoked during installation ! 11: * -b Add master boot block code from "bootb" ! 12: * -c Configure hard disk geometry ! 13: * -r Read only ! 14: * -v Print c:h:s start and end values ! 15: * If no device argument is given, fdisk supplies "/dev/at[01]x" ! 16: * as appropriate. ! 17: */ ! 18: ! 19: #include <stdio.h> ! 20: #include <l.out.h> ! 21: #include <setjmp.h> ! 22: #include <sys/devices.h> ! 23: #include <sys/fdisk.h> ! 24: #include <sys/hdioctl.h> ! 25: #include <sys/stat.h> ! 26: #include "fdisk0.h" ! 27: ! 28: /* Globals. */ ! 29: int Bflag; /* special patching during installation */ ! 30: char *argv0; /* Command name, for error messages. */ ! 31: int badflag; /* Partition table is bad. */ ! 32: char buf[NBUF]; /* Input buffer. */ ! 33: int cfd; /* Current file descriptor. */ ! 34: int cflag; /* Configure disk geometry. */ ! 35: int cylflag; /* Specify base and size in cylinders. */ ! 36: unsigned int cylsize; /* Cylinder size in sectors. */ ! 37: unsigned char *defargs[3] = { "/dev/at0x", "/dev/at1x", NULL }; ! 38: unsigned char *device; /* Partition table device name. */ ! 39: unsigned char *drivename; /* Disk drive name. */ ! 40: unsigned char drive_x[] = "Drive x"; /* Needs to be written on */ ! 41: int drivenum; /* Drive number. */ ! 42: int freepart; /* Free partition. */ ! 43: unsigned long freesize; /* Free size. */ ! 44: unsigned long freestart; /* First free sector. */ ! 45: HDISK_S hd; /* Structure to house boot block. */ ! 46: hdparm_t hdparms; /* Hard disk parameter block. */ ! 47: int isatflag; /* Device is an AT-type disk. */ ! 48: jmp_buf loop; /* Interactive input loop entry point. */ ! 49: char *mboot; /* Name of new master boot file. */ ! 50: int megflag; /* Specify sizes in megabytes. */ ! 51: unsigned int nspt; /* Number of sectors per track. */ ! 52: unsigned int ncyls; /* Number of cylinders. */ ! 53: HDISK_S newhd; /* Structure to house new boot block. */ ! 54: unsigned int nheads; /* Number of heads per track. */ ! 55: int nmods; /* Modifications to the table. */ ! 56: unsigned long nsectors; /* Total sectors. */ ! 57: int openmode = 2; /* Default open mode: read/write. */ ! 58: int partbase; /* Partition number base (0 or 4). */ ! 59: int qflag; /* Quit. */ ! 60: int rflag; /* Readonly. */ ! 61: int vflag; /* Print c:h:s start and end values. */ ! 62: ! 63: main(argc, argv) int argc; char *argv[]; ! 64: { ! 65: register char *s; ! 66: int fd0, fd1, i; ! 67: struct stat sb; ! 68: ! 69: /* Sanity check. */ ! 70: argv0 = argv[0]; ! 71: if (sizeof hd != SSIZE) ! 72: fatal("invalid HDISK_S size %u != %u", sizeof hd, SSIZE); ! 73: while (argc > 1 && **++argv == '-') { ! 74: --argc; ! 75: for (s = &argv[0][1]; *s; ++s) { ! 76: switch(*s) { ! 77: case 'B': ! 78: ++Bflag; ! 79: break; ! 80: case 'b': ! 81: if (argc-- < 2) ! 82: usage(); ! 83: mboot = *++argv; ! 84: break; ! 85: case 'c': ! 86: ++cflag; ! 87: break; ! 88: case 'r': ! 89: ++rflag; ! 90: openmode = 0; ! 91: break; ! 92: case 'v': ! 93: ++vflag; ! 94: break; ! 95: case 'V': ! 96: fprintf(stderr, "%s: V%s\n", argv0, VERSION); ! 97: break; ! 98: default: ! 99: usage(); ! 100: break; ! 101: } ! 102: } ! 103: } ! 104: if (openmode == 0 && mboot != NULL) ! 105: fatal("cannot specify both 'b' and 'r' options"); ! 106: if (--argc == 0) { ! 107: /* No arguments specified, take defaults. */ ! 108: argv = defargs; ! 109: fd0 = open(argv[0], 0); ! 110: fd1 = open(argv[1], 0); ! 111: if (fd1 >= 0) { ! 112: ++argc; ! 113: close(fd1); ! 114: } else ! 115: argv[1] = NULL; ! 116: if (fd0 >= 0) { ! 117: ++argc; ! 118: close(fd0); ! 119: } else ! 120: ++argv; ! 121: if (argc == 0) ! 122: fatal("cannot open default devices"); ! 123: } ! 124: cls(0); ! 125: printf( ! 126: "This program will let you change partition information for each disk drive.\n" ! 127: "A disk drive can be divided into one to four logical partitions.\n" ! 128: "You can change the active partition (the partition which your\n" ! 129: "system boots by default) or change the layout of logical partitions.\n" ! 130: "Other programs which change hard disk partition information\n" ! 131: "may list logical partitions in a different order.\n" ! 132: "Hit <Esc><Enter> to return to the main menu at any time.\n" ! 133: ); ! 134: get_line("Now hit <Enter>."); ! 135: for (i = 0; (device = *argv++) != NULL; ++i) { ! 136: /* ! 137: * Set the drive number, drive name, partition base. ! 138: * /etc/build calls /etc/fdisk with an ordered list of args ! 139: * which correspond to the drive number, so this usually works. ! 140: * But there is no obvious way to find the correct drive number ! 141: * when the user invokes /etc/fdisk directly; hence the ! 142: * kludge below for AT disks. ! 143: */ ! 144: drivenum = i; ! 145: partbase = i * NPARTN; ! 146: drivename = drive_x; ! 147: drivename[6] = drivenum + '0'; ! 148: ! 149: /* ! 150: * Check if device is an AT device. ! 151: * The fix_chs() kludge only works for AT-type disks. ! 152: */ ! 153: if (stat(device, &sb) < 0) ! 154: fatal("cannot stat \"%s\"", device); ! 155: isatflag = (major(sb.st_rdev) == AT_MAJOR); ! 156: if (isatflag) { ! 157: /* Kludge, see comment above... */ ! 158: if (minor(sb.st_rdev) == AT0X_MINOR) { ! 159: drivenum = partbase = 0; ! 160: drivename = "Drive 0"; ! 161: } else if (minor(sb.st_rdev) == AT1X_MINOR) { ! 162: drivenum = 1; ! 163: partbase = 4; ! 164: drivename = "Drive 1"; ! 165: } /* else huh? */ ! 166: } ! 167: ! 168: /* Do it. */ ! 169: fdisk(*argv == NULL); ! 170: if (qflag) ! 171: break; ! 172: } ! 173: exit(0); ! 174: } ! 175: ! 176: /* ! 177: * If 286, copy /coherent to /tmp/coherent and ! 178: * patch /tmp/coherent disk parameters "atparms" with hdparms. ! 179: * [Primary/secondary patch stuff disappears with COH 3.2.1.] ! 180: */ ! 181: void ! 182: atpatch() ! 183: { ! 184: register int i; ! 185: int dbase; ! 186: unsigned char *hdp; ! 187: FILE *fp; ! 188: char line[512]; ! 189: ! 190: if (!Bflag) ! 191: return; ! 192: if (drivenum == 0) ! 193: dbase = 0; ! 194: else if (drivenum == 1) ! 195: dbase = sizeof hdparms; ! 196: else ! 197: fatal("unrecognized drive number"); ! 198: ! 199: /* ! 200: * Second kernel. ! 201: * Write commands to patchfile - they run after kernel is linked. ! 202: */ ! 203: fp = fopen(PATCHFILE, "a"); ! 204: fprintf(fp, "/conf/patch /mnt/coherent >/dev/null \\\n"); ! 205: for (i = 0, hdp = (char *)&hdparms; i < sizeof hdparms; i++, hdp++) { ! 206: fprintf(fp, " atparm+%d=%u:c \\\n", dbase + i, *hdp); ! 207: } ! 208: fprintf(fp, "\n"); ! 209: fclose(fp); ! 210: ! 211: /* Third kernel. */ ! 212: sprintf(line, "_TAG(AT%d)\t_HDPARMS(%d,%d,%d,%d,%d),", ! 213: drivenum, ! 214: (hdparms.ncyl[1] << 8) | hdparms.ncyl[0], ! 215: hdparms.nhead, ! 216: hdparms.nspt, ! 217: hdparms.ctrl, ! 218: (hdparms.wpcc[1] << 8) | hdparms.wpcc[0]); ! 219: ! 220: cohtune_ent("at", drivenum ? "AT1" : "AT0", line); ! 221: } ! 222: ! 223: /* ! 224: * Change the active partition. ! 225: */ ! 226: void ! 227: change_active() ! 228: { ! 229: int active, oactive, i; ! 230: ! 231: active = oactive = -1; ! 232: for (i=0; i < NPARTN; i++) ! 233: if (hd.hd_partn[i].p_boot == 0x80) { ! 234: hd.hd_partn[i].p_boot = 0; /* make inactive */ ! 235: active = oactive = i; /* remember old */ ! 236: } ! 237: if (!yes_no("Do you want to make a partition active")) { ! 238: active = -1; ! 239: if (active != oactive) ! 240: ++nmods; ! 241: return; ! 242: } ! 243: if (active == -1) ! 244: active = 0; /* default */ ! 245: active = get_int("Active partition", active + partbase, partbase, partbase + NPARTN-1); ! 246: active -= partbase; ! 247: hd.hd_partn[active].p_boot = 0x80; /* make active */ ! 248: if (active != oactive) ! 249: ++nmods; ! 250: } ! 251: ! 252: /* ! 253: * Interactively change the table entry for logical partition n. ! 254: * Grunge city. ! 255: */ ! 256: void ! 257: change_part(n) int n; ! 258: { ! 259: register FDISK_S *p; ! 260: int sys, old; ! 261: unsigned int c, h, s; ! 262: unsigned long size, osize, base, obase, end; ! 263: static int optflag; ! 264: ! 265: /* Get options first time through. */ ! 266: if (optflag == 0) { ! 267: cls(0); ! 268: printf( ! 269: "Existing data on a partition will be lost if you change the\n" ! 270: "base or the size of the partition. Be sure you have backed up\n" ! 271: "all data from any partition which you are going to change.\n" ! 272: "\n" ! 273: "You may specify partition bases in cylinders or in tracks.\n" ! 274: ); ! 275: cylflag = yes_no("Do you want to specify bases in cylinders"); ! 276: printf("You may specify partition sizes in %s or in megabytes.\n", ! 277: cylflag ? "cylinders" : "tracks"); ! 278: megflag = !yes_no("Do you want to specify partition sizes in %s", ! 279: cylflag ? "cylinders" : "tracks"); ! 280: ++optflag; ! 281: print_part(0); ! 282: } ! 283: p = &hd.hd_partn[n]; ! 284: printf("\nPartition %d:\n", n + partbase); ! 285: size = p->p_size; ! 286: ! 287: /* Get new system type. */ ! 288: old = p->p_sys; ! 289: again: ! 290: if (old != SYS_EMPTY) ! 291: printf("The current operating system type is %s.\n", sys_type(old)); ! 292: if (yes_no("Do you want this to be a COHERENT partition")) ! 293: sys = SYS_COH; ! 294: #if 0 ! 295: /* any partition they modify better be left as COH or empty! */ ! 296: else if (old != SYS_COH && yes_no("Do you want the partition type left unchanged")) ! 297: sys = old; ! 298: else if (old != SYS_EMPTY && yes_no("Do you want the partition marked as unused")) ! 299: sys = SYS_EMPTY; ! 300: #endif ! 301: else if (yes_no("Do you want the partition marked as unused")) ! 302: sys = SYS_EMPTY; ! 303: else { ! 304: printf( ! 305: #if 0 ! 306: "This program can mark a partition as a COHERENT partition,\n" ! 307: "leave its type unchanged, or mark it as unused. It cannot\n" ! 308: "initialize a partition for use by any other operating system;\n" ! 309: "to do so, you must mark it as unused now and subsequently use\n" ! 310: "the disk partitioning program provided by the other system\n" ! 311: "to initialize it correctly.\n" ! 312: #else ! 313: "\nThis program can mark a partition as a COHERENT partition\n" ! 314: "or mark it as unused. It CANNOT initialize a partition for\n" ! 315: "use by any other operating system. To do so, you must mark\n" ! 316: "it as unused now and subsequently use the disk partitioning\n" ! 317: "program provided by the other system to initialize it correctly.\n\n" ! 318: #endif ! 319: ); ! 320: if (yes_no("Do you still want to modify this partition")) ! 321: goto again; ! 322: return; ! 323: } ! 324: if (sys != old) { ! 325: p->p_sys = sys; ! 326: ++nmods; ! 327: } ! 328: if (sys == SYS_EMPTY) { ! 329: printf( ! 330: "For you convenience in partitioning your hard disk, this program\n" ! 331: "lets you create unused partitions with nonzero base and size.\n" ! 332: "However, other disk partitioning software may not work correctly\n" ! 333: "unless unused partitions have base and size zero.\n" ! 334: ); ! 335: if (yes_no("Do you want to zero the partition base and size")) { ! 336: memset(p, 0, sizeof(FDISK_S)); ! 337: nmods++; ! 338: printf("\n"); ! 339: return; ! 340: } ! 341: } ! 342: getbase: ! 343: /* Specify the base. */ ! 344: /* Default: old or first free or track 1. */ ! 345: obase = p->p_base; ! 346: base = (size != 0L) ? obase : (freesize != 0) ? freestart : nspt; ! 347: if (cylflag) { /* in cylinders */ ! 348: base = sec_to_c(base); ! 349: base = get_long("Base cylinder", base, 0L, (long) ncyls - 1); ! 350: if (base == 0) ! 351: base = nspt; /* skip first track for cyl 0 */ ! 352: else ! 353: base *= nspt * nheads; /* cylinders to sectors */ ! 354: } else { /* in tracks */ ! 355: base = sec_upto_t(base); ! 356: base = get_long("Base track", base, 1L, (long)ncyls * nheads - 1); ! 357: base *= nspt; /* tracks to sectors */ ! 358: } ! 359: ! 360: /* Check that base falls at a track boundary. */ ! 361: /* It might not if the disk was previously partitioned. */ ! 362: c = sec_to_c(base); ! 363: h = sec_to_h(base); ! 364: s = sec_to_s(base); ! 365: if (s != 1) { ! 366: printf("Partitions should begin at a track boundary.\n"); ! 367: printf("The partition does not begin at a track boundary with the selected base.\n"); ! 368: printf("The next track boundary is at track %u\n", sec_upto_t(base)); ! 369: if (yes_no("Do you want to change the partition base")) ! 370: goto getbase; ! 371: } ! 372: ! 373: /* Update the partition table base and start information. */ ! 374: if (base != obase) { ! 375: ++nmods; ! 376: p->p_base = base; ! 377: p->p_bcyl = c & 0xFF; ! 378: p->p_bhd = h; ! 379: p->p_bsec = ((c >> 2) & CYLMASK ) | s; ! 380: } ! 381: ! 382: /* Specify the partition size. */ ! 383: /* Default size: free block size, old size, largest possible. */ ! 384: osize = size; ! 385: size = (base == freestart) ? freesize : (osize != 0L) ? osize : nsectors - base; ! 386: if (megflag) { /* in megabytes */ ! 387: size = meg(size); ! 388: if ((long)meg(nsectors - base) == 0) { ! 389: printf("Less than a megabyte of space remains.\n"); ! 390: size = nsectors - base; ! 391: } else { ! 392: size = get_long("Partition size in megabytes", size, 0L, ! 393: (long) meg(nsectors - base)); ! 394: size *= 1000000L; /* megabytes to bytes */ ! 395: size /= SSIZE; /* to sectors */ ! 396: size = sec_upto_c(size); /* round up to cylinders */ ! 397: size *= nspt * nheads; /* cylinders to sectors */ ! 398: } ! 399: } else if (cylflag) { /* in cylinders */ ! 400: /* Tricky stuff again. */ ! 401: end = base + size - 1; ! 402: size = sec_to_c(end) - sec_to_c(base) + 1; ! 403: size = get_long("Partition size in cylinders", size, 0L, ! 404: (long) ncyls - sec_to_c(base)); ! 405: size *= nspt * nheads; /* cylinders to sectors */ ! 406: } else { /* in tracks */ ! 407: size = sec_upto_t(size); ! 408: size = get_long("Partition size in tracks", size, 0L, ! 409: (long) sec_upto_t(nsectors - base)); ! 410: size *= nspt; /* tracks to sectors */ ! 411: } ! 412: /* ! 413: * Adjust size to end at cylinder boundary ! 414: * if it did not start at cylinder boundary. ! 415: */ ! 416: if ((megflag || cylflag) && size != 0 && base % cylsize != 0 && size > base % cylsize) ! 417: size -= base % cylsize; ! 418: ! 419: /* Check the size. */ ! 420: if (base + size > nsectors) ! 421: size = nsectors - base; /* roundup too big */ ! 422: end = base + size - 1; ! 423: c = sec_to_c(end); ! 424: h = sec_to_h(end); ! 425: s = sec_to_s(end); ! 426: if (s != nspt) { ! 427: printf("Partitions should end at a track boundary.\n"); ! 428: printf("A partition with %u more sectors would end at a track boundary.\n", nspt - s); ! 429: if (yes_no("Do you want to add %u sectors to the partition size", ! 430: nspt - s)) { ! 431: size += nspt - s; ! 432: s = nspt; ! 433: } ! 434: } ! 435: ! 436: /* Update the partition table size and end. */ ! 437: if (base != obase || size != osize) { ! 438: ++nmods; ! 439: p->p_size = size; ! 440: p->p_ecyl = c & 0xFF; ! 441: p->p_ehd = h; ! 442: p->p_esec = ((c >> 2) & CYLMASK ) | s; ! 443: } ! 444: printf("\n"); ! 445: } ! 446: ! 447: /* ! 448: * Check a c:h:s entry in the partition table for consistency. ! 449: * Try correcting any inconsistency found, with warning to the user. ! 450: * The flag is 1 for beginning, 0 for end. ! 451: */ ! 452: void ! 453: check_chs(p, flag) FDISK_S *p; int flag; ! 454: { ! 455: unsigned int c, h, s, nc, nh, ns; ! 456: unsigned long n; ! 457: ! 458: again: ! 459: if (flag) { ! 460: c = bcyl(p); ! 461: h = bhd(p); ! 462: s = bsec(p); ! 463: n = p->p_base; ! 464: } else { ! 465: c = ecyl(p); ! 466: h = ehd(p); ! 467: s = esec(p); ! 468: n = p->p_base + p->p_size - 1; ! 469: } ! 470: if (c >= ncyls ! 471: || h >= nheads ! 472: || (s == 0 || s > nspt) ! 473: || n != chs_to_sec(c, h, s)) { ! 474: nc = sec_to_c(n); ! 475: nh = sec_to_h(n); ! 476: ns = sec_to_s(n); ! 477: cls(1); ! 478: printf("According to your computer system, the disk contains\n"); ! 479: printf("%u cylinders (0 to %u), %u heads (0 to %u), and %u sectors\n", ! 480: ncyls, ncyls - 1, nheads, nheads -1, nspt); ! 481: printf("per track (1 to %u). According to the partition table, a partition\n", ! 482: nspt); ! 483: printf("%s at sector %lu, which corresponds to a c:h:s of %u:%u:%u.\n", ! 484: (flag) ? "begins" : "ends" , n, nc, nh, ns); ! 485: printf("But the partition table entry gives a c:h:s of %u:%u:%u.\n", ! 486: c, h, s); ! 487: ! 488: if (flag) { ! 489: printf( ! 490: "\n" ! 491: "An inconsistency in a partition table entry usually occurs because\n" ! 492: "the system CMOS RAM area specifies the hard disk geometry incorrectly;\n" ! 493: "that is, your disk does not contain %u cylinders, %u heads, and %u sectors.\n", ! 494: ncyls, nheads, nspt); ! 495: if (!cflag) { ! 496: printf( ! 497: "If you think the disk geometry values above are wrong, invoke this program\n" ! 498: "again using the \"-c\" option to correct them. Because changing these\n" ! 499: "values is dangerous and you have not specified the \"-c\" option, this\n" ! 500: "program will now terminate.\n" ! 501: ); ! 502: exit(1); ! 503: } ! 504: if (isatflag) { ! 505: printf( ! 506: "This program lets you to resolve the inconsistency by specifying correct\n" ! 507: "values for the disk geometry (number of cylinders, heads and sectors) or by\n" ! 508: "making the partition table entry consistent with the given values.\n" ! 509: ); ! 510: if (yes_no("Do you think the above disk geometry values are wrong")) { ! 511: fix_chs(); ! 512: goto again; ! 513: } ! 514: } ! 515: } ! 516: ! 517: printf("This program will now change the c:h:s of the entry to %u:%u:%u\n", ! 518: nc, nh, ns); ! 519: printf( ! 520: "to resolve this inconsistency. Changing a partition table entry can\n" ! 521: "make data on existing filesystems inaccessible. If you feel this change is\n" ! 522: "incorrect, exit from this program now without updating the partition table.\n" ! 523: ); ! 524: if (yes_no("Do you want to exit from this program")) ! 525: exit(1); ! 526: ++nmods; ! 527: if (flag) { ! 528: p->p_bcyl = nc & 0xFF; ! 529: p->p_bhd = nh; ! 530: p->p_bsec = ((nc >> 2) & CYLMASK ) | ns; ! 531: } else { ! 532: p->p_ecyl = nc & 0xFF; ! 533: p->p_ehd = nh; ! 534: p->p_esec = ((nc >> 2) & CYLMASK ) | ns; ! 535: } ! 536: } ! 537: } ! 538: ! 539: /* ! 540: * Clear the IBM-AT console screen. ! 541: * Prompt for <Enter> if the flag is true or if rflag. ! 542: */ ! 543: void ! 544: cls(flag) register int flag; ! 545: { ! 546: if (flag || rflag) { ! 547: printf("\nHit <Enter> to continue..."); ! 548: fflush(stdout); ! 549: fgets(buf, sizeof buf, stdin); ! 550: } ! 551: putchar(0x1B); ! 552: putchar('['); ! 553: putchar('2'); ! 554: putchar('J'); ! 555: fflush(stdout); ! 556: } ! 557: ! 558: #if DOSSHRINK ! 559: /* ! 560: * Shrink an MS-DOS partition. ! 561: * PFM. ! 562: */ ! 563: void ! 564: dos_shrink(n) int n; ! 565: { ! 566: cls(0); ! 567: printf( ! 568: "You can sometimes shrink an existing MS-DOS partition to make room for\n" ! 569: "a COHERENT partition if your disk is entirely allocated to MS-DOS.\n" ! 570: "This program will attempt to shrink the MS-DOS partition without destroying\n" ! 571: "the data on it. However, you should BACK UP ALL DATA from the MS-DOS\n" ! 572: "partition to diskettes before you try to shrink it.\n" ! 573: ); ! 574: if (freepart == -1) { ! 575: printf("%s", drivename); ! 576: printf( ! 577: " does not contain an unused partition. Shrinking an MS-DOS\n" ! 578: "partition will create additional free space on the disk, but there\n" ! 579: "is currently no partition table entry available for the freed space.\n" ! 580: ); ! 581: if (!yes_no("Do you want to shrink the MS-DOS partition anyway")) ! 582: return; ! 583: } ! 584: ! 585: /* Go for smoke. */ ! 586: sprintf(buf, "/etc/dosshrink %s %d %s\n", device, n, device); ! 587: buf[strlen(buf) - 2] = 'a' + n; ! 588: if (system(buf) != 0) { ! 589: printf("Shrinking of MS-DOS partition failed.\n"); ! 590: return; ! 591: } ! 592: ! 593: /* Read the partition table again to get the changed entry. */ ! 594: if (lseek(cfd, 0L, 0) != 0L) ! 595: fatal("%s: seek failed", device); ! 596: else if (read(cfd, &newhd, sizeof hd) != sizeof hd) { ! 597: close(cfd); ! 598: fatal("%s: read error", device); ! 599: } else ! 600: memcpy(&hd.hd_partn[n], &newhd.hd_partn[n], sizeof(FDISK_S)); ! 601: } ! 602: #endif /* DOSSHRINK */ ! 603: ! 604: /* ! 605: * Print drive information. ! 606: */ ! 607: void ! 608: drive_info() ! 609: { ! 610: printf("%s has %u cylinders, %u heads, and %u sectors per track.\n", ! 611: drivename, ncyls, nheads, nspt); ! 612: printf("It contains:\n"); ! 613: printf("\t%u cylinders of %lu bytes each,\n", ! 614: ncyls, (long)cylsize * SSIZE); ! 615: printf("\t%u tracks of %lu bytes each,\n", ! 616: ncyls * nheads, (long)nspt * SSIZE); ! 617: printf("\t%lu sectors of %d bytes each,\n", ! 618: nsectors, SSIZE); ! 619: printf("or a total of %ld bytes (%.2f megabytes).\n", ! 620: nsectors * SSIZE, meg(nsectors)); ! 621: } ! 622: ! 623: /* ! 624: * Print a fatal error message and die. ! 625: */ ! 626: void ! 627: fatal(args) char *args; ! 628: { ! 629: fprintf(stderr, "%s: %r\n", argv0, &args); ! 630: exit(1); ! 631: } ! 632: ! 633: /* ! 634: * Print/change configuration for given device. ! 635: * The 'lastflag' is true if the current device is the last one. ! 636: */ ! 637: void ! 638: fdisk(lastflag) int lastflag; ! 639: { ! 640: int nfd, p, flag; ! 641: unsigned action; ! 642: static int firstflag = 1; ! 643: ! 644: nmods = 0; ! 645: if ((cfd = open(device, openmode)) < 0) ! 646: fatal("cannot open \"%s\"", device); ! 647: ! 648: /* Obtain drive characteristics. */ ! 649: if (ioctl(cfd, HDGETA, (char *)&hdparms) == -1) ! 650: fatal("cannot get \"%s\" drive characteristics", device); ! 651: ncyls = (hdparms.ncyl[1] << 8) | hdparms.ncyl[0]; ! 652: if (ncyls > 1024) { ! 653: printf( ! 654: "\n" ! 655: "The disk controller says your disk has %d cylinders.\n" ! 656: "COHERENT requires cylinder numbers in the range 0 to 1023.\n" ! 657: "Accordingly, this program will use 1024 as the effective\n" ! 658: "number of cylinders on your disk.\n" ! 659: , ncyls); ! 660: ncyls = 1024; ! 661: } ! 662: nheads = hdparms.nhead; ! 663: nspt = hdparms.nspt; ! 664: cylsize = nheads * nspt; ! 665: nsectors = (long)ncyls * cylsize; ! 666: ! 667: /* Print drive characteristics and allow user to patch. */ ! 668: if (cflag && isatflag) { ! 669: cls(1); ! 670: printf("According to your computer system:\n"); ! 671: drive_info(); ! 672: if (!yes_no("Do you think the above values are correct")) ! 673: fix_chs(); ! 674: } ! 675: close(cfd); ! 676: ! 677: /* Read the current boot block. */ ! 678: cfd = get_boot(device, openmode, &hd); /* read boot */ ! 679: if (cflag) ! 680: saveboot(); ! 681: ! 682: /* Check for Ontrack Disk Manager. */ ! 683: if (*(unsigned short *)(&hd.hd_boot[0xFC]) == HDSIG) { ! 684: printf( ! 685: "\n" ! 686: "Your hard disk appears to include Disk Manager software. Disk Manager can\n" ! 687: "partition your disk into more than four partitions, but COHERENT only\n" ! 688: "understands the first four partitions. If you have more than four\n" ! 689: "partitions on your disk, you will not see information about the additional\n" ! 690: "partitions, so proceed with extreme caution.\n" ! 691: "To install COHERENT while leaving Disk Manager intact, you must\n" ! 692: "remove all data from one of the first four disk partitions.\n" ! 693: ); ! 694: if (firstflag && mboot != NULL) ! 695: printf( ! 696: "\n" ! 697: "If you use the COHERENT master bootstrap and you have more than four\n" ! 698: "Disk Manager partitions, ALL data in any Disk Manager partition\n" ! 699: "other than the first four partitions WILL BE LOST!\n" ! 700: ); ! 701: if (!yes_no("Do you want to continue partitioning your disk")) ! 702: exit(1); ! 703: } ! 704: ! 705: /* Read master boot if desired. */ ! 706: if (firstflag && mboot != NULL) { ! 707: nfd = get_boot(mboot, 0, &newhd); /* read new boot */ ! 708: close(nfd); ! 709: if (newhd.hd_sig != HDSIG) ! 710: fatal("invalid signature in \"%s\"", mboot); ! 711: memcpy(hd.hd_boot, newhd.hd_boot, sizeof hd.hd_boot); ! 712: nmods++; ! 713: } ! 714: firstflag = 0; /* replace mboot only on first device */ ! 715: ! 716: /* If no signature, zap the partition entries. */ ! 717: if (hd.hd_sig != HDSIG) { ! 718: printf( ! 719: "The boot block on this disk drive does not contain a valid partition table.\n" ! 720: "This program will now create a valid partition table with zeroed entries.\n" ! 721: "Exit from this program immediately if you do not want to zero the entries.\n" ! 722: ); ! 723: if (yes_no("Do you want to exit instead of zeroing the partition table")) ! 724: exit(1); ! 725: memset(hd.hd_partn, 0, NPARTN * sizeof(FDISK_S)); ! 726: hd.hd_sig = HDSIG; ! 727: nmods++; ! 728: } ! 729: ! 730: /* If readonly, print information and return. */ ! 731: if (openmode == 0) { ! 732: print_part(0); ! 733: close(cfd); ! 734: return; ! 735: } ! 736: ! 737: /* Interactive input loop. */ ! 738: for (flag = 1; ; ) { ! 739: setjmp(loop); ! 740: print_part(flag); ! 741: flag = 0; ! 742: printf( ! 743: "Possible actions:\n" ! 744: "\t0 = Quit\n" ! 745: "\t1 = Change active partition (or make no partition active)\n" ! 746: "\t2 = Change one logical partition\n" ! 747: "\t3 = Change all logical partitions\n" ! 748: "\t4 = Delete one logical partition\n" ! 749: "\t5 = Change drive characteristics\n" ! 750: "\t6 = Display drive information\n" ! 751: ); ! 752: if (lastflag) ! 753: action = get_int("Action", 0, 0, 6); ! 754: else { ! 755: printf("\t7 = Proceed with next drive\n"); ! 756: action = get_int("Action", 7, 0, 7); ! 757: } ! 758: ! 759: switch(action) { ! 760: case 0: ! 761: if (quit(device, cfd) == 1) { ! 762: qflag = 1; ! 763: return; ! 764: } ! 765: continue; ! 766: case 1: ! 767: printf("Change active partition:\n"); ! 768: change_active(); ! 769: continue; ! 770: case 2: ! 771: p = (freepart != -1) ? freepart : 0; ! 772: p = get_int("Which partition", p + partbase, partbase, partbase + NPARTN - 1); ! 773: p -= partbase; ! 774: if (action == 2) ! 775: change_part(p); ! 776: continue; ! 777: case 3: ! 778: for (p=0; p < NPARTN; ) { ! 779: change_part(p++); ! 780: if (p < NPARTN) ! 781: print_part(0); ! 782: } ! 783: continue; ! 784: case 4: ! 785: p = get_int("Which partition", partbase, partbase, partbase + NPARTN - 1); ! 786: p -= partbase; ! 787: memset(&hd.hd_partn[p], 0, sizeof(FDISK_S)); ! 788: nmods++; ! 789: continue; ! 790: case 5: ! 791: cls(0); ! 792: printf("According to your computer system:\n"); ! 793: drive_info(); ! 794: if (!yes_no("Do you think the above values are correct")) ! 795: fix_chs(); ! 796: continue; ! 797: case 6: ! 798: cls(0); ! 799: drive_info(); ! 800: flag = 1; ! 801: continue; ! 802: case 7: ! 803: if (quit(device, cfd) == 1) ! 804: return; ! 805: continue; ! 806: default: ! 807: continue; ! 808: } ! 809: } ! 810: } ! 811: ! 812: /* ! 813: * Interactively obtain new disk geometry values. ! 814: * Update running /coherent with correct values using HDSETA. ! 815: * Call atpatch to create patched /tmp/coherent and /tmp/boot.[01]. ! 816: */ ! 817: void ! 818: fix_chs() ! 819: { ! 820: register int i; ! 821: ! 822: printf( ! 823: "Warning: if you specify incorrect disk parameter values, data on\n" ! 824: "existing partitions may be lost or your disk may not operate correctly.\n" ! 825: "Consult your disk controller manual or call your disk vendor\n" ! 826: "if you do not know the correct values.\n" ! 827: ); ! 828: if (!yes_no("Are you sure you want to change the disk parameter values")) ! 829: return; ! 830: ! 831: /* ! 832: * Modify current values before displaying them as defaults. ! 833: */ ! 834: i = (hdparms.wpcc[1] << 8) | (hdparms.wpcc[0]); ! 835: if (i < -1 || i >= ncyls) ! 836: i = -1; ! 837: hdparms.ctrl &= 0x0f; ! 838: ! 839: ncyls = get_int("Number of cylinders", ncyls, 1, 1024); ! 840: nheads = get_int("Number of heads", nheads, 1, 255); ! 841: nspt = get_int("Number of sectors per track", nspt, 1, 255); ! 842: hdparms.ctrl = get_int("Control byte", hdparms.ctrl, 0, 255); ! 843: i = get_int("Write pre-compensation cylinder", i, -1, ncyls+1); ! 844: hdparms.wpcc[1] = i >> 8; ! 845: hdparms.wpcc[0] = i & 0xFF; ! 846: cylsize = nheads * nspt; ! 847: nsectors = (long)ncyls * cylsize; ! 848: hdparms.ncyl[1] = ncyls >> 8; ! 849: hdparms.ncyl[0] = ncyls & 0xFF; ! 850: hdparms.nhead = nheads; ! 851: hdparms.nspt = nspt; ! 852: if (ioctl(cfd, HDSETA, (char *)&hdparms) == -1) ! 853: fatal("cannot set \"%s\" drive characteristics", device); ! 854: if (isatflag) ! 855: atpatch(); ! 856: } ! 857: ! 858: /* ! 859: * Read boot block from a file into the given structure. ! 860: * Return a file descriptor to the open file. ! 861: */ ! 862: int ! 863: get_boot(name, mode, hdp) char *name; HDISK_S *hdp; ! 864: { ! 865: int fd; ! 866: ! 867: /* Open the file. */ ! 868: if ((fd = open(name, mode)) < 0) ! 869: fatal("cannot open \"%s\"", name); ! 870: /* Read the current boot block into the hd structure. */ ! 871: if (read(fd, hdp, sizeof hd) != sizeof hd) { ! 872: close(fd); ! 873: fatal("read error on \"%s\"", name); ! 874: } ! 875: return fd; ! 876: } ! 877: ! 878: /* ! 879: * Prompt for integer input from the user. ! 880: * Accept data in range min to max. ! 881: * Return a valid result. ! 882: */ ! 883: int ! 884: get_int(prompt, defval, min, max) char *prompt; register int defval, min, max; ! 885: { ! 886: int val; ! 887: char *s; ! 888: ! 889: for (;;) { ! 890: s = get_line("%s [%u]?", prompt, defval); ! 891: if (*s == '\0') ! 892: return defval; /* take default */ ! 893: val = atoi(s); ! 894: if (val >= min && val <= max) ! 895: return val; ! 896: printf("Please enter a value between %u and %u.\n", min, max); ! 897: } ! 898: } ! 899: ! 900: /* ! 901: * Print the args and get a line from the user to buf[]. ! 902: * Strip the trailing newline and return a pointer to the first non-space. ! 903: */ ! 904: char * ! 905: get_line(args) char *args; ! 906: { ! 907: register char *s; ! 908: ! 909: printf("%r ", &args); ! 910: fflush(stdout); ! 911: fgets(buf, sizeof buf, stdin); ! 912: buf[strlen(buf) - 1] = '\0'; ! 913: for (s = buf; ; ++s) { ! 914: if (*s == 0x1B) /* <Esc> returns to loop */ ! 915: longjmp(loop, 1); ! 916: else if (*s != ' ' && *s != '\t') ! 917: return s; ! 918: } ! 919: } ! 920: ! 921: /* ! 922: * Prompt for long input from the user. ! 923: * Accept data in range min to max. ! 924: * Return the result. ! 925: */ ! 926: long ! 927: get_long(prompt, defval, min, max) char *prompt; register long defval, min, max; ! 928: { ! 929: long val; ! 930: char *s; ! 931: ! 932: for (;;) { ! 933: s = get_line("%s [%lu]?", prompt, defval); ! 934: if (*s == '\0') ! 935: return defval; /* take default */ ! 936: val = atol(s); ! 937: if (val >= min && val <= max) ! 938: return val; ! 939: printf("Please enter a value between %lu and %lu.\n", min, max); ! 940: } ! 941: } ! 942: ! 943: /* ! 944: * Compare two partition table entries. ! 945: * Called by qsort. ! 946: * The result is sorted by base, with empty entries at the end. ! 947: */ ! 948: int ! 949: pcompare(pp1, pp2) FDISK_S **pp1, **pp2; ! 950: { ! 951: register FDISK_S *p1, *p2; ! 952: ! 953: p1 = *pp1; ! 954: p2 = *pp2; ! 955: if (p1->p_size == 0) ! 956: return (p2->p_size == 0) ? 0 : 1; ! 957: else if (p2->p_size == 0) ! 958: return -1; ! 959: else if (p1->p_base < p2->p_base) ! 960: return -1; ! 961: else if (p1->p_base == p2->p_base) ! 962: return 0; ! 963: else ! 964: return 1; ! 965: } ! 966: ! 967: /* ! 968: * Output partition information. ! 969: */ ! 970: void ! 971: print_part(flag) int flag; ! 972: { ! 973: register FDISK_S *p; ! 974: register char c, *s, *dname; ! 975: int i; ! 976: unsigned long end; ! 977: ! 978: cls(flag); ! 979: printf("%s currently has the following logical partitions:\n", drivename); ! 980: printf( ! 981: " [ In Cylinders ] [ In Tracks ]\n" ! 982: "Number Type Start End Size Start End Size Mbytes Blocks Name\n"); ! 983: for (i = 0; i < NPARTN; ++i) { ! 984: p = &hd.hd_partn[i]; ! 985: if (p->p_size == 0L) ! 986: end = p->p_base = 0L; ! 987: else ! 988: end = p->p_base + p->p_size - 1; ! 989: printf("%d", partbase + i); ! 990: printf("%s\t", (p->p_boot == 0x80) ? " Boot" : ""); ! 991: printf("%8s ", sys_type(p->p_sys)); ! 992: printf("%5u ", sec_to_c(p->p_base)); ! 993: printf("%4u ", sec_to_c(end)); ! 994: printf("%5u ", sec_upto_c(p->p_size)); ! 995: printf("%6lu ", p->p_base / nspt); ! 996: printf("%6lu ", end / nspt); ! 997: printf("%6u ", sec_upto_t(p->p_size)); ! 998: printf("%6.2f ", meg(p->p_size)); ! 999: printf("%7lu ", p->p_size); ! 1000: if ((dname = malloc(strlen(device)+1)) == NULL) ! 1001: fatal("out of memory"); ! 1002: strcpy(dname, device); ! 1003: if (strncmp(dname, "/tmp", 4) == 0) ! 1004: dname += 4; ! 1005: s = &dname[strlen(dname) - 1]; ! 1006: c = *s; ! 1007: *s = 'a' + i; ! 1008: printf("%s", dname); ! 1009: *s = c; ! 1010: if (vflag) { ! 1011: printf("\n\t%3u:%u:%u ", bcyl(p), bhd(p), bsec(p)); ! 1012: printf("%3u:%u:%u ", ecyl(p), ehd(p), esec(p)); ! 1013: } ! 1014: printf("\n"); ! 1015: } ! 1016: sanity(); ! 1017: printf("\n"); ! 1018: } ! 1019: ! 1020: /* ! 1021: * Done. ! 1022: * If changes, prompt for confirmation and save. ! 1023: * Return 1 to quit, 0 to not quit. ! 1024: */ ! 1025: int ! 1026: quit(fname) char *fname; ! 1027: { ! 1028: if (badflag) { ! 1029: printf("Because the partition table defines overlapping disk\n"); ! 1030: printf("partitions, it will not be saved to the disk if you quit.\n"); ! 1031: if (!yes_no("Do you wish to quit without saving the changes")) ! 1032: return 0; ! 1033: } else if (nmods != 0) { ! 1034: if (yes_no("\nAre you sure you want to write the updated partition table")) { ! 1035: if (lseek(cfd, 0L, 0) != 0L) ! 1036: fatal("seek failed on \"%s\"", fname); ! 1037: else if (write(cfd, &hd, sizeof hd) != sizeof hd) ! 1038: fatal("write error on \"%s\"", fname); ! 1039: /* ! 1040: * This HDGETA is for the benefit of the SCSI driver, ! 1041: * which needs to reset the parameters if they changed. ! 1042: */ ! 1043: if (ioctl(cfd, HDGETA, (char *)&hdparms) == -1) ! 1044: fprintf(stderr, "HDGETA failed on \"%s\"\n", fname); ! 1045: sync(); ! 1046: } else if (!yes_no("Changes will not be saved. Quit anyway")) ! 1047: longjmp(loop, 2); ! 1048: else ! 1049: printf("Changes not saved.\n"); ! 1050: } else ! 1051: printf("The partition table is unchanged.\n"); ! 1052: close(cfd); ! 1053: return 1; ! 1054: } ! 1055: ! 1056: /* ! 1057: * Check a partition table for sanity. ! 1058: * Sort the partitions, look for gaps and overlaps. ! 1059: */ ! 1060: void ! 1061: sanity() ! 1062: { ! 1063: register int i; ! 1064: FDISK_S *p[NPARTN]; ! 1065: unsigned long base, next, size, safe; ! 1066: ! 1067: badflag = 0; ! 1068: freepart = -1; ! 1069: freesize = freestart = 0; ! 1070: for (i = 0; i < NPARTN; i++) { ! 1071: p[i] = &hd.hd_partn[i]; ! 1072: if (p[i]->p_size != 0) { ! 1073: check_chs(p[i], 1); /* check start c:h:s */ ! 1074: check_chs(p[i], 0); /* check end c:h:s */ ! 1075: } else if (freepart == -1) ! 1076: freepart = i; /* first free partition */ ! 1077: } ! 1078: qsort(p, NPARTN, sizeof(FDISK_S *), pcompare); ! 1079: next = 1; /* next block available after boot sector */ ! 1080: for (i = 0; i < NPARTN; i++) { ! 1081: base = p[i]->p_base; ! 1082: size = p[i]->p_size; ! 1083: if (size == 0) ! 1084: break; /* done when empty reached */ ! 1085: if (base < next) { ! 1086: if (next == 1) ! 1087: printf("Partition overlaps boot sector.\n"); ! 1088: else if (cylflag) ! 1089: printf("Partitions overlap starting at cylinder %lu.\n", base / cylsize); ! 1090: else ! 1091: printf("Partitions overlap starting at track %lu.\n", base / nspt); ! 1092: ++badflag; ! 1093: } else if (base != next) { ! 1094: if (i == 0 && (base == nspt || base == cylsize)) ! 1095: ; /* first partition at 0:1:1 or 1:0:1 */ ! 1096: else ! 1097: unused(base, next); ! 1098: } ! 1099: if (base + size > next) ! 1100: next = base + size; ! 1101: } ! 1102: safe = nsectors - nspt * nheads; /* safely usable sectors */ ! 1103: if (next < safe) ! 1104: unused(safe, next); ! 1105: else if (next > safe) ! 1106: printf( ! 1107: "\n" ! 1108: "Warning: the last cylinder of a hard disk is usually reserved for use by\n" ! 1109: "disk diagnostic programs. The current disk partitioning uses part of the\n" ! 1110: "the last cylinder in a disk partition. Mark Williams strongly recommends\n" ! 1111: "that you change the partitioning to avoid using the last cylinder.\n" ! 1112: ); ! 1113: } ! 1114: ! 1115: struct nlist nl[2] = { ! 1116: #if _I386 ! 1117: { "rootdev", 0, 0 }, ! 1118: #else ! 1119: { "rootdev_", 0, 0 }, ! 1120: #endif ! 1121: { "", 0, 0 } ! 1122: }; ! 1123: ! 1124: /* ! 1125: * Save/restore a copy of boot block to/from floppy. ! 1126: * Some fuss required to find the name of the root device. ! 1127: */ ! 1128: void ! 1129: saveboot() ! 1130: { ! 1131: register int fd; ! 1132: dev_t dev; ! 1133: char *floppy; ! 1134: ! 1135: /* Open kernel memory and read value of rootdev_. */ ! 1136: if ((fd = open(KMEM, 0)) < 0) ! 1137: return; ! 1138: nlist(COH, nl); ! 1139: if (lseek(fd, (long)nl[0].n_value, 0) == -1L) ! 1140: return; ! 1141: if (read(fd, &dev, sizeof(dev_t)) != sizeof(dev_t)) ! 1142: return; ! 1143: close(fd); ! 1144: ! 1145: /* ! 1146: * Bail out if not running floppy-based COHERENT ! 1147: * or if floppy open fails. ! 1148: */ ! 1149: if (dev == makedev(FL_MAJOR, 14)) ! 1150: floppy = "/dev/rfha0"; ! 1151: else if (dev == makedev(FL_MAJOR, 15)) ! 1152: floppy = "/dev/rfva0"; ! 1153: else ! 1154: return; /* not running from floppy */ ! 1155: if ((fd = open(floppy, 2)) == -1) ! 1156: return; /* open failed, bag out */ ! 1157: ! 1158: cls(0); ! 1159: sync(); ! 1160: printf( ! 1161: "If you are installing COHERENT on your hard disk for the first time and you\n" ! 1162: "want to use your drive with other operating systems, we recommend that you\n" ! 1163: "save a copy of the current boot block (which includes the partition table)\n" ! 1164: "to a diskette. You can restore the original boot block from the diskette\n" ! 1165: "if your COHERENT installation fails or if you are subsequently unable to run\n" ! 1166: "another operating system on the drive.\n" ! 1167: "\n" ! 1168: "You will be asked about saving and restoring the boot block once for each\n" ! 1169: "hard drive you are using. Use a separate diskette for each hard drive.\n" ! 1170: ); ! 1171: if (yes_no("Do you want to save the original boot block")) { ! 1172: printf( ! 1173: "\n" ! 1174: "Remove the COHERENT boot diskette, insert a formatted blank diskette,\n" ! 1175: ); ! 1176: get_line("then hit <Enter>."); ! 1177: if (write(fd, &hd, sizeof hd) != sizeof hd) ! 1178: fprintf(stderr, "fdisk: write error on \"%s\"\n", floppy); ! 1179: else ! 1180: printf( ! 1181: "\n" ! 1182: "Remove the diskette containing the original boot block.\n" ! 1183: "Label it and file it with your COHERENT installation disks.\n" ! 1184: ); ! 1185: } else if (yes_no("Do you want to restore a previously saved boot block")) { ! 1186: printf( ! 1187: "\n" ! 1188: "WARNING: This step will overwrite your hard disk partition table\n" ! 1189: "with the previously saved copy from the diskette in drive A:.\n" ! 1190: "Type <Ctrl-C> if you do not want to overwrite the existing partition table.\n" ! 1191: "\n" ! 1192: "Remove the COHERENT boot diskette,\n" ! 1193: "insert the diskette containing the saved boot block,\n" ! 1194: ); ! 1195: get_line("then hit <Enter>."); ! 1196: if (read(fd, &hd, sizeof hd) != sizeof hd) ! 1197: fprintf(stderr, "fdisk: read error on \"%s\"\n", floppy); ! 1198: else if (lseek(cfd, 0L, 0) != 0L) ! 1199: fatal("seek failed on \"%s\"", device); ! 1200: else if (write(cfd, &hd, sizeof hd) != sizeof hd) ! 1201: fatal("write error on \"%s\"", device); ! 1202: } else { ! 1203: close(fd); ! 1204: return; ! 1205: } ! 1206: close(fd); ! 1207: sync(); ! 1208: get_line("\nReplace the COHERENT boot diskette, then hit <Enter>."); ! 1209: } ! 1210: ! 1211: /* ! 1212: * Execute a command. ! 1213: */ ! 1214: void ! 1215: sys(cmd) char *cmd; ! 1216: { ! 1217: if (system(cmd) != 0) ! 1218: fatal("command \"%s\" failed", cmd); ! 1219: } ! 1220: ! 1221: /* ! 1222: * Convert system type code i to a string describing the system type. ! 1223: * Return a pointer to statically allocated buffer. ! 1224: */ ! 1225: char * ! 1226: sys_type(i) register int i; ! 1227: { ! 1228: static char buf[8+1]; /* longest name is "COHERENT" or "<Unused>"XS */ ! 1229: register char *s; ! 1230: ! 1231: switch (i) { ! 1232: case SYS_EMPTY: s = "<Unused>"; break; ! 1233: case SYS_DOS_12: ! 1234: case SYS_DOS_16: ! 1235: case SYS_DOS_LARGE: ! 1236: s = "MS-DOS"; break; ! 1237: case SYS_DOS_XP: ! 1238: s = "Ext.DOS"; break; ! 1239: case SYS_XENIX: s = "Xenix"; break; ! 1240: case SYS_COH: s = "Coherent"; break; ! 1241: case SYS_SWAP: s = "Swap"; break; ! 1242: default: s = NULL; break; ! 1243: } ! 1244: ! 1245: if (s == NULL) ! 1246: sprintf(buf, "%8u", i); ! 1247: else ! 1248: strcpy(buf, s); ! 1249: return buf; ! 1250: } ! 1251: ! 1252: /* ! 1253: * Report unused portion of disk. ! 1254: */ ! 1255: void ! 1256: unused(base, next) unsigned long base, next; ! 1257: { ! 1258: register unsigned long n, x, y; ! 1259: register char *s; ! 1260: ! 1261: n = base - next; ! 1262: if (cylflag && n >= cylsize) { ! 1263: s = "cylinder"; ! 1264: x = sec_to_c(n); ! 1265: y = sec_upto_c(next); ! 1266: } else if (n >= nspt) { ! 1267: s = "track"; ! 1268: x = n / nspt; ! 1269: y = sec_upto_t(next); ! 1270: } else { ! 1271: s = "sector"; ! 1272: x = n; ! 1273: y = next; ! 1274: } ! 1275: if (x == 1) ! 1276: printf("%lu %s (%.2f megabytes) is unused starting at %s %lu.\n", ! 1277: x, s, meg(n), s, y); ! 1278: else ! 1279: printf("%lu %ss (%.2f megabytes) are unused starting at %s %lu.\n", ! 1280: x, s, meg(n), s, y); ! 1281: if (freesize < n) { ! 1282: freesize = n; ! 1283: freestart = next; ! 1284: } ! 1285: } ! 1286: ! 1287: /* ! 1288: * Print a usage message and die. ! 1289: */ ! 1290: void ! 1291: usage() ! 1292: { ! 1293: fprintf(stderr, USAGE); ! 1294: exit(1); ! 1295: } ! 1296: ! 1297: /* ! 1298: * Get the answer to a yes/no question. ! 1299: * Return 1 for yes, 0 for no. ! 1300: */ ! 1301: int ! 1302: yes_no(args) char *args; ! 1303: { ! 1304: register char *s; ! 1305: ! 1306: for (;;) { ! 1307: printf("%r", &args); ! 1308: s = get_line(" [y or n]?"); ! 1309: if (*s == 'y') ! 1310: return 1; ! 1311: else if (*s == 'n') ! 1312: return 0; ! 1313: } ! 1314: } ! 1315: ! 1316: /* end of fdisk.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.