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