# 2.11BSD#431 - /usr/src/bin/disklabel/disklabel.c

##### Functions

    Perror            X
    Warning           X
    checklabel        X
    display           X
    edit              X
    editit            X
    getasciilabel     X
    l_perror          X
    main              X
    makebootarea      X
    makelabel         X
    readlabel         X
    skip              X
    usage             X
    word              X
    writelabel        X

##### Variables

    boot0             X
    bootarea          X
    debug             X
    dkname            X
    installboot       X
    lab               X
    namebuf           X
    np                X
    rflag             X
    specname          X
    tmpfil            X
    xxboot            X

##### Macros

    DEFEDITOR         X
    DKTYPENAMES       X
    NXTNUM            X
    OPTIONS           X
    RAWPARTITION      X
    streq             X

       1: /*
       2:  * Copyright (c) 1987, 1993
       3:  *	The Regents of the University of California.  All rights reserved.
       4:  *
       5:  * This code is derived from software contributed to Berkeley by
       6:  * Symmetric Computer Systems.
       7:  *
       8:  * Redistribution and use in source and binary forms, with or without
       9:  * modification, are permitted provided that the following conditions
      10:  * are met:
      11:  * 1. Redistributions of source code must retain the above copyright
      12:  *    notice, this list of conditions and the following disclaimer.
      13:  * 2. Redistributions in binary form must reproduce the above copyright
      14:  *    notice, this list of conditions and the following disclaimer in the
      15:  *    documentation and/or other materials provided with the distribution.
      16:  * 3. All advertising materials mentioning features or use of this software
      17:  *    must display the following acknowledgement:
      18:  *	This product includes software developed by the University of
      19:  *	California, Berkeley and its contributors.
      20:  * 4. Neither the name of the University nor the names of its contributors
      21:  *    may be used to endorse or promote products derived from this software
      22:  *    without specific prior written permission.
      23:  *
      24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34:  * SUCH DAMAGE.
      35:  */
      36:
      37: #if !defined(lint) && defined(DOSCCS)
      38: static char copyright[] =
      39: "@(#) Copyright (c) 1987, 1993\n\
      40: 	The Regents of the University of California.  All rights reserved.\n";
      41:
      42: static char sccsid[] = "@(#)disklabel.c	8.1.3 (2.11BSD) 1999/10/25";
      43: /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
      44: #endif
      45:
      46: #include <sys/param.h>
      47: #include <sys/signal.h>
      48: #include <sys/errno.h>
      49: #include <sys/file.h>
      50: #include <sys/ioctl.h>
      51: #include <sys/stat.h>
      52: #define DKTYPENAMES
      53: #include <sys/disklabel.h>
      54: #include <sys/fs.h>
      55: #include <string.h>
      56: #include <stdlib.h>
      57: #include <stdio.h>
      58: #include <ctype.h>
      59: #include "pathnames.h"
      60:
      61: /*
      62:  * Disklabel: read and write disklabels.
      63:  * The label is usually placed on one of the first sectors of the disk.
      64:  * Many machines also place a bootstrap in the same area,
      65:  * in which case the label is embedded in the bootstrap.
      66:  * The bootstrap source must leave space at the proper offset
      67:  * for the label on such machines.
      68:  */
      69:
      70: /*
      71:  * 2.11BSD has to do some things differently than other systems.  BBSIZE
      72:  * may be 1024 bytes but the disk boot roms only read the 512 byte sector 0.
      73:  * The boot and label areas each occupy 1/2 of the 1kb 'filesystem block'
      74:  * which precedes the superblock.  The bootblock is sector 0 and the label block
      75:  * is sector 1.  Each is a disjoint and independent area.  Thus the logic in
      76:  * this program which treated the label area as a subset or offset of the
      77:  * boot area had to change.
      78:  *
      79:  * The 'a' partition is used to access the raw device - as did the 'tahoe'.
      80: */
      81:
      82: #define RAWPARTITION    'a'
      83:
      84: #define DEFEDITOR   _PATH_VI
      85: #define streq(a,b)  (strcmp(a,b) == 0)
      86:
      87: char    *dkname;
      88: char    *specname;
      89: char    tmpfil[] = _PATH_TMP;
      90:
      91: char    namebuf[256], *np = namebuf;
      92: struct  disklabel lab;
      93: struct  disklabel *readlabel(), *makebootarea();
      94: char    bootarea[BBSIZE];   /* 512 for bootblock, 512 for label */
      95:
      96: int installboot;    /* non-zero if we should install a boot program */
      97: char    *xxboot;    /* primary boot */
      98: char    boot0[MAXPATHLEN];
      99:
     100: enum    {
     101:     UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT
     102: } op = UNSPEC;
     103:
     104: int rflag;
     105:
     106: #ifdef DEBUG
     107: int debug;
     108: #define OPTIONS "BNRWb:derw"
     109: #else
     110: #define OPTIONS "BNRWb:erw"
     111: #endif
     112:
     113: main(argc, argv)
     114:     int argc;
     115:     char *argv[];
     116: {
     117:     register struct disklabel *lp;
     118:     FILE *t;
     119:     int ch, f, flag, error = 0;
     120:     char *name = 0;
     121:
     122:     while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
     123:         switch (ch) {
     124:             case 'B':
     125:                 ++installboot;
     126:                 break;
     127:             case 'b':
     128:                 xxboot = optarg;
     129:                 break;
     130:             case 'N':
     131:                 if (op != UNSPEC)
     132:                     usage();
     133:                 op = NOWRITE;
     134:                 break;
     135:             case 'R':
     136:                 if (op != UNSPEC)
     137:                     usage();
     138:                 op = RESTORE;
     139:                 break;
     140:             case 'W':
     141:                 if (op != UNSPEC)
     142:                     usage();
     143:                 op = WRITEABLE;
     144:                 break;
     145:             case 'e':
     146:                 if (op != UNSPEC)
     147:                     usage();
     148:                 op = EDIT;
     149:                 break;
     150:             case 'r':
     151:                 ++rflag;
     152:                 break;
     153:             case 'w':
     154:                 if (op != UNSPEC)
     155:                     usage();
     156:                 op = WRITE;
     157:                 break;
     158: #ifdef DEBUG
     159:             case 'd':
     160:                 debug++;
     161:                 break;
     162: #endif
     163:             case '?':
     164:             default:
     165:                 usage();
     166:         }
     167:     argc -= optind;
     168:     argv += optind;
     169:     if (installboot) {
     170:         rflag++;
     171:         if (op == UNSPEC)
     172:             op = WRITEBOOT;
     173:     } else {
     174:         if (op == UNSPEC)
     175:             op = READ;
     176:         xxboot = 0;
     177:     }
     178:
     179:     if (argc < 1)
     180:         usage();
     181:
     182:     dkname = argv[0];
     183:     if (dkname[0] != '/') {
     184:         (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION);
     185:         specname = np;
     186:         np += strlen(specname) + 1;
     187:     } else
     188:         specname = dkname;
     189:     f = open(specname, op == READ ? O_RDONLY : O_RDWR);
     190:     if (f < 0 && errno == ENOENT && dkname[0] != '/') {
     191:         (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname);
     192:         np = namebuf + strlen(specname) + 1;
     193:         f = open(specname, op == READ ? O_RDONLY : O_RDWR);
     194:     }
     195:     if (f < 0)
     196:         Perror(specname);
     197:
     198:     switch(op) {
     199:
     200:     case EDIT:
     201:         if (argc != 1)
     202:             usage();
     203:         lp = readlabel(f);
     204:         error = edit(lp, f);
     205:         break;
     206:
     207:     case NOWRITE:
     208:         flag = 0;
     209:         if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
     210:             Perror("ioctl DIOCWLABEL");
     211:         break;
     212:
     213:     case READ:
     214:         if (argc != 1)
     215:             usage();
     216:         lp = readlabel(f);
     217:         display(stdout, lp);
     218:         error = checklabel(lp);
     219:         break;
     220:
     221:     case RESTORE:
     222:         if (installboot && argc == 3) {
     223:             makelabel(argv[2], 0, &lab);
     224:             argc--;
     225:         }
     226:         if (argc != 2)
     227:             usage();
     228:         lp = makebootarea(bootarea, &lab, f);
     229:         if (!(t = fopen(argv[1], "r")))
     230:             Perror(argv[1]);
     231:         if (getasciilabel(t, lp))
     232:             error = writelabel(f, bootarea, lp);
     233:         break;
     234:
     235:     case WRITE:
     236:         if (argc == 3) {
     237:             name = argv[2];
     238:             argc--;
     239:         }
     240:         if (argc != 2)
     241:             usage();
     242:         makelabel(argv[1], name, &lab);
     243:         lp = makebootarea(bootarea, &lab, f);
     244:         *lp = lab;
     245:         if (checklabel(lp) == 0)
     246:             error = writelabel(f, bootarea, lp);
     247:         break;
     248:
     249:     case WRITEABLE:
     250:         flag = 1;
     251:         if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
     252:             Perror("ioctl DIOCWLABEL");
     253:         break;
     254:
     255:     case WRITEBOOT:
     256:     {
     257:         struct disklabel tlab;
     258:
     259:         lp = readlabel(f);
     260:         tlab = *lp;
     261:         if (argc == 2)
     262:             makelabel(argv[1], 0, &lab);
     263:         lp = makebootarea(bootarea, &lab, f);
     264:         *lp = tlab;
     265:         if (checklabel(lp) == 0)
     266:             error = writelabel(f, bootarea, lp);
     267:         break;
     268:     }
     269:     }
     270:     exit(error);
     271: }
     272:
     273: /*
     274:  * Construct a prototype disklabel from /etc/disktab.  As a side
     275:  * effect, set the names of the primary and secondary boot files
     276:  * if specified.
     277:  */
     278: makelabel(type, name, lp)
     279:     char *type, *name;
     280:     register struct disklabel *lp;
     281: {
     282:     register struct disklabel *dp;
     283:     char *strcpy();
     284:
     285:     dp = getdiskbyname(type);
     286:     if (dp == NULL) {
     287:         fprintf(stderr, "%s: unknown disk type\n", type);
     288:         exit(1);
     289:     }
     290:     *lp = *dp;
     291:
     292:     /*
     293: 	 * Set bootstrap name.
     294: 	 * 1. If set from command line, use it,
     295: 	 * 2. otherwise, check if disktab specifies it (b0),
     296: 	 * 3. otherwise, makebootarea() will choose one based on the name
     297: 	 *    of the disk special file. E.g. /dev/ra0 -> rauboot
     298: 	 */
     299:     if (!xxboot && lp->d_boot0) {
     300:         if (*lp->d_boot0 != '/')
     301:             (void)sprintf(boot0, "%s/%s",
     302:                       _PATH_BOOTDIR, lp->d_boot0);
     303:         else
     304:             (void)strcpy(boot0, lp->d_boot0);
     305:         xxboot = boot0;
     306:     }
     307:     /* d_packname is union d_boot0, so zero */
     308:     bzero(lp->d_packname, sizeof(lp->d_packname));
     309:     if (name)
     310:         (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
     311: }
     312:
     313: writelabel(f, boot, lp)
     314:     int f;
     315:     char *boot;
     316:     register struct disklabel *lp;
     317: {
     318:     register int i;
     319:     int flag;
     320:
     321:     lp->d_magic = DISKMAGIC;
     322:     lp->d_magic2 = DISKMAGIC;
     323:     lp->d_checksum = 0;
     324:     lp->d_checksum = dkcksum(lp);
     325:     if (rflag) {
     326:         /*
     327: 		 * First set the kernel disk label,
     328: 		 * then write a label to the raw disk.
     329: 		 * If the SDINFO ioctl fails because it is unimplemented,
     330: 		 * keep going; otherwise, the kernel consistency checks
     331: 		 * may prevent us from changing the current (in-core)
     332: 		 * label.  Normally EFAULT would not be here - but the ioctl
     333: 		 * maximum data length changed and old kernels would generate
     334: 		 * an error prematurely in the ioctl dispatch.
     335: 		 */
     336:         if (ioctl(f, DIOCSDINFO, lp) < 0 &&
     337:             errno != EFAULT && errno != ENODEV && errno != ENOTTY) {
     338:             l_perror("ioctl DIOCSDINFO");
     339:             return (1);
     340:         }
     341:         (void)lseek(f, (off_t)0, L_SET);
     342:         /*
     343: 		 * write enable label sector before write (if necessary),
     344: 		 * disable after writing.
     345: 		 */
     346:         flag = 1;
     347:         if (ioctl(f, DIOCWLABEL, &flag) < 0)
     348:             perror("ioctl DIOCWLABEL");
     349: /*
     350:  * Write the boot block sector (512 bytes) followed immediately by the
     351:  * label sector (512 bytes) = BBSIZE (1kb) total.
     352: */
     353:         if (write(f, boot, BBSIZE) != BBSIZE) {
     354:             perror("write");
     355:             return (1);
     356:         }
     357:         flag = 0;
     358:         (void) ioctl(f, DIOCWLABEL, &flag);
     359:     } else if (ioctl(f, DIOCWDINFO, lp) < 0) {
     360:         l_perror("ioctl DIOCWDINFO");
     361:         return (1);
     362:     }
     363:     return (0);
     364: }
     365:
     366: l_perror(s)
     367:     char *s;
     368: {
     369:     int saverrno = errno;
     370:
     371:     fprintf(stderr, "disklabel: %s: ", s);
     372:
     373:     switch (saverrno) {
     374:
     375:     case ESRCH:
     376:         fprintf(stderr, "No disk label on disk;\n");
     377:         fprintf(stderr,
     378:             "use \"disklabel -r\" to install initial label\n");
     379:         break;
     380:
     381:     case EINVAL:
     382:         fprintf(stderr, "Label magic number or checksum is wrong!\n");
     383:         fprintf(stderr, "(disklabel or kernel is out of date?)\n");
     384:         break;
     385:
     386:     case EBUSY:
     387:         fprintf(stderr, "Open partition would move or shrink\n");
     388:         break;
     389:
     390:     case EXDEV:
     391:         fprintf(stderr,
     392:     "Labeled partition or 'a' partition must start at beginning of disk\n");
     393:         break;
     394:
     395:     default:
     396:         errno = saverrno;
     397:         perror((char *)NULL);
     398:         break;
     399:     }
     400: }
     401:
     402: /*
     403:  * Fetch disklabel for disk.
     404:  * Use ioctl to get label unless -r flag is given.
     405:  *
     406:  * We use the search logic for the label even though the label will be
     407:  * in the second half of the bootarea.  If there ever is a valid label
     408:  * residing in the boot sector things are going to get weird.
     409:  */
     410: struct disklabel *
     411: readlabel(f)
     412:     int f;
     413: {
     414:     register struct disklabel *lp;
     415: register struct disklabel *xx = (struct disklabel *)(bootarea + BBSIZE - sizeof (struct disklabel));
     416:
     417:     if (rflag) {
     418:         if (lseek(f, (daddr_t)0, L_SET) < 0)
     419:             Perror(specname);
     420:         if (read(f, bootarea, BBSIZE) < BBSIZE)
     421:             Perror(specname);
     422:         for (lp = (struct disklabel *)bootarea;
     423:             lp <= xx;
     424:             lp = (struct disklabel *)((char *)lp + 16))
     425:             if (lp->d_magic == DISKMAGIC &&
     426:                 lp->d_magic2 == DISKMAGIC)
     427:                 break;
     428:         if (lp > xx ||
     429:             lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
     430:             dkcksum(lp) != 0) {
     431:             fprintf(stderr,
     432:     "Bad pack magic number (label is damaged, or pack is unlabeled)\n");
     433:             exit (1);
     434:         }
     435:     } else {
     436:         lp = &lab;
     437:         if (ioctl(f, DIOCGDINFO, lp) < 0)
     438:             Perror("ioctl DIOCGDINFO");
     439:     }
     440:     return (lp);
     441: }
     442:
     443: /*
     444:  * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot''
     445:  * Returns a pointer to the disklabel portion of the bootarea.
     446:  */
     447: struct disklabel *
     448: makebootarea(boot, dp, f)
     449:     char *boot;
     450:     register struct disklabel *dp;
     451:     int f;
     452: {
     453:     struct disklabel *lp;
     454:     register char *p;
     455:     int b;
     456:     char *dkbasename;
     457:     struct stat sb;
     458:
     459:     /* XXX */
     460:     /*
     461: 	 * sectors are 512 bytes, filesystem blocks are DEV_BSIZE (1024) bytes.
     462: 	 * We override the sector size so that things like the RL02 work
     463: 	 * right.  The RL drives use a hardware sector size of 256 bytes
     464: 	 * which would wreck havoc in the calculation below.  Actually the
     465: 	 * disktab file should be "fixed" - all entries should omit 'se' and
     466: 	 * use the default of 512.
     467: 	*/
     468:     dp->d_secsize = 512;
     469:     dp->d_bbsize = 512;
     470:     lp = (struct disklabel *)
     471:         (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET);
     472:     bzero((char *)lp, sizeof *lp);
     473:
     474:     /*
     475: 	 * If we are not installing a boot program but we are installing a
     476: 	 * label on disk then we must read the current bootarea so we don't
     477: 	 * clobber the existing boot.
     478: 	 */
     479:     if (!installboot) {
     480:         if (rflag) {
     481:             if (lseek(f, (daddr_t)0, L_SET) < 0)
     482:                 Perror(specname);
     483:             if (read(f, boot, BBSIZE) < BBSIZE)
     484:                 Perror(specname);
     485:             bzero((char *)lp, sizeof *lp);
     486:         }
     487:         return (lp);
     488:     }
     489:     /*
     490: 	 * We are installing a boot program.  Determine the name(s) and
     491: 	 * read them into the appropriate places in the boot area.
     492: 	 */
     493:     if (!xxboot) {
     494:         dkbasename = np;
     495:         if ((p = rindex(dkname, '/')) == NULL)
     496:             p = dkname;
     497:         else
     498:             p++;
     499:         while (*p && !isdigit(*p))
     500:             *np++ = *p++;
     501:         *np++ = '\0';
     502:
     503:         (void)sprintf(np, "%s/%suboot",
     504:                   _PATH_BOOTDIR, dkbasename);
     505:         if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
     506:             dkbasename++;
     507:         xxboot = np;
     508:         (void)sprintf(xxboot, "%s/%suboot",
     509:                   _PATH_BOOTDIR, dkbasename);
     510:         np += strlen(xxboot) + 1;
     511:     }
     512: #ifdef DEBUG
     513:     if (debug)
     514:         fprintf(stderr, "bootstrap: xxboot = %s\n", xxboot);
     515: #endif
     516:
     517:     /*
     518: 	 * Rule:
     519: 	 * 1. One-piece bootstrap up to 512 bytes is all that is supported.
     520: 	 */
     521:     b = open(xxboot, O_RDONLY);
     522:     if (b < 0)
     523:         Perror(xxboot);
     524:     if (read(b, boot, 512) < 0)
     525:         Perror(xxboot);
     526:     (void)fstat(b, &sb);
     527:     if (sb.st_size > 512)
     528:         Warning("boot > 512 bytes - filesystem likely not bootable");
     529:     (void)close(b);
     530:     return (lp);
     531: }
     532:
     533: display(f, lp)
     534:     FILE *f;
     535:     register struct disklabel *lp;
     536: {
     537:     register int i, j;
     538:     register struct partition *pp;
     539:
     540:     fprintf(f, "# %s:\n", specname);
     541:     if ((unsigned) lp->d_type < DKMAXTYPES)
     542:         fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
     543:     else
     544:         fprintf(f, "type: %d\n", lp->d_type);
     545:     fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
     546:     fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
     547:     fprintf(f, "flags:");
     548:     if (lp->d_flags & D_REMOVABLE)
     549:         fprintf(f, " removeable");
     550:     if (lp->d_flags & D_ECC)
     551:         fprintf(f, " ecc");
     552:     if (lp->d_flags & D_BADSECT)
     553:         fprintf(f, " badsect");
     554:     fprintf(f, "\n");
     555:     fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
     556:     fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
     557:     fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
     558:     fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
     559:     fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
     560:     fprintf(f, "rpm: %d\n", lp->d_rpm);
     561:     fprintf(f, "interleave: %d\n", lp->d_interleave);
     562:     fprintf(f, "trackskew: %d\n", lp->d_trackskew);
     563:     fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
     564:     fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
     565:     fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
     566:     fprintf(f, "drivedata: ");
     567:     for (i = NDDATA - 1; i >= 0; i--)
     568:         if (lp->d_drivedata[i])
     569:             break;
     570:     if (i < 0)
     571:         i = 0;
     572:     for (j = 0; j <= i; j++)
     573:         fprintf(f, "%ld ", lp->d_drivedata[j]);
     574:     fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
     575:     fprintf(f,
     576:         "#        size   offset    fstype   [fsize bsize]\n");
     577:     pp = lp->d_partitions;
     578:     for (i = 0; i < lp->d_npartitions; i++, pp++) {
     579:         if (pp->p_size) {
     580:             fprintf(f, "  %c: %8ld %8ld  ", 'a' + i,
     581:                pp->p_size, pp->p_offset);
     582:             if ((unsigned) pp->p_fstype < FSMAXTYPES)
     583:                 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
     584:             else
     585:                 fprintf(f, "%8d", pp->p_fstype);
     586:             switch (pp->p_fstype) {
     587:
     588:             case FS_V71K:
     589:             case FS_UNUSED:             /* XXX */
     590:                 fprintf(f, "    %5d %5d ",
     591:                     pp->p_fsize, pp->p_fsize * pp->p_frag);
     592:                 break;
     593:
     594:             default:
     595:                 fprintf(f, "%20.20s", "");
     596:                 break;
     597:             }
     598:             fprintf(f, "\t# (Cyl. %4ld",
     599:                 pp->p_offset / lp->d_secpercyl);
     600:             if (pp->p_offset % lp->d_secpercyl)
     601:                 putc('*', f);
     602:             else
     603:                 putc(' ', f);
     604:             fprintf(f, "- %ld",
     605:                 (pp->p_offset +
     606:                 pp->p_size + lp->d_secpercyl - 1) /
     607:                 lp->d_secpercyl - 1);
     608:             if (pp->p_size % lp->d_secpercyl)
     609:                 putc('*', f);
     610:             fprintf(f, ")\n");
     611:         }
     612:     }
     613:     fflush(f);
     614: }
     615:
     616: edit(lp, f)
     617:     struct disklabel *lp;
     618:     int f;
     619: {
     620:     register int c;
     621:     struct disklabel label;
     622:     FILE *fd;
     623:     char *mktemp();
     624:
     625:     (void) mktemp(tmpfil);
     626:     fd = fopen(tmpfil, "w");
     627:     if (fd == NULL) {
     628:         fprintf(stderr, "%s: Can't create\n", tmpfil);
     629:         return (1);
     630:     }
     631:     (void)fchmod(fileno(fd), 0600);
     632:     display(fd, lp);
     633:     fclose(fd);
     634:     for (;;) {
     635:         if (!editit())
     636:             break;
     637:         fd = fopen(tmpfil, "r");
     638:         if (fd == NULL) {
     639:             fprintf(stderr, "%s: Can't reopen for reading\n",
     640:                 tmpfil);
     641:             break;
     642:         }
     643:         bzero((char *)&label, sizeof(label));
     644:         if (getasciilabel(fd, &label)) {
     645:             *lp = label;
     646:             if (writelabel(f, bootarea, lp) == 0) {
     647:                 (void) unlink(tmpfil);
     648:                 return (0);
     649:             }
     650:         }
     651:         printf("re-edit the label? [y]: "); fflush(stdout);
     652:         c = getchar();
     653:         if (c != EOF && c != (int)'\n')
     654:             while (getchar() != (int)'\n')
     655:                 ;
     656:         if  (c == (int)'n')
     657:             break;
     658:     }
     659:     (void) unlink(tmpfil);
     660:     return (1);
     661: }
     662:
     663: editit()
     664: {
     665:     register int pid, xpid;
     666:     int stat;
     667:     sigset_t set, oset;
     668:
     669:     sigemptyset(&set);
     670:     sigaddset(&set, SIGINT);
     671:     sigaddset(&set, SIGHUP);
     672:     sigaddset(&set, SIGQUIT);
     673:     (void)sigprocmask(SIG_BLOCK, &set, &oset);
     674:     while ((pid = fork()) < 0) {
     675:
     676:         if (errno == EPROCLIM) {
     677:             fprintf(stderr, "You have too many processes\n");
     678:             return(0);
     679:         }
     680:         if (errno != EAGAIN) {
     681:             perror("fork");
     682:             return(0);
     683:         }
     684:         sleep(1);
     685:     }
     686:     if (pid == 0) {
     687:         register char *ed;
     688:
     689:         (void)sigprocmask(SIG_SETMASK, &oset, NULL);
     690:         setgid(getgid());
     691:         setuid(getuid());
     692:         if ((ed = getenv("EDITOR")) == (char *)0)
     693:             ed = DEFEDITOR;
     694:         execlp(ed, ed, tmpfil, 0);
     695:         perror(ed);
     696:         exit(1);
     697:     }
     698:     while ((xpid = wait(&stat)) >= 0)
     699:         if (xpid == pid)
     700:             break;
     701:     (void)sigprocmask(SIG_SETMASK, &oset, NULL);
     702:     return(!stat);
     703: }
     704:
     705: char *
     706: skip(cp)
     707:     register char *cp;
     708: {
     709:
     710:     while (*cp != '\0' && isspace(*cp))
     711:         cp++;
     712:     if (*cp == '\0' || *cp == '#')
     713:         return ((char *)NULL);
     714:     return (cp);
     715: }
     716:
     717: char *
     718: word(cp)
     719:     register char *cp;
     720: {
     721:     register char c;
     722:
     723:     while (*cp != '\0' && !isspace(*cp) && *cp != '#')
     724:         cp++;
     725:     if ((c = *cp) != '\0') {
     726:         *cp++ = '\0';
     727:         if (c != '#')
     728:             return (skip(cp));
     729:     }
     730:     return ((char *)NULL);
     731: }
     732:
     733: /*
     734:  * Read an ascii label in from fd f,
     735:  * in the same format as that put out by display(),
     736:  * and fill in lp.
     737:  */
     738: getasciilabel(f, lp)
     739:     FILE    *f;
     740:     register struct disklabel *lp;
     741: {
     742:     register char **cpp, *cp;
     743:     register struct partition *pp;
     744:     char *tp, *s, line[BUFSIZ];
     745:     int lineno = 0, errors = 0;
     746:     long v;
     747:
     748:     lp->d_bbsize = 512;             /* XXX */
     749:     lp->d_sbsize = SBSIZE;
     750:     while (fgets(line, sizeof(line) - 1, f)) {
     751:         lineno++;
     752:         if (cp = index(line,'\n'))
     753:             *cp = '\0';
     754:         cp = skip(line);
     755:         if (cp == NULL)
     756:             continue;
     757:         tp = index(cp, ':');
     758:         if (tp == NULL) {
     759:             fprintf(stderr, "line %d: syntax error\n", lineno);
     760:             errors++;
     761:             continue;
     762:         }
     763:         *tp++ = '\0', tp = skip(tp);
     764:         if (streq(cp, "type")) {
     765:             if (tp == NULL)
     766:                 tp = "unknown";
     767:             cpp = dktypenames;
     768:             for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
     769:                 if ((s = *cpp) && streq(s, tp)) {
     770:                     lp->d_type = cpp - dktypenames;
     771:                     goto next;
     772:                 }
     773:             v = atoi(tp);
     774:             if ((unsigned)v >= DKMAXTYPES)
     775:                 fprintf(stderr, "line %d:%s %d\n", lineno,
     776:                     "Warning, unknown disk type", v);
     777:             lp->d_type = v;
     778:             continue;
     779:         }
     780:         if (streq(cp, "flags")) {
     781:             for (v = 0; (cp = tp) && *cp != '\0';) {
     782:                 tp = word(cp);
     783:                 if (streq(cp, "removeable"))
     784:                     v |= D_REMOVABLE;
     785:                 else if (streq(cp, "ecc"))
     786:                     v |= D_ECC;
     787:                 else if (streq(cp, "badsect"))
     788:                     v |= D_BADSECT;
     789:                 else {
     790:                     fprintf(stderr,
     791:                         "line %d: %s: bad flag\n",
     792:                         lineno, cp);
     793:                     errors++;
     794:                 }
     795:             }
     796:             lp->d_flags = v;
     797:             continue;
     798:         }
     799:         if (streq(cp, "drivedata")) {
     800:             register int i;
     801:
     802:             for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
     803:                 lp->d_drivedata[i++] = atol(cp);
     804:                 tp = word(cp);
     805:             }
     806:             continue;
     807:         }
     808:         if (sscanf(cp, "%ld partitions", &v) == 1) {
     809:             if (v == 0 || (unsigned)v > MAXPARTITIONS) {
     810:                 fprintf(stderr,
     811:                     "line %d: bad # of partitions\n", lineno);
     812:                 lp->d_npartitions = MAXPARTITIONS;
     813:                 errors++;
     814:             } else
     815:                 lp->d_npartitions = v;
     816:             continue;
     817:         }
     818:         if (tp == NULL)
     819:             tp = "";
     820:         if (streq(cp, "disk")) {
     821:             strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
     822:             continue;
     823:         }
     824:         if (streq(cp, "label")) {
     825:             strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
     826:             continue;
     827:         }
     828: /*
     829:  * ARGH!  Have to fix the 'se#256' entries in disktab after all or this
     830:  * check will cause errors.
     831: */
     832:         if (streq(cp, "bytes/sector")) {
     833:             v = atoi(tp);
     834:             if (v <= 0 || (v % 512) != 0) {
     835:                 fprintf(stderr,
     836:                     "line %d: %s: bad sector size\n",
     837:                     lineno, tp);
     838:                 errors++;
     839:             } else
     840:                 lp->d_secsize = v;
     841:             continue;
     842:         }
     843:         if (streq(cp, "sectors/track")) {
     844:             v = atoi(tp);
     845:             if (v <= 0) {
     846:                 fprintf(stderr, "line %d: %s: bad %s\n",
     847:                     lineno, tp, cp);
     848:                 errors++;
     849:             } else
     850:                 lp->d_nsectors = v;
     851:             continue;
     852:         }
     853:         if (streq(cp, "sectors/cylinder")) {
     854:             v = atoi(tp);
     855:             if (v <= 0) {
     856:                 fprintf(stderr, "line %d: %s: bad %s\n",
     857:                     lineno, tp, cp);
     858:                 errors++;
     859:             } else
     860:                 lp->d_secpercyl = v;
     861:             continue;
     862:         }
     863:         if (streq(cp, "tracks/cylinder")) {
     864:             v = atoi(tp);
     865:             if (v <= 0) {
     866:                 fprintf(stderr, "line %d: %s: bad %s\n",
     867:                     lineno, tp, cp);
     868:                 errors++;
     869:             } else
     870:                 lp->d_ntracks = v;
     871:             continue;
     872:         }
     873:         if (streq(cp, "cylinders")) {
     874:             v = atoi(tp);
     875:             if (v <= 0) {
     876:                 fprintf(stderr, "line %d: %s: bad %s\n",
     877:                     lineno, tp, cp);
     878:                 errors++;
     879:             } else
     880:                 lp->d_ncylinders = v;
     881:             continue;
     882:         }
     883:         if (streq(cp, "rpm")) {
     884:             v = atoi(tp);
     885:             if (v <= 0) {
     886:                 fprintf(stderr, "line %d: %s: bad %s\n",
     887:                     lineno, tp, cp);
     888:                 errors++;
     889:             } else
     890:                 lp->d_rpm = v;
     891:             continue;
     892:         }
     893:         if (streq(cp, "interleave")) {
     894:             v = atoi(tp);
     895:             if (v <= 0) {
     896:                 fprintf(stderr, "line %d: %s: bad %s\n",
     897:                     lineno, tp, cp);
     898:                 errors++;
     899:             } else
     900:                 lp->d_interleave = v;
     901:             continue;
     902:         }
     903:         if (streq(cp, "trackskew")) {
     904:             v = atoi(tp);
     905:             if (v < 0) {
     906:                 fprintf(stderr, "line %d: %s: bad %s\n",
     907:                     lineno, tp, cp);
     908:                 errors++;
     909:             } else
     910:                 lp->d_trackskew = v;
     911:             continue;
     912:         }
     913:         if (streq(cp, "cylinderskew")) {
     914:             v = atoi(tp);
     915:             if (v < 0) {
     916:                 fprintf(stderr, "line %d: %s: bad %s\n",
     917:                     lineno, tp, cp);
     918:                 errors++;
     919:             } else
     920:                 lp->d_cylskew = v;
     921:             continue;
     922:         }
     923:         if (streq(cp, "headswitch")) {
     924:             v = atoi(tp);
     925:             if (v < 0) {
     926:                 fprintf(stderr, "line %d: %s: bad %s\n",
     927:                     lineno, tp, cp);
     928:                 errors++;
     929:             } else
     930:                 lp->d_headswitch = v;
     931:             continue;
     932:         }
     933:         if (streq(cp, "track-to-track seek")) {
     934:             v = atoi(tp);
     935:             if (v < 0) {
     936:                 fprintf(stderr, "line %d: %s: bad %s\n",
     937:                     lineno, tp, cp);
     938:                 errors++;
     939:             } else
     940:                 lp->d_trkseek = v;
     941:             continue;
     942:         }
     943:         if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
     944:             unsigned part = *cp - 'a';
     945:
     946:             if (part > lp->d_npartitions) {
     947:                 fprintf(stderr,
     948:                     "line %d: bad partition name '%c' %d %d\n",
     949:                     lineno, *cp, part, lp->d_npartitions);
     950:                 errors++;
     951:                 continue;
     952:             }
     953:             pp = &lp->d_partitions[part];
     954: #define NXTNUM(n) { \
     955:     cp = tp, tp = word(cp); \
     956:     if (tp == NULL) \
     957:         tp = cp; \
     958:     (n) = atol(cp); \
     959:      }
     960:
     961:             NXTNUM(v);
     962:             if (v < 0) {
     963:                 fprintf(stderr,
     964:                     "line %d: %s: bad partition size\n",
     965:                     lineno, cp);
     966:                 errors++;
     967:             } else
     968:                 pp->p_size = v;
     969:             NXTNUM(v);
     970:             if (v < 0) {
     971:                 fprintf(stderr,
     972:                     "line %d: %s: bad partition offset\n",
     973:                     lineno, cp);
     974:                 errors++;
     975:             } else
     976:                 pp->p_offset = v;
     977:             cp = tp, tp = word(cp);
     978:             cpp = fstypenames;
     979:             for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
     980:                 if ((s = *cpp) && streq(s, cp)) {
     981:                     pp->p_fstype = cpp - fstypenames;
     982:                     goto gottype;
     983:                 }
     984:             if (isdigit(*cp))
     985:                 v = atoi(cp);
     986:             else
     987:                 v = FSMAXTYPES;
     988:             if ((unsigned)v >= FSMAXTYPES) {
     989:                 fprintf(stderr, "line %d: %s %s\n", lineno,
     990:                     "Warning, unknown filesystem type", cp);
     991:                 v = FS_UNUSED;
     992:             }
     993:             pp->p_fstype = v;
     994:     gottype:
     995:
     996:             switch (pp->p_fstype) {
     997:
     998:             case FS_UNUSED:             /* XXX */
     999:             case FS_V71K:
    1000:                 NXTNUM(pp->p_fsize);
    1001:                 if (pp->p_fsize == 0)
    1002:                     break;
    1003:                 NXTNUM(v);
    1004:                 pp->p_frag = v / pp->p_fsize;
    1005:                 break;
    1006:
    1007:             default:
    1008:                 break;
    1009:             }
    1010:             continue;
    1011:         }
    1012:         fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
    1013:             lineno, cp);
    1014:         errors++;
    1015:     next:
    1016:         ;
    1017:     }
    1018:     errors += checklabel(lp);
    1019:     return (errors == 0);
    1020: }
    1021:
    1022: /*
    1023:  * Check disklabel for errors and fill in
    1024:  * derived fields according to supplied values.
    1025:  */
    1026: checklabel(lp)
    1027:     register struct disklabel *lp;
    1028: {
    1029:     register struct partition *pp;
    1030:     int i, errors = 0;
    1031:     char part;
    1032:
    1033:     if (lp->d_secsize == 0) {
    1034:         fprintf(stderr, "sector size %d\n", lp->d_secsize);
    1035:         return (1);
    1036:     }
    1037:     if (lp->d_nsectors == 0) {
    1038:         fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
    1039:         return (1);
    1040:     }
    1041:     if (lp->d_ntracks == 0) {
    1042:         fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
    1043:         return (1);
    1044:     }
    1045:     if  (lp->d_ncylinders == 0) {
    1046:         fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
    1047:         errors++;
    1048:     }
    1049:     if (lp->d_rpm == 0)
    1050:         Warning("revolutions/minute %d", lp->d_rpm);
    1051:     if (lp->d_secpercyl == 0)
    1052:         lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
    1053:     if (lp->d_secperunit == 0)
    1054:         lp->d_secperunit = (long) lp->d_secpercyl * lp->d_ncylinders;
    1055:     if (lp->d_bbsize == 0) {
    1056:         fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
    1057:         errors++;
    1058:     } else if (lp->d_bbsize % lp->d_secsize)
    1059:         Warning("boot block size %% sector-size != 0");
    1060:     if (lp->d_sbsize == 0) {
    1061:         fprintf(stderr, "super block size %d\n", lp->d_sbsize);
    1062:         errors++;
    1063:     } else if (lp->d_sbsize % lp->d_secsize)
    1064:         Warning("super block size %% sector-size != 0");
    1065:     if (lp->d_npartitions > MAXPARTITIONS)
    1066:         Warning("number of partitions (%d) > MAXPARTITIONS (%d)",
    1067:             lp->d_npartitions, MAXPARTITIONS);
    1068:     for (i = 0; i < lp->d_npartitions; i++) {
    1069:         part = 'a' + i;
    1070:         pp = &lp->d_partitions[i];
    1071:         if (pp->p_size == 0 && pp->p_offset != 0)
    1072:             Warning("partition %c: size 0, but offset %ld",
    1073:                 part, pp->p_offset);
    1074: #ifdef notdef
    1075:         if (pp->p_size % lp->d_secpercyl)
    1076:             Warning("partition %c: size %% cylinder-size != 0",
    1077:                 part);
    1078:         if (pp->p_offset % lp->d_secpercyl)
    1079:             Warning("partition %c: offset %% cylinder-size != 0",
    1080:                 part);
    1081: #endif
    1082:         if (pp->p_offset > lp->d_secperunit) {
    1083:             fprintf(stderr,
    1084:                 "partition %c: offset past end of unit %ld %ld\n",
    1085:                 part, pp->p_offset, lp->d_secperunit);
    1086:             errors++;
    1087:         }
    1088:         if (pp->p_offset + pp->p_size > lp->d_secperunit) {
    1089:             fprintf(stderr,
    1090:                 "partition %c: extends past end of unit %ld %ld %ld\n",
    1091:                 part, pp->p_offset, pp->p_size, lp->d_secperunit);
    1092:             errors++;
    1093:         }
    1094:     }
    1095:     for (; i < MAXPARTITIONS; i++) {
    1096:         part = 'a' + i;
    1097:         pp = &lp->d_partitions[i];
    1098:         if (pp->p_size || pp->p_offset)
    1099:             Warning("unused partition %c: size %ld offset %ld",
    1100:                 'a' + i, pp->p_size, pp->p_offset);
    1101:     }
    1102:     return (errors);
    1103: }
    1104:
    1105: /*VARARGS1*/
    1106: Warning(fmt, a1, a2, a3, a4, a5)
    1107:     char *fmt;
    1108: {
    1109:
    1110:     fprintf(stderr, "Warning, ");
    1111:     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
    1112:     fprintf(stderr, "\n");
    1113: }
    1114:
    1115: Perror(str)
    1116:     char *str;
    1117: {
    1118:     fputs("disklabel: ", stderr); perror(str);
    1119:     exit(4);
    1120: }
    1121:
    1122: usage()
    1123: {
    1124:     fprintf(stderr,
    1125: "%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n",
    1126: "usage: disklabel [-r] disk",
    1127:         "(to read label)",
    1128: "or disklabel -w [-r] disk type [ packid ]",
    1129:         "(to write label with existing boot program)",
    1130: "or disklabel -e [-r] disk",
    1131:         "(to edit label)",
    1132: "or disklabel -R [-r] disk protofile",
    1133:         "(to restore label with existing boot program)",
    1134: "or disklabel -B [ -b bootprog ] disk [ type ]",
    1135:         "(to install boot program with existing on-disk label)",
    1136: "or disklabel -w -B [ -b bootprog ] disk type [ packid ]",
    1137:         "(to write label and install boot program)",
    1138: "or disklabel -R -B [ -b bootprog ] disk protofile [ type ]",
    1139:         "(to restore label and install boot program)",
    1140: "or disklabel [-NW] disk",
    1141:         "(to write disable/enable label)");
    1142:     exit(1);
    1143: }

