1*10748Ssam /* @(#)disklabel.c 4.1 (Berkeley) 02/06/83 */ 2*10748Ssam 3*10748Ssam #include <disktab.h> 4*10748Ssam #include <stdio.h> 5*10748Ssam 6*10748Ssam static char *dgetstr(); 7*10748Ssam 8*10748Ssam struct disktab * 9*10748Ssam getdiskbyname(name) 10*10748Ssam char *name; 11*10748Ssam { 12*10748Ssam static struct disktab disk; 13*10748Ssam static char localbuf[100], *cp = localbuf; 14*10748Ssam register struct disktab *dp = &disk; 15*10748Ssam char p, part[3], buf[BUFSIZ]; 16*10748Ssam 17*10748Ssam if (dgetent(buf, name) <= 0) 18*10748Ssam return ((struct disktab *)0); 19*10748Ssam dp->d_name = cp; 20*10748Ssam strcpy(cp, name); 21*10748Ssam cp += strlen(name) + 1; 22*10748Ssam dp->d_type = dgetstr("ty", &cp); 23*10748Ssam dp->d_secsize = dgetnum("se"); 24*10748Ssam if (dp->d_secsize < 0) 25*10748Ssam dp->d_secsize = 512; 26*10748Ssam dp->d_ntracks = dgetnum("nt"); 27*10748Ssam dp->d_nsectors = dgetnum("ns"); 28*10748Ssam dp->d_ncylinders = dgetnum("nc"); 29*10748Ssam dp->d_rpm = dgetnum("rm"); 30*10748Ssam if (dp->d_rpm < 0) 31*10748Ssam dp->d_rpm = 3600; 32*10748Ssam strcpy(part, "px"); 33*10748Ssam for (p = 'a'; p < 'i'; p++) { 34*10748Ssam part[1] = p; 35*10748Ssam dp->d_partitions[p - 'a'] = dgetnum(part); 36*10748Ssam } 37*10748Ssam return (dp); 38*10748Ssam } 39*10748Ssam 40*10748Ssam #include <ctype.h> 41*10748Ssam 42*10748Ssam static char *tbuf; 43*10748Ssam static char *dskip(); 44*10748Ssam static char *ddecode(); 45*10748Ssam 46*10748Ssam /* 47*10748Ssam * Get an entry for disk name in buffer bp, 48*10748Ssam * from the diskcap file. Parse is very rudimentary; 49*10748Ssam * we just notice escaped newlines. 50*10748Ssam */ 51*10748Ssam static 52*10748Ssam dgetent(bp, name) 53*10748Ssam char *bp, *name; 54*10748Ssam { 55*10748Ssam register char *cp; 56*10748Ssam register int c; 57*10748Ssam register int i = 0, cnt = 0; 58*10748Ssam char ibuf[BUFSIZ]; 59*10748Ssam int tf; 60*10748Ssam 61*10748Ssam tbuf = bp; 62*10748Ssam tf = open(DISKTAB, 0); 63*10748Ssam if (tf < 0) 64*10748Ssam return (-1); 65*10748Ssam for (;;) { 66*10748Ssam cp = bp; 67*10748Ssam for (;;) { 68*10748Ssam if (i == cnt) { 69*10748Ssam cnt = read(tf, ibuf, BUFSIZ); 70*10748Ssam if (cnt <= 0) { 71*10748Ssam close(tf); 72*10748Ssam return (0); 73*10748Ssam } 74*10748Ssam i = 0; 75*10748Ssam } 76*10748Ssam c = ibuf[i++]; 77*10748Ssam if (c == '\n') { 78*10748Ssam if (cp > bp && cp[-1] == '\\'){ 79*10748Ssam cp--; 80*10748Ssam continue; 81*10748Ssam } 82*10748Ssam break; 83*10748Ssam } 84*10748Ssam if (cp >= bp+BUFSIZ) { 85*10748Ssam write(2,"Disktab entry too long\n", 23); 86*10748Ssam break; 87*10748Ssam } else 88*10748Ssam *cp++ = c; 89*10748Ssam } 90*10748Ssam *cp = 0; 91*10748Ssam 92*10748Ssam /* 93*10748Ssam * The real work for the match. 94*10748Ssam */ 95*10748Ssam if (dnamatch(name)) { 96*10748Ssam close(tf); 97*10748Ssam return (1); 98*10748Ssam } 99*10748Ssam } 100*10748Ssam } 101*10748Ssam 102*10748Ssam /* 103*10748Ssam * Dnamatch deals with name matching. The first field of the disktab 104*10748Ssam * entry is a sequence of names separated by |'s, so we compare 105*10748Ssam * against each such name. The normal : terminator after the last 106*10748Ssam * name (before the first field) stops us. 107*10748Ssam */ 108*10748Ssam static 109*10748Ssam dnamatch(np) 110*10748Ssam char *np; 111*10748Ssam { 112*10748Ssam register char *Np, *Bp; 113*10748Ssam 114*10748Ssam Bp = tbuf; 115*10748Ssam if (*Bp == '#') 116*10748Ssam return (0); 117*10748Ssam for (;;) { 118*10748Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 119*10748Ssam continue; 120*10748Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 121*10748Ssam return (1); 122*10748Ssam while (*Bp && *Bp != ':' && *Bp != '|') 123*10748Ssam Bp++; 124*10748Ssam if (*Bp == 0 || *Bp == ':') 125*10748Ssam return (0); 126*10748Ssam Bp++; 127*10748Ssam } 128*10748Ssam } 129*10748Ssam 130*10748Ssam /* 131*10748Ssam * Skip to the next field. Notice that this is very dumb, not 132*10748Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 133*10748Ssam * into the diskcap file in octal. 134*10748Ssam */ 135*10748Ssam static char * 136*10748Ssam dskip(bp) 137*10748Ssam register char *bp; 138*10748Ssam { 139*10748Ssam 140*10748Ssam while (*bp && *bp != ':') 141*10748Ssam bp++; 142*10748Ssam if (*bp == ':') 143*10748Ssam bp++; 144*10748Ssam return (bp); 145*10748Ssam } 146*10748Ssam 147*10748Ssam /* 148*10748Ssam * Return the (numeric) option id. 149*10748Ssam * Numeric options look like 150*10748Ssam * li#80 151*10748Ssam * i.e. the option string is separated from the numeric value by 152*10748Ssam * a # character. If the option is not found we return -1. 153*10748Ssam * Note that we handle octal numbers beginning with 0. 154*10748Ssam */ 155*10748Ssam static 156*10748Ssam dgetnum(id) 157*10748Ssam char *id; 158*10748Ssam { 159*10748Ssam register int i, base; 160*10748Ssam register char *bp = tbuf; 161*10748Ssam 162*10748Ssam for (;;) { 163*10748Ssam bp = dskip(bp); 164*10748Ssam if (*bp == 0) 165*10748Ssam return (-1); 166*10748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 167*10748Ssam continue; 168*10748Ssam if (*bp == '@') 169*10748Ssam return (-1); 170*10748Ssam if (*bp != '#') 171*10748Ssam continue; 172*10748Ssam bp++; 173*10748Ssam base = 10; 174*10748Ssam if (*bp == '0') 175*10748Ssam base = 8; 176*10748Ssam i = 0; 177*10748Ssam while (isdigit(*bp)) 178*10748Ssam i *= base, i += *bp++ - '0'; 179*10748Ssam return (i); 180*10748Ssam } 181*10748Ssam } 182*10748Ssam 183*10748Ssam /* 184*10748Ssam * Handle a flag option. 185*10748Ssam * Flag options are given "naked", i.e. followed by a : or the end 186*10748Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 187*10748Ssam * not given. 188*10748Ssam */ 189*10748Ssam static 190*10748Ssam dgetflag(id) 191*10748Ssam char *id; 192*10748Ssam { 193*10748Ssam register char *bp = tbuf; 194*10748Ssam 195*10748Ssam for (;;) { 196*10748Ssam bp = dskip(bp); 197*10748Ssam if (!*bp) 198*10748Ssam return (0); 199*10748Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 200*10748Ssam if (!*bp || *bp == ':') 201*10748Ssam return (1); 202*10748Ssam else if (*bp == '@') 203*10748Ssam return (0); 204*10748Ssam } 205*10748Ssam } 206*10748Ssam } 207*10748Ssam 208*10748Ssam /* 209*10748Ssam * Get a string valued option. 210*10748Ssam * These are given as 211*10748Ssam * cl=^Z 212*10748Ssam * Much decoding is done on the strings, and the strings are 213*10748Ssam * placed in area, which is a ref parameter which is updated. 214*10748Ssam * No checking on area overflow. 215*10748Ssam */ 216*10748Ssam static char * 217*10748Ssam dgetstr(id, area) 218*10748Ssam char *id, **area; 219*10748Ssam { 220*10748Ssam register char *bp = tbuf; 221*10748Ssam 222*10748Ssam for (;;) { 223*10748Ssam bp = dskip(bp); 224*10748Ssam if (!*bp) 225*10748Ssam return (0); 226*10748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 227*10748Ssam continue; 228*10748Ssam if (*bp == '@') 229*10748Ssam return (0); 230*10748Ssam if (*bp != '=') 231*10748Ssam continue; 232*10748Ssam bp++; 233*10748Ssam return (ddecode(bp, area)); 234*10748Ssam } 235*10748Ssam } 236*10748Ssam 237*10748Ssam /* 238*10748Ssam * Tdecode does the grung work to decode the 239*10748Ssam * string capability escapes. 240*10748Ssam */ 241*10748Ssam static char * 242*10748Ssam ddecode(str, area) 243*10748Ssam register char *str; 244*10748Ssam char **area; 245*10748Ssam { 246*10748Ssam register char *cp; 247*10748Ssam register int c; 248*10748Ssam register char *dp; 249*10748Ssam int i; 250*10748Ssam 251*10748Ssam cp = *area; 252*10748Ssam while ((c = *str++) && c != ':') { 253*10748Ssam switch (c) { 254*10748Ssam 255*10748Ssam case '^': 256*10748Ssam c = *str++ & 037; 257*10748Ssam break; 258*10748Ssam 259*10748Ssam case '\\': 260*10748Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 261*10748Ssam c = *str++; 262*10748Ssam nextc: 263*10748Ssam if (*dp++ == c) { 264*10748Ssam c = *dp++; 265*10748Ssam break; 266*10748Ssam } 267*10748Ssam dp++; 268*10748Ssam if (*dp) 269*10748Ssam goto nextc; 270*10748Ssam if (isdigit(c)) { 271*10748Ssam c -= '0', i = 2; 272*10748Ssam do 273*10748Ssam c <<= 3, c |= *str++ - '0'; 274*10748Ssam while (--i && isdigit(*str)); 275*10748Ssam } 276*10748Ssam break; 277*10748Ssam } 278*10748Ssam *cp++ = c; 279*10748Ssam } 280*10748Ssam *cp++ = 0; 281*10748Ssam str = *area; 282*10748Ssam *area = cp; 283*10748Ssam return (str); 284*10748Ssam } 285