|
|
1.1 root 1: /*
2: * Copyright (c) 1983,1987 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #if defined(LIBC_SCCS) && !defined(lint)
8: static char sccsid[] = "@(#)disklabel.c 5.9 (Berkeley) 1/27/88";
9: #endif LIBC_SCCS and not lint
10:
11: #include <sys/param.h>
12: #include <sys/fs.h>
13: #include <sys/file.h>
14: #define DKTYPENAMES
15: #include <sys/disklabel.h>
16: #include <stdio.h>
17: #include <strings.h>
18:
19: static char *dgetstr();
20:
21: struct disklabel *
22: getdiskbyname(name)
23: char *name;
24: {
25: static struct disklabel disk;
26: static char boot[BUFSIZ];
27: char localbuf[BUFSIZ];
28: char buf[BUFSIZ];
29: char *cp, *cq; /* can't be register */
30: register struct disklabel *dp = &disk;
31: register struct partition *pp;
32: char p, max, psize[3], pbsize[3],
33: pfsize[3], poffset[3], ptype[3];
34: u_long *dx;
35:
36: if (dgetent(buf, name) <= 0)
37: return ((struct disklabel *)0);
38: bzero((char *)&disk, sizeof(disk));
39: /*
40: * typename
41: */
42: cq = dp->d_typename;
43: cp = buf;
44: while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 &&
45: (*cq = *cp) && *cq != '|' && *cq != ':')
46: cq++, cp++;
47: *cq = '\0';
48: /*
49: * boot name (optional) xxboot, bootxx
50: */
51: cp = boot;
52: dp->d_boot0 = dgetstr("b0", &cp);
53: dp->d_boot1 = dgetstr("b1", &cp);
54: cp = localbuf;
55: cq = dgetstr("ty", &cp);
56: if (cq && strcmp(cq, "removable") == 0)
57: dp->d_flags |= D_REMOVABLE;
58: else if (cq && strcmp(cq, "simulated") == 0)
59: dp->d_flags |= D_RAMDISK;
60: if (dgetflag("sf"))
61: dp->d_flags |= D_BADSECT;
62:
63: #define getnumdflt(field, dname, dflt) \
64: { int f = dgetnum(dname); \
65: (field) = f == -1 ? (dflt) : f; }
66:
67: getnumdflt(dp->d_secsize, "se", DEV_BSIZE);
68: dp->d_ntracks = dgetnum("nt");
69: dp->d_nsectors = dgetnum("ns");
70: dp->d_ncylinders = dgetnum("nc");
71: cq = dgetstr("dt", &cp);
72: if (cq)
73: dp->d_type = gettype(cq, dktypenames);
74: else
75: getnumdflt(dp->d_type, "dt", 0);
76: getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
77: getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
78: getnumdflt(dp->d_rpm, "rm", 3600);
79: getnumdflt(dp->d_interleave, "il", 1);
80: getnumdflt(dp->d_trackskew, "sk", 0);
81: getnumdflt(dp->d_cylskew, "cs", 0);
82: getnumdflt(dp->d_headswitch, "hs", 0);
83: getnumdflt(dp->d_trkseek, "ts", 0);
84: getnumdflt(dp->d_bbsize, "bs", BBSIZE);
85: getnumdflt(dp->d_sbsize, "sb", SBSIZE);
86: strcpy(psize, "px");
87: strcpy(pbsize, "bx");
88: strcpy(pfsize, "fx");
89: strcpy(poffset, "ox");
90: strcpy(ptype, "tx");
91: max = 'a' - 1;
92: pp = &dp->d_partitions[0];
93: for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) {
94: psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p;
95: pp->p_size = dgetnum(psize);
96: if (pp->p_size == -1)
97: pp->p_size = 0;
98: else {
99: pp->p_offset = dgetnum(poffset);
100: getnumdflt(pp->p_fsize, pfsize, 0);
101: if (pp->p_fsize)
102: pp->p_frag = dgetnum(pbsize) / pp->p_fsize;
103: getnumdflt(pp->p_fstype, ptype, 0);
104: if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp)))
105: pp->p_fstype = gettype(cq, fstypenames);
106: max = p;
107: }
108: }
109: dp->d_npartitions = max + 1 - 'a';
110: (void)strcpy(psize, "dx");
111: dx = dp->d_drivedata;
112: for (p = '0'; p < '0' + NDDATA; p++, dx++) {
113: psize[1] = p;
114: getnumdflt(*dx, psize, 0);
115: }
116: dp->d_magic = DISKMAGIC;
117: dp->d_magic2 = DISKMAGIC;
118: return (dp);
119: }
120:
121: #include <ctype.h>
122:
123: static char *tbuf;
124: static char *dskip();
125: static char *ddecode();
126:
127: /*
128: * Get an entry for disk name in buffer bp,
129: * from the diskcap file. Parse is very rudimentary;
130: * we just notice escaped newlines.
131: */
132: static
133: dgetent(bp, name)
134: char *bp, *name;
135: {
136: register char *cp;
137: register int c;
138: register int i = 0, cnt = 0;
139: char ibuf[BUFSIZ];
140: int tf;
141:
142: tbuf = bp;
143: tf = open(DISKTAB, 0);
144: if (tf < 0)
145: return (-1);
146: for (;;) {
147: cp = bp;
148: for (;;) {
149: if (i == cnt) {
150: cnt = read(tf, ibuf, BUFSIZ);
151: if (cnt <= 0) {
152: close(tf);
153: return (0);
154: }
155: i = 0;
156: }
157: c = ibuf[i++];
158: if (c == '\n') {
159: if (cp > bp && cp[-1] == '\\'){
160: cp--;
161: continue;
162: }
163: break;
164: }
165: if (cp >= bp+BUFSIZ) {
166: write(2,"Disktab entry too long\n", 23);
167: break;
168: } else
169: *cp++ = c;
170: }
171: *cp = 0;
172:
173: /*
174: * The real work for the match.
175: */
176: if (dnamatch(name)) {
177: close(tf);
178: return (1);
179: }
180: }
181: }
182:
183: /*
184: * Dnamatch deals with name matching. The first field of the disktab
185: * entry is a sequence of names separated by |'s, so we compare
186: * against each such name. The normal : terminator after the last
187: * name (before the first field) stops us.
188: */
189: static
190: dnamatch(np)
191: char *np;
192: {
193: register char *Np, *Bp;
194:
195: Bp = tbuf;
196: if (*Bp == '#')
197: return (0);
198: for (;;) {
199: for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
200: continue;
201: if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
202: return (1);
203: while (*Bp && *Bp != ':' && *Bp != '|')
204: Bp++;
205: if (*Bp == 0 || *Bp == ':')
206: return (0);
207: Bp++;
208: }
209: }
210:
211: /*
212: * Skip to the next field. Notice that this is very dumb, not
213: * knowing about \: escapes or any such. If necessary, :'s can be put
214: * into the diskcap file in octal.
215: */
216: static char *
217: dskip(bp)
218: register char *bp;
219: {
220:
221: while (*bp && *bp != ':')
222: bp++;
223: if (*bp == ':')
224: bp++;
225: return (bp);
226: }
227:
228: /*
229: * Return the (numeric) option id.
230: * Numeric options look like
231: * li#80
232: * i.e. the option string is separated from the numeric value by
233: * a # character. If the option is not found we return -1.
234: * Note that we handle octal numbers beginning with 0.
235: */
236: static
237: dgetnum(id)
238: char *id;
239: {
240: register int i, base;
241: register char *bp = tbuf;
242:
243: for (;;) {
244: bp = dskip(bp);
245: if (*bp == 0)
246: return (-1);
247: if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
248: continue;
249: if (*bp == '@')
250: return (-1);
251: if (*bp != '#')
252: continue;
253: bp++;
254: base = 10;
255: if (*bp == '0')
256: base = 8;
257: i = 0;
258: while (isdigit(*bp))
259: i *= base, i += *bp++ - '0';
260: return (i);
261: }
262: }
263:
264: /*
265: * Handle a flag option.
266: * Flag options are given "naked", i.e. followed by a : or the end
267: * of the buffer. Return 1 if we find the option, or 0 if it is
268: * not given.
269: */
270: static
271: dgetflag(id)
272: char *id;
273: {
274: register char *bp = tbuf;
275:
276: for (;;) {
277: bp = dskip(bp);
278: if (!*bp)
279: return (0);
280: if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
281: if (!*bp || *bp == ':')
282: return (1);
283: else if (*bp == '@')
284: return (0);
285: }
286: }
287: }
288:
289: /*
290: * Get a string valued option.
291: * These are given as
292: * cl=^Z
293: * Much decoding is done on the strings, and the strings are
294: * placed in area, which is a ref parameter which is updated.
295: * No checking on area overflow.
296: */
297: static char *
298: dgetstr(id, area)
299: char *id, **area;
300: {
301: register char *bp = tbuf;
302:
303: for (;;) {
304: bp = dskip(bp);
305: if (!*bp)
306: return (0);
307: if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
308: continue;
309: if (*bp == '@')
310: return (0);
311: if (*bp != '=')
312: continue;
313: bp++;
314: return (ddecode(bp, area));
315: }
316: }
317:
318: /*
319: * Tdecode does the grung work to decode the
320: * string capability escapes.
321: */
322: static char *
323: ddecode(str, area)
324: register char *str;
325: char **area;
326: {
327: register char *cp;
328: register int c;
329: register char *dp;
330: int i;
331:
332: cp = *area;
333: while ((c = *str++) && c != ':') {
334: switch (c) {
335:
336: case '^':
337: c = *str++ & 037;
338: break;
339:
340: case '\\':
341: dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
342: c = *str++;
343: nextc:
344: if (*dp++ == c) {
345: c = *dp++;
346: break;
347: }
348: dp++;
349: if (*dp)
350: goto nextc;
351: if (isdigit(c)) {
352: c -= '0', i = 2;
353: do
354: c <<= 3, c |= *str++ - '0';
355: while (--i && isdigit(*str));
356: }
357: break;
358: }
359: *cp++ = c;
360: }
361: *cp++ = 0;
362: str = *area;
363: *area = cp;
364: return (str);
365: }
366:
367: static
368: gettype(t, names)
369: char *t;
370: char **names;
371: {
372: register char **nm;
373:
374: for (nm = names; *nm; nm++)
375: if (strcasecmp(t, *nm) == 0)
376: return (nm - names);
377: if (isdigit(*t))
378: return (atoi(t));
379: return (0);
380: }
381:
382: dkcksum(lp)
383: register struct disklabel *lp;
384: {
385: register u_short *start, *end;
386: register u_short sum = 0;
387:
388: start = (u_short *)lp;
389: end = (u_short *)&lp->d_partitions[lp->d_npartitions];
390: while (start < end)
391: sum ^= *start++;
392: return (sum);
393: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.