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