11e80345cSdist /* 272f9a726Skarels * Copyright (c) 1983, 1987 Regents of the University of California. 3da55c904Sbostic * All rights reserved. 4da55c904Sbostic * 5e40b1377Sbostic * %sccs.include.redist.c% 61e80345cSdist */ 71e80345cSdist 887176300Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*d5da809dSbostic static char sccsid[] = "@(#)disklabel.c 5.14 (Berkeley) 11/28/90"; 10da55c904Sbostic #endif /* LIBC_SCCS and not lint */ 119876a848Ssam 1272f9a726Skarels #include <sys/param.h> 13*d5da809dSbostic #include <sys/errno.h> 146c9fc4b7Sbostic #include <ufs/fs.h> 1572f9a726Skarels #include <sys/file.h> 1672f9a726Skarels #define DKTYPENAMES 1772f9a726Skarels #include <sys/disklabel.h> 189876a848Ssam #include <stdio.h> 1972a6a662Sbostic #include <string.h> 209876a848Ssam 219876a848Ssam static char *dgetstr(); 229876a848Ssam 2372f9a726Skarels struct disklabel * 249876a848Ssam getdiskbyname(name) 259876a848Ssam char *name; 269876a848Ssam { 2772f9a726Skarels static struct disklabel disk; 28af6dc062Smarc static char boot[BUFSIZ]; 29af6dc062Smarc char localbuf[BUFSIZ]; 30af6dc062Smarc char buf[BUFSIZ]; 31af6dc062Smarc char *cp, *cq; /* can't be register */ 3272f9a726Skarels register struct disklabel *dp = &disk; 33ef743ec4Ssam register struct partition *pp; 34af6dc062Smarc char p, max, psize[3], pbsize[3], 35af6dc062Smarc pfsize[3], poffset[3], ptype[3]; 3672f9a726Skarels u_long *dx; 379876a848Ssam 389876a848Ssam if (dgetent(buf, name) <= 0) 3972f9a726Skarels return ((struct disklabel *)0); 4072f9a726Skarels bzero((char *)&disk, sizeof(disk)); 41af6dc062Smarc /* 42af6dc062Smarc * typename 43af6dc062Smarc */ 4472f9a726Skarels cq = dp->d_typename; 4572f9a726Skarels cp = buf; 4672f9a726Skarels while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 && 4772f9a726Skarels (*cq = *cp) && *cq != '|' && *cq != ':') 4872f9a726Skarels cq++, cp++; 4972f9a726Skarels *cq = '\0'; 50af6dc062Smarc /* 51af6dc062Smarc * boot name (optional) xxboot, bootxx 52af6dc062Smarc */ 53af6dc062Smarc cp = boot; 54af6dc062Smarc dp->d_boot0 = dgetstr("b0", &cp); 55af6dc062Smarc dp->d_boot1 = dgetstr("b1", &cp); 5672f9a726Skarels cp = localbuf; 5772f9a726Skarels cq = dgetstr("ty", &cp); 5872f9a726Skarels if (cq && strcmp(cq, "removable") == 0) 5972f9a726Skarels dp->d_flags |= D_REMOVABLE; 6072f9a726Skarels else if (cq && strcmp(cq, "simulated") == 0) 6172f9a726Skarels dp->d_flags |= D_RAMDISK; 6272f9a726Skarels if (dgetflag("sf")) 6372f9a726Skarels dp->d_flags |= D_BADSECT; 64af6dc062Smarc 6572f9a726Skarels #define getnumdflt(field, dname, dflt) \ 6672f9a726Skarels { int f = dgetnum(dname); \ 6772f9a726Skarels (field) = f == -1 ? (dflt) : f; } 6872f9a726Skarels 6972f9a726Skarels getnumdflt(dp->d_secsize, "se", DEV_BSIZE); 709876a848Ssam dp->d_ntracks = dgetnum("nt"); 719876a848Ssam dp->d_nsectors = dgetnum("ns"); 729876a848Ssam dp->d_ncylinders = dgetnum("nc"); 7372f9a726Skarels cq = dgetstr("dt", &cp); 7472f9a726Skarels if (cq) 7572f9a726Skarels dp->d_type = gettype(cq, dktypenames); 7672f9a726Skarels else 7772f9a726Skarels getnumdflt(dp->d_type, "dt", 0); 7872f9a726Skarels getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks); 7972f9a726Skarels getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders); 8072f9a726Skarels getnumdflt(dp->d_rpm, "rm", 3600); 8172f9a726Skarels getnumdflt(dp->d_interleave, "il", 1); 8272f9a726Skarels getnumdflt(dp->d_trackskew, "sk", 0); 8372f9a726Skarels getnumdflt(dp->d_cylskew, "cs", 0); 8472f9a726Skarels getnumdflt(dp->d_headswitch, "hs", 0); 8572f9a726Skarels getnumdflt(dp->d_trkseek, "ts", 0); 8672f9a726Skarels getnumdflt(dp->d_bbsize, "bs", BBSIZE); 8772f9a726Skarels getnumdflt(dp->d_sbsize, "sb", SBSIZE); 88ef743ec4Ssam strcpy(psize, "px"); 89ef743ec4Ssam strcpy(pbsize, "bx"); 90ef743ec4Ssam strcpy(pfsize, "fx"); 9172f9a726Skarels strcpy(poffset, "ox"); 9272f9a726Skarels strcpy(ptype, "tx"); 9372f9a726Skarels max = 'a' - 1; 9472f9a726Skarels pp = &dp->d_partitions[0]; 9572f9a726Skarels for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) { 9672f9a726Skarels psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p; 97ef743ec4Ssam pp->p_size = dgetnum(psize); 9872f9a726Skarels if (pp->p_size == -1) 9972f9a726Skarels pp->p_size = 0; 10072f9a726Skarels else { 10172f9a726Skarels pp->p_offset = dgetnum(poffset); 10272f9a726Skarels getnumdflt(pp->p_fsize, pfsize, 0); 10372f9a726Skarels if (pp->p_fsize) 10472f9a726Skarels pp->p_frag = dgetnum(pbsize) / pp->p_fsize; 10572f9a726Skarels getnumdflt(pp->p_fstype, ptype, 0); 10672f9a726Skarels if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp))) 10772f9a726Skarels pp->p_fstype = gettype(cq, fstypenames); 10872f9a726Skarels max = p; 1099876a848Ssam } 11072f9a726Skarels } 11172f9a726Skarels dp->d_npartitions = max + 1 - 'a'; 1120a8a25dfSbostic (void)strcpy(psize, "dx"); 11372f9a726Skarels dx = dp->d_drivedata; 11472f9a726Skarels for (p = '0'; p < '0' + NDDATA; p++, dx++) { 11572f9a726Skarels psize[1] = p; 11672f9a726Skarels getnumdflt(*dx, psize, 0); 11772f9a726Skarels } 11872f9a726Skarels dp->d_magic = DISKMAGIC; 11972f9a726Skarels dp->d_magic2 = DISKMAGIC; 1209876a848Ssam return (dp); 1219876a848Ssam } 1229876a848Ssam 1239876a848Ssam #include <ctype.h> 1249876a848Ssam 1259876a848Ssam static char *tbuf; 1269876a848Ssam static char *dskip(); 1279876a848Ssam static char *ddecode(); 1289876a848Ssam 1299876a848Ssam /* 1309876a848Ssam * Get an entry for disk name in buffer bp, 1319876a848Ssam * from the diskcap file. Parse is very rudimentary; 1329876a848Ssam * we just notice escaped newlines. 1339876a848Ssam */ 1349876a848Ssam static 1359876a848Ssam dgetent(bp, name) 1369876a848Ssam char *bp, *name; 1379876a848Ssam { 1389876a848Ssam register char *cp; 1399876a848Ssam register int c; 1409876a848Ssam register int i = 0, cnt = 0; 1419876a848Ssam char ibuf[BUFSIZ]; 1429876a848Ssam int tf; 1439876a848Ssam 1449876a848Ssam tbuf = bp; 145*d5da809dSbostic tf = open(_PATH_DISKTAB, 0); 146*d5da809dSbostic if (tf < 0) { 147*d5da809dSbostic error(errno); 1489876a848Ssam return (-1); 149*d5da809dSbostic } 1509876a848Ssam for (;;) { 1519876a848Ssam cp = bp; 1529876a848Ssam for (;;) { 1539876a848Ssam if (i == cnt) { 1549876a848Ssam cnt = read(tf, ibuf, BUFSIZ); 1559876a848Ssam if (cnt <= 0) { 156*d5da809dSbostic error(errno); 1579876a848Ssam close(tf); 1589876a848Ssam return (0); 1599876a848Ssam } 1609876a848Ssam i = 0; 1619876a848Ssam } 1629876a848Ssam c = ibuf[i++]; 1639876a848Ssam if (c == '\n') { 1649876a848Ssam if (cp > bp && cp[-1] == '\\'){ 1659876a848Ssam cp--; 1669876a848Ssam continue; 1679876a848Ssam } 1689876a848Ssam break; 1699876a848Ssam } 1709876a848Ssam if (cp >= bp+BUFSIZ) { 171*d5da809dSbostic error(EBADFORMAT); 1729876a848Ssam break; 1739876a848Ssam } else 1749876a848Ssam *cp++ = c; 1759876a848Ssam } 1769876a848Ssam *cp = 0; 1779876a848Ssam 1789876a848Ssam /* 1799876a848Ssam * The real work for the match. 1809876a848Ssam */ 1819876a848Ssam if (dnamatch(name)) { 1829876a848Ssam close(tf); 1839876a848Ssam return (1); 1849876a848Ssam } 1859876a848Ssam } 1869876a848Ssam } 1879876a848Ssam 1889876a848Ssam /* 1899876a848Ssam * Dnamatch deals with name matching. The first field of the disktab 1909876a848Ssam * entry is a sequence of names separated by |'s, so we compare 1919876a848Ssam * against each such name. The normal : terminator after the last 1929876a848Ssam * name (before the first field) stops us. 1939876a848Ssam */ 1949876a848Ssam static 1959876a848Ssam dnamatch(np) 1969876a848Ssam char *np; 1979876a848Ssam { 1989876a848Ssam register char *Np, *Bp; 1999876a848Ssam 2009876a848Ssam Bp = tbuf; 2019876a848Ssam if (*Bp == '#') 2029876a848Ssam return (0); 2039876a848Ssam for (;;) { 2049876a848Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 2059876a848Ssam continue; 2069876a848Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 2079876a848Ssam return (1); 2089876a848Ssam while (*Bp && *Bp != ':' && *Bp != '|') 2099876a848Ssam Bp++; 2109876a848Ssam if (*Bp == 0 || *Bp == ':') 2119876a848Ssam return (0); 2129876a848Ssam Bp++; 2139876a848Ssam } 2149876a848Ssam } 2159876a848Ssam 2169876a848Ssam /* 2179876a848Ssam * Skip to the next field. Notice that this is very dumb, not 2189876a848Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 2199876a848Ssam * into the diskcap file in octal. 2209876a848Ssam */ 2219876a848Ssam static char * 2229876a848Ssam dskip(bp) 2239876a848Ssam register char *bp; 2249876a848Ssam { 2259876a848Ssam 2269876a848Ssam while (*bp && *bp != ':') 2279876a848Ssam bp++; 2289876a848Ssam if (*bp == ':') 2299876a848Ssam bp++; 2309876a848Ssam return (bp); 2319876a848Ssam } 2329876a848Ssam 2339876a848Ssam /* 2349876a848Ssam * Return the (numeric) option id. 2359876a848Ssam * Numeric options look like 2369876a848Ssam * li#80 2379876a848Ssam * i.e. the option string is separated from the numeric value by 2389876a848Ssam * a # character. If the option is not found we return -1. 2399876a848Ssam * Note that we handle octal numbers beginning with 0. 2409876a848Ssam */ 2419876a848Ssam static 2429876a848Ssam dgetnum(id) 2439876a848Ssam char *id; 2449876a848Ssam { 2459876a848Ssam register int i, base; 2469876a848Ssam register char *bp = tbuf; 2479876a848Ssam 2489876a848Ssam for (;;) { 2499876a848Ssam bp = dskip(bp); 2509876a848Ssam if (*bp == 0) 2519876a848Ssam return (-1); 2529876a848Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 2539876a848Ssam continue; 2549876a848Ssam if (*bp == '@') 2559876a848Ssam return (-1); 2569876a848Ssam if (*bp != '#') 2579876a848Ssam continue; 2589876a848Ssam bp++; 2599876a848Ssam base = 10; 2609876a848Ssam if (*bp == '0') 2619876a848Ssam base = 8; 2629876a848Ssam i = 0; 2639876a848Ssam while (isdigit(*bp)) 2649876a848Ssam i *= base, i += *bp++ - '0'; 2659876a848Ssam return (i); 2669876a848Ssam } 2679876a848Ssam } 2689876a848Ssam 2699876a848Ssam /* 2709876a848Ssam * Handle a flag option. 2719876a848Ssam * Flag options are given "naked", i.e. followed by a : or the end 2729876a848Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 2739876a848Ssam * not given. 2749876a848Ssam */ 2759876a848Ssam static 2769876a848Ssam dgetflag(id) 2779876a848Ssam char *id; 2789876a848Ssam { 2799876a848Ssam register char *bp = tbuf; 2809876a848Ssam 2819876a848Ssam for (;;) { 2829876a848Ssam bp = dskip(bp); 2839876a848Ssam if (!*bp) 2849876a848Ssam return (0); 2859876a848Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 2869876a848Ssam if (!*bp || *bp == ':') 2879876a848Ssam return (1); 2889876a848Ssam else if (*bp == '@') 2899876a848Ssam return (0); 2909876a848Ssam } 2919876a848Ssam } 2929876a848Ssam } 2939876a848Ssam 2949876a848Ssam /* 2959876a848Ssam * Get a string valued option. 2969876a848Ssam * These are given as 2979876a848Ssam * cl=^Z 2989876a848Ssam * Much decoding is done on the strings, and the strings are 2999876a848Ssam * placed in area, which is a ref parameter which is updated. 3009876a848Ssam * No checking on area overflow. 3019876a848Ssam */ 3029876a848Ssam static char * 3039876a848Ssam dgetstr(id, area) 3049876a848Ssam char *id, **area; 3059876a848Ssam { 3069876a848Ssam register char *bp = tbuf; 3079876a848Ssam 3089876a848Ssam for (;;) { 3099876a848Ssam bp = dskip(bp); 3109876a848Ssam if (!*bp) 3119876a848Ssam return (0); 3129876a848Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 3139876a848Ssam continue; 3149876a848Ssam if (*bp == '@') 3159876a848Ssam return (0); 3169876a848Ssam if (*bp != '=') 3179876a848Ssam continue; 3189876a848Ssam bp++; 3199876a848Ssam return (ddecode(bp, area)); 3209876a848Ssam } 3219876a848Ssam } 3229876a848Ssam 3239876a848Ssam /* 3249876a848Ssam * Tdecode does the grung work to decode the 3259876a848Ssam * string capability escapes. 3269876a848Ssam */ 3279876a848Ssam static char * 3289876a848Ssam ddecode(str, area) 3299876a848Ssam register char *str; 3309876a848Ssam char **area; 3319876a848Ssam { 3329876a848Ssam register char *cp; 3339876a848Ssam register int c; 3349876a848Ssam register char *dp; 3359876a848Ssam int i; 3369876a848Ssam 3379876a848Ssam cp = *area; 3389876a848Ssam while ((c = *str++) && c != ':') { 3399876a848Ssam switch (c) { 3409876a848Ssam 3419876a848Ssam case '^': 3429876a848Ssam c = *str++ & 037; 3439876a848Ssam break; 3449876a848Ssam 3459876a848Ssam case '\\': 3469876a848Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 3479876a848Ssam c = *str++; 3489876a848Ssam nextc: 3499876a848Ssam if (*dp++ == c) { 3509876a848Ssam c = *dp++; 3519876a848Ssam break; 3529876a848Ssam } 3539876a848Ssam dp++; 3549876a848Ssam if (*dp) 3559876a848Ssam goto nextc; 3569876a848Ssam if (isdigit(c)) { 3579876a848Ssam c -= '0', i = 2; 3589876a848Ssam do 3599876a848Ssam c <<= 3, c |= *str++ - '0'; 3609876a848Ssam while (--i && isdigit(*str)); 3619876a848Ssam } 3629876a848Ssam break; 3639876a848Ssam } 3649876a848Ssam *cp++ = c; 3659876a848Ssam } 3669876a848Ssam *cp++ = 0; 3679876a848Ssam str = *area; 3689876a848Ssam *area = cp; 3699876a848Ssam return (str); 3709876a848Ssam } 37172f9a726Skarels 37272f9a726Skarels static 37372f9a726Skarels gettype(t, names) 37472f9a726Skarels char *t; 37572f9a726Skarels char **names; 37672f9a726Skarels { 37772f9a726Skarels register char **nm; 37872f9a726Skarels 37972f9a726Skarels for (nm = names; *nm; nm++) 380c32170efSmckusick if (strcasecmp(t, *nm) == 0) 38172f9a726Skarels return (nm - names); 38272f9a726Skarels if (isdigit(*t)) 38372f9a726Skarels return (atoi(t)); 38472f9a726Skarels return (0); 38572f9a726Skarels } 38672f9a726Skarels 38772f9a726Skarels dkcksum(lp) 38872f9a726Skarels register struct disklabel *lp; 38972f9a726Skarels { 39072f9a726Skarels register u_short *start, *end; 39172f9a726Skarels register u_short sum = 0; 39272f9a726Skarels 39372f9a726Skarels start = (u_short *)lp; 39472f9a726Skarels end = (u_short *)&lp->d_partitions[lp->d_npartitions]; 39572f9a726Skarels while (start < end) 39672f9a726Skarels sum ^= *start++; 39772f9a726Skarels return (sum); 39872f9a726Skarels } 399*d5da809dSbostic 400*d5da809dSbostic static 401*d5da809dSbostic error(err) 402*d5da809dSbostic int err; 403*d5da809dSbostic { 404*d5da809dSbostic char *p; 405*d5da809dSbostic 406*d5da809dSbostic (void)write(STDERR_FILENO, "disktab: ", 9); 407*d5da809dSbostic (void)write(STDERR_FILENO, _PATH_DISKTAB, sizeof(_PATH_DISKTAB) - 1); 408*d5da809dSbostic p = strerror(err); 409*d5da809dSbostic (void)write(STDERR_FILENO, p, strlen(p)); 410*d5da809dSbostic (void)write(STDERR_FILENO, "\n", 1); 411*d5da809dSbostic } 412