#### Defined functions

Perror defined in line 1115; used 11 times

- in line 196, 210, 230, 252, 419-421(2), 438, 482-484(2), 523-525(2)

Warning defined in line 1106; used 9 times

- in line 528, 1050, 1059-1066(3), 1072-1079(3), 1099

checklabel defined in line 1026; used 4 times

- in line 218, 245, 265, 1018

display defined in line 533; used 2 times

- in line 217, 632

edit defined in line 616; used 1 times

- in line 204

editit defined in line 663; used 1 times

- in line 635

getasciilabel defined in line 738; used 2 times

- in line 231, 644

l_perror defined in line 366; used 2 times

- in line 338, 360

main defined in line 113; never used
makebootarea defined in line 447; used 4 times

- in line 93, 228, 243, 263

makelabel defined in line 278; used 3 times

- in line 223, 242, 262

readlabel defined in line 410; used 4 times

- in line 93, 203, 216, 259

skip defined in line 705; used 3 times

- in line 728, 754, 763

usage defined in line 1122; used 11 times

- in line 132-147(4), 155, 165, 180, 202, 215, 227, 241

word defined in line 717; used 4 times

- in line 782, 804, 955, 977

writelabel defined in line 313; used 4 times

- in line 232, 246, 266, 646

#### Defined variables

