Annotation of coherent/d/etc/build/fdisk.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.