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