xref: /original-bsd/sys/hp300/stand/sys.c (revision e21485a6)
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.2 (Berkeley) 07/01/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 = 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 dinode *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->di_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->di_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 	struct direct *readdir();
168 	register struct dinode *ip;
169 	struct dirstuff dirp;
170 	int len;
171 
172 	if (s == NULL || *s == '\0')
173 		return (0);
174 	ip = &io->i_ino;
175 	if ((ip->di_mode&IFMT) != IFDIR) {
176 		printf("not a directory\n");
177 		printf("%s: not a directory\n", s);
178 		return (0);
179 	}
180 	if (ip->di_size == 0) {
181 		printf("%s: zero length directory\n", s);
182 		return (0);
183 	}
184 	len = strlen(s);
185 	dirp.loc = 0;
186 	dirp.io = io;
187 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
188 		if(dp->d_ino == 0)
189 			continue;
190 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
191 			return (dp->d_ino);
192 	}
193 	return (0);
194 }
195 
196 /*
197  * get next entry in a directory.
198  */
199 struct direct *
200 readdir(dirp)
201 	register struct dirstuff *dirp;
202 {
203 	register struct direct *dp;
204 	register struct iob *io;
205 	daddr_t lbn, d;
206 	int off;
207 
208 	io = dirp->io;
209 	for(;;) {
210 		if (dirp->loc >= io->i_ino.di_size)
211 			return (NULL);
212 		off = blkoff(&io->i_fs, dirp->loc);
213 		if (off == 0) {
214 			lbn = lblkno(&io->i_fs, dirp->loc);
215 			d = sbmap(io, lbn);
216 			if(d == 0)
217 				return NULL;
218 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
219 			io->i_ma = io->i_buf;
220 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
221 			if (devread(io) < 0) {
222 				errno = io->i_error;
223 				printf("bn %D: directory read error\n",
224 					io->i_bn);
225 				return (NULL);
226 			}
227 		}
228 		dp = (struct direct *)(io->i_buf + off);
229 		dirp->loc += dp->d_reclen;
230 		if (dp->d_ino == 0)
231 			continue;
232 		return (dp);
233 	}
234 }
235 
236 lseek(fdesc, addr, ptr)
237 	int fdesc, ptr;
238 	off_t addr;
239 {
240 	register struct iob *io;
241 
242 #ifndef	SMALL
243 	if (ptr != 0) {
244 		printf("Seek not from beginning of file\n");
245 		errno = EOFFSET;
246 		return (-1);
247 	}
248 #endif SMALL
249 	fdesc -= 3;
250 	if (fdesc < 0 || fdesc >= NFILES ||
251 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
252 		errno = EBADF;
253 		return (-1);
254 	}
255 	io->i_offset = addr;
256 	io->i_bn = addr / DEV_BSIZE;
257 	io->i_cc = 0;
258 	return (0);
259 }
260 
261 getc(fdesc)
262 	int fdesc;
263 {
264 	register struct iob *io;
265 	register struct fs *fs;
266 	register char *p;
267 	int c, lbn, off, size, diff;
268 
269 
270 	if (fdesc >= 0 && fdesc <= 2)
271 		return (getchar());
272 	fdesc -= 3;
273 	if (fdesc < 0 || fdesc >= NFILES ||
274 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
275 		errno = EBADF;
276 		return (-1);
277 	}
278 	p = io->i_ma;
279 	if (io->i_cc <= 0) {
280 		if ((io->i_flgs & F_FILE) != 0) {
281 			diff = io->i_ino.di_size - io->i_offset;
282 			if (diff <= 0)
283 				return (-1);
284 			fs = &io->i_fs;
285 			lbn = lblkno(fs, io->i_offset);
286 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
287 			off = blkoff(fs, io->i_offset);
288 			size = dblksize(fs, &io->i_ino, lbn);
289 		} else {
290 			io->i_bn = io->i_offset / DEV_BSIZE;
291 			off = 0;
292 			size = DEV_BSIZE;
293 		}
294 		io->i_ma = io->i_buf;
295 		io->i_cc = size;
296 		if (devread(io) < 0) {
297 			errno = io->i_error;
298 			return (-1);
299 		}
300 		if ((io->i_flgs & F_FILE) != 0) {
301 			if (io->i_offset - off + size >= io->i_ino.di_size)
302 				io->i_cc = diff + off;
303 			io->i_cc -= off;
304 		}
305 		p = &io->i_buf[off];
306 	}
307 	io->i_cc--;
308 	io->i_offset++;
309 	c = (unsigned)*p++;
310 	io->i_ma = p;
311 	return (c);
312 }
313 
314 int	errno;
315 
316 read(fdesc, buf, count)
317 	int fdesc, count;
318 	char *buf;
319 {
320 	register i, size;
321 	register struct iob *file;
322 	register struct fs *fs;
323 	int lbn, off;
324 
325 	errno = 0;
326 	if (fdesc >= 0 & fdesc <= 2) {
327 		i = count;
328 		do {
329 			*buf = getchar();
330 		} while (--i && *buf++ != '\n');
331 		return (count - i);
332 	}
333 	fdesc -= 3;
334 	if (fdesc < 0 || fdesc >= NFILES ||
335 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
336 		errno = EBADF;
337 		return (-1);
338 	}
339 	if ((file->i_flgs&F_READ) == 0) {
340 		errno = EBADF;
341 		return (-1);
342 	}
343 #ifndef	SMALL
344 	if ((file->i_flgs & F_FILE) == 0) {
345 		file->i_cc = count;
346 		file->i_ma = buf;
347 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
348 		i = devread(file);
349 		file->i_offset += count;
350 		if (i < 0)
351 			errno = file->i_error;
352 		return (i);
353 	}
354 #endif SMALL
355 	if (file->i_offset+count > file->i_ino.di_size)
356 		count = file->i_ino.di_size - file->i_offset;
357 	if ((i = count) <= 0)
358 		return (0);
359 	/*
360 	 * While reading full blocks, do I/O into user buffer.
361 	 * Anything else uses getc().
362 	 */
363 	fs = &file->i_fs;
364 	while (i) {
365 		off = blkoff(fs, file->i_offset);
366 		lbn = lblkno(fs, file->i_offset);
367 		size = dblksize(fs, &file->i_ino, lbn);
368 		if (off == 0 && size <= i) {
369 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
370 			    file->i_boff;
371 			file->i_cc = size;
372 			file->i_ma = buf;
373 			if (devread(file) < 0) {
374 				errno = file->i_error;
375 				return (-1);
376 			}
377 			file->i_offset += size;
378 			file->i_cc = 0;
379 			buf += size;
380 			i -= size;
381 		} else {
382 			size -= off;
383 			if (size > i)
384 				size = i;
385 			i -= size;
386 			do {
387 				*buf++ = getc(fdesc+3);
388 			} while (--size);
389 		}
390 	}
391 	return (count);
392 }
393 
394 #ifndef	SMALL
395 write(fdesc, buf, count)
396 	int fdesc, count;
397 	char *buf;
398 {
399 	register i;
400 	register struct iob *file;
401 
402 	errno = 0;
403 	if (fdesc >= 0 && fdesc <= 2) {
404 		i = count;
405 		while (i--)
406 			putchar(0, *buf++);
407 		return (count);
408 	}
409 	fdesc -= 3;
410 	if (fdesc < 0 || fdesc >= NFILES ||
411 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
412 		errno = EBADF;
413 		return (-1);
414 	}
415 	if ((file->i_flgs&F_WRITE) == 0) {
416 		errno = EBADF;
417 		return (-1);
418 	}
419 	file->i_cc = count;
420 	file->i_ma = buf;
421 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
422 	i = devwrite(file);
423 	file->i_offset += count;
424 	if (i < 0)
425 		errno = file->i_error;
426 	return (i);
427 }
428 #endif SMALL
429 
430 int	openfirst = 1;
431 #ifdef notyet
432 int	opendev;	/* last device opened; for boot to set bootdev */
433 extern	int bootdev;
434 #endif notyet
435 
436 open(str, how)
437 	char *str;
438 	int how;
439 {
440 	register char *cp;
441 	int i;
442 	register struct iob *file;
443 	register struct devsw *dp;
444 	int fdesc;
445 	long atol();
446 
447 	if (openfirst) {
448 		for (i = 0; i < NFILES; i++)
449 			iob[i].i_flgs = 0;
450 		openfirst = 0;
451 	}
452 
453 	for (fdesc = 0; fdesc < NFILES; fdesc++)
454 		if (iob[fdesc].i_flgs == 0)
455 			goto gotfile;
456 	_stop("No more file slots");
457 gotfile:
458 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
459 
460 #ifdef notyet
461 	for (cp = str; *cp && *cp != '/' && *cp != ':'; cp++)
462 			;
463 	if (*cp != ':') {
464 		/* default bootstrap unit and device */
465 		file->i_dev = bootdev;
466 		cp = str;
467 	} else {
468 # define isdigit(n)	((n>='0') && (n<='9'))
469 		/*
470 	 	 * syntax for possible device name:
471 	 	 *	<alpha-string><digit-string><letter>:
472 	 	 */
473 		for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
474 			;
475 		for (dp = devsw; dp->dv_name; dp++) {
476 			if (!strncmp(str, dp->dv_name,cp-str))
477 				goto gotdev;
478 		}
479 		printf("unknown device\n");
480 		file->i_flgs = 0;
481 		errno = EDEV;
482 		return (-1);
483 	gotdev:
484 		i = 0;
485 		while (*cp >= '0' && *cp <= '9')
486 			i = i * 10 + *cp++ - '0';
487 		if (i < 0 || i > 255) {
488 			printf("minor device number out of range (0-255)\n");
489 			file->i_flgs = 0;
490 			errno = EUNIT;
491 			return (-1);
492 		}
493 		if (*cp >= 'a' && *cp <= 'h') {
494 			if (i > 31) {
495 				printf("unit number out of range (0-31)\n");
496 				file->i_flgs = 0;
497 				errno = EUNIT;
498 				return (-1);
499 			}
500 			i = make_minor(i, *cp++ - 'a');
501 		}
502 
503 		if (*cp++ != ':') {
504 			printf("incorrect device specification\n");
505 			file->i_flgs = 0;
506 			errno = EOFFSET;
507 			return (-1);
508 		}
509 		opendev = file->i_dev = makedev(dp-devsw, i);
510 	}
511 	file->i_boff = 0;
512 	devopen(file);
513 	if (cp != str && *cp == '\0') {
514 		file->i_flgs |= how+1;
515 		file->i_cc = 0;
516 		file->i_offset = 0;
517 		return (fdesc+3);
518 	}
519 #else notyet
520 	for (cp = str; *cp && *cp != '('; cp++)
521 			;
522 	if (*cp != '(') {
523 		printf("Bad device\n");
524 		file->i_flgs = 0;
525 		errno = EDEV;
526 		return (-1);
527 	}
528 	*cp = '\0';
529 	for (dp = devsw; dp->dv_name; dp++)
530 		if (!strcmp(str, dp->dv_name))
531 			break;
532 	*cp++ = '(';
533 	if (dp->dv_name == NULL) {
534 		printf("Unknown device\n");
535 		file->i_flgs = 0;
536 		errno = ENXIO;
537 		return (-1);
538 	}
539 	file->i_dev = dp-devsw;
540 	file->i_unit = *cp++ - '0';
541 	if (*cp >= '0' && *cp <= '9')
542 		file->i_unit = file->i_unit * 10 + *cp++ - '0';
543 	if (file->i_unit < 0 || file->i_unit > 63) {
544 		printf("Bad unit specifier\n");
545 		file->i_flgs = 0;
546 		errno = EUNIT;
547 		return (-1);
548 	}
549 	if (*cp++ != ',') {
550 badoff:
551 		printf("Missing offset specification\n");
552 		file->i_flgs = 0;
553 		errno = EOFFSET;
554 		return (-1);
555 	}
556 	file->i_boff = atol(cp);
557 	for (;;) {
558 		if (*cp == ')')
559 			break;
560 		if (*cp++)
561 			continue;
562 		goto badoff;
563 	}
564 	devopen(file);
565 	if (*++cp == '\0') {
566 		file->i_flgs |= how+1;
567 		file->i_cc = 0;
568 		file->i_offset = 0;
569 		return (fdesc+3);
570 	}
571 #endif notyet
572 	file->i_ma = (char *)(&file->i_fs);
573 	file->i_cc = SBSIZE;
574 	file->i_bn = SBLOCK + file->i_boff;
575 	file->i_offset = 0;
576 	if (devread(file) < 0) {
577 		errno = file->i_error;
578 		printf("super block read error\n");
579 		return (-1);
580 	}
581 	if ((i = find(cp, file)) == 0) {
582 		file->i_flgs = 0;
583 		errno = ESRCH;
584 		return (-1);
585 	}
586 #ifndef	SMALL
587 	if (how != 0) {
588 		printf("Can't write files yet.. Sorry\n");
589 		file->i_flgs = 0;
590 		errno = EIO;
591 		return (-1);
592 	}
593 #endif SMALL
594 	if (openi(i, file) < 0) {
595 		errno = file->i_error;
596 		return (-1);
597 	}
598 	file->i_offset = 0;
599 	file->i_cc = 0;
600 	file->i_flgs |= F_FILE | (how+1);
601 	return (fdesc+3);
602 }
603 
604 close(fdesc)
605 	int fdesc;
606 {
607 	struct iob *file;
608 
609 	fdesc -= 3;
610 	if (fdesc < 0 || fdesc >= NFILES ||
611 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
612 		errno = EBADF;
613 		return (-1);
614 	}
615 	if ((file->i_flgs&F_FILE) == 0)
616 		devclose(file);
617 	file->i_flgs = 0;
618 	return (0);
619 }
620 
621 exit()
622 {
623 	_stop("Exit called");
624 }
625 
626 _stop(s)
627 	char *s;
628 {
629 	static int stopped = 0;
630 	int i;
631 
632 	if (!stopped) {
633 		stopped++;
634 		for (i = 0; i < NFILES; i++)
635 			if (iob[i].i_flgs != 0)
636 				close(i);
637 	}
638 	printf("%s\n", s);
639 	_rtt();
640 }
641 
642 #ifndef	SMALL
643 ioctl(fdesc, cmd, arg)
644 	int fdesc, cmd;
645 	char *arg;
646 {
647 	register struct iob *file;
648 	int error = 0;
649 
650 	fdesc -= 3;
651 	if (fdesc < 0 || fdesc >= NFILES ||
652 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
653 		errno = EBADF;
654 		return (-1);
655 	}
656 	switch (cmd) {
657 
658 	case SAIOHDR:
659 		file->i_flgs |= F_HDR;
660 		break;
661 
662 	case SAIOCHECK:
663 		file->i_flgs |= F_CHECK;
664 		break;
665 
666 	case SAIOHCHECK:
667 		file->i_flgs |= F_HCHECK;
668 		break;
669 
670 	case SAIONOBAD:
671 		file->i_flgs |= F_NBSF;
672 		break;
673 
674 	case SAIODOBAD:
675 		file->i_flgs &= ~F_NBSF;
676 		break;
677 
678 	default:
679 		error = devioctl(file, cmd, arg);
680 		break;
681 	}
682 	if (error < 0)
683 		errno = file->i_error;
684 	return (error);
685 }
686 
687 extern char end;
688 static caddr_t theend = 0;
689 
690 caddr_t
691 brk(addr)
692  char *addr;
693 {
694 	char stkloc;
695 
696 	if (theend == (caddr_t)0)
697 		theend = &end;
698 	if (addr > &stkloc || addr < &end)
699 		return((caddr_t)-1);
700 	if (addr > theend)
701 		bzero(theend, addr-theend);
702 	theend = addr;
703 	return(0);
704 }
705 
706 caddr_t
707 sbrk(incr)
708  int incr;
709 {
710 	caddr_t obrk, brk();
711 
712 	if (theend == (caddr_t)0)
713 		theend = &end;
714 	obrk = theend;
715 	if (brk(theend+incr) == (caddr_t)-1)
716 		return((caddr_t)-1);
717 	return(obrk);
718 }
719 
720 getpagesize()
721 {
722 	return(NBPG);
723 }
724 
725 getdtablesize()
726 {
727 	return(NFILES);
728 }
729 
730 fstat(fdesc, sb)
731 	struct stat *sb;
732 {
733 	register struct iob *io;
734 
735 	fdesc -= 3;
736 	if (fdesc < 0 || fdesc >= NFILES ||
737 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
738 		errno = EBADF;
739 		return (-1);
740 	}
741 	/* only important stuff */
742 	sb->st_mode = io->i_ino.di_mode;
743 	sb->st_uid = io->i_ino.di_uid;
744 	sb->st_gid = io->i_ino.di_gid;
745 	sb->st_size = io->i_ino.di_size;
746 	return (0);
747 }
748 
749 stat(str, sb)
750 {
751 	/* the easy way */
752 	int f, rv = 0;
753 
754 	f = open(str, 0);
755 	if (f < 0 || fstat(f, sb) < 0)
756 		rv = -1;
757 	(void) close(f);
758 	return(rv);
759 }
760 
761 #endif SMALL
762