boot0 defined in line 98; used 3 times

- in line 301-305(3)

bootarea defined in line 94; used 10 times

- in line 228-232(2), 243-246(2), 263-266(2), 415-422(3), 646

copyright defined in line 38; never used
debug defined in line 107; used 2 times

- in line 160, 513

dkname defined in line 87; used 8 times

- in line 182-191(6), 495-496(2)

installboot defined in line 96; used 4 times

- in line 125, 169, 222, 479

lab defined in line 92; used 8 times

- in line 223-228(2), 242-244(3), 262-263(2), 436

namebuf defined in line 91; used 2 times

- in line 91, 192

np defined in line 91; used 11 times

- in line 184-186(3), 192, 494, 500-510(6)

rflag defined in line 104; used 5 times

- in line 151, 170, 325, 417, 480

sccsid defined in line 42; never used
specname defined in line 88; used 13 times

- in line 185-196(8), 419-421(2), 482-484(2), 540

tmpfil defined in line 89; used 8 times

- in line 625-628(3), 637-640(2), 647, 659, 694

xxboot defined in line 97; used 12 times

- in line 128, 176, 299, 305, 493, 507-514(4), 521-525(3)

#### Defined macros

DEFEDITOR defined in line 84; used 1 times

- in line 693

DKTYPENAMES defined in line 52; never used
NXTNUM defined in line 954; used 4 times

- in line 961, 969, 1000-1003(2)

OPTIONS defined in line 110; used 1 times

- in line 122

RAWPARTITION defined in line 82; used 1 times

- in line 184

streq defined in line 85; used 21 times

- in line 764-769(2), 780-787(4), 799, 820-824(2), 832, 843, 853, 863, 873, 883, 893, 903, 913, 923, 933, 980

Last modified: 1999-10-26 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4125 |