delete setgrfile, ANSI style declarations, minor cleanups
[unix-history] / usr / src / lib / libc / gen / disklabel.c
CommitLineData
586c39b1 1/*
64022921
KB
2 * Copyright (c) 1983, 1987 Regents of the University of California.
3 * All rights reserved.
4 *
269a7923 5 * %sccs.include.redist.c%
586c39b1
DF
6 */
7
2ce81398 8#if defined(LIBC_SCCS) && !defined(lint)
c5980113 9static char sccsid[] = "@(#)disklabel.c 5.17 (Berkeley) %G%";
64022921 10#endif /* LIBC_SCCS and not lint */
ae284747 11
77118868 12#include <sys/param.h>
90793b84 13#include <sys/errno.h>
d0fa101e 14#include <ufs/fs.h>
77118868
MK
15#include <sys/file.h>
16#define DKTYPENAMES
17#include <sys/disklabel.h>
ae284747 18#include <stdio.h>
6ebcb998 19#include <string.h>
c5980113
DS
20#include <stdlib.h>
21#include <unistd.h>
ae284747
SL
22
23static char *dgetstr();
c5980113
DS
24static dgetent();
25static dnamatch();
26static dgetnum();
27static dgetflag();
28static gettype();
29static error();
ae284747 30
77118868 31struct disklabel *
ae284747 32getdiskbyname(name)
c5980113 33 const char *name;
ae284747 34{
572daa42
MT
35 static struct disklabel disk;
36 static char boot[BUFSIZ];
37 char localbuf[BUFSIZ];
38 char buf[BUFSIZ];
39 char *cp, *cq; /* can't be register */
77118868 40 register struct disklabel *dp = &disk;
8f13241a 41 register struct partition *pp;
572daa42
MT
42 char p, max, psize[3], pbsize[3],
43 pfsize[3], poffset[3], ptype[3];
44 u_long *dx;
ae284747
SL
45
46 if (dgetent(buf, name) <= 0)
77118868
MK
47 return ((struct disklabel *)0);
48 bzero((char *)&disk, sizeof(disk));
572daa42
MT
49 /*
50 * typename
51 */
77118868
MK
52 cq = dp->d_typename;
53 cp = buf;
54 while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 &&
55 (*cq = *cp) && *cq != '|' && *cq != ':')
56 cq++, cp++;
57 *cq = '\0';
572daa42
MT
58 /*
59 * boot name (optional) xxboot, bootxx
60 */
61 cp = boot;
62 dp->d_boot0 = dgetstr("b0", &cp);
63 dp->d_boot1 = dgetstr("b1", &cp);
77118868
MK
64 cp = localbuf;
65 cq = dgetstr("ty", &cp);
66 if (cq && strcmp(cq, "removable") == 0)
67 dp->d_flags |= D_REMOVABLE;
68 else if (cq && strcmp(cq, "simulated") == 0)
69 dp->d_flags |= D_RAMDISK;
70 if (dgetflag("sf"))
71 dp->d_flags |= D_BADSECT;
572daa42 72
77118868
MK
73#define getnumdflt(field, dname, dflt) \
74 { int f = dgetnum(dname); \
75 (field) = f == -1 ? (dflt) : f; }
76
77 getnumdflt(dp->d_secsize, "se", DEV_BSIZE);
ae284747
SL
78 dp->d_ntracks = dgetnum("nt");
79 dp->d_nsectors = dgetnum("ns");
80 dp->d_ncylinders = dgetnum("nc");
77118868
MK
81 cq = dgetstr("dt", &cp);
82 if (cq)
83 dp->d_type = gettype(cq, dktypenames);
84 else
85 getnumdflt(dp->d_type, "dt", 0);
86 getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
87 getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
88 getnumdflt(dp->d_rpm, "rm", 3600);
89 getnumdflt(dp->d_interleave, "il", 1);
90 getnumdflt(dp->d_trackskew, "sk", 0);
91 getnumdflt(dp->d_cylskew, "cs", 0);
92 getnumdflt(dp->d_headswitch, "hs", 0);
93 getnumdflt(dp->d_trkseek, "ts", 0);
94 getnumdflt(dp->d_bbsize, "bs", BBSIZE);
95 getnumdflt(dp->d_sbsize, "sb", SBSIZE);
8f13241a
SL
96 strcpy(psize, "px");
97 strcpy(pbsize, "bx");
98 strcpy(pfsize, "fx");
77118868
MK
99 strcpy(poffset, "ox");
100 strcpy(ptype, "tx");
101 max = 'a' - 1;
102 pp = &dp->d_partitions[0];
103 for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) {
104 psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p;
8f13241a 105 pp->p_size = dgetnum(psize);
77118868
MK
106 if (pp->p_size == -1)
107 pp->p_size = 0;
108 else {
109 pp->p_offset = dgetnum(poffset);
110 getnumdflt(pp->p_fsize, pfsize, 0);
111 if (pp->p_fsize)
112 pp->p_frag = dgetnum(pbsize) / pp->p_fsize;
113 getnumdflt(pp->p_fstype, ptype, 0);
114 if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp)))
115 pp->p_fstype = gettype(cq, fstypenames);
116 max = p;
117 }
118 }
119 dp->d_npartitions = max + 1 - 'a';
6665218a 120 (void)strcpy(psize, "dx");
77118868
MK
121 dx = dp->d_drivedata;
122 for (p = '0'; p < '0' + NDDATA; p++, dx++) {
123 psize[1] = p;
124 getnumdflt(*dx, psize, 0);
ae284747 125 }
77118868
MK
126 dp->d_magic = DISKMAGIC;
127 dp->d_magic2 = DISKMAGIC;
ae284747
SL
128 return (dp);
129}
130
131#include <ctype.h>
132
133static char *tbuf;
134static char *dskip();
135static char *ddecode();
136
137/*
138 * Get an entry for disk name in buffer bp,
139 * from the diskcap file. Parse is very rudimentary;
140 * we just notice escaped newlines.
141 */
142static
143dgetent(bp, name)
144 char *bp, *name;
145{
146 register char *cp;
147 register int c;
148 register int i = 0, cnt = 0;
149 char ibuf[BUFSIZ];
150 int tf;
151
152 tbuf = bp;
90793b84
KB
153 tf = open(_PATH_DISKTAB, 0);
154 if (tf < 0) {
155 error(errno);
ae284747 156 return (-1);
90793b84 157 }
ae284747
SL
158 for (;;) {
159 cp = bp;
160 for (;;) {
161 if (i == cnt) {
162 cnt = read(tf, ibuf, BUFSIZ);
163 if (cnt <= 0) {
90793b84 164 error(errno);
ae284747
SL
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) {
30681d11 179 error(EFTYPE);
ae284747
SL
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 */
202static
203dnamatch(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 */
229static char *
230dskip(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 */
249static
250dgetnum(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 */
283static
284dgetflag(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 */
310static char *
311dgetstr(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 */
335static char *
336ddecode(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++;
356nextc:
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}
77118868
MK
379
380static
381gettype(t, names)
382 char *t;
383 char **names;
384{
385 register char **nm;
386
387 for (nm = names; *nm; nm++)
49f0b7cf 388 if (strcasecmp(t, *nm) == 0)
77118868
MK
389 return (nm - names);
390 if (isdigit(*t))
391 return (atoi(t));
392 return (0);
393}
394
90793b84
KB
395static
396error(err)
397 int err;
398{
399 char *p;
400
401 (void)write(STDERR_FILENO, "disktab: ", 9);
402 (void)write(STDERR_FILENO, _PATH_DISKTAB, sizeof(_PATH_DISKTAB) - 1);
403 p = strerror(err);
404 (void)write(STDERR_FILENO, p, strlen(p));
405 (void)write(STDERR_FILENO, "\n", 1);
406}