xref: /original-bsd/sys/luna68k/stand/sys.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)sys.c	8.1 (Berkeley) 06/10/93
12  */
13 
14 #include <sys/param.h>
15 #include <sys/stat.h>
16 #include <ufs/ufs/dir.h>
17 #include <luna68k/stand/saio.h>
18 
19 ino_t	dlook();
20 
21 struct dirstuff {
22 	int loc;
23 	struct iob *io;
24 };
25 
26 openi(n, io)
27 	register struct iob *io;
28 {
29 	register struct dinode *dp;
30 	int cc;
31 
32 	io->i_offset = 0;
33 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
34 	io->i_cc = io->i_fs.fs_bsize;
35 	io->i_ma = io->i_buf;
36 	cc = devread(io);
37 	dp = (struct dinode *)io->i_buf;
38 	io->i_ino = dp[itoo(&io->i_fs, n)];
39 	return (cc);
40 }
41 
42 find(path, file)
43 	register char *path;
44 	struct iob *file;
45 {
46 	register char *q;
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 	while (*path) {
60 		while (*path == '/')
61 			path++;
62 		q = path;
63 		while(*q != '/' && *q != '\0')
64 			q++;
65 		c = *q;
66 		*q = '\0';
67 		if (q == path) path = "." ;	/* "/" means "/." */
68 
69 		if ((n = dlook(path, file)) != 0) {
70 			if (c == '\0')
71 				break;
72 			if (openi(n, file) < 0)
73 				return (0);
74 			*q = c;
75 			path = q;
76 			continue;
77 		} else {
78 			printf("%s: not found\n", path);
79 			return (0);
80 		}
81 	}
82 	return (n);
83 }
84 
85 daddr_t
86 sbmap(io, bn)
87 	register struct iob *io;
88 	daddr_t bn;
89 {
90 	register struct dinode *ip;
91 	int i, j, sh;
92 	daddr_t nb, *bap;
93 
94 	ip = &io->i_ino;
95 	if (bn < 0) {
96 		printf("bn negative\n");
97 		return ((daddr_t)0);
98 	}
99 
100 	/*
101 	 * blocks 0..NDADDR are direct blocks
102 	 */
103 	if(bn < NDADDR) {
104 		nb = ip->di_db[bn];
105 		return (nb);
106 	}
107 
108 	/*
109 	 * addresses NIADDR have single and double indirect blocks.
110 	 * the first step is to determine how many levels of indirection.
111 	 */
112 	sh = 1;
113 	bn -= NDADDR;
114 	for (j = NIADDR; j > 0; j--) {
115 		sh *= NINDIR(&io->i_fs);
116 		if (bn < sh)
117 			break;
118 		bn -= sh;
119 	}
120 	if (j == 0) {
121 		printf("bn ovf %D\n", bn);
122 		return ((daddr_t)0);
123 	}
124 
125 	/*
126 	 * fetch the first indirect block address from the inode
127 	 */
128 	nb = ip->di_ib[NIADDR - j];
129 	if (nb == 0) {
130 		printf("bn void %D\n",bn);
131 		return ((daddr_t)0);
132 	}
133 
134 	/*
135 	 * fetch through the indirect blocks
136 	 */
137 	for (; j <= NIADDR; j++) {
138 		if (blknos[j] != nb) {
139 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
140 			io->i_ma = b[j];
141 			io->i_cc = io->i_fs.fs_bsize;
142 			if (devread(io) != io->i_fs.fs_bsize) {
143 				if (io->i_error)
144 					errno = io->i_error;
145 				printf("bn %D: read error\n", io->i_bn);
146 				return ((daddr_t)0);
147 			}
148 			blknos[j] = nb;
149 		}
150 		bap = (daddr_t *)b[j];
151 		sh /= NINDIR(&io->i_fs);
152 		i = (bn / sh) % NINDIR(&io->i_fs);
153 		nb = bap[i];
154 		if(nb == 0) {
155 			printf("bn void %D\n",bn);
156 			return ((daddr_t)0);
157 		}
158 	}
159 	return (nb);
160 }
161 
162 ino_t
163 dlook(s, io)
164 	char *s;
165 	register struct iob *io;
166 {
167 	register struct direct *dp;
168 	struct direct *readdir();
169 	register struct dinode *ip;
170 	struct dirstuff dirp;
171 	int len;
172 
173 	if (s == NULL || *s == '\0')
174 		return (0);
175 	ip = &io->i_ino;
176 	if ((ip->di_mode&IFMT) != IFDIR) {
177 		printf("not a directory\n");
178 		printf("%s: not a directory\n", s);
179 		return (0);
180 	}
181 	if (ip->di_size == 0) {
182 		printf("%s: zero length directory\n", s);
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.di_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 = dblksize(&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 	if (ptr != 0) {
244 		printf("Seek not from beginning of file\n");
245 		errno = EOFFSET;
246 		return (-1);
247 	}
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 (cngetc());
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.di_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 = dblksize(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.di_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 = cngetc();
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 	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 	if (file->i_offset+count > file->i_ino.di_size)
353 		count = file->i_ino.di_size - file->i_offset;
354 	if ((i = count) <= 0)
355 		return (0);
356 	/*
357 	 * While reading full blocks, do I/O into user buffer.
358 	 * Anything else uses getc().
359 	 */
360 	fs = &file->i_fs;
361 	while (i) {
362 		off = blkoff(fs, file->i_offset);
363 		lbn = lblkno(fs, file->i_offset);
364 		size = dblksize(fs, &file->i_ino, lbn);
365 		if (off == 0 && size <= i) {
366 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
367 			    file->i_boff;
368 			file->i_cc = size;
369 			file->i_ma = buf;
370 			if (devread(file) < 0) {
371 				errno = file->i_error;
372 				return (-1);
373 			}
374 			file->i_offset += size;
375 			file->i_cc = 0;
376 			buf += size;
377 			i -= size;
378 		} else {
379 			size -= off;
380 			if (size > i)
381 				size = i;
382 			i -= size;
383 			do {
384 				*buf++ = getc(fdesc+3);
385 			} while (--size);
386 		}
387 	}
388 	return (count);
389 }
390 
391 write(fdesc, buf, count)
392 	int fdesc, count;
393 	char *buf;
394 {
395 	register i;
396 	register struct iob *file;
397 
398 	errno = 0;
399 	if (fdesc >= 0 && fdesc <= 2) {
400 		i = count;
401 		while (i--)
402 			putchar(0, *buf++);
403 		return (count);
404 	}
405 	fdesc -= 3;
406 	if (fdesc < 0 || fdesc >= NFILES ||
407 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
408 		errno = EBADF;
409 		return (-1);
410 	}
411 	if ((file->i_flgs&F_WRITE) == 0) {
412 		errno = EBADF;
413 		return (-1);
414 	}
415 	file->i_cc = count;
416 	file->i_ma = buf;
417 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
418 	i = devwrite(file);
419 	file->i_offset += count;
420 	if (i < 0)
421 		errno = file->i_error;
422 	return (i);
423 }
424 
425 int	openfirst = 1;
426 
427 open(str, how)
428 	char *str;
429 	int how;
430 {
431 	register char *cp;
432 	int i;
433 	register struct iob *file;
434 	register struct devsw *dp;
435 	int fdesc;
436 	long atol();
437 
438 	if (openfirst) {
439 		for (i = 0; i < NFILES; i++)
440 			iob[i].i_flgs = 0;
441 		openfirst = 0;
442 	}
443 
444 	for (fdesc = 0; fdesc < NFILES; fdesc++)
445 		if (iob[fdesc].i_flgs == 0)
446 			goto gotfile;
447 	_stop("No more file slots");
448 gotfile:
449 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
450 
451 	/*
452 	 * parse path strings
453 	 */
454 							/* find end of dev type name */
455 	for (cp = str; *cp && *cp != '('; cp++)
456 			;
457 	if (*cp != '(') {
458 		printf("Bad device\n");
459 		file->i_flgs = 0;
460 		errno = EDEV;
461 		return (-1);
462 	}
463 							/* compare dev type name */
464 	*cp = '\0';
465 	for (dp = devsw; dp->dv_name; dp++)
466 		if (!strcmp(str, dp->dv_name))
467 			break;
468 	*cp++ = '(';
469 	if (dp->dv_name == NULL) {
470 		printf("Unknown device\n");
471 		file->i_flgs = 0;
472 		errno = ENXIO;
473 		return (-1);
474 	}
475 	file->i_dev = dp-devsw;
476 							/* get unit number */
477 	file->i_unit = *cp++ - '0';
478 	if (*cp >= '0' && *cp <= '9')
479 		file->i_unit = file->i_unit * 10 + *cp++ - '0';
480 	if (file->i_unit < 0 || file->i_unit > 63) {
481 		printf("Bad unit specifier\n");
482 		file->i_flgs = 0;
483 		errno = EUNIT;
484 		return (-1);
485 	}
486 							/* get partition offset */
487 	if (*cp++ != ',') {
488 badoff:
489 		printf("Missing offset specification\n");
490 		file->i_flgs = 0;
491 		errno = EOFFSET;
492 		return (-1);
493 	}
494 	file->i_boff = *cp - '0';
495 							/* check out end of dev spec */
496 	for (;;) {
497 		if (*cp == ')')
498 			break;
499 		if (*cp++)
500 			continue;
501 		goto badoff;
502 	}
503 							/* device open */
504 	devopen(file);
505 							/* if it's specified only device */
506 	if (*++cp == '\0') {
507 		file->i_flgs |= how+1;
508 		file->i_cc = 0;
509 		file->i_offset = 0;
510 		return (fdesc+3);
511 	}
512 							/* No, it's specified file */
513 							/* read super block */
514 	file->i_ma = (char *)(&file->i_fs);
515 	file->i_cc = SBSIZE;
516 	file->i_bn = SBLOCK + file->i_boff;
517 	file->i_offset = 0;
518 	if (devread(file) < 0) {
519 		errno = file->i_error;
520 		printf("super block read error\n");
521 		return (-1);
522 	}
523 
524 	if ((i = find(cp, file)) == 0) {
525 		file->i_flgs = 0;
526 		errno = ESRCH;
527 		return (-1);
528 	}
529 
530 	if (how != 0) {
531 		printf("Can't write files yet.. Sorry\n");
532 		file->i_flgs = 0;
533 		errno = EIO;
534 		return (-1);
535 	}
536 
537 	if (openi(i, file) < 0) {
538 		errno = file->i_error;
539 		return (-1);
540 	}
541 	file->i_offset = 0;
542 	file->i_cc = 0;
543 	file->i_flgs |= F_FILE | (how+1);
544 	return (fdesc+3);
545 }
546 
547 close(fdesc)
548 	int fdesc;
549 {
550 	struct iob *file;
551 
552 	fdesc -= 3;
553 	if (fdesc < 0 || fdesc >= NFILES ||
554 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
555 		errno = EBADF;
556 		return (-1);
557 	}
558 	if ((file->i_flgs&F_FILE) == 0)
559 		devclose(file);
560 	file->i_flgs = 0;
561 	return (0);
562 }
563 
564 _stop(s)
565 	char *s;
566 {
567 	static int stopped = 0;
568 	int i;
569 
570 	if (!stopped) {
571 		stopped++;
572 		for (i = 0; i < NFILES; i++)
573 			if (iob[i].i_flgs != 0)
574 				close(i);
575 	}
576 	printf("%s\n", s);
577 	exit();
578 }
579 
580 ioctl(fdesc, cmd, arg)
581 	int fdesc, cmd;
582 	char *arg;
583 {
584 	register struct iob *file;
585 	int error = 0;
586 
587 	fdesc -= 3;
588 	if (fdesc < 0 || fdesc >= NFILES ||
589 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
590 		errno = EBADF;
591 		return (-1);
592 	}
593 	switch (cmd) {
594 
595 	case SAIOHDR:
596 		file->i_flgs |= F_HDR;
597 		break;
598 
599 	case SAIOCHECK:
600 		file->i_flgs |= F_CHECK;
601 		break;
602 
603 	case SAIOHCHECK:
604 		file->i_flgs |= F_HCHECK;
605 		break;
606 
607 	case SAIONOBAD:
608 		file->i_flgs |= F_NBSF;
609 		break;
610 
611 	case SAIODOBAD:
612 		file->i_flgs &= ~F_NBSF;
613 		break;
614 
615 	default:
616 		error = devioctl(file, cmd, arg);
617 		break;
618 	}
619 	if (error < 0)
620 		errno = file->i_error;
621 	return (error);
622 }
623 
624 extern char end;
625 static caddr_t theend = 0;
626 
627 caddr_t
628 brk(addr)
629  char *addr;
630 {
631 	char stkloc;
632 
633 	if (theend == (caddr_t)0)
634 		theend = &end;
635 	if (addr > &stkloc || addr < &end)
636 		return((caddr_t)-1);
637 	if (addr > theend)
638 		bzero(theend, addr-theend);
639 	theend = addr;
640 	return(0);
641 }
642 
643 caddr_t
644 sbrk(incr)
645  int incr;
646 {
647 	caddr_t obrk, brk();
648 
649 	if (theend == (caddr_t)0)
650 		theend = &end;
651 	obrk = theend;
652 	if (brk(theend+incr) == (caddr_t)-1)
653 		return((caddr_t)-1);
654 	return(obrk);
655 }
656 
657 int
658 getpagesize()
659 {
660 	return(NBPG);
661 }
662 
663 int
664 getdtablesize()
665 {
666 	return(NFILES);
667 }
668