xref: /original-bsd/sys/stand.att/open.c (revision 27427f15)
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.7 (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 static
220 atoi(cp)
221 	char *cp;
222 {
223 	int val = 0;
224 
225 	while (*cp >= '0' && *cp <= '9')
226 		val = val * 10 + (*cp++ - '0');
227 	return (val);
228 }
229 #endif /* SMALL */
230 
231 static
232 find(path, file)
233 	register char *path;
234 	struct iob *file;
235 {
236 	register char *q;
237 	char *dir, c;
238 	int n;
239 
240 	if (path == NULL || *path == '\0') {
241 		printf("null path\n");
242 		return (0);
243 	}
244 
245 	if (openi((ino_t) ROOTINO, file) < 0) {
246 		printf("can't read root inode\n");
247 		return (0);
248 	}
249 	dir = path;
250 	while (*path) {
251 		while (*path == '/')
252 			path++;
253 		q = path;
254 		while(*q != '/' && *q != '\0')
255 			q++;
256 		c = *q;
257 		*q = '\0';
258 		if (q == path) path = "." ;	/* "/" means "/." */
259 
260 		if ((n = dlook(path, file, dir)) != 0) {
261 			if (c == '\0')
262 				break;
263 			if (openi(n, file) < 0)
264 				return (0);
265 			*q = c;
266 			path = q;
267 			continue;
268 		} else {
269 			printf("%s: not found\n", path);
270 			return (0);
271 		}
272 	}
273 	return (n);
274 }
275 
276 static ino_t
277 dlook(s, io, dir)
278 	char *s;
279 	register struct iob *io;
280 	char *dir;
281 {
282 	register struct direct *dp;
283 	register struct dinode *ip;
284 	struct dirstuff dirp;
285 	int len;
286 
287 	if (s == NULL || *s == '\0')
288 		return (0);
289 	ip = &io->i_ino;
290 	if ((ip->di_mode&IFMT) != IFDIR) {
291 		printf("%s: not a directory\n", dir);
292 		return (0);
293 	}
294 	if (ip->di_size == 0) {
295 		printf("%s: zero length directory\n", dir);
296 		return (0);
297 	}
298 	len = strlen(s);
299 	dirp.loc = 0;
300 	dirp.io = io;
301 	dirp.name = dir;
302 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
303 		if(dp->d_ino == 0)
304 			continue;
305 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
306 			return (dp->d_ino);
307 	}
308 	return (0);
309 }
310 
311 static struct direct *
312 readdir(dirp)
313 	register struct dirstuff *dirp;
314 {
315 	register struct direct *dp;
316 	register struct iob *io;
317 	daddr_t lbn, d;
318 	int off;
319 
320 	io = dirp->io;
321 	for(;;) {
322 		if (dirp->loc >= io->i_ino.di_size)
323 			return (NULL);
324 		off = blkoff(&io->i_fs, dirp->loc);
325 		if (off == 0) {
326 			lbn = lblkno(&io->i_fs, dirp->loc);
327 			d = bmap(io, lbn);
328 			if(d == 0)
329 				return (NULL);
330 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
331 			io->i_ma = io->i_buf;
332 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
333 			if (devread(io) < 0) {
334 				errno = io->i_error;
335 				printf("%s: directory read error, bn %ld\n",
336 					dirp->name, io->i_bn);
337 				return (NULL);
338 			}
339 		}
340 		dp = (struct direct *)(io->i_buf + off);
341 		dirp->loc += dp->d_reclen;
342 		if (dp->d_ino == 0) {
343 			if (dp->d_reclen == 0) {
344 				printf("%s: bad directory entry, offset %ld\n",
345 				       dirp->name, dirp->loc);
346 				return (NULL);
347 			}
348 			continue;
349 		}
350 		return (dp);
351 	}
352 }
353 
354 static
355 openi(n, io)
356 	int n;
357 	register struct iob *io;
358 {
359 	register struct dinode *dp;
360 	int cc;
361 
362 	io->i_offset = 0;
363 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
364 	io->i_cc = io->i_fs.fs_bsize;
365 	io->i_ma = io->i_buf;
366 	cc = devread(io);
367 	dp = (struct dinode *)io->i_buf;
368 	io->i_ino = dp[itoo(&io->i_fs, n)];
369 	return (cc);
370 }
371