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