|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983,1987 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #if defined(LIBC_SCCS) && !defined(lint) ! 8: static char sccsid[] = "@(#)disklabel.c 5.9 (Berkeley) 1/27/88"; ! 9: #endif LIBC_SCCS and not lint ! 10: ! 11: #include <sys/param.h> ! 12: #include <sys/fs.h> ! 13: #include <sys/file.h> ! 14: #define DKTYPENAMES ! 15: #include <sys/disklabel.h> ! 16: #include <stdio.h> ! 17: #include <strings.h> ! 18: ! 19: static char *dgetstr(); ! 20: ! 21: struct disklabel * ! 22: getdiskbyname(name) ! 23: char *name; ! 24: { ! 25: static struct disklabel disk; ! 26: static char boot[BUFSIZ]; ! 27: char localbuf[BUFSIZ]; ! 28: char buf[BUFSIZ]; ! 29: char *cp, *cq; /* can't be register */ ! 30: register struct disklabel *dp = &disk; ! 31: register struct partition *pp; ! 32: char p, max, psize[3], pbsize[3], ! 33: pfsize[3], poffset[3], ptype[3]; ! 34: u_long *dx; ! 35: ! 36: if (dgetent(buf, name) <= 0) ! 37: return ((struct disklabel *)0); ! 38: bzero((char *)&disk, sizeof(disk)); ! 39: /* ! 40: * typename ! 41: */ ! 42: cq = dp->d_typename; ! 43: cp = buf; ! 44: while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 && ! 45: (*cq = *cp) && *cq != '|' && *cq != ':') ! 46: cq++, cp++; ! 47: *cq = '\0'; ! 48: /* ! 49: * boot name (optional) xxboot, bootxx ! 50: */ ! 51: cp = boot; ! 52: dp->d_boot0 = dgetstr("b0", &cp); ! 53: dp->d_boot1 = dgetstr("b1", &cp); ! 54: cp = localbuf; ! 55: cq = dgetstr("ty", &cp); ! 56: if (cq && strcmp(cq, "removable") == 0) ! 57: dp->d_flags |= D_REMOVABLE; ! 58: else if (cq && strcmp(cq, "simulated") == 0) ! 59: dp->d_flags |= D_RAMDISK; ! 60: if (dgetflag("sf")) ! 61: dp->d_flags |= D_BADSECT; ! 62: ! 63: #define getnumdflt(field, dname, dflt) \ ! 64: { int f = dgetnum(dname); \ ! 65: (field) = f == -1 ? (dflt) : f; } ! 66: ! 67: getnumdflt(dp->d_secsize, "se", DEV_BSIZE); ! 68: dp->d_ntracks = dgetnum("nt"); ! 69: dp->d_nsectors = dgetnum("ns"); ! 70: dp->d_ncylinders = dgetnum("nc"); ! 71: cq = dgetstr("dt", &cp); ! 72: if (cq) ! 73: dp->d_type = gettype(cq, dktypenames); ! 74: else ! 75: getnumdflt(dp->d_type, "dt", 0); ! 76: getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks); ! 77: getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders); ! 78: getnumdflt(dp->d_rpm, "rm", 3600); ! 79: getnumdflt(dp->d_interleave, "il", 1); ! 80: getnumdflt(dp->d_trackskew, "sk", 0); ! 81: getnumdflt(dp->d_cylskew, "cs", 0); ! 82: getnumdflt(dp->d_headswitch, "hs", 0); ! 83: getnumdflt(dp->d_trkseek, "ts", 0); ! 84: getnumdflt(dp->d_bbsize, "bs", BBSIZE); ! 85: getnumdflt(dp->d_sbsize, "sb", SBSIZE); ! 86: strcpy(psize, "px"); ! 87: strcpy(pbsize, "bx"); ! 88: strcpy(pfsize, "fx"); ! 89: strcpy(poffset, "ox"); ! 90: strcpy(ptype, "tx"); ! 91: max = 'a' - 1; ! 92: pp = &dp->d_partitions[0]; ! 93: for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) { ! 94: psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p; ! 95: pp->p_size = dgetnum(psize); ! 96: if (pp->p_size == -1) ! 97: pp->p_size = 0; ! 98: else { ! 99: pp->p_offset = dgetnum(poffset); ! 100: getnumdflt(pp->p_fsize, pfsize, 0); ! 101: if (pp->p_fsize) ! 102: pp->p_frag = dgetnum(pbsize) / pp->p_fsize; ! 103: getnumdflt(pp->p_fstype, ptype, 0); ! 104: if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp))) ! 105: pp->p_fstype = gettype(cq, fstypenames); ! 106: max = p; ! 107: } ! 108: } ! 109: dp->d_npartitions = max + 1 - 'a'; ! 110: (void)strcpy(psize, "dx"); ! 111: dx = dp->d_drivedata; ! 112: for (p = '0'; p < '0' + NDDATA; p++, dx++) { ! 113: psize[1] = p; ! 114: getnumdflt(*dx, psize, 0); ! 115: } ! 116: dp->d_magic = DISKMAGIC; ! 117: dp->d_magic2 = DISKMAGIC; ! 118: return (dp); ! 119: } ! 120: ! 121: #include <ctype.h> ! 122: ! 123: static char *tbuf; ! 124: static char *dskip(); ! 125: static char *ddecode(); ! 126: ! 127: /* ! 128: * Get an entry for disk name in buffer bp, ! 129: * from the diskcap file. Parse is very rudimentary; ! 130: * we just notice escaped newlines. ! 131: */ ! 132: static ! 133: dgetent(bp, name) ! 134: char *bp, *name; ! 135: { ! 136: register char *cp; ! 137: register int c; ! 138: register int i = 0, cnt = 0; ! 139: char ibuf[BUFSIZ]; ! 140: int tf; ! 141: ! 142: tbuf = bp; ! 143: tf = open(DISKTAB, 0); ! 144: if (tf < 0) ! 145: return (-1); ! 146: for (;;) { ! 147: cp = bp; ! 148: for (;;) { ! 149: if (i == cnt) { ! 150: cnt = read(tf, ibuf, BUFSIZ); ! 151: if (cnt <= 0) { ! 152: close(tf); ! 153: return (0); ! 154: } ! 155: i = 0; ! 156: } ! 157: c = ibuf[i++]; ! 158: if (c == '\n') { ! 159: if (cp > bp && cp[-1] == '\\'){ ! 160: cp--; ! 161: continue; ! 162: } ! 163: break; ! 164: } ! 165: if (cp >= bp+BUFSIZ) { ! 166: write(2,"Disktab entry too long\n", 23); ! 167: break; ! 168: } else ! 169: *cp++ = c; ! 170: } ! 171: *cp = 0; ! 172: ! 173: /* ! 174: * The real work for the match. ! 175: */ ! 176: if (dnamatch(name)) { ! 177: close(tf); ! 178: return (1); ! 179: } ! 180: } ! 181: } ! 182: ! 183: /* ! 184: * Dnamatch deals with name matching. The first field of the disktab ! 185: * entry is a sequence of names separated by |'s, so we compare ! 186: * against each such name. The normal : terminator after the last ! 187: * name (before the first field) stops us. ! 188: */ ! 189: static ! 190: dnamatch(np) ! 191: char *np; ! 192: { ! 193: register char *Np, *Bp; ! 194: ! 195: Bp = tbuf; ! 196: if (*Bp == '#') ! 197: return (0); ! 198: for (;;) { ! 199: for (Np = np; *Np && *Bp == *Np; Bp++, Np++) ! 200: continue; ! 201: if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) ! 202: return (1); ! 203: while (*Bp && *Bp != ':' && *Bp != '|') ! 204: Bp++; ! 205: if (*Bp == 0 || *Bp == ':') ! 206: return (0); ! 207: Bp++; ! 208: } ! 209: } ! 210: ! 211: /* ! 212: * Skip to the next field. Notice that this is very dumb, not ! 213: * knowing about \: escapes or any such. If necessary, :'s can be put ! 214: * into the diskcap file in octal. ! 215: */ ! 216: static char * ! 217: dskip(bp) ! 218: register char *bp; ! 219: { ! 220: ! 221: while (*bp && *bp != ':') ! 222: bp++; ! 223: if (*bp == ':') ! 224: bp++; ! 225: return (bp); ! 226: } ! 227: ! 228: /* ! 229: * Return the (numeric) option id. ! 230: * Numeric options look like ! 231: * li#80 ! 232: * i.e. the option string is separated from the numeric value by ! 233: * a # character. If the option is not found we return -1. ! 234: * Note that we handle octal numbers beginning with 0. ! 235: */ ! 236: static ! 237: dgetnum(id) ! 238: char *id; ! 239: { ! 240: register int i, base; ! 241: register char *bp = tbuf; ! 242: ! 243: for (;;) { ! 244: bp = dskip(bp); ! 245: if (*bp == 0) ! 246: return (-1); ! 247: if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) ! 248: continue; ! 249: if (*bp == '@') ! 250: return (-1); ! 251: if (*bp != '#') ! 252: continue; ! 253: bp++; ! 254: base = 10; ! 255: if (*bp == '0') ! 256: base = 8; ! 257: i = 0; ! 258: while (isdigit(*bp)) ! 259: i *= base, i += *bp++ - '0'; ! 260: return (i); ! 261: } ! 262: } ! 263: ! 264: /* ! 265: * Handle a flag option. ! 266: * Flag options are given "naked", i.e. followed by a : or the end ! 267: * of the buffer. Return 1 if we find the option, or 0 if it is ! 268: * not given. ! 269: */ ! 270: static ! 271: dgetflag(id) ! 272: char *id; ! 273: { ! 274: register char *bp = tbuf; ! 275: ! 276: for (;;) { ! 277: bp = dskip(bp); ! 278: if (!*bp) ! 279: return (0); ! 280: if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { ! 281: if (!*bp || *bp == ':') ! 282: return (1); ! 283: else if (*bp == '@') ! 284: return (0); ! 285: } ! 286: } ! 287: } ! 288: ! 289: /* ! 290: * Get a string valued option. ! 291: * These are given as ! 292: * cl=^Z ! 293: * Much decoding is done on the strings, and the strings are ! 294: * placed in area, which is a ref parameter which is updated. ! 295: * No checking on area overflow. ! 296: */ ! 297: static char * ! 298: dgetstr(id, area) ! 299: char *id, **area; ! 300: { ! 301: register char *bp = tbuf; ! 302: ! 303: for (;;) { ! 304: bp = dskip(bp); ! 305: if (!*bp) ! 306: return (0); ! 307: if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) ! 308: continue; ! 309: if (*bp == '@') ! 310: return (0); ! 311: if (*bp != '=') ! 312: continue; ! 313: bp++; ! 314: return (ddecode(bp, area)); ! 315: } ! 316: } ! 317: ! 318: /* ! 319: * Tdecode does the grung work to decode the ! 320: * string capability escapes. ! 321: */ ! 322: static char * ! 323: ddecode(str, area) ! 324: register char *str; ! 325: char **area; ! 326: { ! 327: register char *cp; ! 328: register int c; ! 329: register char *dp; ! 330: int i; ! 331: ! 332: cp = *area; ! 333: while ((c = *str++) && c != ':') { ! 334: switch (c) { ! 335: ! 336: case '^': ! 337: c = *str++ & 037; ! 338: break; ! 339: ! 340: case '\\': ! 341: dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; ! 342: c = *str++; ! 343: nextc: ! 344: if (*dp++ == c) { ! 345: c = *dp++; ! 346: break; ! 347: } ! 348: dp++; ! 349: if (*dp) ! 350: goto nextc; ! 351: if (isdigit(c)) { ! 352: c -= '0', i = 2; ! 353: do ! 354: c <<= 3, c |= *str++ - '0'; ! 355: while (--i && isdigit(*str)); ! 356: } ! 357: break; ! 358: } ! 359: *cp++ = c; ! 360: } ! 361: *cp++ = 0; ! 362: str = *area; ! 363: *area = cp; ! 364: return (str); ! 365: } ! 366: ! 367: static ! 368: gettype(t, names) ! 369: char *t; ! 370: char **names; ! 371: { ! 372: register char **nm; ! 373: ! 374: for (nm = names; *nm; nm++) ! 375: if (strcasecmp(t, *nm) == 0) ! 376: return (nm - names); ! 377: if (isdigit(*t)) ! 378: return (atoi(t)); ! 379: return (0); ! 380: } ! 381: ! 382: dkcksum(lp) ! 383: register struct disklabel *lp; ! 384: { ! 385: register u_short *start, *end; ! 386: register u_short sum = 0; ! 387: ! 388: start = (u_short *)lp; ! 389: end = (u_short *)&lp->d_partitions[lp->d_npartitions]; ! 390: while (start < end) ! 391: sum ^= *start++; ! 392: return (sum); ! 393: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.