1*ef743ec4Ssam /* @(#)disklabel.c 4.2 (Berkeley) 02/08/83 */ 29876a848Ssam 39876a848Ssam #include <disktab.h> 49876a848Ssam #include <stdio.h> 59876a848Ssam 69876a848Ssam static char *dgetstr(); 79876a848Ssam 89876a848Ssam struct disktab * 99876a848Ssam getdiskbyname(name) 109876a848Ssam char *name; 119876a848Ssam { 129876a848Ssam static struct disktab disk; 139876a848Ssam static char localbuf[100], *cp = localbuf; 149876a848Ssam register struct disktab *dp = &disk; 15*ef743ec4Ssam register struct partition *pp; 16*ef743ec4Ssam char p, psize[3], pbsize[3], pfsize[3]; 17*ef743ec4Ssam char buf[BUFSIZ]; 189876a848Ssam 199876a848Ssam if (dgetent(buf, name) <= 0) 209876a848Ssam return ((struct disktab *)0); 219876a848Ssam dp->d_name = cp; 229876a848Ssam strcpy(cp, name); 239876a848Ssam cp += strlen(name) + 1; 249876a848Ssam dp->d_type = dgetstr("ty", &cp); 259876a848Ssam dp->d_secsize = dgetnum("se"); 269876a848Ssam if (dp->d_secsize < 0) 279876a848Ssam dp->d_secsize = 512; 289876a848Ssam dp->d_ntracks = dgetnum("nt"); 299876a848Ssam dp->d_nsectors = dgetnum("ns"); 309876a848Ssam dp->d_ncylinders = dgetnum("nc"); 319876a848Ssam dp->d_rpm = dgetnum("rm"); 329876a848Ssam if (dp->d_rpm < 0) 339876a848Ssam dp->d_rpm = 3600; 34*ef743ec4Ssam strcpy(psize, "px"); 35*ef743ec4Ssam strcpy(pbsize, "bx"); 36*ef743ec4Ssam strcpy(pfsize, "fx"); 379876a848Ssam for (p = 'a'; p < 'i'; p++) { 38*ef743ec4Ssam psize[1] = pbsize[1] = pfsize[1] = p; 39*ef743ec4Ssam pp = &dp->d_partitions[p - 'a']; 40*ef743ec4Ssam pp->p_size = dgetnum(psize); 41*ef743ec4Ssam pp->p_bsize = dgetnum(pbsize); 42*ef743ec4Ssam pp->p_fsize = dgetnum(pfsize); 439876a848Ssam } 449876a848Ssam return (dp); 459876a848Ssam } 469876a848Ssam 479876a848Ssam #include <ctype.h> 489876a848Ssam 499876a848Ssam static char *tbuf; 509876a848Ssam static char *dskip(); 519876a848Ssam static char *ddecode(); 529876a848Ssam 539876a848Ssam /* 549876a848Ssam * Get an entry for disk name in buffer bp, 559876a848Ssam * from the diskcap file. Parse is very rudimentary; 569876a848Ssam * we just notice escaped newlines. 579876a848Ssam */ 589876a848Ssam static 599876a848Ssam dgetent(bp, name) 609876a848Ssam char *bp, *name; 619876a848Ssam { 629876a848Ssam register char *cp; 639876a848Ssam register int c; 649876a848Ssam register int i = 0, cnt = 0; 659876a848Ssam char ibuf[BUFSIZ]; 669876a848Ssam int tf; 679876a848Ssam 689876a848Ssam tbuf = bp; 699876a848Ssam tf = open(DISKTAB, 0); 709876a848Ssam if (tf < 0) 719876a848Ssam return (-1); 729876a848Ssam for (;;) { 739876a848Ssam cp = bp; 749876a848Ssam for (;;) { 759876a848Ssam if (i == cnt) { 769876a848Ssam cnt = read(tf, ibuf, BUFSIZ); 779876a848Ssam if (cnt <= 0) { 789876a848Ssam close(tf); 799876a848Ssam return (0); 809876a848Ssam } 819876a848Ssam i = 0; 829876a848Ssam } 839876a848Ssam c = ibuf[i++]; 849876a848Ssam if (c == '\n') { 859876a848Ssam if (cp > bp && cp[-1] == '\\'){ 869876a848Ssam cp--; 879876a848Ssam continue; 889876a848Ssam } 899876a848Ssam break; 909876a848Ssam } 919876a848Ssam if (cp >= bp+BUFSIZ) { 929876a848Ssam write(2,"Disktab entry too long\n", 23); 939876a848Ssam break; 949876a848Ssam } else 959876a848Ssam *cp++ = c; 969876a848Ssam } 979876a848Ssam *cp = 0; 989876a848Ssam 999876a848Ssam /* 1009876a848Ssam * The real work for the match. 1019876a848Ssam */ 1029876a848Ssam if (dnamatch(name)) { 1039876a848Ssam close(tf); 1049876a848Ssam return (1); 1059876a848Ssam } 1069876a848Ssam } 1079876a848Ssam } 1089876a848Ssam 1099876a848Ssam /* 1109876a848Ssam * Dnamatch deals with name matching. The first field of the disktab 1119876a848Ssam * entry is a sequence of names separated by |'s, so we compare 1129876a848Ssam * against each such name. The normal : terminator after the last 1139876a848Ssam * name (before the first field) stops us. 1149876a848Ssam */ 1159876a848Ssam static 1169876a848Ssam dnamatch(np) 1179876a848Ssam char *np; 1189876a848Ssam { 1199876a848Ssam register char *Np, *Bp; 1209876a848Ssam 1219876a848Ssam Bp = tbuf; 1229876a848Ssam if (*Bp == '#') 1239876a848Ssam return (0); 1249876a848Ssam for (;;) { 1259876a848Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 1269876a848Ssam continue; 1279876a848Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 1289876a848Ssam return (1); 1299876a848Ssam while (*Bp && *Bp != ':' && *Bp != '|') 1309876a848Ssam Bp++; 1319876a848Ssam if (*Bp == 0 || *Bp == ':') 1329876a848Ssam return (0); 1339876a848Ssam Bp++; 1349876a848Ssam } 1359876a848Ssam } 1369876a848Ssam 1379876a848Ssam /* 1389876a848Ssam * Skip to the next field. Notice that this is very dumb, not 1399876a848Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 1409876a848Ssam * into the diskcap file in octal. 1419876a848Ssam */ 1429876a848Ssam static char * 1439876a848Ssam dskip(bp) 1449876a848Ssam register char *bp; 1459876a848Ssam { 1469876a848Ssam 1479876a848Ssam while (*bp && *bp != ':') 1489876a848Ssam bp++; 1499876a848Ssam if (*bp == ':') 1509876a848Ssam bp++; 1519876a848Ssam return (bp); 1529876a848Ssam } 1539876a848Ssam 1549876a848Ssam /* 1559876a848Ssam * Return the (numeric) option id. 1569876a848Ssam * Numeric options look like 1579876a848Ssam * li#80 1589876a848Ssam * i.e. the option string is separated from the numeric value by 1599876a848Ssam * a # character. If the option is not found we return -1. 1609876a848Ssam * Note that we handle octal numbers beginning with 0. 1619876a848Ssam */ 1629876a848Ssam static 1639876a848Ssam dgetnum(id) 1649876a848Ssam char *id; 1659876a848Ssam { 1669876a848Ssam register int i, base; 1679876a848Ssam register char *bp = tbuf; 1689876a848Ssam 1699876a848Ssam for (;;) { 1709876a848Ssam bp = dskip(bp); 1719876a848Ssam if (*bp == 0) 1729876a848Ssam return (-1); 1739876a848Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 1749876a848Ssam continue; 1759876a848Ssam if (*bp == '@') 1769876a848Ssam return (-1); 1779876a848Ssam if (*bp != '#') 1789876a848Ssam continue; 1799876a848Ssam bp++; 1809876a848Ssam base = 10; 1819876a848Ssam if (*bp == '0') 1829876a848Ssam base = 8; 1839876a848Ssam i = 0; 1849876a848Ssam while (isdigit(*bp)) 1859876a848Ssam i *= base, i += *bp++ - '0'; 1869876a848Ssam return (i); 1879876a848Ssam } 1889876a848Ssam } 1899876a848Ssam 1909876a848Ssam /* 1919876a848Ssam * Handle a flag option. 1929876a848Ssam * Flag options are given "naked", i.e. followed by a : or the end 1939876a848Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 1949876a848Ssam * not given. 1959876a848Ssam */ 1969876a848Ssam static 1979876a848Ssam dgetflag(id) 1989876a848Ssam char *id; 1999876a848Ssam { 2009876a848Ssam register char *bp = tbuf; 2019876a848Ssam 2029876a848Ssam for (;;) { 2039876a848Ssam bp = dskip(bp); 2049876a848Ssam if (!*bp) 2059876a848Ssam return (0); 2069876a848Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 2079876a848Ssam if (!*bp || *bp == ':') 2089876a848Ssam return (1); 2099876a848Ssam else if (*bp == '@') 2109876a848Ssam return (0); 2119876a848Ssam } 2129876a848Ssam } 2139876a848Ssam } 2149876a848Ssam 2159876a848Ssam /* 2169876a848Ssam * Get a string valued option. 2179876a848Ssam * These are given as 2189876a848Ssam * cl=^Z 2199876a848Ssam * Much decoding is done on the strings, and the strings are 2209876a848Ssam * placed in area, which is a ref parameter which is updated. 2219876a848Ssam * No checking on area overflow. 2229876a848Ssam */ 2239876a848Ssam static char * 2249876a848Ssam dgetstr(id, area) 2259876a848Ssam char *id, **area; 2269876a848Ssam { 2279876a848Ssam register char *bp = tbuf; 2289876a848Ssam 2299876a848Ssam for (;;) { 2309876a848Ssam bp = dskip(bp); 2319876a848Ssam if (!*bp) 2329876a848Ssam return (0); 2339876a848Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 2349876a848Ssam continue; 2359876a848Ssam if (*bp == '@') 2369876a848Ssam return (0); 2379876a848Ssam if (*bp != '=') 2389876a848Ssam continue; 2399876a848Ssam bp++; 2409876a848Ssam return (ddecode(bp, area)); 2419876a848Ssam } 2429876a848Ssam } 2439876a848Ssam 2449876a848Ssam /* 2459876a848Ssam * Tdecode does the grung work to decode the 2469876a848Ssam * string capability escapes. 2479876a848Ssam */ 2489876a848Ssam static char * 2499876a848Ssam ddecode(str, area) 2509876a848Ssam register char *str; 2519876a848Ssam char **area; 2529876a848Ssam { 2539876a848Ssam register char *cp; 2549876a848Ssam register int c; 2559876a848Ssam register char *dp; 2569876a848Ssam int i; 2579876a848Ssam 2589876a848Ssam cp = *area; 2599876a848Ssam while ((c = *str++) && c != ':') { 2609876a848Ssam switch (c) { 2619876a848Ssam 2629876a848Ssam case '^': 2639876a848Ssam c = *str++ & 037; 2649876a848Ssam break; 2659876a848Ssam 2669876a848Ssam case '\\': 2679876a848Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 2689876a848Ssam c = *str++; 2699876a848Ssam nextc: 2709876a848Ssam if (*dp++ == c) { 2719876a848Ssam c = *dp++; 2729876a848Ssam break; 2739876a848Ssam } 2749876a848Ssam dp++; 2759876a848Ssam if (*dp) 2769876a848Ssam goto nextc; 2779876a848Ssam if (isdigit(c)) { 2789876a848Ssam c -= '0', i = 2; 2799876a848Ssam do 2809876a848Ssam c <<= 3, c |= *str++ - '0'; 2819876a848Ssam while (--i && isdigit(*str)); 2829876a848Ssam } 2839876a848Ssam break; 2849876a848Ssam } 2859876a848Ssam *cp++ = c; 2869876a848Ssam } 2879876a848Ssam *cp++ = 0; 2889876a848Ssam str = *area; 2899876a848Ssam *area = cp; 2909876a848Ssam return (str); 2919876a848Ssam } 292