xref: /csrg-svn/sys/tahoe/stand/sys.c (revision 25871)
1 /*	sys.c	1.1	86/01/12	*/
2 /*	sys.c	6.2	83/09/23	*/
3 
4 #include "../machine/mtpr.h"
5 
6 #include "param.h"
7 #include "inode.h"
8 #include "fs.h"
9 #include "dir.h"
10 
11 #include "saio.h"
12 
13 ino_t	dlook();
14 
15 struct dirstuff {
16 	int loc;
17 	struct iob *io;
18 };
19 
20 static
21 openi(n, io)
22 	register struct iob *io;
23 {
24 	register struct dinode *dp;
25 	int cc;
26 
27 	io->i_offset = 0;
28 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
29 	io->i_cc = io->i_fs.fs_bsize;
30 	io->i_ma = io->i_buf;
31 	cc = devread(io);
32 	dp = (struct dinode *)io->i_buf;
33 	io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
34 	return (cc);
35 }
36 
37 static
38 find(path, file)
39 	register char *path;
40 	struct iob *file;
41 {
42 	register char *q;
43 	char c;
44 	int n;
45 
46 	if (path==NULL || *path=='\0') {
47 		printf("null path\n");
48 		return (0);
49 	}
50 
51 	if (openi((ino_t) ROOTINO, file) < 0) {
52 		printf("can't read root inode\n");
53 		return (0);
54 	}
55 	while (*path) {
56 		while (*path == '/')
57 			path++;
58 		q = path;
59 		while(*q != '/' && *q != '\0')
60 			q++;
61 		c = *q;
62 		*q = '\0';
63 
64 		if ((n = dlook(path, file)) != 0) {
65 			if (c == '\0')
66 				break;
67 			if (openi(n, file) < 0)
68 				return (0);
69 			*q = c;
70 			path = q;
71 			continue;
72 		} else {
73 			printf("%s not found\n", path);
74 			return (0);
75 		}
76 	}
77 	return (n);
78 }
79 
80 static daddr_t
81 sbmap(io, bn)
82 	register struct iob *io;
83 	daddr_t bn;
84 {
85 	register struct inode *ip;
86 	int i, j, sh;
87 	daddr_t nb, *bap;
88 
89 	ip = &io->i_ino;
90 	if (bn < 0) {
91 		printf("bn negative\n");
92 		return ((daddr_t)0);
93 	}
94 
95 	/*
96 	 * blocks 0..NDADDR are direct blocks
97 	 */
98 	if(bn < NDADDR) {
99 		nb = ip->i_db[bn];
100 		return (nb);
101 	}
102 
103 	/*
104 	 * addresses NIADDR have single and double indirect blocks.
105 	 * the first step is to determine how many levels of indirection.
106 	 */
107 	sh = 1;
108 	bn -= NDADDR;
109 	for (j = NIADDR; j > 0; j--) {
110 		sh *= NINDIR(&io->i_fs);
111 		if (bn < sh)
112 			break;
113 		bn -= sh;
114 	}
115 	if (j == 0) {
116 		printf("bn ovf %D\n", bn);
117 		return ((daddr_t)0);
118 	}
119 
120 	/*
121 	 * fetch the first indirect block address from the inode
122 	 */
123 	nb = ip->i_ib[NIADDR - j];
124 	if (nb == 0) {
125 		printf("bn void %D\n",bn);
126 		return ((daddr_t)0);
127 	}
128 
129 	/*
130 	 * fetch through the indirect blocks
131 	 */
132 	for (; j <= NIADDR; j++) {
133 		if (blknos[j] != nb) {
134 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
135 			io->i_ma = b[j];
136 			io->i_cc = io->i_fs.fs_bsize;
137 			if (devread(io) != io->i_fs.fs_bsize) {
138 				if (io->i_error)
139 					errno = io->i_error;
140 				printf("bn %D: read error\n", io->i_bn);
141 				return ((daddr_t)0);
142 			}
143 			blknos[j] = nb;
144 		}
145 		bap = (daddr_t *)b[j];
146 		sh /= NINDIR(&io->i_fs);
147 		i = (bn / sh) % NINDIR(&io->i_fs);
148 		nb = bap[i];
149 		if(nb == 0) {
150 			printf("bn void %D\n",bn);
151 			return ((daddr_t)0);
152 		}
153 	}
154 	return (nb);
155 }
156 
157 static ino_t
158 dlook(s, io)
159 	char *s;
160 	register struct iob *io;
161 {
162 	register struct direct *dp;
163 	register struct inode *ip;
164 	struct dirstuff dirp;
165 	int len;
166 
167 	if (s == NULL || *s == '\0')
168 		return (0);
169 	ip = &io->i_ino;
170 	if ((ip->i_mode&IFMT) != IFDIR) {
171 		printf("not a directory\n");
172 		return (0);
173 	}
174 	if (ip->i_size == 0) {
175 		printf("zero length directory\n");
176 		return (0);
177 	}
178 	len = strlen(s);
179 	dirp.loc = 0;
180 	dirp.io = io;
181 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
182 		if(dp->d_ino == 0)
183 			continue;
184 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
185 			return (dp->d_ino);
186 	}
187 	return (0);
188 }
189 
190 /*
191  * get next entry in a directory.
192  */
193 struct direct *
194 readdir(dirp)
195 	register struct dirstuff *dirp;
196 {
197 	register struct direct *dp;
198 	register struct iob *io;
199 	daddr_t lbn, d;
200 	int off;
201 
202 	io = dirp->io;
203 	for(;;) {
204 		if (dirp->loc >= io->i_ino.i_size)
205 			return (NULL);
206 		off = blkoff(&io->i_fs, dirp->loc);
207 		if (off == 0) {
208 			lbn = lblkno(&io->i_fs, dirp->loc);
209 			d = sbmap(io, lbn);
210 			if(d == 0)
211 				return NULL;
212 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
213 			io->i_ma = io->i_buf;
214 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
215 			if (devread(io) < 0) {
216 				errno = io->i_error;
217 				printf("bn %D: read error\n", io->i_bn);
218 				return (NULL);
219 			}
220 		}
221 		dp = (struct direct *)(io->i_buf + off);
222 		dirp->loc += dp->d_reclen;
223 		if (dp->d_ino == 0)
224 			continue;
225 		return (dp);
226 	}
227 }
228 
229 lseek(fdesc, addr, ptr)
230 	int fdesc, ptr;
231 	off_t addr;
232 {
233 	register struct iob *io;
234 
235 	if (ptr != 0) {
236 		printf("Seek not from beginning of file\n");
237 		errno = EOFFSET;
238 		return (-1);
239 	}
240 	fdesc -= 3;
241 	if (fdesc < 0 || fdesc >= NFILES ||
242 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
243 		errno = EBADF;
244 		return (-1);
245 	}
246 	io->i_offset = addr;
247 	io->i_bn = addr / DEV_BSIZE;
248 	io->i_cc = 0;
249 	return (0);
250 }
251 
252 getc(fdesc)
253 	int fdesc;
254 {
255 	register struct iob *io;
256 	register struct fs *fs;
257 	register char *p;
258 	int c, lbn, off, size, diff;
259 
260 
261 	if (fdesc >= 0 && fdesc <= 2)
262 		return (getchar());
263 	fdesc -= 3;
264 	if (fdesc < 0 || fdesc >= NFILES ||
265 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
266 		errno = EBADF;
267 		return (-1);
268 	}
269 	p = io->i_ma;
270 	if (io->i_cc <= 0) {
271 		if ((io->i_flgs & F_FILE) != 0) {
272 			diff = io->i_ino.i_size - io->i_offset;
273 			if (diff <= 0)
274 				return (-1);
275 			fs = &io->i_fs;
276 			lbn = lblkno(fs, io->i_offset);
277 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
278 			off = blkoff(fs, io->i_offset);
279 			size = blksize(fs, &io->i_ino, lbn);
280 		} else {
281 			io->i_bn = io->i_offset / DEV_BSIZE;
282 			off = 0;
283 			size = DEV_BSIZE;
284 		}
285 		io->i_ma = io->i_buf;
286 		io->i_cc = size;
287 		if (devread(io) < 0) {
288 			errno = io->i_error;
289 			return (-1);
290 		}
291 		if ((io->i_flgs & F_FILE) != 0) {
292 			if (io->i_offset - off + size >= io->i_ino.i_size)
293 				io->i_cc = diff + off;
294 			io->i_cc -= off;
295 		}
296 		p = &io->i_buf[off];
297 	}
298 	io->i_cc--;
299 	io->i_offset++;
300 	c = (unsigned)*p++;
301 	io->i_ma = p;
302 	return (c);
303 }
304 
305 /* does this port?
306 getw(fdesc)
307 	int fdesc;
308 {
309 	register w,i;
310 	int val;
311 
312 	for (i = 0, val = 0; i < sizeof(val); i++) {
313 		w = getc(fdesc);
314 		if (w < 0) {
315 			if (i == 0)
316 				return (-1);
317 			else
318 				return (val);
319 		}
320 		val = (val << 8) | (w & 0xff);
321 	}
322 	return (val);
323 }
324 */
325 int	errno;
326 
327 read(fdesc, buf, count)
328 	int fdesc, count;
329 	char *buf;
330 {
331 	register i;
332 	register struct iob *file;
333 
334 	errno = 0;
335 	if (fdesc >= 0 && fdesc <= 2) {
336 		i = count;
337 		do {
338 			*buf = getchar();
339 		} while (--i && *buf++ != '\n');
340 		return (count - i);
341 	}
342 	fdesc -= 3;
343 	if (fdesc < 0 || fdesc >= NFILES ||
344 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
345 		errno = EBADF;
346 		return (-1);
347 	}
348 	if ((file->i_flgs&F_READ) == 0) {
349 		errno = EBADF;
350 		return (-1);
351 	}
352 	if ((file->i_flgs & F_FILE) == 0) {
353 		file->i_cc = count;
354 		file->i_ma = buf;
355 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
356 		i = devread(file);
357 		file->i_offset += count;
358 		if (i < 0)
359 			errno = file->i_error;
360 		return (i);
361 	} else {
362 		if (file->i_offset+count > file->i_ino.i_size)
363 			count = file->i_ino.i_size - file->i_offset;
364 		if ((i = count) <= 0)
365 			return (0);
366 		do {
367 			*buf++ = getc(fdesc+3);
368 		} while (--i);
369 		return (count);
370 	}
371 }
372 
373 write(fdesc, buf, count)
374 	int fdesc, count;
375 	char *buf;
376 {
377 	register i;
378 	register struct iob *file;
379 
380 	errno = 0;
381 	if (fdesc >= 0 && fdesc <= 2) {
382 		i = count;
383 		while (i--)
384 			putchar(*buf++);
385 		return (count);
386 	}
387 	fdesc -= 3;
388 	if (fdesc < 0 || fdesc >= NFILES ||
389 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
390 		errno = EBADF;
391 		return (-1);
392 	}
393 	if ((file->i_flgs&F_WRITE) == 0) {
394 		errno = EBADF;
395 		return (-1);
396 	}
397 	file->i_cc = count;
398 	file->i_ma = buf;
399 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
400 	i = devwrite(file);
401 	file->i_offset += count;
402 	if (i < 0)
403 		errno = file->i_error;
404 	return (i);
405 }
406 
407 int	openfirst = 1;
408 
409 open(str, how)
410 	char *str;
411 	int how;
412 {
413 	register char *cp;
414 	int i;
415 	register struct iob *file;
416 	register struct devsw *dp;
417 	int fdesc;
418 	long atol();
419 
420 	if (openfirst) {
421 		for (i = 0; i < NFILES; i++)
422 			iob[i].i_flgs = 0;
423 		openfirst = 0;
424 	}
425 
426 	for (fdesc = 0; fdesc < NFILES; fdesc++)
427 		if (iob[fdesc].i_flgs == 0)
428 			goto gotfile;
429 	_stop("No more file slots");
430 gotfile:
431 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
432 
433 	for (cp = str; *cp && *cp != '('; cp++)
434 			;
435 	if (*cp != '(') {
436 		printf("Bad device\n");
437 		file->i_flgs = 0;
438 		errno = EDEV;
439 		return (-1);
440 	}
441 	*cp++ = '\0';
442 	for (dp = devsw; dp->dv_name; dp++) {
443 		if (!strcmp(str, dp->dv_name))
444 			goto gotdev;
445 	}
446 	printf("Unknown device\n");
447 	file->i_flgs = 0;
448 	errno = ENXIO;
449 	return (-1);
450 gotdev:
451 	*(cp-1) = '(';
452 	file->i_ino.i_dev = dp-devsw;
453 	file->i_unit = *cp++ - '0';
454 	if (*cp >= '0' && *cp <= '9')
455 		file->i_unit = file->i_unit * 10 + *cp++ - '0';
456 	if (file->i_unit < 0 || file->i_unit > 63) {
457 		printf("Bad unit specifier\n");
458 		file->i_flgs = 0;
459 		errno = EUNIT;
460 		return (-1);
461 	}
462 	if (*cp++ != ',') {
463 badoff:
464 		printf("Missing offset specification\n");
465 		file->i_flgs = 0;
466 		errno = EOFFSET;
467 		return (-1);
468 	}
469 	file->i_boff = atol(cp);
470 	for (;;) {
471 		if (*cp == ')')
472 			break;
473 		if (*cp++)
474 			continue;
475 		goto badoff;
476 	}
477 	file->i_flgs |= how+1;
478 	devopen(file);
479 	if (*++cp == '\0') {
480 		file->i_cc = 0;
481 		file->i_offset = 0;
482 		return (fdesc+3);
483 	}
484 	file->i_ma = (char *)(&file->i_fs);
485 	file->i_cc = SBSIZE;
486 	file->i_bn = SBLOCK + file->i_boff;
487 	file->i_offset = 0;
488 	if (devread(file) < 0) {
489 		errno = file->i_error;
490 		printf("super block read error\n");
491 		file->i_flgs = 0;
492 		return (-1);
493 	}
494 	if ((i = find(cp, file)) == 0) {
495 		file->i_flgs = 0;
496 		errno = ESRCH;
497 		return (-1);
498 	}
499 	if (how != 0) {
500 		printf("Can't write files yet.. Sorry\n");
501 		file->i_flgs = 0;
502 		errno = EIO;
503 		return (-1);
504 	}
505 	if (openi(i, file) < 0) {
506 		errno = file->i_error;
507 		file->i_flgs = 0;
508 		return (-1);
509 	}
510 	file->i_offset = 0;
511 	file->i_cc = 0;
512 	file->i_flgs |= F_FILE | (how+1);
513 	return (fdesc+3);
514 }
515 
516 close(fdesc)
517 	int fdesc;
518 {
519 	struct iob *file;
520 
521 	fdesc -= 3;
522 	if (fdesc < 0 || fdesc >= NFILES ||
523 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
524 		errno = EBADF;
525 		return (-1);
526 	}
527 	if ((file->i_flgs&F_FILE) == 0)
528 		devclose(file);
529 	file->i_flgs = 0;
530 	return (0);
531 }
532 
533 
534 exit()
535 {
536 	_stop("Exit called");
537 }
538 
539 _stop(s)
540 	char *s;
541 {
542 	int i;
543 
544 	for (i = 0; i < NFILES; i++)
545 		if (iob[i].i_flgs != 0)
546 			close(i);
547 	printf("%s\n", s);
548 	_rtt();
549 }
550 
551 trap(ps)
552 	int ps;
553 {
554 	printf("Trap %o\n", ps);
555 	for (;;)
556 		;
557 }
558 
559 uncache (addr)
560 	char *addr;
561 {
562 	/* Return *(addr-0x4000); DIRTY assumes this address is valid */
563 	mtpr(PDCS, addr);
564 }
565