1: /*
   2:  * Copyright (c) 1983, 1987 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms, with or without
   6:  * modification, are permitted provided that the following conditions
   7:  * are met:
   8:  * 1. Redistributions of source code must retain the above copyright
   9:  *    notice, this list of conditions and the following disclaimer.
  10:  * 2. Redistributions in binary form must reproduce the above copyright
  11:  *    notice, this list of conditions and the following disclaimer in the
  12:  *    documentation and/or other materials provided with the distribution.
  13:  * 3. All advertising materials mentioning features or use of this software
  14:  *    must display the following acknowledgement:
  15:  *	This product includes software developed by the University of
  16:  *	California, Berkeley and its contributors.
  17:  * 4. Neither the name of the University nor the names of its contributors
  18:  *    may be used to endorse or promote products derived from this software
  19:  *    without specific prior written permission.
  20:  *
  21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31:  * SUCH DAMAGE.
  32:  */
  33: 
  34: #if defined(LIBC_SCCS) && !defined(lint)
  35: static char sccsid[] = "@(#)disklabel.c	5.17.1 (2.11BSD) 4/10/95";
  36: #endif /* LIBC_SCCS and not lint */
  37: 
  38: #include <sys/param.h>
  39: #include <sys/errno.h>
  40: #include <sys/fs.h>
  41: #include <sys/file.h>
  42: #include <sys/uio.h>
  43: 
  44: #define DKTYPENAMES
  45: #include <sys/disklabel.h>
  46: #include <stdio.h>
  47: #include <string.h>
  48: 
  49: extern  int errno;
  50: 
  51: static  char *dgetstr();
  52: static  dgetent();
  53: static  dnamatch();
  54: static  long dgetnum(), _gtnumdflt();
  55: static  dgetflag();
  56: static  gettype();
  57: static  error();
  58: 
  59: #define getnumdflt(field, dname, dflt) field=_gtnumdflt(dname,(long)dflt)
  60: 
  61: struct disklabel *
  62: getdiskbyname(name)
  63:     char *name;
  64: {
  65:     static struct   disklabel disk;
  66:     static char     boot[MAXPATHLEN];
  67:     char    localbuf[256];  /* BUFSIZ reduced to save stack space */
  68:     char    buf[BUFSIZ];
  69:     char    *cp, *cq;   /* can't be register */
  70:     register struct disklabel *dp = &disk;
  71:     register struct partition *pp;
  72:     char    p, max, psize[3], pbsize[3],
  73:         pfsize[3], poffset[3], ptype[3];
  74:     u_long  *dx;
  75: 
  76:     if (dgetent(buf, name) <= 0)
  77:         return ((struct disklabel *)0);
  78:     bzero((char *)&disk, sizeof(disk));
  79:     /*
  80: 	 * typename
  81: 	 */
  82:     cq = dp->d_typename;
  83:     cp = buf;
  84:     while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 &&
  85:         (*cq = *cp) && *cq != '|' && *cq != ':')
  86:         cq++, cp++;
  87:     *cq = '\0';
  88:     /*
  89: 	 * boot name (optional)  xxboot
  90: 	 */
  91:     cp = boot;
  92:     dp->d_boot0 = dgetstr("b0", &cp);
  93:     cp = localbuf;
  94:     cq = dgetstr("ty", &cp);
  95:     if (cq && strcmp(cq, "removable") == 0)
  96:         dp->d_flags |= D_REMOVABLE;
  97:     else  if (cq && strcmp(cq, "simulated") == 0)
  98:         dp->d_flags |= D_RAMDISK;
  99:     if (dgetflag("sf"))
 100:         dp->d_flags |= D_BADSECT;
 101: 
 102: /*
 103:  *	Have to do this because anything except 512 will cause chaos in
 104:  *	disklabel(8).  disklabel(8) tries to protect itself against this
 105:  *	but the safest thing is to fix the sector size here.  The only thing
 106:  *	which ever used a value other than 512 was the RL02 and RL01
 107:  *	disktab entries and they have been fixed.
 108: */
 109: 
 110: #ifdef  corrupt_filesystems
 111:     getnumdflt(dp->d_secsize, "se", 512);
 112: #endif
 113:     dp->d_secsize = 512;
 114: 
 115:     dp->d_ntracks = dgetnum("nt");
 116:     dp->d_nsectors = dgetnum("ns");
 117:     dp->d_ncylinders = dgetnum("nc");
 118:     cq = dgetstr("dt", &cp);
 119:     if (cq)
 120:         dp->d_type = gettype(cq, dktypenames);
 121:     else
 122:         getnumdflt(dp->d_type, "dt", 0);
 123:     getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
 124:     getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
 125:     getnumdflt(dp->d_sparespertrack, "rt", 0);
 126:     getnumdflt(dp->d_sparespercyl, "rc", 0);
 127:     getnumdflt(dp->d_acylinders, "ac", 0);
 128:     getnumdflt(dp->d_rpm, "rm", 3600);
 129:     getnumdflt(dp->d_interleave, "il", 1);
 130:     getnumdflt(dp->d_trackskew, "sk", 0);
 131:     getnumdflt(dp->d_cylskew, "cs", 0);
 132:     getnumdflt(dp->d_headswitch, "hs", 0);
 133:     getnumdflt(dp->d_trkseek, "ts", 0);
 134: 
 135: /*
 136:  * See the comments in src/bin/disklabel.c for a more detailed explaination
 137:  * which the 'bbsize' is set to 512.  The simple explanation is that the
 138:  * designers of disklabeling confused 'sectors' and 'filesystem blocks'.
 139:  * BBSIZE is set to 1024 even though the real boot area (what the boot roms
 140:  * will read) is 512.
 141: */
 142: #ifdef  boot_area_really_is_1k
 143:     getnumdflt(dp->d_bbsize, "bs", BBSIZE);
 144: #endif
 145:     dp->d_bbsize = 512;
 146: 
 147:     getnumdflt(dp->d_sbsize, "sb", SBSIZE);
 148:     strcpy(psize, "px");
 149:     strcpy(pbsize, "bx");
 150:     strcpy(pfsize, "fx");
 151:     strcpy(poffset, "ox");
 152:     strcpy(ptype, "tx");
 153:     max = 'a' - 1;
 154:     pp = &dp->d_partitions[0];
 155:     for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) {
 156:         psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p;
 157:         pp->p_size = dgetnum(psize);
 158:         if (pp->p_size == -1L)
 159:             pp->p_size = 0L;
 160:         else {
 161:             pp->p_offset = dgetnum(poffset);
 162:             getnumdflt(pp->p_fsize, pfsize, 0);
 163:             if (pp->p_fsize)
 164:                 pp->p_frag = dgetnum(pbsize) / pp->p_fsize;
 165:             getnumdflt(pp->p_fstype, ptype, 0);
 166:             if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp)))
 167:                 pp->p_fstype = gettype(cq, fstypenames);
 168:             max = p;
 169:         }
 170:     }
 171:     dp->d_npartitions = max + 1 - 'a';
 172:     (void)strcpy(psize, "dx");
 173:     dx = dp->d_drivedata;
 174:     for (p = '0'; p < '0' + NDDATA; p++, dx++) {
 175:         psize[1] = p;
 176:         getnumdflt(*dx, psize, 0);
 177:     }
 178:     dp->d_magic = DISKMAGIC;
 179:     dp->d_magic2 = DISKMAGIC;
 180:     return (dp);
 181: }
 182: 
 183: #include <ctype.h>
 184: 
 185: static  char *tbuf;
 186: static  char *dskip();
 187: static  char *ddecode();
 188: 
 189: /*
 190:  * Get an entry for disk name in buffer bp,
 191:  * from the diskcap file.  Parse is very rudimentary;
 192:  * we just notice escaped newlines.
 193:  */
 194: static
 195: dgetent(bp, name)
 196:     char *bp, *name;
 197: {
 198:     register char *cp;
 199:     register int c;
 200:     register int i = 0, cnt = 0;
 201:     char ibuf[512];     /* BUFSIZE - reduced to conserve stack space */
 202:     int tf;
 203: 
 204:     tbuf = bp;
 205:     tf = open(_PATH_DISKTAB, 0);
 206:     if (tf < 0) {
 207:         error(errno);
 208:         return (-1);
 209:     }
 210:     for (;;) {
 211:         cp = bp;
 212:         for (;;) {
 213:             if (i == cnt) {
 214:                 cnt = read(tf, ibuf, sizeof (ibuf));
 215:                 if (cnt <= 0) {
 216:                     error(errno);
 217:                     close(tf);
 218:                     return (0);
 219:                 }
 220:                 i = 0;
 221:             }
 222:             c = ibuf[i++];
 223:             if (c == '\n') {
 224:                 if (cp > bp && cp[-1] == '\\'){
 225:                     cp--;
 226:                     continue;
 227:                 }
 228:                 break;
 229:             }
 230:             if (cp >= bp+BUFSIZ) {
 231:                 error(EFTYPE);
 232:                 break;
 233:             } else
 234:                 *cp++ = c;
 235:         }
 236:         *cp = 0;
 237: 
 238:         /*
 239: 		 * The real work for the match.
 240: 		 */
 241:         if (dnamatch(name)) {
 242:             close(tf);
 243:             return (1);
 244:         }
 245:     }
 246: }
 247: 
 248: /*
 249:  * Dnamatch deals with name matching.  The first field of the disktab
 250:  * entry is a sequence of names separated by |'s, so we compare
 251:  * against each such name.  The normal : terminator after the last
 252:  * name (before the first field) stops us.
 253:  */
 254: static
 255: dnamatch(np)
 256:     char *np;
 257: {
 258:     register char *Np, *Bp;
 259: 
 260:     Bp = tbuf;
 261:     if (*Bp == '#')
 262:         return (0);
 263:     for (;;) {
 264:         for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
 265:             continue;
 266:         if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
 267:             return (1);
 268:         while (*Bp && *Bp != ':' && *Bp != '|')
 269:             Bp++;
 270:         if (*Bp == 0 || *Bp == ':')
 271:             return (0);
 272:         Bp++;
 273:     }
 274: }
 275: 
 276: /*
 277:  * Skip to the next field.  Notice that this is very dumb, not
 278:  * knowing about \: escapes or any such.  If necessary, :'s can be put
 279:  * into the diskcap file in octal.
 280:  */
 281: static char *
 282: dskip(bp)
 283:     register char *bp;
 284: {
 285: 
 286:     while (*bp && *bp != ':')
 287:         bp++;
 288:     while (*bp == ':')
 289:         bp++;
 290:     return (bp);
 291: }
 292: 
 293: /*
 294:  * Return the (numeric) option id.
 295:  * Numeric options look like
 296:  *	li#80
 297:  * i.e. the option string is separated from the numeric value by
 298:  * a # character.  If the option is not found we return -1.
 299:  * Note that we handle octal numbers beginning with 0.
 300:  */
 301: static long
 302: dgetnum(id)
 303:     char *id;
 304: {
 305:     register int base;
 306:     long i;
 307:     register char *bp = tbuf;
 308: 
 309:     for (;;) {
 310:         bp = dskip(bp);
 311:         if (*bp == 0)
 312:             return (-1);
 313:         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
 314:             continue;
 315:         if (*bp == '@')
 316:             return (-1);
 317:         if (*bp != '#')
 318:             continue;
 319:         bp++;
 320:         base = 10;
 321:         if (*bp == '0')
 322:             base = 8;
 323:         i = 0;
 324:         while (isdigit(*bp))
 325:             i *= base, i += *bp++ - '0';
 326:         return (i);
 327:     }
 328: }
 329: 
 330: /*
 331:  * Handle a flag option.
 332:  * Flag options are given "naked", i.e. followed by a : or the end
 333:  * of the buffer.  Return 1 if we find the option, or 0 if it is
 334:  * not given.
 335:  */
 336: static
 337: dgetflag(id)
 338:     char *id;
 339: {
 340:     register char *bp = tbuf;
 341: 
 342:     for (;;) {
 343:         bp = dskip(bp);
 344:         if (!*bp)
 345:             return (0);
 346:         if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
 347:             if (!*bp || *bp == ':')
 348:                 return (1);
 349:             else if (*bp == '@')
 350:                 return (0);
 351:         }
 352:     }
 353: }
 354: 
 355: /*
 356:  * Get a string valued option.
 357:  * These are given as
 358:  *	cl=^Z
 359:  * Much decoding is done on the strings, and the strings are
 360:  * placed in area, which is a ref parameter which is updated.
 361:  * No checking on area overflow.
 362:  */
 363: static char *
 364: dgetstr(id, area)
 365:     char *id, **area;
 366: {
 367:     register char *bp = tbuf;
 368: 
 369:     for (;;) {
 370:         bp = dskip(bp);
 371:         if (!*bp)
 372:             return (0);
 373:         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
 374:             continue;
 375:         if (*bp == '@')
 376:             return (0);
 377:         if (*bp != '=')
 378:             continue;
 379:         bp++;
 380:         return (ddecode(bp, area));
 381:     }
 382: }
 383: 
 384: /*
 385:  * Tdecode does the grung work to decode the
 386:  * string capability escapes.
 387:  */
 388: static char *
 389: ddecode(str, area)
 390:     register char *str;
 391:     char **area;
 392: {
 393:     register char *cp;
 394:     register int c;
 395:     register char *dp;
 396:     int i;
 397: 
 398:     cp = *area;
 399:     while ((c = *str++) && c != ':') {
 400:         switch (c) {
 401: 
 402:         case '^':
 403:             c = *str++ & 037;
 404:             break;
 405: 
 406:         case '\\':
 407:             dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
 408:             c = *str++;
 409: nextc:
 410:             if (*dp++ == c) {
 411:                 c = *dp++;
 412:                 break;
 413:             }
 414:             dp++;
 415:             if (*dp)
 416:                 goto nextc;
 417:             if (isdigit(c)) {
 418:                 c -= '0', i = 2;
 419:                 do
 420:                     c <<= 3, c |= *str++ - '0';
 421:                 while (--i && isdigit(*str));
 422:             }
 423:             break;
 424:         }
 425:         *cp++ = c;
 426:     }
 427:     *cp++ = 0;
 428:     str = *area;
 429:     *area = cp;
 430:     return (str);
 431: }
 432: 
 433: static
 434: gettype(t, names)
 435:     char *t;
 436:     char **names;
 437: {
 438:     register char **nm;
 439: 
 440:     for (nm = names; *nm; nm++)
 441:         if (strcasecmp(t, *nm) == 0)
 442:             return (nm - names);
 443:     if (isdigit(*t))
 444:         return (atoi(t));
 445:     return (0);
 446: }
 447: 
 448: static
 449: error(err)
 450:     int err;
 451: {
 452:     struct iovec iov[4];
 453: 
 454:     iov[0].iov_base = "disktab: ";
 455:     iov[0].iov_len = 9;
 456:     iov[1].iov_base = _PATH_DISKTAB;
 457:     iov[1].iov_len = sizeof (_PATH_DISKTAB) -  1;
 458:     iov[2].iov_base = strerror(err);
 459:     iov[2].iov_len = strlen(iov[2].iov_base);
 460:     iov[3].iov_base = "\n";
 461:     iov[3].iov_len = 1;
 462:     (void)writev(fileno(stderr), &iov, 4);
 463: }
 464: 
 465: static long
 466: _gtnumdflt(dname, dflt)
 467:     char *dname;
 468:     long dflt;
 469:     {
 470:     long f;
 471: 
 472:     f = dgetnum(dname);
 473:     if  (f == -1L)
 474:         f = dflt;
 475:     return(f);
 476:     }

Defined functions

_gtnumdflt defined in line 465; used 2 times
ddecode defined in line 388; used 2 times
dgetent defined in line 194; used 2 times
dgetflag defined in line 336; used 2 times
dgetnum defined in line 301; used 8 times
dgetstr defined in line 363; used 5 times
dnamatch defined in line 254; used 2 times
dskip defined in line 281; used 4 times
error defined in line 448; used 4 times
gettype defined in line 433; used 3 times

Defined variables

sccsid defined in line 35; never used
tbuf defined in line 185; used 5 times

Defined macros

DKTYPENAMES defined in line 44; never used
getnumdflt defined in line 59; used 18 times
Last modified: 1995-04-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3270
Valid CSS Valid XHTML 1.0 Strict