xref: /csrg-svn/sys/stand.att/sys.c (revision 29310)
1 /*
2  * Copyright (c) 1982, 1986 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	7.1 (Berkeley) 06/05/86
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 		if (q == path) path = "." ;	/* "/" means "/." */
66 
67 		if ((n = dlook(path, file)) != 0) {
68 			if (c == '\0')
69 				break;
70 			if (openi(n, file) < 0)
71 				return (0);
72 			*q = c;
73 			path = q;
74 			continue;
75 		} else {
76 			printf("%s: not found\n", path);
77 			return (0);
78 		}
79 	}
80 	return (n);
81 }
82 
83 static daddr_t
84 sbmap(io, bn)
85 	register struct iob *io;
86 	daddr_t bn;
87 {
88 	register struct inode *ip;
89 	int i, j, sh;
90 	daddr_t nb, *bap;
91 
92 	ip = &io->i_ino;
93 	if (bn < 0) {
94 		printf("bn negative\n");
95 		return ((daddr_t)0);
96 	}
97 
98 	/*
99 	 * blocks 0..NDADDR are direct blocks
100 	 */
101 	if(bn < NDADDR) {
102 		nb = ip->i_db[bn];
103 		return (nb);
104 	}
105 
106 	/*
107 	 * addresses NIADDR have single and double indirect blocks.
108 	 * the first step is to determine how many levels of indirection.
109 	 */
110 	sh = 1;
111 	bn -= NDADDR;
112 	for (j = NIADDR; j > 0; j--) {
113 		sh *= NINDIR(&io->i_fs);
114 		if (bn < sh)
115 			break;
116 		bn -= sh;
117 	}
118 	if (j == 0) {
119 		printf("bn ovf %D\n", bn);
120 		return ((daddr_t)0);
121 	}
122 
123 	/*
124 	 * fetch the first indirect block address from the inode
125 	 */
126 	nb = ip->i_ib[NIADDR - j];
127 	if (nb == 0) {
128 		printf("bn void %D\n",bn);
129 		return ((daddr_t)0);
130 	}
131 
132 	/*
133 	 * fetch through the indirect blocks
134 	 */
135 	for (; j <= NIADDR; j++) {
136 		if (blknos[j] != nb) {
137 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
138 			io->i_ma = b[j];
139 			io->i_cc = io->i_fs.fs_bsize;
140 			if (devread(io) != io->i_fs.fs_bsize) {
141 				if (io->i_error)
142 					errno = io->i_error;
143 				printf("bn %D: read error\n", io->i_bn);
144 				return ((daddr_t)0);
145 			}
146 			blknos[j] = nb;
147 		}
148 		bap = (daddr_t *)b[j];
149 		sh /= NINDIR(&io->i_fs);
150 		i = (bn / sh) % NINDIR(&io->i_fs);
151 		nb = bap[i];
152 		if(nb == 0) {
153 			printf("bn void %D\n",bn);
154 			return ((daddr_t)0);
155 		}
156 	}
157 	return (nb);
158 }
159 
160 static ino_t
161 dlook(s, io)
162 	char *s;
163 	register struct iob *io;
164 {
165 	register struct direct *dp;
166 	register struct inode *ip;
167 	struct dirstuff dirp;
168 	int len;
169 
170 	if (s == NULL || *s == '\0')
171 		return (0);
172 	ip = &io->i_ino;
173 	if ((ip->i_mode&IFMT) != IFDIR) {
174 		printf("not a directory\n");
175 		printf("%s: not a directory\n", s);
176 		return (0);
177 	}
178 	if (ip->i_size == 0) {
179 		printf("%s: zero length directory\n", s);
180 		return (0);
181 	}
182 	len = strlen(s);
183 	dirp.loc = 0;
184 	dirp.io = io;
185 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
186 		if(dp->d_ino == 0)
187 			continue;
188 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
189 			return (dp->d_ino);
190 	}
191 	return (0);
192 }
193 
194 /*
195  * get next entry in a directory.
196  */
197 struct direct *
198 readdir(dirp)
199 	register struct dirstuff *dirp;
200 {
201 	register struct direct *dp;
202 	register struct iob *io;
203 	daddr_t lbn, d;
204 	int off;
205 
206 	io = dirp->io;
207 	for(;;) {
208 		if (dirp->loc >= io->i_ino.i_size)
209 			return (NULL);
210 		off = blkoff(&io->i_fs, dirp->loc);
211 		if (off == 0) {
212 			lbn = lblkno(&io->i_fs, dirp->loc);
213 			d = sbmap(io, lbn);
214 			if(d == 0)
215 				return NULL;
216 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
217 			io->i_ma = io->i_buf;
218 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
219 			if (devread(io) < 0) {
220 				errno = io->i_error;
221 				printf("bn %D: directory read error\n",
222 					io->i_bn);
223 				return (NULL);
224 			}
225 		}
226 		dp = (struct direct *)(io->i_buf + off);
227 		dirp->loc += dp->d_reclen;
228 		if (dp->d_ino == 0)
229 			continue;
230 		return (dp);
231 	}
232 }
233 
234 lseek(fdesc, addr, ptr)
235 	int fdesc, ptr;
236 	off_t addr;
237 {
238 	register struct iob *io;
239 
240 #ifndef	SMALL
241 	if (ptr != 0) {
242 		printf("Seek not from beginning of file\n");
243 		errno = EOFFSET;
244 		return (-1);
245 	}
246 #endif SMALL
247 	fdesc -= 3;
248 	if (fdesc < 0 || fdesc >= NFILES ||
249 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
250 		errno = EBADF;
251 		return (-1);
252 	}
253 	io->i_offset = addr;
254 	io->i_bn = addr / DEV_BSIZE;
255 	io->i_cc = 0;
256 	return (0);
257 }
258 
259 getc(fdesc)
260 	int fdesc;
261 {
262 	register struct iob *io;
263 	register struct fs *fs;
264 	register char *p;
265 	int c, lbn, off, size, diff;
266 
267 
268 	if (fdesc >= 0 && fdesc <= 2)
269 		return (getchar());
270 	fdesc -= 3;
271 	if (fdesc < 0 || fdesc >= NFILES ||
272 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
273 		errno = EBADF;
274 		return (-1);
275 	}
276 	p = io->i_ma;
277 	if (io->i_cc <= 0) {
278 		if ((io->i_flgs & F_FILE) != 0) {
279 			diff = io->i_ino.i_size - io->i_offset;
280 			if (diff <= 0)
281 				return (-1);
282 			fs = &io->i_fs;
283 			lbn = lblkno(fs, io->i_offset);
284 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
285 			off = blkoff(fs, io->i_offset);
286 			size = blksize(fs, &io->i_ino, lbn);
287 		} else {
288 			io->i_bn = io->i_offset / DEV_BSIZE;
289 			off = 0;
290 			size = DEV_BSIZE;
291 		}
292 		io->i_ma = io->i_buf;
293 		io->i_cc = size;
294 		if (devread(io) < 0) {
295 			errno = io->i_error;
296 			return (-1);
297 		}
298 		if ((io->i_flgs & F_FILE) != 0) {
299 			if (io->i_offset - off + size >= io->i_ino.i_size)
300 				io->i_cc = diff + off;
301 			io->i_cc -= off;
302 		}
303 		p = &io->i_buf[off];
304 	}
305 	io->i_cc--;
306 	io->i_offset++;
307 	c = (unsigned)*p++;
308 	io->i_ma = p;
309 	return (c);
310 }
311 
312 int	errno;
313 
314 read(fdesc, buf, count)
315 	int fdesc, count;
316 	char *buf;
317 {
318 	register i, size;
319 	register struct iob *file;
320 	register struct fs *fs;
321 	int lbn, off;
322 
323 	errno = 0;
324 	if (fdesc >= 0 & fdesc <= 2) {
325 		i = count;
326 		do {
327 			*buf = getchar();
328 		} while (--i && *buf++ != '\n');
329 		return (count - i);
330 	}
331 	fdesc -= 3;
332 	if (fdesc < 0 || fdesc >= NFILES ||
333 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
334 		errno = EBADF;
335 		return (-1);
336 	}
337 	if ((file->i_flgs&F_READ) == 0) {
338 		errno = EBADF;
339 		return (-1);
340 	}
341 #ifndef	SMALL
342 	if ((file->i_flgs & F_FILE) == 0) {
343 		file->i_cc = count;
344 		file->i_ma = buf;
345 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
346 		i = devread(file);
347 		file->i_offset += count;
348 		if (i < 0)
349 			errno = file->i_error;
350 		return (i);
351 	}
352 #endif SMALL
353 	if (file->i_offset+count > file->i_ino.i_size)
354 		count = file->i_ino.i_size - file->i_offset;
355 	if ((i = count) <= 0)
356 		return (0);
357 	/*
358 	 * While reading full blocks, do I/O into user buffer.
359 	 * Anything else uses getc().
360 	 */
361 	fs = &file->i_fs;
362 	while (i) {
363 		off = blkoff(fs, file->i_offset);
364 		lbn = lblkno(fs, file->i_offset);
365 		size = blksize(fs, &file->i_ino, lbn);
366 		if (off == 0 && size <= i) {
367 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
368 			    file->i_boff;
369 			file->i_cc = size;
370 			file->i_ma = buf;
371 			if (devread(file) < 0) {
372 				errno = file->i_error;
373 				return (-1);
374 			}
375 			file->i_offset += size;
376 			file->i_cc = 0;
377 			buf += size;
378 			i -= size;
379 		} else {
380 			size -= off;
381 			if (size > i)
382 				size = i;
383 			i -= size;
384 			do {
385 				*buf++ = getc(fdesc+3);
386 			} while (--size);
387 		}
388 	}
389 	return (count);
390 }
391 
392 #ifndef	SMALL
393 write(fdesc, buf, count)
394 	int fdesc, count;
395 	char *buf;
396 {
397 	register i;
398 	register struct iob *file;
399 
400 	errno = 0;
401 	if (fdesc >= 0 && fdesc <= 2) {
402 		i = count;
403 		while (i--)
404 			putchar(*buf++);
405 		return (count);
406 	}
407 	fdesc -= 3;
408 	if (fdesc < 0 || fdesc >= NFILES ||
409 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
410 		errno = EBADF;
411 		return (-1);
412 	}
413 	if ((file->i_flgs&F_WRITE) == 0) {
414 		errno = EBADF;
415 		return (-1);
416 	}
417 	file->i_cc = count;
418 	file->i_ma = buf;
419 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
420 	i = devwrite(file);
421 	file->i_offset += count;
422 	if (i < 0)
423 		errno = file->i_error;
424 	return (i);
425 }
426 #endif SMALL
427 
428 int	openfirst = 1;
429 #ifdef notyet
430 int	opendev;	/* last device opened; for boot to set bootdev */
431 extern	int bootdev;
432 #endif notyet
433 
434 open(str, how)
435 	char *str;
436 	int how;
437 {
438 	register char *cp;
439 	int i;
440 	register struct iob *file;
441 	register struct devsw *dp;
442 	int fdesc;
443 	long atol();
444 
445 	if (openfirst) {
446 		for (i = 0; i < NFILES; i++)
447 			iob[i].i_flgs = 0;
448 		openfirst = 0;
449 	}
450 
451 	for (fdesc = 0; fdesc < NFILES; fdesc++)
452 		if (iob[fdesc].i_flgs == 0)
453 			goto gotfile;
454 	_stop("No more file slots");
455 gotfile:
456 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
457 
458 #ifdef notyet
459 	for (cp = str; *cp && *cp != '/' && *cp != ':'; cp++)
460 			;
461 	if (*cp != ':') {
462 		/* default bootstrap unit and device */
463 		file->i_ino.i_dev = bootdev;
464 		cp = str;
465 	} else {
466 # define isdigit(n)	((n>='0') && (n<='9'))
467 		/*
468 	 	 * syntax for possible device name:
469 	 	 *	<alpha-string><digit-string><letter>:
470 	 	 */
471 		for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
472 			;
473 		for (dp = devsw; dp->dv_name; dp++) {
474 			if (!strncmp(str, dp->dv_name,cp-str))
475 				goto gotdev;
476 		}
477 		printf("unknown device\n");
478 		file->i_flgs = 0;
479 		errno = EDEV;
480 		return (-1);
481 	gotdev:
482 		i = 0;
483 		while (*cp >= '0' && *cp <= '9')
484 			i = i * 10 + *cp++ - '0';
485 		if (i < 0 || i > 255) {
486 			printf("minor device number out of range (0-255)\n");
487 			file->i_flgs = 0;
488 			errno = EUNIT;
489 			return (-1);
490 		}
491 		if (*cp >= 'a' && *cp <= 'h') {
492 			if (i > 31) {
493 				printf("unit number out of range (0-31)\n");
494 				file->i_flgs = 0;
495 				errno = EUNIT;
496 				return (-1);
497 			}
498 			i = make_minor(i, *cp++ - 'a');
499 		}
500 
501 		if (*cp++ != ':') {
502 			printf("incorrect device specification\n");
503 			file->i_flgs = 0;
504 			errno = EOFFSET;
505 			return (-1);
506 		}
507 		opendev = file->i_ino.i_dev = makedev(dp-devsw, i);
508 	}
509 	file->i_boff = 0;
510 	devopen(file);
511 	if (cp != str && *cp == '\0') {
512 		file->i_flgs |= how+1;
513 		file->i_cc = 0;
514 		file->i_offset = 0;
515 		return (fdesc+3);
516 	}
517 #else notyet
518 	for (cp = str; *cp && *cp != '('; cp++)
519 			;
520 	if (*cp != '(') {
521 		printf("Bad device\n");
522 		file->i_flgs = 0;
523 		errno = EDEV;
524 		return (-1);
525 	}
526 	*cp++ = '\0';
527 	for (dp = devsw; dp->dv_name; dp++) {
528 		if (!strcmp(str, dp->dv_name))
529 			goto gotdev;
530 	}
531 	printf("Unknown device\n");
532 	file->i_flgs = 0;
533 	errno = ENXIO;
534 	return (-1);
535 gotdev:
536 	*(cp-1) = '(';
537 	file->i_ino.i_dev = dp-devsw;
538 	file->i_unit = *cp++ - '0';
539 	if (*cp >= '0' && *cp <= '9')
540 		file->i_unit = file->i_unit * 10 + *cp++ - '0';
541 	if (file->i_unit < 0 || file->i_unit > 63) {
542 		printf("Bad unit specifier\n");
543 		file->i_flgs = 0;
544 		errno = EUNIT;
545 		return (-1);
546 	}
547 	if (*cp++ != ',') {
548 badoff:
549 		printf("Missing offset specification\n");
550 		file->i_flgs = 0;
551 		errno = EOFFSET;
552 		return (-1);
553 	}
554 	file->i_boff = atol(cp);
555 	for (;;) {
556 		if (*cp == ')')
557 			break;
558 		if (*cp++)
559 			continue;
560 		goto badoff;
561 	}
562 	devopen(file);
563 	if (*++cp == '\0') {
564 		file->i_flgs |= how+1;
565 		file->i_cc = 0;
566 		file->i_offset = 0;
567 		return (fdesc+3);
568 	}
569 #endif notyet
570 	file->i_ma = (char *)(&file->i_fs);
571 	file->i_cc = SBSIZE;
572 	file->i_bn = SBLOCK + file->i_boff;
573 	file->i_offset = 0;
574 	if (devread(file) < 0) {
575 		errno = file->i_error;
576 		printf("super block read error\n");
577 		return (-1);
578 	}
579 	if ((i = find(cp, file)) == 0) {
580 		file->i_flgs = 0;
581 		errno = ESRCH;
582 		return (-1);
583 	}
584 #ifndef	SMALL
585 	if (how != 0) {
586 		printf("Can't write files yet.. Sorry\n");
587 		file->i_flgs = 0;
588 		errno = EIO;
589 		return (-1);
590 	}
591 #endif SMALL
592 	if (openi(i, file) < 0) {
593 		errno = file->i_error;
594 		return (-1);
595 	}
596 	file->i_offset = 0;
597 	file->i_cc = 0;
598 	file->i_flgs |= F_FILE | (how+1);
599 	return (fdesc+3);
600 }
601 
602 close(fdesc)
603 	int fdesc;
604 {
605 	struct iob *file;
606 
607 	fdesc -= 3;
608 	if (fdesc < 0 || fdesc >= NFILES ||
609 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
610 		errno = EBADF;
611 		return (-1);
612 	}
613 	if ((file->i_flgs&F_FILE) == 0)
614 		devclose(file);
615 	file->i_flgs = 0;
616 	return (0);
617 }
618 
619 #ifndef	SMALL
620 ioctl(fdesc, cmd, arg)
621 	int fdesc, cmd;
622 	char *arg;
623 {
624 	register struct iob *file;
625 	int error = 0;
626 
627 	fdesc -= 3;
628 	if (fdesc < 0 || fdesc >= NFILES ||
629 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
630 		errno = EBADF;
631 		return (-1);
632 	}
633 	switch (cmd) {
634 
635 	case SAIOHDR:
636 		file->i_flgs |= F_HDR;
637 		break;
638 
639 	case SAIOCHECK:
640 		file->i_flgs |= F_CHECK;
641 		break;
642 
643 	case SAIOHCHECK:
644 		file->i_flgs |= F_HCHECK;
645 		break;
646 
647 	case SAIONOBAD:
648 		file->i_flgs |= F_NBSF;
649 		break;
650 
651 	case SAIODOBAD:
652 		file->i_flgs &= ~F_NBSF;
653 		break;
654 
655 	default:
656 		error = devioctl(file, cmd, arg);
657 		break;
658 	}
659 	if (error < 0)
660 		errno = file->i_error;
661 	return (error);
662 }
663 #endif SMALL
664 
665 exit()
666 {
667 	_stop("Exit called");
668 }
669 
670 _stop(s)
671 	char *s;
672 {
673 	int i;
674 
675 	for (i = 0; i < NFILES; i++)
676 		if (iob[i].i_flgs != 0)
677 			close(i);
678 	printf("%s\n", s);
679 	_rtt();
680 }
681