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