date and time created 91/05/12 22:30:02 by william
[unix-history] / usr / src / sys / i386 / stand / sys.c
CommitLineData
5f15d2b7
WN
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) %G%
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__)
23ino_t dlook();
24
25struct dirstuff {
26 int loc;
27 struct iob *io;
28};
29
30#undef register
31
32static
33openi(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
49static
50find(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
93char b[MAXBSIZE];
94daddr_t blkno;
95
96static daddr_t
97sbmap(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
173static ino_t
174dlook(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 */
209struct direct *
210readdir(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
246lseek(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
268getc(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?
324getw(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*/
344int errno;
345
346read(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
435write(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
470int openfirst = 1;
471int opendev; /* last device opened; for boot to set bootdev */
472
473open(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");
495gotfile:
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
588close(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
606ioctl(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
679trap(ps)
680 int ps;
681{
682 printf("trap %o\n", ps);
683 for (;;)
684 ;
685}