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