121417Sdist /* 230420Skarels * Copyright (c) 1983,1987 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 726675Sdonn #if defined(LIBC_SCCS) && !defined(lint) 8*33261Smckusick static char sccsid[] = "@(#)disklabel.c 5.8 (Berkeley) 01/03/88"; 926675Sdonn #endif LIBC_SCCS and not lint 1021417Sdist 1130420Skarels #include <sys/param.h> 1230420Skarels #include <sys/fs.h> 1330420Skarels #include <sys/file.h> 1430420Skarels #define DKTYPENAMES 1530420Skarels #include <sys/disklabel.h> 1610748Ssam #include <stdio.h> 1730681Sbostic #include <strings.h> 1810748Ssam 1910748Ssam static char *dgetstr(); 2010748Ssam 2130420Skarels struct disklabel * 2210748Ssam getdiskbyname(name) 2310748Ssam char *name; 2410748Ssam { 2530420Skarels static struct disklabel disk; 2630420Skarels static char localbuf[100]; 2730420Skarels char *cp, *cq; 2830420Skarels register struct disklabel *dp = &disk; 2910760Ssam register struct partition *pp; 3030420Skarels char p, max, psize[3], pbsize[3], pfsize[3], poffset[3], ptype[3]; 3110760Ssam char buf[BUFSIZ]; 3230420Skarels u_long *dx; 3310748Ssam 3410748Ssam if (dgetent(buf, name) <= 0) 3530420Skarels return ((struct disklabel *)0); 3630420Skarels bzero((char *)&disk, sizeof(disk)); 3730420Skarels cq = dp->d_typename; 3830420Skarels cp = buf; 3930420Skarels while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 && 4030420Skarels (*cq = *cp) && *cq != '|' && *cq != ':') 4130420Skarels cq++, cp++; 4230420Skarels *cq = '\0'; 4330420Skarels cp = localbuf; 4430420Skarels cq = dgetstr("ty", &cp); 4530420Skarels if (cq && strcmp(cq, "removable") == 0) 4630420Skarels dp->d_flags |= D_REMOVABLE; 4730420Skarels else if (cq && strcmp(cq, "simulated") == 0) 4830420Skarels dp->d_flags |= D_RAMDISK; 4930420Skarels if (dgetflag("sf")) 5030420Skarels dp->d_flags |= D_BADSECT; 5130420Skarels #define getnumdflt(field, dname, dflt) \ 5230420Skarels { int f = dgetnum(dname); \ 5330420Skarels (field) = f == -1 ? (dflt) : f; } 5430420Skarels 5530420Skarels getnumdflt(dp->d_secsize, "se", DEV_BSIZE); 5610748Ssam dp->d_ntracks = dgetnum("nt"); 5710748Ssam dp->d_nsectors = dgetnum("ns"); 5810748Ssam dp->d_ncylinders = dgetnum("nc"); 5930420Skarels cq = dgetstr("dt", &cp); 6030420Skarels if (cq) 6130420Skarels dp->d_type = gettype(cq, dktypenames); 6230420Skarels else 6330420Skarels getnumdflt(dp->d_type, "dt", 0); 6430420Skarels getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks); 6530420Skarels getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders); 6630420Skarels getnumdflt(dp->d_rpm, "rm", 3600); 6730420Skarels getnumdflt(dp->d_interleave, "il", 1); 6830420Skarels getnumdflt(dp->d_trackskew, "sk", 0); 6930420Skarels getnumdflt(dp->d_cylskew, "cs", 0); 7030420Skarels getnumdflt(dp->d_headswitch, "hs", 0); 7130420Skarels getnumdflt(dp->d_trkseek, "ts", 0); 7230420Skarels getnumdflt(dp->d_bbsize, "bs", BBSIZE); 7330420Skarels getnumdflt(dp->d_sbsize, "sb", SBSIZE); 7410760Ssam strcpy(psize, "px"); 7510760Ssam strcpy(pbsize, "bx"); 7610760Ssam strcpy(pfsize, "fx"); 7730420Skarels strcpy(poffset, "ox"); 7830420Skarels strcpy(ptype, "tx"); 7930420Skarels max = 'a' - 1; 8030420Skarels pp = &dp->d_partitions[0]; 8130420Skarels for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) { 8230420Skarels psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p; 8310760Ssam pp->p_size = dgetnum(psize); 8430420Skarels if (pp->p_size == -1) 8530420Skarels pp->p_size = 0; 8630420Skarels else { 8730420Skarels pp->p_offset = dgetnum(poffset); 8830420Skarels getnumdflt(pp->p_fsize, pfsize, 0); 8930420Skarels if (pp->p_fsize) 9030420Skarels pp->p_frag = dgetnum(pbsize) / pp->p_fsize; 9130420Skarels getnumdflt(pp->p_fstype, ptype, 0); 9230420Skarels if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp))) 9330420Skarels pp->p_fstype = gettype(cq, fstypenames); 9430420Skarels max = p; 9530420Skarels } 9610748Ssam } 9730420Skarels dp->d_npartitions = max + 1 - 'a'; 9830681Sbostic (void)strcpy(psize, "dx"); 9930420Skarels dx = dp->d_drivedata; 10030420Skarels for (p = '0'; p < '0' + NDDATA; p++, dx++) { 10130420Skarels psize[1] = p; 10230420Skarels getnumdflt(*dx, psize, 0); 10330420Skarels } 10430420Skarels dp->d_magic = DISKMAGIC; 10530420Skarels dp->d_magic2 = DISKMAGIC; 10610748Ssam return (dp); 10710748Ssam } 10810748Ssam 10910748Ssam #include <ctype.h> 11010748Ssam 11110748Ssam static char *tbuf; 11210748Ssam static char *dskip(); 11310748Ssam static char *ddecode(); 11410748Ssam 11510748Ssam /* 11610748Ssam * Get an entry for disk name in buffer bp, 11710748Ssam * from the diskcap file. Parse is very rudimentary; 11810748Ssam * we just notice escaped newlines. 11910748Ssam */ 12010748Ssam static 12110748Ssam dgetent(bp, name) 12210748Ssam char *bp, *name; 12310748Ssam { 12410748Ssam register char *cp; 12510748Ssam register int c; 12610748Ssam register int i = 0, cnt = 0; 12710748Ssam char ibuf[BUFSIZ]; 12810748Ssam int tf; 12910748Ssam 13010748Ssam tbuf = bp; 13110748Ssam tf = open(DISKTAB, 0); 13210748Ssam if (tf < 0) 13310748Ssam return (-1); 13410748Ssam for (;;) { 13510748Ssam cp = bp; 13610748Ssam for (;;) { 13710748Ssam if (i == cnt) { 13810748Ssam cnt = read(tf, ibuf, BUFSIZ); 13910748Ssam if (cnt <= 0) { 14010748Ssam close(tf); 14110748Ssam return (0); 14210748Ssam } 14310748Ssam i = 0; 14410748Ssam } 14510748Ssam c = ibuf[i++]; 14610748Ssam if (c == '\n') { 14710748Ssam if (cp > bp && cp[-1] == '\\'){ 14810748Ssam cp--; 14910748Ssam continue; 15010748Ssam } 15110748Ssam break; 15210748Ssam } 15310748Ssam if (cp >= bp+BUFSIZ) { 15410748Ssam write(2,"Disktab entry too long\n", 23); 15510748Ssam break; 15610748Ssam } else 15710748Ssam *cp++ = c; 15810748Ssam } 15910748Ssam *cp = 0; 16010748Ssam 16110748Ssam /* 16210748Ssam * The real work for the match. 16310748Ssam */ 16410748Ssam if (dnamatch(name)) { 16510748Ssam close(tf); 16610748Ssam return (1); 16710748Ssam } 16810748Ssam } 16910748Ssam } 17010748Ssam 17110748Ssam /* 17210748Ssam * Dnamatch deals with name matching. The first field of the disktab 17310748Ssam * entry is a sequence of names separated by |'s, so we compare 17410748Ssam * against each such name. The normal : terminator after the last 17510748Ssam * name (before the first field) stops us. 17610748Ssam */ 17710748Ssam static 17810748Ssam dnamatch(np) 17910748Ssam char *np; 18010748Ssam { 18110748Ssam register char *Np, *Bp; 18210748Ssam 18310748Ssam Bp = tbuf; 18410748Ssam if (*Bp == '#') 18510748Ssam return (0); 18610748Ssam for (;;) { 18710748Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 18810748Ssam continue; 18910748Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 19010748Ssam return (1); 19110748Ssam while (*Bp && *Bp != ':' && *Bp != '|') 19210748Ssam Bp++; 19310748Ssam if (*Bp == 0 || *Bp == ':') 19410748Ssam return (0); 19510748Ssam Bp++; 19610748Ssam } 19710748Ssam } 19810748Ssam 19910748Ssam /* 20010748Ssam * Skip to the next field. Notice that this is very dumb, not 20110748Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 20210748Ssam * into the diskcap file in octal. 20310748Ssam */ 20410748Ssam static char * 20510748Ssam dskip(bp) 20610748Ssam register char *bp; 20710748Ssam { 20810748Ssam 20910748Ssam while (*bp && *bp != ':') 21010748Ssam bp++; 21110748Ssam if (*bp == ':') 21210748Ssam bp++; 21310748Ssam return (bp); 21410748Ssam } 21510748Ssam 21610748Ssam /* 21710748Ssam * Return the (numeric) option id. 21810748Ssam * Numeric options look like 21910748Ssam * li#80 22010748Ssam * i.e. the option string is separated from the numeric value by 22110748Ssam * a # character. If the option is not found we return -1. 22210748Ssam * Note that we handle octal numbers beginning with 0. 22310748Ssam */ 22410748Ssam static 22510748Ssam dgetnum(id) 22610748Ssam char *id; 22710748Ssam { 22810748Ssam register int i, base; 22910748Ssam register char *bp = tbuf; 23010748Ssam 23110748Ssam for (;;) { 23210748Ssam bp = dskip(bp); 23310748Ssam if (*bp == 0) 23410748Ssam return (-1); 23510748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 23610748Ssam continue; 23710748Ssam if (*bp == '@') 23810748Ssam return (-1); 23910748Ssam if (*bp != '#') 24010748Ssam continue; 24110748Ssam bp++; 24210748Ssam base = 10; 24310748Ssam if (*bp == '0') 24410748Ssam base = 8; 24510748Ssam i = 0; 24610748Ssam while (isdigit(*bp)) 24710748Ssam i *= base, i += *bp++ - '0'; 24810748Ssam return (i); 24910748Ssam } 25010748Ssam } 25110748Ssam 25210748Ssam /* 25310748Ssam * Handle a flag option. 25410748Ssam * Flag options are given "naked", i.e. followed by a : or the end 25510748Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 25610748Ssam * not given. 25710748Ssam */ 25810748Ssam static 25910748Ssam dgetflag(id) 26010748Ssam char *id; 26110748Ssam { 26210748Ssam register char *bp = tbuf; 26310748Ssam 26410748Ssam for (;;) { 26510748Ssam bp = dskip(bp); 26610748Ssam if (!*bp) 26710748Ssam return (0); 26810748Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 26910748Ssam if (!*bp || *bp == ':') 27010748Ssam return (1); 27110748Ssam else if (*bp == '@') 27210748Ssam return (0); 27310748Ssam } 27410748Ssam } 27510748Ssam } 27610748Ssam 27710748Ssam /* 27810748Ssam * Get a string valued option. 27910748Ssam * These are given as 28010748Ssam * cl=^Z 28110748Ssam * Much decoding is done on the strings, and the strings are 28210748Ssam * placed in area, which is a ref parameter which is updated. 28310748Ssam * No checking on area overflow. 28410748Ssam */ 28510748Ssam static char * 28610748Ssam dgetstr(id, area) 28710748Ssam char *id, **area; 28810748Ssam { 28910748Ssam register char *bp = tbuf; 29010748Ssam 29110748Ssam for (;;) { 29210748Ssam bp = dskip(bp); 29310748Ssam if (!*bp) 29410748Ssam return (0); 29510748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 29610748Ssam continue; 29710748Ssam if (*bp == '@') 29810748Ssam return (0); 29910748Ssam if (*bp != '=') 30010748Ssam continue; 30110748Ssam bp++; 30210748Ssam return (ddecode(bp, area)); 30310748Ssam } 30410748Ssam } 30510748Ssam 30610748Ssam /* 30710748Ssam * Tdecode does the grung work to decode the 30810748Ssam * string capability escapes. 30910748Ssam */ 31010748Ssam static char * 31110748Ssam ddecode(str, area) 31210748Ssam register char *str; 31310748Ssam char **area; 31410748Ssam { 31510748Ssam register char *cp; 31610748Ssam register int c; 31710748Ssam register char *dp; 31810748Ssam int i; 31910748Ssam 32010748Ssam cp = *area; 32110748Ssam while ((c = *str++) && c != ':') { 32210748Ssam switch (c) { 32310748Ssam 32410748Ssam case '^': 32510748Ssam c = *str++ & 037; 32610748Ssam break; 32710748Ssam 32810748Ssam case '\\': 32910748Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 33010748Ssam c = *str++; 33110748Ssam nextc: 33210748Ssam if (*dp++ == c) { 33310748Ssam c = *dp++; 33410748Ssam break; 33510748Ssam } 33610748Ssam dp++; 33710748Ssam if (*dp) 33810748Ssam goto nextc; 33910748Ssam if (isdigit(c)) { 34010748Ssam c -= '0', i = 2; 34110748Ssam do 34210748Ssam c <<= 3, c |= *str++ - '0'; 34310748Ssam while (--i && isdigit(*str)); 34410748Ssam } 34510748Ssam break; 34610748Ssam } 34710748Ssam *cp++ = c; 34810748Ssam } 34910748Ssam *cp++ = 0; 35010748Ssam str = *area; 35110748Ssam *area = cp; 35210748Ssam return (str); 35310748Ssam } 35430420Skarels 35530420Skarels static 35630420Skarels gettype(t, names) 35730420Skarels char *t; 35830420Skarels char **names; 35930420Skarels { 36030420Skarels register char **nm; 36130420Skarels 36230420Skarels for (nm = names; *nm; nm++) 363*33261Smckusick if (strcasecmp(t, *nm) == 0) 36430420Skarels return (nm - names); 36530420Skarels if (isdigit(*t)) 36630420Skarels return (atoi(t)); 36730420Skarels return (0); 36830420Skarels } 36930420Skarels 37030420Skarels dkcksum(lp) 37130420Skarels register struct disklabel *lp; 37230420Skarels { 37330420Skarels register u_short *start, *end; 37430420Skarels register u_short sum = 0; 37530420Skarels 37630420Skarels start = (u_short *)lp; 37730420Skarels end = (u_short *)&lp->d_partitions[lp->d_npartitions]; 37830420Skarels while (start < end) 37930420Skarels sum ^= *start++; 38030420Skarels return (sum); 38130420Skarels } 382