121417Sdist /* 2*30420Skarels * Copyright (c) 1983,1987 Regents of the University of California. 321417Sdist * All rights reserved. The Berkeley software License Agreement 421417Sdist * specifies the terms and conditions for redistribution. 521417Sdist */ 610748Ssam 726675Sdonn #if defined(LIBC_SCCS) && !defined(lint) 8*30420Skarels static char sccsid[] = "@(#)disklabel.c 5.5 (Berkeley) 01/19/87"; 926675Sdonn #endif LIBC_SCCS and not lint 1021417Sdist 11*30420Skarels #include <sys/param.h> 12*30420Skarels #include <sys/fs.h> 13*30420Skarels #include <sys/file.h> 14*30420Skarels #define DKTYPENAMES 15*30420Skarels #include <sys/disklabel.h> 1610748Ssam #include <stdio.h> 1710748Ssam 1810748Ssam static char *dgetstr(); 1910748Ssam 20*30420Skarels struct disklabel * 2110748Ssam getdiskbyname(name) 2210748Ssam char *name; 2310748Ssam { 24*30420Skarels static struct disklabel disk; 25*30420Skarels static char localbuf[100]; 26*30420Skarels char *cp, *cq; 27*30420Skarels register struct disklabel *dp = &disk; 2810760Ssam register struct partition *pp; 29*30420Skarels char p, max, psize[3], pbsize[3], pfsize[3], poffset[3], ptype[3]; 3010760Ssam char buf[BUFSIZ]; 31*30420Skarels int i; 32*30420Skarels u_long *dx; 3310748Ssam 3410748Ssam if (dgetent(buf, name) <= 0) 35*30420Skarels return ((struct disklabel *)0); 36*30420Skarels bzero((char *)&disk, sizeof(disk)); 37*30420Skarels cq = dp->d_typename; 38*30420Skarels cp = buf; 39*30420Skarels while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 && 40*30420Skarels (*cq = *cp) && *cq != '|' && *cq != ':') 41*30420Skarels cq++, cp++; 42*30420Skarels *cq = '\0'; 43*30420Skarels cp = localbuf; 44*30420Skarels cq = dgetstr("ty", &cp); 45*30420Skarels if (cq && strcmp(cq, "removable") == 0) 46*30420Skarels dp->d_flags |= D_REMOVABLE; 47*30420Skarels else if (cq && strcmp(cq, "simulated") == 0) 48*30420Skarels dp->d_flags |= D_RAMDISK; 49*30420Skarels if (dgetflag("sf")) 50*30420Skarels dp->d_flags |= D_BADSECT; 51*30420Skarels #define getnumdflt(field, dname, dflt) \ 52*30420Skarels { int f = dgetnum(dname); \ 53*30420Skarels (field) = f == -1 ? (dflt) : f; } 54*30420Skarels 55*30420Skarels getnumdflt(dp->d_secsize, "se", DEV_BSIZE); 5610748Ssam dp->d_ntracks = dgetnum("nt"); 5710748Ssam dp->d_nsectors = dgetnum("ns"); 5810748Ssam dp->d_ncylinders = dgetnum("nc"); 59*30420Skarels cq = dgetstr("dt", &cp); 60*30420Skarels if (cq) 61*30420Skarels dp->d_type = gettype(cq, dktypenames); 62*30420Skarels else 63*30420Skarels getnumdflt(dp->d_type, "dt", 0); 64*30420Skarels getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks); 65*30420Skarels getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders); 66*30420Skarels getnumdflt(dp->d_rpm, "rm", 3600); 67*30420Skarels getnumdflt(dp->d_interleave, "il", 1); 68*30420Skarels getnumdflt(dp->d_trackskew, "sk", 0); 69*30420Skarels getnumdflt(dp->d_cylskew, "cs", 0); 70*30420Skarels getnumdflt(dp->d_headswitch, "hs", 0); 71*30420Skarels getnumdflt(dp->d_trkseek, "ts", 0); 72*30420Skarels getnumdflt(dp->d_bbsize, "bs", BBSIZE); 73*30420Skarels getnumdflt(dp->d_sbsize, "sb", SBSIZE); 7410760Ssam strcpy(psize, "px"); 7510760Ssam strcpy(pbsize, "bx"); 7610760Ssam strcpy(pfsize, "fx"); 77*30420Skarels strcpy(poffset, "ox"); 78*30420Skarels strcpy(ptype, "tx"); 79*30420Skarels max = 'a' - 1; 80*30420Skarels pp = &dp->d_partitions[0]; 81*30420Skarels for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) { 82*30420Skarels psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p; 8310760Ssam pp->p_size = dgetnum(psize); 84*30420Skarels if (pp->p_size == -1) 85*30420Skarels pp->p_size = 0; 86*30420Skarels else { 87*30420Skarels pp->p_offset = dgetnum(poffset); 88*30420Skarels getnumdflt(pp->p_fsize, pfsize, 0); 89*30420Skarels if (pp->p_fsize) 90*30420Skarels pp->p_frag = dgetnum(pbsize) / pp->p_fsize; 91*30420Skarels getnumdflt(pp->p_fstype, ptype, 0); 92*30420Skarels if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp))) 93*30420Skarels pp->p_fstype = gettype(cq, fstypenames); 94*30420Skarels max = p; 95*30420Skarels } 9610748Ssam } 97*30420Skarels dp->d_npartitions = max + 1 - 'a'; 98*30420Skarels strcpy(psize, "dx"); 99*30420Skarels dx = dp->d_drivedata; 100*30420Skarels for (p = '0'; p < '0' + NDDATA; p++, dx++) { 101*30420Skarels psize[1] = p; 102*30420Skarels getnumdflt(*dx, psize, 0); 103*30420Skarels } 104*30420Skarels dp->d_magic = DISKMAGIC; 105*30420Skarels dp->d_magic2 = DISKMAGIC; 10610748Ssam return (dp); 10710748Ssam } 10810748Ssam 10910748Ssam #include <ctype.h> 11010748Ssam 11110748Ssam static char *tbuf; 11210748Ssam static char *dskip(); 11310748Ssam static char *ddecode(); 11410748Ssam 11510748Ssam /* 11610748Ssam * Get an entry for disk name in buffer bp, 11710748Ssam * from the diskcap file. Parse is very rudimentary; 11810748Ssam * we just notice escaped newlines. 11910748Ssam */ 12010748Ssam static 12110748Ssam dgetent(bp, name) 12210748Ssam char *bp, *name; 12310748Ssam { 12410748Ssam register char *cp; 12510748Ssam register int c; 12610748Ssam register int i = 0, cnt = 0; 12710748Ssam char ibuf[BUFSIZ]; 12810748Ssam int tf; 12910748Ssam 13010748Ssam tbuf = bp; 13110748Ssam tf = open(DISKTAB, 0); 13210748Ssam if (tf < 0) 13310748Ssam return (-1); 13410748Ssam for (;;) { 13510748Ssam cp = bp; 13610748Ssam for (;;) { 13710748Ssam if (i == cnt) { 13810748Ssam cnt = read(tf, ibuf, BUFSIZ); 13910748Ssam if (cnt <= 0) { 14010748Ssam close(tf); 14110748Ssam return (0); 14210748Ssam } 14310748Ssam i = 0; 14410748Ssam } 14510748Ssam c = ibuf[i++]; 14610748Ssam if (c == '\n') { 14710748Ssam if (cp > bp && cp[-1] == '\\'){ 14810748Ssam cp--; 14910748Ssam continue; 15010748Ssam } 15110748Ssam break; 15210748Ssam } 15310748Ssam if (cp >= bp+BUFSIZ) { 15410748Ssam write(2,"Disktab entry too long\n", 23); 15510748Ssam break; 15610748Ssam } else 15710748Ssam *cp++ = c; 15810748Ssam } 15910748Ssam *cp = 0; 16010748Ssam 16110748Ssam /* 16210748Ssam * The real work for the match. 16310748Ssam */ 16410748Ssam if (dnamatch(name)) { 16510748Ssam close(tf); 16610748Ssam return (1); 16710748Ssam } 16810748Ssam } 16910748Ssam } 17010748Ssam 17110748Ssam /* 17210748Ssam * Dnamatch deals with name matching. The first field of the disktab 17310748Ssam * entry is a sequence of names separated by |'s, so we compare 17410748Ssam * against each such name. The normal : terminator after the last 17510748Ssam * name (before the first field) stops us. 17610748Ssam */ 17710748Ssam static 17810748Ssam dnamatch(np) 17910748Ssam char *np; 18010748Ssam { 18110748Ssam register char *Np, *Bp; 18210748Ssam 18310748Ssam Bp = tbuf; 18410748Ssam if (*Bp == '#') 18510748Ssam return (0); 18610748Ssam for (;;) { 18710748Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 18810748Ssam continue; 18910748Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 19010748Ssam return (1); 19110748Ssam while (*Bp && *Bp != ':' && *Bp != '|') 19210748Ssam Bp++; 19310748Ssam if (*Bp == 0 || *Bp == ':') 19410748Ssam return (0); 19510748Ssam Bp++; 19610748Ssam } 19710748Ssam } 19810748Ssam 19910748Ssam /* 20010748Ssam * Skip to the next field. Notice that this is very dumb, not 20110748Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 20210748Ssam * into the diskcap file in octal. 20310748Ssam */ 20410748Ssam static char * 20510748Ssam dskip(bp) 20610748Ssam register char *bp; 20710748Ssam { 20810748Ssam 20910748Ssam while (*bp && *bp != ':') 21010748Ssam bp++; 21110748Ssam if (*bp == ':') 21210748Ssam bp++; 21310748Ssam return (bp); 21410748Ssam } 21510748Ssam 21610748Ssam /* 21710748Ssam * Return the (numeric) option id. 21810748Ssam * Numeric options look like 21910748Ssam * li#80 22010748Ssam * i.e. the option string is separated from the numeric value by 22110748Ssam * a # character. If the option is not found we return -1. 22210748Ssam * Note that we handle octal numbers beginning with 0. 22310748Ssam */ 22410748Ssam static 22510748Ssam dgetnum(id) 22610748Ssam char *id; 22710748Ssam { 22810748Ssam register int i, base; 22910748Ssam register char *bp = tbuf; 23010748Ssam 23110748Ssam for (;;) { 23210748Ssam bp = dskip(bp); 23310748Ssam if (*bp == 0) 23410748Ssam return (-1); 23510748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 23610748Ssam continue; 23710748Ssam if (*bp == '@') 23810748Ssam return (-1); 23910748Ssam if (*bp != '#') 24010748Ssam continue; 24110748Ssam bp++; 24210748Ssam base = 10; 24310748Ssam if (*bp == '0') 24410748Ssam base = 8; 24510748Ssam i = 0; 24610748Ssam while (isdigit(*bp)) 24710748Ssam i *= base, i += *bp++ - '0'; 24810748Ssam return (i); 24910748Ssam } 25010748Ssam } 25110748Ssam 25210748Ssam /* 25310748Ssam * Handle a flag option. 25410748Ssam * Flag options are given "naked", i.e. followed by a : or the end 25510748Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 25610748Ssam * not given. 25710748Ssam */ 25810748Ssam static 25910748Ssam dgetflag(id) 26010748Ssam char *id; 26110748Ssam { 26210748Ssam register char *bp = tbuf; 26310748Ssam 26410748Ssam for (;;) { 26510748Ssam bp = dskip(bp); 26610748Ssam if (!*bp) 26710748Ssam return (0); 26810748Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 26910748Ssam if (!*bp || *bp == ':') 27010748Ssam return (1); 27110748Ssam else if (*bp == '@') 27210748Ssam return (0); 27310748Ssam } 27410748Ssam } 27510748Ssam } 27610748Ssam 27710748Ssam /* 27810748Ssam * Get a string valued option. 27910748Ssam * These are given as 28010748Ssam * cl=^Z 28110748Ssam * Much decoding is done on the strings, and the strings are 28210748Ssam * placed in area, which is a ref parameter which is updated. 28310748Ssam * No checking on area overflow. 28410748Ssam */ 28510748Ssam static char * 28610748Ssam dgetstr(id, area) 28710748Ssam char *id, **area; 28810748Ssam { 28910748Ssam register char *bp = tbuf; 29010748Ssam 29110748Ssam for (;;) { 29210748Ssam bp = dskip(bp); 29310748Ssam if (!*bp) 29410748Ssam return (0); 29510748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 29610748Ssam continue; 29710748Ssam if (*bp == '@') 29810748Ssam return (0); 29910748Ssam if (*bp != '=') 30010748Ssam continue; 30110748Ssam bp++; 30210748Ssam return (ddecode(bp, area)); 30310748Ssam } 30410748Ssam } 30510748Ssam 30610748Ssam /* 30710748Ssam * Tdecode does the grung work to decode the 30810748Ssam * string capability escapes. 30910748Ssam */ 31010748Ssam static char * 31110748Ssam ddecode(str, area) 31210748Ssam register char *str; 31310748Ssam char **area; 31410748Ssam { 31510748Ssam register char *cp; 31610748Ssam register int c; 31710748Ssam register char *dp; 31810748Ssam int i; 31910748Ssam 32010748Ssam cp = *area; 32110748Ssam while ((c = *str++) && c != ':') { 32210748Ssam switch (c) { 32310748Ssam 32410748Ssam case '^': 32510748Ssam c = *str++ & 037; 32610748Ssam break; 32710748Ssam 32810748Ssam case '\\': 32910748Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 33010748Ssam c = *str++; 33110748Ssam nextc: 33210748Ssam if (*dp++ == c) { 33310748Ssam c = *dp++; 33410748Ssam break; 33510748Ssam } 33610748Ssam dp++; 33710748Ssam if (*dp) 33810748Ssam goto nextc; 33910748Ssam if (isdigit(c)) { 34010748Ssam c -= '0', i = 2; 34110748Ssam do 34210748Ssam c <<= 3, c |= *str++ - '0'; 34310748Ssam while (--i && isdigit(*str)); 34410748Ssam } 34510748Ssam break; 34610748Ssam } 34710748Ssam *cp++ = c; 34810748Ssam } 34910748Ssam *cp++ = 0; 35010748Ssam str = *area; 35110748Ssam *area = cp; 35210748Ssam return (str); 35310748Ssam } 354*30420Skarels 355*30420Skarels static 356*30420Skarels gettype(t, names) 357*30420Skarels char *t; 358*30420Skarels char **names; 359*30420Skarels { 360*30420Skarels register char **nm; 361*30420Skarels 362*30420Skarels for (nm = names; *nm; nm++) 363*30420Skarels if (ustrcmp(t, *nm) == 0) 364*30420Skarels return (nm - names); 365*30420Skarels if (isdigit(*t)) 366*30420Skarels return (atoi(t)); 367*30420Skarels return (0); 368*30420Skarels } 369*30420Skarels 370*30420Skarels static 371*30420Skarels ustrcmp(s1, s2) 372*30420Skarels register char *s1, *s2; 373*30420Skarels { 374*30420Skarels #define lower(c) (islower(c) ? (c) : tolower(c)) 375*30420Skarels 376*30420Skarels for (; *s1; s1++, s2++) { 377*30420Skarels if (*s1 == *s2) 378*30420Skarels continue; 379*30420Skarels if (isalpha(*s1) && isalpha(*s2) && 380*30420Skarels lower(*s1) == lower(*s2)) 381*30420Skarels continue; 382*30420Skarels return (*s2 - *s1); 383*30420Skarels } 384*30420Skarels return (0); 385*30420Skarels } 386*30420Skarels 387*30420Skarels /* 388*30420Skarels * Swab disk label if needed. 389*30420Skarels */ 390*30420Skarels #if ENDIAN != BIG 391*30420Skarels /* ARGSUSED */ 392*30420Skarels #endif 393*30420Skarels swablabel(lp) 394*30420Skarels register struct disklabel *lp; 395*30420Skarels { 396*30420Skarels #if ENDIAN != BIG 397*30420Skarels register u_long *p; 398*30420Skarels register struct partition *pp; 399*30420Skarels int npart; 400*30420Skarels 401*30420Skarels lp->d_magic = ntohl(lp->d_magic); 402*30420Skarels lp->d_type = ntohs(lp->d_type); 403*30420Skarels lp->d_subtype = ntohs(lp->d_subtype); 404*30420Skarels for (p = &lp->d_swabfirst; p <= &lp->d_swablast; p++) 405*30420Skarels *p = ntohl(*p); 406*30420Skarels npart = lp->d_npartitions; 407*30420Skarels for (pp = lp->d_partitions; pp < &lp->d_partitions[npart]; pp++) { 408*30420Skarels pp->p_size = ntohl(pp->p_size); 409*30420Skarels pp->p_offset = ntohl(pp->p_offset); 410*30420Skarels pp->p_fsize = ntohl(pp->p_fsize); 411*30420Skarels pp->p_cpg = ntohs(pp->p_cpg); 412*30420Skarels } 413*30420Skarels #endif 414*30420Skarels } 415*30420Skarels 416*30420Skarels dkcksum(lp) 417*30420Skarels register struct disklabel *lp; 418*30420Skarels { 419*30420Skarels register u_short *start, *end; 420*30420Skarels register u_short sum = 0; 421*30420Skarels 422*30420Skarels start = (u_short *)lp; 423*30420Skarels end = (u_short *)&lp->d_partitions[lp->d_npartitions]; 424*30420Skarels while (start < end) 425*30420Skarels sum ^= *start++; 426*30420Skarels return (sum); 427*30420Skarels } 428