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