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