1*10760Ssam /* @(#)disklabel.c 4.2 (Berkeley) 02/08/83 */ 210748Ssam 310748Ssam #include <disktab.h> 410748Ssam #include <stdio.h> 510748Ssam 610748Ssam static char *dgetstr(); 710748Ssam 810748Ssam struct disktab * 910748Ssam getdiskbyname(name) 1010748Ssam char *name; 1110748Ssam { 1210748Ssam static struct disktab disk; 1310748Ssam static char localbuf[100], *cp = localbuf; 1410748Ssam register struct disktab *dp = &disk; 15*10760Ssam register struct partition *pp; 16*10760Ssam char p, psize[3], pbsize[3], pfsize[3]; 17*10760Ssam char buf[BUFSIZ]; 1810748Ssam 1910748Ssam if (dgetent(buf, name) <= 0) 2010748Ssam return ((struct disktab *)0); 2110748Ssam dp->d_name = cp; 2210748Ssam strcpy(cp, name); 2310748Ssam cp += strlen(name) + 1; 2410748Ssam dp->d_type = dgetstr("ty", &cp); 2510748Ssam dp->d_secsize = dgetnum("se"); 2610748Ssam if (dp->d_secsize < 0) 2710748Ssam dp->d_secsize = 512; 2810748Ssam dp->d_ntracks = dgetnum("nt"); 2910748Ssam dp->d_nsectors = dgetnum("ns"); 3010748Ssam dp->d_ncylinders = dgetnum("nc"); 3110748Ssam dp->d_rpm = dgetnum("rm"); 3210748Ssam if (dp->d_rpm < 0) 3310748Ssam dp->d_rpm = 3600; 34*10760Ssam strcpy(psize, "px"); 35*10760Ssam strcpy(pbsize, "bx"); 36*10760Ssam strcpy(pfsize, "fx"); 3710748Ssam for (p = 'a'; p < 'i'; p++) { 38*10760Ssam psize[1] = pbsize[1] = pfsize[1] = p; 39*10760Ssam pp = &dp->d_partitions[p - 'a']; 40*10760Ssam pp->p_size = dgetnum(psize); 41*10760Ssam pp->p_bsize = dgetnum(pbsize); 42*10760Ssam pp->p_fsize = dgetnum(pfsize); 4310748Ssam } 4410748Ssam return (dp); 4510748Ssam } 4610748Ssam 4710748Ssam #include <ctype.h> 4810748Ssam 4910748Ssam static char *tbuf; 5010748Ssam static char *dskip(); 5110748Ssam static char *ddecode(); 5210748Ssam 5310748Ssam /* 5410748Ssam * Get an entry for disk name in buffer bp, 5510748Ssam * from the diskcap file. Parse is very rudimentary; 5610748Ssam * we just notice escaped newlines. 5710748Ssam */ 5810748Ssam static 5910748Ssam dgetent(bp, name) 6010748Ssam char *bp, *name; 6110748Ssam { 6210748Ssam register char *cp; 6310748Ssam register int c; 6410748Ssam register int i = 0, cnt = 0; 6510748Ssam char ibuf[BUFSIZ]; 6610748Ssam int tf; 6710748Ssam 6810748Ssam tbuf = bp; 6910748Ssam tf = open(DISKTAB, 0); 7010748Ssam if (tf < 0) 7110748Ssam return (-1); 7210748Ssam for (;;) { 7310748Ssam cp = bp; 7410748Ssam for (;;) { 7510748Ssam if (i == cnt) { 7610748Ssam cnt = read(tf, ibuf, BUFSIZ); 7710748Ssam if (cnt <= 0) { 7810748Ssam close(tf); 7910748Ssam return (0); 8010748Ssam } 8110748Ssam i = 0; 8210748Ssam } 8310748Ssam c = ibuf[i++]; 8410748Ssam if (c == '\n') { 8510748Ssam if (cp > bp && cp[-1] == '\\'){ 8610748Ssam cp--; 8710748Ssam continue; 8810748Ssam } 8910748Ssam break; 9010748Ssam } 9110748Ssam if (cp >= bp+BUFSIZ) { 9210748Ssam write(2,"Disktab entry too long\n", 23); 9310748Ssam break; 9410748Ssam } else 9510748Ssam *cp++ = c; 9610748Ssam } 9710748Ssam *cp = 0; 9810748Ssam 9910748Ssam /* 10010748Ssam * The real work for the match. 10110748Ssam */ 10210748Ssam if (dnamatch(name)) { 10310748Ssam close(tf); 10410748Ssam return (1); 10510748Ssam } 10610748Ssam } 10710748Ssam } 10810748Ssam 10910748Ssam /* 11010748Ssam * Dnamatch deals with name matching. The first field of the disktab 11110748Ssam * entry is a sequence of names separated by |'s, so we compare 11210748Ssam * against each such name. The normal : terminator after the last 11310748Ssam * name (before the first field) stops us. 11410748Ssam */ 11510748Ssam static 11610748Ssam dnamatch(np) 11710748Ssam char *np; 11810748Ssam { 11910748Ssam register char *Np, *Bp; 12010748Ssam 12110748Ssam Bp = tbuf; 12210748Ssam if (*Bp == '#') 12310748Ssam return (0); 12410748Ssam for (;;) { 12510748Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 12610748Ssam continue; 12710748Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 12810748Ssam return (1); 12910748Ssam while (*Bp && *Bp != ':' && *Bp != '|') 13010748Ssam Bp++; 13110748Ssam if (*Bp == 0 || *Bp == ':') 13210748Ssam return (0); 13310748Ssam Bp++; 13410748Ssam } 13510748Ssam } 13610748Ssam 13710748Ssam /* 13810748Ssam * Skip to the next field. Notice that this is very dumb, not 13910748Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 14010748Ssam * into the diskcap file in octal. 14110748Ssam */ 14210748Ssam static char * 14310748Ssam dskip(bp) 14410748Ssam register char *bp; 14510748Ssam { 14610748Ssam 14710748Ssam while (*bp && *bp != ':') 14810748Ssam bp++; 14910748Ssam if (*bp == ':') 15010748Ssam bp++; 15110748Ssam return (bp); 15210748Ssam } 15310748Ssam 15410748Ssam /* 15510748Ssam * Return the (numeric) option id. 15610748Ssam * Numeric options look like 15710748Ssam * li#80 15810748Ssam * i.e. the option string is separated from the numeric value by 15910748Ssam * a # character. If the option is not found we return -1. 16010748Ssam * Note that we handle octal numbers beginning with 0. 16110748Ssam */ 16210748Ssam static 16310748Ssam dgetnum(id) 16410748Ssam char *id; 16510748Ssam { 16610748Ssam register int i, base; 16710748Ssam register char *bp = tbuf; 16810748Ssam 16910748Ssam for (;;) { 17010748Ssam bp = dskip(bp); 17110748Ssam if (*bp == 0) 17210748Ssam return (-1); 17310748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 17410748Ssam continue; 17510748Ssam if (*bp == '@') 17610748Ssam return (-1); 17710748Ssam if (*bp != '#') 17810748Ssam continue; 17910748Ssam bp++; 18010748Ssam base = 10; 18110748Ssam if (*bp == '0') 18210748Ssam base = 8; 18310748Ssam i = 0; 18410748Ssam while (isdigit(*bp)) 18510748Ssam i *= base, i += *bp++ - '0'; 18610748Ssam return (i); 18710748Ssam } 18810748Ssam } 18910748Ssam 19010748Ssam /* 19110748Ssam * Handle a flag option. 19210748Ssam * Flag options are given "naked", i.e. followed by a : or the end 19310748Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 19410748Ssam * not given. 19510748Ssam */ 19610748Ssam static 19710748Ssam dgetflag(id) 19810748Ssam char *id; 19910748Ssam { 20010748Ssam register char *bp = tbuf; 20110748Ssam 20210748Ssam for (;;) { 20310748Ssam bp = dskip(bp); 20410748Ssam if (!*bp) 20510748Ssam return (0); 20610748Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 20710748Ssam if (!*bp || *bp == ':') 20810748Ssam return (1); 20910748Ssam else if (*bp == '@') 21010748Ssam return (0); 21110748Ssam } 21210748Ssam } 21310748Ssam } 21410748Ssam 21510748Ssam /* 21610748Ssam * Get a string valued option. 21710748Ssam * These are given as 21810748Ssam * cl=^Z 21910748Ssam * Much decoding is done on the strings, and the strings are 22010748Ssam * placed in area, which is a ref parameter which is updated. 22110748Ssam * No checking on area overflow. 22210748Ssam */ 22310748Ssam static char * 22410748Ssam dgetstr(id, area) 22510748Ssam char *id, **area; 22610748Ssam { 22710748Ssam register char *bp = tbuf; 22810748Ssam 22910748Ssam for (;;) { 23010748Ssam bp = dskip(bp); 23110748Ssam if (!*bp) 23210748Ssam return (0); 23310748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 23410748Ssam continue; 23510748Ssam if (*bp == '@') 23610748Ssam return (0); 23710748Ssam if (*bp != '=') 23810748Ssam continue; 23910748Ssam bp++; 24010748Ssam return (ddecode(bp, area)); 24110748Ssam } 24210748Ssam } 24310748Ssam 24410748Ssam /* 24510748Ssam * Tdecode does the grung work to decode the 24610748Ssam * string capability escapes. 24710748Ssam */ 24810748Ssam static char * 24910748Ssam ddecode(str, area) 25010748Ssam register char *str; 25110748Ssam char **area; 25210748Ssam { 25310748Ssam register char *cp; 25410748Ssam register int c; 25510748Ssam register char *dp; 25610748Ssam int i; 25710748Ssam 25810748Ssam cp = *area; 25910748Ssam while ((c = *str++) && c != ':') { 26010748Ssam switch (c) { 26110748Ssam 26210748Ssam case '^': 26310748Ssam c = *str++ & 037; 26410748Ssam break; 26510748Ssam 26610748Ssam case '\\': 26710748Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 26810748Ssam c = *str++; 26910748Ssam nextc: 27010748Ssam if (*dp++ == c) { 27110748Ssam c = *dp++; 27210748Ssam break; 27310748Ssam } 27410748Ssam dp++; 27510748Ssam if (*dp) 27610748Ssam goto nextc; 27710748Ssam if (isdigit(c)) { 27810748Ssam c -= '0', i = 2; 27910748Ssam do 28010748Ssam c <<= 3, c |= *str++ - '0'; 28110748Ssam while (--i && isdigit(*str)); 28210748Ssam } 28310748Ssam break; 28410748Ssam } 28510748Ssam *cp++ = c; 28610748Ssam } 28710748Ssam *cp++ = 0; 28810748Ssam str = *area; 28910748Ssam *area = cp; 29010748Ssam return (str); 29110748Ssam } 292