Annotation of coherent/f/tmp/inst2/fdisk.c, revision 1.1

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 */

unix.superglobalmegacorp.com

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