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