121417Sdist /* 235104Sbostic * Copyright (c) 1983, 1987 Regents of the University of California. 335104Sbostic * All rights reserved. 435104Sbostic * 542622Sbostic * %sccs.include.redist.c% 621417Sdist */ 710748Ssam 826675Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*45646Sbostic static char sccsid[] = "@(#)disklabel.c 5.14 (Berkeley) 11/28/90"; 1035104Sbostic #endif /* LIBC_SCCS and not lint */ 1121417Sdist 1230420Skarels #include <sys/param.h> 13*45646Sbostic #include <sys/errno.h> 1438498Sbostic #include <ufs/fs.h> 1530420Skarels #include <sys/file.h> 1630420Skarels #define DKTYPENAMES 1730420Skarels #include <sys/disklabel.h> 1810748Ssam #include <stdio.h> 1942022Sbostic #include <string.h> 2010748Ssam 2110748Ssam static char *dgetstr(); 2210748Ssam 2330420Skarels struct disklabel * 2410748Ssam getdiskbyname(name) 2510748Ssam char *name; 2610748Ssam { 2733399Smarc static struct disklabel disk; 2833399Smarc static char boot[BUFSIZ]; 2933399Smarc char localbuf[BUFSIZ]; 3033399Smarc char buf[BUFSIZ]; 3133399Smarc char *cp, *cq; /* can't be register */ 3230420Skarels register struct disklabel *dp = &disk; 3310760Ssam register struct partition *pp; 3433399Smarc char p, max, psize[3], pbsize[3], 3533399Smarc pfsize[3], poffset[3], ptype[3]; 3633399Smarc u_long *dx; 3710748Ssam 3810748Ssam if (dgetent(buf, name) <= 0) 3930420Skarels return ((struct disklabel *)0); 4030420Skarels bzero((char *)&disk, sizeof(disk)); 4133399Smarc /* 4233399Smarc * typename 4333399Smarc */ 4430420Skarels cq = dp->d_typename; 4530420Skarels cp = buf; 4630420Skarels while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 && 4730420Skarels (*cq = *cp) && *cq != '|' && *cq != ':') 4830420Skarels cq++, cp++; 4930420Skarels *cq = '\0'; 5033399Smarc /* 5133399Smarc * boot name (optional) xxboot, bootxx 5233399Smarc */ 5333399Smarc cp = boot; 5433399Smarc dp->d_boot0 = dgetstr("b0", &cp); 5533399Smarc dp->d_boot1 = dgetstr("b1", &cp); 5630420Skarels cp = localbuf; 5730420Skarels cq = dgetstr("ty", &cp); 5830420Skarels if (cq && strcmp(cq, "removable") == 0) 5930420Skarels dp->d_flags |= D_REMOVABLE; 6030420Skarels else if (cq && strcmp(cq, "simulated") == 0) 6130420Skarels dp->d_flags |= D_RAMDISK; 6230420Skarels if (dgetflag("sf")) 6330420Skarels dp->d_flags |= D_BADSECT; 6433399Smarc 6530420Skarels #define getnumdflt(field, dname, dflt) \ 6630420Skarels { int f = dgetnum(dname); \ 6730420Skarels (field) = f == -1 ? (dflt) : f; } 6830420Skarels 6930420Skarels getnumdflt(dp->d_secsize, "se", DEV_BSIZE); 7010748Ssam dp->d_ntracks = dgetnum("nt"); 7110748Ssam dp->d_nsectors = dgetnum("ns"); 7210748Ssam dp->d_ncylinders = dgetnum("nc"); 7330420Skarels cq = dgetstr("dt", &cp); 7430420Skarels if (cq) 7530420Skarels dp->d_type = gettype(cq, dktypenames); 7630420Skarels else 7730420Skarels getnumdflt(dp->d_type, "dt", 0); 7830420Skarels getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks); 7930420Skarels getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders); 8030420Skarels getnumdflt(dp->d_rpm, "rm", 3600); 8130420Skarels getnumdflt(dp->d_interleave, "il", 1); 8230420Skarels getnumdflt(dp->d_trackskew, "sk", 0); 8330420Skarels getnumdflt(dp->d_cylskew, "cs", 0); 8430420Skarels getnumdflt(dp->d_headswitch, "hs", 0); 8530420Skarels getnumdflt(dp->d_trkseek, "ts", 0); 8630420Skarels getnumdflt(dp->d_bbsize, "bs", BBSIZE); 8730420Skarels getnumdflt(dp->d_sbsize, "sb", SBSIZE); 8810760Ssam strcpy(psize, "px"); 8910760Ssam strcpy(pbsize, "bx"); 9010760Ssam strcpy(pfsize, "fx"); 9130420Skarels strcpy(poffset, "ox"); 9230420Skarels strcpy(ptype, "tx"); 9330420Skarels max = 'a' - 1; 9430420Skarels pp = &dp->d_partitions[0]; 9530420Skarels for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) { 9630420Skarels psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p; 9710760Ssam pp->p_size = dgetnum(psize); 9830420Skarels if (pp->p_size == -1) 9930420Skarels pp->p_size = 0; 10030420Skarels else { 10130420Skarels pp->p_offset = dgetnum(poffset); 10230420Skarels getnumdflt(pp->p_fsize, pfsize, 0); 10330420Skarels if (pp->p_fsize) 10430420Skarels pp->p_frag = dgetnum(pbsize) / pp->p_fsize; 10530420Skarels getnumdflt(pp->p_fstype, ptype, 0); 10630420Skarels if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp))) 10730420Skarels pp->p_fstype = gettype(cq, fstypenames); 10830420Skarels max = p; 10930420Skarels } 11010748Ssam } 11130420Skarels dp->d_npartitions = max + 1 - 'a'; 11230681Sbostic (void)strcpy(psize, "dx"); 11330420Skarels dx = dp->d_drivedata; 11430420Skarels for (p = '0'; p < '0' + NDDATA; p++, dx++) { 11530420Skarels psize[1] = p; 11630420Skarels getnumdflt(*dx, psize, 0); 11730420Skarels } 11830420Skarels dp->d_magic = DISKMAGIC; 11930420Skarels dp->d_magic2 = DISKMAGIC; 12010748Ssam return (dp); 12110748Ssam } 12210748Ssam 12310748Ssam #include <ctype.h> 12410748Ssam 12510748Ssam static char *tbuf; 12610748Ssam static char *dskip(); 12710748Ssam static char *ddecode(); 12810748Ssam 12910748Ssam /* 13010748Ssam * Get an entry for disk name in buffer bp, 13110748Ssam * from the diskcap file. Parse is very rudimentary; 13210748Ssam * we just notice escaped newlines. 13310748Ssam */ 13410748Ssam static 13510748Ssam dgetent(bp, name) 13610748Ssam char *bp, *name; 13710748Ssam { 13810748Ssam register char *cp; 13910748Ssam register int c; 14010748Ssam register int i = 0, cnt = 0; 14110748Ssam char ibuf[BUFSIZ]; 14210748Ssam int tf; 14310748Ssam 14410748Ssam tbuf = bp; 145*45646Sbostic tf = open(_PATH_DISKTAB, 0); 146*45646Sbostic if (tf < 0) { 147*45646Sbostic error(errno); 14810748Ssam return (-1); 149*45646Sbostic } 15010748Ssam for (;;) { 15110748Ssam cp = bp; 15210748Ssam for (;;) { 15310748Ssam if (i == cnt) { 15410748Ssam cnt = read(tf, ibuf, BUFSIZ); 15510748Ssam if (cnt <= 0) { 156*45646Sbostic error(errno); 15710748Ssam close(tf); 15810748Ssam return (0); 15910748Ssam } 16010748Ssam i = 0; 16110748Ssam } 16210748Ssam c = ibuf[i++]; 16310748Ssam if (c == '\n') { 16410748Ssam if (cp > bp && cp[-1] == '\\'){ 16510748Ssam cp--; 16610748Ssam continue; 16710748Ssam } 16810748Ssam break; 16910748Ssam } 17010748Ssam if (cp >= bp+BUFSIZ) { 171*45646Sbostic error(EBADFORMAT); 17210748Ssam break; 17310748Ssam } else 17410748Ssam *cp++ = c; 17510748Ssam } 17610748Ssam *cp = 0; 17710748Ssam 17810748Ssam /* 17910748Ssam * The real work for the match. 18010748Ssam */ 18110748Ssam if (dnamatch(name)) { 18210748Ssam close(tf); 18310748Ssam return (1); 18410748Ssam } 18510748Ssam } 18610748Ssam } 18710748Ssam 18810748Ssam /* 18910748Ssam * Dnamatch deals with name matching. The first field of the disktab 19010748Ssam * entry is a sequence of names separated by |'s, so we compare 19110748Ssam * against each such name. The normal : terminator after the last 19210748Ssam * name (before the first field) stops us. 19310748Ssam */ 19410748Ssam static 19510748Ssam dnamatch(np) 19610748Ssam char *np; 19710748Ssam { 19810748Ssam register char *Np, *Bp; 19910748Ssam 20010748Ssam Bp = tbuf; 20110748Ssam if (*Bp == '#') 20210748Ssam return (0); 20310748Ssam for (;;) { 20410748Ssam for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 20510748Ssam continue; 20610748Ssam if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 20710748Ssam return (1); 20810748Ssam while (*Bp && *Bp != ':' && *Bp != '|') 20910748Ssam Bp++; 21010748Ssam if (*Bp == 0 || *Bp == ':') 21110748Ssam return (0); 21210748Ssam Bp++; 21310748Ssam } 21410748Ssam } 21510748Ssam 21610748Ssam /* 21710748Ssam * Skip to the next field. Notice that this is very dumb, not 21810748Ssam * knowing about \: escapes or any such. If necessary, :'s can be put 21910748Ssam * into the diskcap file in octal. 22010748Ssam */ 22110748Ssam static char * 22210748Ssam dskip(bp) 22310748Ssam register char *bp; 22410748Ssam { 22510748Ssam 22610748Ssam while (*bp && *bp != ':') 22710748Ssam bp++; 22810748Ssam if (*bp == ':') 22910748Ssam bp++; 23010748Ssam return (bp); 23110748Ssam } 23210748Ssam 23310748Ssam /* 23410748Ssam * Return the (numeric) option id. 23510748Ssam * Numeric options look like 23610748Ssam * li#80 23710748Ssam * i.e. the option string is separated from the numeric value by 23810748Ssam * a # character. If the option is not found we return -1. 23910748Ssam * Note that we handle octal numbers beginning with 0. 24010748Ssam */ 24110748Ssam static 24210748Ssam dgetnum(id) 24310748Ssam char *id; 24410748Ssam { 24510748Ssam register int i, base; 24610748Ssam register char *bp = tbuf; 24710748Ssam 24810748Ssam for (;;) { 24910748Ssam bp = dskip(bp); 25010748Ssam if (*bp == 0) 25110748Ssam return (-1); 25210748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 25310748Ssam continue; 25410748Ssam if (*bp == '@') 25510748Ssam return (-1); 25610748Ssam if (*bp != '#') 25710748Ssam continue; 25810748Ssam bp++; 25910748Ssam base = 10; 26010748Ssam if (*bp == '0') 26110748Ssam base = 8; 26210748Ssam i = 0; 26310748Ssam while (isdigit(*bp)) 26410748Ssam i *= base, i += *bp++ - '0'; 26510748Ssam return (i); 26610748Ssam } 26710748Ssam } 26810748Ssam 26910748Ssam /* 27010748Ssam * Handle a flag option. 27110748Ssam * Flag options are given "naked", i.e. followed by a : or the end 27210748Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 27310748Ssam * not given. 27410748Ssam */ 27510748Ssam static 27610748Ssam dgetflag(id) 27710748Ssam char *id; 27810748Ssam { 27910748Ssam register char *bp = tbuf; 28010748Ssam 28110748Ssam for (;;) { 28210748Ssam bp = dskip(bp); 28310748Ssam if (!*bp) 28410748Ssam return (0); 28510748Ssam if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 28610748Ssam if (!*bp || *bp == ':') 28710748Ssam return (1); 28810748Ssam else if (*bp == '@') 28910748Ssam return (0); 29010748Ssam } 29110748Ssam } 29210748Ssam } 29310748Ssam 29410748Ssam /* 29510748Ssam * Get a string valued option. 29610748Ssam * These are given as 29710748Ssam * cl=^Z 29810748Ssam * Much decoding is done on the strings, and the strings are 29910748Ssam * placed in area, which is a ref parameter which is updated. 30010748Ssam * No checking on area overflow. 30110748Ssam */ 30210748Ssam static char * 30310748Ssam dgetstr(id, area) 30410748Ssam char *id, **area; 30510748Ssam { 30610748Ssam register char *bp = tbuf; 30710748Ssam 30810748Ssam for (;;) { 30910748Ssam bp = dskip(bp); 31010748Ssam if (!*bp) 31110748Ssam return (0); 31210748Ssam if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 31310748Ssam continue; 31410748Ssam if (*bp == '@') 31510748Ssam return (0); 31610748Ssam if (*bp != '=') 31710748Ssam continue; 31810748Ssam bp++; 31910748Ssam return (ddecode(bp, area)); 32010748Ssam } 32110748Ssam } 32210748Ssam 32310748Ssam /* 32410748Ssam * Tdecode does the grung work to decode the 32510748Ssam * string capability escapes. 32610748Ssam */ 32710748Ssam static char * 32810748Ssam ddecode(str, area) 32910748Ssam register char *str; 33010748Ssam char **area; 33110748Ssam { 33210748Ssam register char *cp; 33310748Ssam register int c; 33410748Ssam register char *dp; 33510748Ssam int i; 33610748Ssam 33710748Ssam cp = *area; 33810748Ssam while ((c = *str++) && c != ':') { 33910748Ssam switch (c) { 34010748Ssam 34110748Ssam case '^': 34210748Ssam c = *str++ & 037; 34310748Ssam break; 34410748Ssam 34510748Ssam case '\\': 34610748Ssam dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 34710748Ssam c = *str++; 34810748Ssam nextc: 34910748Ssam if (*dp++ == c) { 35010748Ssam c = *dp++; 35110748Ssam break; 35210748Ssam } 35310748Ssam dp++; 35410748Ssam if (*dp) 35510748Ssam goto nextc; 35610748Ssam if (isdigit(c)) { 35710748Ssam c -= '0', i = 2; 35810748Ssam do 35910748Ssam c <<= 3, c |= *str++ - '0'; 36010748Ssam while (--i && isdigit(*str)); 36110748Ssam } 36210748Ssam break; 36310748Ssam } 36410748Ssam *cp++ = c; 36510748Ssam } 36610748Ssam *cp++ = 0; 36710748Ssam str = *area; 36810748Ssam *area = cp; 36910748Ssam return (str); 37010748Ssam } 37130420Skarels 37230420Skarels static 37330420Skarels gettype(t, names) 37430420Skarels char *t; 37530420Skarels char **names; 37630420Skarels { 37730420Skarels register char **nm; 37830420Skarels 37930420Skarels for (nm = names; *nm; nm++) 38033261Smckusick if (strcasecmp(t, *nm) == 0) 38130420Skarels return (nm - names); 38230420Skarels if (isdigit(*t)) 38330420Skarels return (atoi(t)); 38430420Skarels return (0); 38530420Skarels } 38630420Skarels 38730420Skarels dkcksum(lp) 38830420Skarels register struct disklabel *lp; 38930420Skarels { 39030420Skarels register u_short *start, *end; 39130420Skarels register u_short sum = 0; 39230420Skarels 39330420Skarels start = (u_short *)lp; 39430420Skarels end = (u_short *)&lp->d_partitions[lp->d_npartitions]; 39530420Skarels while (start < end) 39630420Skarels sum ^= *start++; 39730420Skarels return (sum); 39830420Skarels } 399*45646Sbostic 400*45646Sbostic static 401*45646Sbostic error(err) 402*45646Sbostic int err; 403*45646Sbostic { 404*45646Sbostic char *p; 405*45646Sbostic 406*45646Sbostic (void)write(STDERR_FILENO, "disktab: ", 9); 407*45646Sbostic (void)write(STDERR_FILENO, _PATH_DISKTAB, sizeof(_PATH_DISKTAB) - 1); 408*45646Sbostic p = strerror(err); 409*45646Sbostic (void)write(STDERR_FILENO, p, strlen(p)); 410*45646Sbostic (void)write(STDERR_FILENO, "\n", 1); 411*45646Sbostic } 412