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