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