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