xref: /csrg-svn/sys/stand.att/open.c (revision 49149)
1*49149Sbostic /*-
2*49149Sbostic  * Copyright (c) 1982, 1988 The Regents of the University of California.
3*49149Sbostic  * All rights reserved.
4*49149Sbostic  *
5*49149Sbostic  * %sccs.include.proprietary.c%
6*49149Sbostic  *
7*49149Sbostic  *	@(#)open.c	7.1 (Berkeley) 05/05/91
8*49149Sbostic  */
9*49149Sbostic 
10*49149Sbostic #include <sys/param.h>
11*49149Sbostic #include <sys/reboot.h>
12*49149Sbostic #include <ufs/dir.h>
13*49149Sbostic #include "saio.h"
14*49149Sbostic 
15*49149Sbostic int	firstopen;
16*49149Sbostic u_int	opendev;			/* last device opened */
17*49149Sbostic extern u_int bootdev;
18*49149Sbostic 
19*49149Sbostic struct dirstuff {
20*49149Sbostic 	int loc;
21*49149Sbostic 	struct iob *io;
22*49149Sbostic };
23*49149Sbostic 
24*49149Sbostic #ifndef SMALL
25*49149Sbostic static ino_t dlook __P((char *, struct iob *, char *));
26*49149Sbostic static int find __P((char *, struct iob *));
27*49149Sbostic static int getdev __P((char *, int));
28*49149Sbostic static int getunit __P((char *));
29*49149Sbostic static struct direct *readdir __P((struct dirstuff *));
30*49149Sbostic static int openi __P((int, struct iob *));
31*49149Sbostic #endif
32*49149Sbostic 
33*49149Sbostic open(str, how)
34*49149Sbostic 	char *str;
35*49149Sbostic 	int how;
36*49149Sbostic {
37*49149Sbostic 	static int firstopen = 1;
38*49149Sbostic 	register struct iob *file;
39*49149Sbostic 	register char *t;
40*49149Sbostic 	register int cnt;
41*49149Sbostic 	int fdesc, args[8], *argp;
42*49149Sbostic 
43*49149Sbostic 	if (firstopen) {
44*49149Sbostic 		for (cnt = 0; cnt < SOPEN_MAX; cnt++)
45*49149Sbostic 			iob[cnt].i_flgs = 0;
46*49149Sbostic 		firstopen = 0;
47*49149Sbostic 	}
48*49149Sbostic 
49*49149Sbostic 	for (fdesc = 0;; fdesc++) {
50*49149Sbostic 		if (fdesc == SOPEN_MAX)
51*49149Sbostic 			_stop("No more file slots");
52*49149Sbostic 		if (iob[fdesc].i_flgs == 0) {
53*49149Sbostic 			file = &iob[fdesc];
54*49149Sbostic 			file->i_flgs |= F_ALLOC;
55*49149Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
56*49149Sbostic 			    file->i_part = 0;
57*49149Sbostic 			break;
58*49149Sbostic 		}
59*49149Sbostic 	}
60*49149Sbostic 
61*49149Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
62*49149Sbostic #ifndef SMALL
63*49149Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
64*49149Sbostic 		if (isupper(*t))
65*49149Sbostic 			*t = tolower(*t);
66*49149Sbostic 	switch(*t) {
67*49149Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
68*49149Sbostic 		if ((file->i_dev = getdev(str, t - str)) == -1)
69*49149Sbostic 			goto bad;
70*49149Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
71*49149Sbostic 			for (++t; isspace(*t); ++t);
72*49149Sbostic 			if (*t == ')')
73*49149Sbostic 				break;
74*49149Sbostic 			if (!isdigit(*t))
75*49149Sbostic 				goto badspec;
76*49149Sbostic 			*argp++ = atoi(t);
77*49149Sbostic 			for (++t; isdigit(*t); ++t);
78*49149Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
79*49149Sbostic 				goto badspec;
80*49149Sbostic 		}
81*49149Sbostic 		for (++t; isspace(*t); ++t);
82*49149Sbostic 		argp -= 4;
83*49149Sbostic 		file->i_adapt = *argp++;
84*49149Sbostic 		file->i_ctlr = *argp++;
85*49149Sbostic 		file->i_unit = *argp++;
86*49149Sbostic 		file->i_part = *argp;
87*49149Sbostic 		break;
88*49149Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
89*49149Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
90*49149Sbostic 		if ((file->i_dev = getdev(str, t - str)) == -1)
91*49149Sbostic 			goto bad;
92*49149Sbostic 		if ((file->i_unit = getunit(t)) == -1)
93*49149Sbostic 			goto bad;
94*49149Sbostic 		for (; isdigit(*t); ++t);
95*49149Sbostic 		if (*t >= 'a' && *t <= 'h')
96*49149Sbostic 			file->i_part = *t++ - 'a';
97*49149Sbostic 		if (*t != ':') {
98*49149Sbostic 			errno = EOFFSET;
99*49149Sbostic 			goto badspec;
100*49149Sbostic 		}
101*49149Sbostic 		for (++t; isspace(*t); ++t);
102*49149Sbostic 		break;
103*49149Sbostic 	case '/':
104*49149Sbostic 	default:		/* default bootstrap unit and device */
105*49149Sbostic #else
106*49149Sbostic 	{
107*49149Sbostic #endif /* SMALL */
108*49149Sbostic 		file->i_dev = B_TYPE(bootdev);
109*49149Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
110*49149Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
111*49149Sbostic 		file->i_unit = B_UNIT(bootdev);
112*49149Sbostic 		file->i_part = B_PARTITION(bootdev);
113*49149Sbostic 		t = str;
114*49149Sbostic 	}
115*49149Sbostic 
116*49149Sbostic 	opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr,
117*49149Sbostic 	    file->i_unit, file->i_part);
118*49149Sbostic 
119*49149Sbostic 	if (errno = devopen(file))
120*49149Sbostic 		goto bad;
121*49149Sbostic 
122*49149Sbostic 	if (*t == '\0') {
123*49149Sbostic 		file->i_flgs |= how + 1;
124*49149Sbostic 		file->i_cc = 0;
125*49149Sbostic 		file->i_offset = 0;
126*49149Sbostic 		return (fdesc+3);
127*49149Sbostic 	}
128*49149Sbostic #ifndef SMALL
129*49149Sbostic 	else if (how != 0) {
130*49149Sbostic 		printf("Can't write files yet.. Sorry\n");
131*49149Sbostic 		errno = EIO;
132*49149Sbostic 		goto bad;
133*49149Sbostic 	}
134*49149Sbostic #endif
135*49149Sbostic 	file->i_ma = (char *)(&file->i_fs);
136*49149Sbostic 	file->i_cc = SBSIZE;
137*49149Sbostic 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
138*49149Sbostic 	file->i_offset = 0;
139*49149Sbostic 	if (devread(file) < 0) {
140*49149Sbostic 		errno = file->i_error;
141*49149Sbostic 		printf("super block read error\n");
142*49149Sbostic 		goto bad;
143*49149Sbostic 	}
144*49149Sbostic 	if ((cnt = find(t, file)) == 0) {
145*49149Sbostic 		errno = ESRCH;
146*49149Sbostic 		goto bad;
147*49149Sbostic 	}
148*49149Sbostic 	if (openi(cnt, file) < 0) {
149*49149Sbostic 		errno = file->i_error;
150*49149Sbostic 		goto bad;
151*49149Sbostic 	}
152*49149Sbostic 	file->i_offset = 0;
153*49149Sbostic 	file->i_cc = 0;
154*49149Sbostic 	file->i_flgs |= F_FILE | (how+1);
155*49149Sbostic 	return (fdesc+3);
156*49149Sbostic 
157*49149Sbostic #ifndef SMALL
158*49149Sbostic badspec:
159*49149Sbostic 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n");
160*49149Sbostic #endif
161*49149Sbostic bad:
162*49149Sbostic 	file->i_flgs = 0;
163*49149Sbostic 	return (-1);
164*49149Sbostic }
165*49149Sbostic 
166*49149Sbostic #ifndef SMALL
167*49149Sbostic static
168*49149Sbostic getdev(str, len)
169*49149Sbostic 	register char *str;
170*49149Sbostic 	int len;
171*49149Sbostic {
172*49149Sbostic 	register struct devsw *dp;
173*49149Sbostic 	register int i;
174*49149Sbostic 	char savedch = str[len];
175*49149Sbostic 
176*49149Sbostic 	str[len] = '\0';
177*49149Sbostic 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
178*49149Sbostic 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
179*49149Sbostic 			str[len] = savedch;
180*49149Sbostic 			return (i);
181*49149Sbostic 		}
182*49149Sbostic 	printf("Unknown device\nKnown devices are:\n");
183*49149Sbostic 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
184*49149Sbostic 		if (dp->dv_name)
185*49149Sbostic 			printf(" %s", dp->dv_name);
186*49149Sbostic 	printf("\n");
187*49149Sbostic 	errno = ENXIO;
188*49149Sbostic 	return (-1);
189*49149Sbostic }
190*49149Sbostic 
191*49149Sbostic static
192*49149Sbostic getunit(cp)
193*49149Sbostic 	register char *cp;
194*49149Sbostic {
195*49149Sbostic 	int unit;
196*49149Sbostic 
197*49149Sbostic 	unit = atoi(cp);
198*49149Sbostic 	if ((u_int)unit > 255) {
199*49149Sbostic 		printf("minor device number out of range (0-255)\n");
200*49149Sbostic 		errno = EUNIT;
201*49149Sbostic 		return (-1);
202*49149Sbostic 	}
203*49149Sbostic 	return (unit);
204*49149Sbostic }
205*49149Sbostic #endif /* SMALL */
206*49149Sbostic 
207*49149Sbostic static
208*49149Sbostic find(path, file)
209*49149Sbostic 	register char *path;
210*49149Sbostic 	struct iob *file;
211*49149Sbostic {
212*49149Sbostic 	register char *q;
213*49149Sbostic 	char *dir, c;
214*49149Sbostic 	int n;
215*49149Sbostic 
216*49149Sbostic 	if (path == NULL || *path == '\0') {
217*49149Sbostic 		printf("null path\n");
218*49149Sbostic 		return (0);
219*49149Sbostic 	}
220*49149Sbostic 
221*49149Sbostic 	if (openi((ino_t) ROOTINO, file) < 0) {
222*49149Sbostic 		printf("can't read root inode\n");
223*49149Sbostic 		return (0);
224*49149Sbostic 	}
225*49149Sbostic 	dir = path;
226*49149Sbostic 	while (*path) {
227*49149Sbostic 		while (*path == '/')
228*49149Sbostic 			path++;
229*49149Sbostic 		q = path;
230*49149Sbostic 		while(*q != '/' && *q != '\0')
231*49149Sbostic 			q++;
232*49149Sbostic 		c = *q;
233*49149Sbostic 		*q = '\0';
234*49149Sbostic 		if (q == path) path = "." ;	/* "/" means "/." */
235*49149Sbostic 
236*49149Sbostic 		if ((n = dlook(path, file, dir)) != 0) {
237*49149Sbostic 			if (c == '\0')
238*49149Sbostic 				break;
239*49149Sbostic 			if (openi(n, file) < 0)
240*49149Sbostic 				return (0);
241*49149Sbostic 			*q = c;
242*49149Sbostic 			path = q;
243*49149Sbostic 			continue;
244*49149Sbostic 		} else {
245*49149Sbostic 			printf("%s: not found\n", path);
246*49149Sbostic 			return (0);
247*49149Sbostic 		}
248*49149Sbostic 	}
249*49149Sbostic 	return (n);
250*49149Sbostic }
251*49149Sbostic 
252*49149Sbostic static ino_t
253*49149Sbostic dlook(s, io, dir)
254*49149Sbostic 	char *s;
255*49149Sbostic 	register struct iob *io;
256*49149Sbostic 	char *dir;
257*49149Sbostic {
258*49149Sbostic 	register struct direct *dp;
259*49149Sbostic 	register struct dinode *ip;
260*49149Sbostic 	struct dirstuff dirp;
261*49149Sbostic 	int len;
262*49149Sbostic 
263*49149Sbostic 	if (s == NULL || *s == '\0')
264*49149Sbostic 		return (0);
265*49149Sbostic 	ip = &io->i_ino;
266*49149Sbostic 	if ((ip->di_mode&IFMT) != IFDIR) {
267*49149Sbostic 		printf("%s: not a directory\n", dir);
268*49149Sbostic 		return (0);
269*49149Sbostic 	}
270*49149Sbostic 	if (ip->di_size == 0) {
271*49149Sbostic 		printf("%s: zero length directory\n", dir);
272*49149Sbostic 		return (0);
273*49149Sbostic 	}
274*49149Sbostic 	len = strlen(s);
275*49149Sbostic 	dirp.loc = 0;
276*49149Sbostic 	dirp.io = io;
277*49149Sbostic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
278*49149Sbostic 		if(dp->d_ino == 0)
279*49149Sbostic 			continue;
280*49149Sbostic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
281*49149Sbostic 			return (dp->d_ino);
282*49149Sbostic 	}
283*49149Sbostic 	return (0);
284*49149Sbostic }
285*49149Sbostic 
286*49149Sbostic static struct direct *
287*49149Sbostic readdir(dirp)
288*49149Sbostic 	register struct dirstuff *dirp;
289*49149Sbostic {
290*49149Sbostic 	register struct direct *dp;
291*49149Sbostic 	register struct iob *io;
292*49149Sbostic 	daddr_t lbn, d;
293*49149Sbostic 	int off;
294*49149Sbostic 
295*49149Sbostic 	io = dirp->io;
296*49149Sbostic 	for(;;) {
297*49149Sbostic 		if (dirp->loc >= io->i_ino.di_size)
298*49149Sbostic 			return (NULL);
299*49149Sbostic 		off = blkoff(&io->i_fs, dirp->loc);
300*49149Sbostic 		if (off == 0) {
301*49149Sbostic 			lbn = lblkno(&io->i_fs, dirp->loc);
302*49149Sbostic 			d = bmap(io, lbn);
303*49149Sbostic 			if(d == 0)
304*49149Sbostic 				return (NULL);
305*49149Sbostic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
306*49149Sbostic 			io->i_ma = io->i_buf;
307*49149Sbostic 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
308*49149Sbostic 			if (devread(io) < 0) {
309*49149Sbostic 				errno = io->i_error;
310*49149Sbostic 				printf("bn %D: directory read error\n",
311*49149Sbostic 					io->i_bn);
312*49149Sbostic 				return (NULL);
313*49149Sbostic 			}
314*49149Sbostic 		}
315*49149Sbostic 		dp = (struct direct *)(io->i_buf + off);
316*49149Sbostic 		dirp->loc += dp->d_reclen;
317*49149Sbostic 		if (dp->d_ino == 0)
318*49149Sbostic 			continue;
319*49149Sbostic 		return (dp);
320*49149Sbostic 	}
321*49149Sbostic }
322*49149Sbostic 
323*49149Sbostic static
324*49149Sbostic openi(n, io)
325*49149Sbostic 	int n;
326*49149Sbostic 	register struct iob *io;
327*49149Sbostic {
328*49149Sbostic 	register struct dinode *dp;
329*49149Sbostic 	int cc;
330*49149Sbostic 
331*49149Sbostic 	io->i_offset = 0;
332*49149Sbostic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
333*49149Sbostic 	io->i_cc = io->i_fs.fs_bsize;
334*49149Sbostic 	io->i_ma = io->i_buf;
335*49149Sbostic 	cc = devread(io);
336*49149Sbostic 	dp = (struct dinode *)io->i_buf;
337*49149Sbostic 	io->i_ino = dp[itoo(&io->i_fs, n)];
338*49149Sbostic 	return (cc);
339*49149Sbostic }
340*49149Sbostic 
341