|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)sys.c 7.7 (Berkeley) 7/1/88
7: */
8:
9: #include "param.h"
10: #include "inode.h"
11: #include "fs.h"
12: #include "dir.h"
13: #include "reboot.h"
14: #include "saio.h"
15:
16: #define isdigit(c) ((u_int)((c) - '0') <= 9)
17: #define isspace(c) ((c) == ' ' || (c) == '\t')
18: #define isupper(c) ((u_int)((c) - 'A') <= 'Z' - 'A')
19: #define tolower(c) ((c) - 'A' + 'a')
20:
21: ino_t dlook();
22:
23: struct dirstuff {
24: int loc;
25: struct iob *io;
26: };
27:
28: struct iob iob[NFILES];
29:
30: static
31: openi(n, io)
32: register struct iob *io;
33: {
34: register struct dinode *dp;
35: int cc;
36:
37: io->i_offset = 0;
38: io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
39: io->i_cc = io->i_fs.fs_bsize;
40: io->i_ma = io->i_buf;
41: cc = devread(io);
42: dp = (struct dinode *)io->i_buf;
43: io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
44: return (cc);
45: }
46:
47: static
48: find(path, file)
49: register char *path;
50: struct iob *file;
51: {
52: register char *q;
53: char *dir, c;
54: int n;
55:
56: if (path == NULL || *path == '\0') {
57: printf("null path\n");
58: return (0);
59: }
60:
61: if (openi((ino_t) ROOTINO, file) < 0) {
62: printf("can't read root inode\n");
63: return (0);
64: }
65: dir = path;
66: while (*path) {
67: while (*path == '/')
68: path++;
69: q = path;
70: while(*q != '/' && *q != '\0')
71: q++;
72: c = *q;
73: *q = '\0';
74: if (q == path) path = "." ; /* "/" means "/." */
75:
76: if ((n = dlook(path, file, dir)) != 0) {
77: if (c == '\0')
78: break;
79: if (openi(n, file) < 0)
80: return (0);
81: *q = c;
82: path = q;
83: continue;
84: } else {
85: printf("%s: not found\n", path);
86: return (0);
87: }
88: }
89: return (n);
90: }
91:
92: #define NBUFS 4
93: static char b[NBUFS][MAXBSIZE];
94: static daddr_t blknos[NBUFS];
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 (blknos[j] != nb) {
150: io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
151: io->i_ma = b[j];
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: blknos[j] = nb;
160: }
161: bap = (daddr_t *)b[j];
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, dir)
175: char *s;
176: register struct iob *io;
177: char *dir;
178: {
179: register struct direct *dp;
180: register struct inode *ip;
181: struct dirstuff dirp;
182: int len;
183:
184: if (s == NULL || *s == '\0')
185: return (0);
186: ip = &io->i_ino;
187: if ((ip->i_mode&IFMT) != IFDIR) {
188: printf("%s: not a directory\n", dir);
189: return (0);
190: }
191: if (ip->i_size == 0) {
192: printf("%s: zero length directory\n", dir);
193: return (0);
194: }
195: len = strlen(s);
196: dirp.loc = 0;
197: dirp.io = io;
198: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
199: if(dp->d_ino == 0)
200: continue;
201: if (dp->d_namlen == len && !strcmp(s, dp->d_name))
202: return (dp->d_ino);
203: }
204: return (0);
205: }
206:
207: /*
208: * get next entry in a directory.
209: */
210: struct direct *
211: readdir(dirp)
212: register struct dirstuff *dirp;
213: {
214: register struct direct *dp;
215: register struct iob *io;
216: daddr_t lbn, d;
217: int off;
218:
219: io = dirp->io;
220: for(;;) {
221: if (dirp->loc >= io->i_ino.i_size)
222: return (NULL);
223: off = blkoff(&io->i_fs, dirp->loc);
224: if (off == 0) {
225: lbn = lblkno(&io->i_fs, dirp->loc);
226: d = sbmap(io, lbn);
227: if(d == 0)
228: return (NULL);
229: io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
230: io->i_ma = io->i_buf;
231: io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
232: if (devread(io) < 0) {
233: errno = io->i_error;
234: printf("bn %D: directory read error\n",
235: io->i_bn);
236: return (NULL);
237: }
238: }
239: dp = (struct direct *)(io->i_buf + off);
240: dirp->loc += dp->d_reclen;
241: if (dp->d_ino == 0)
242: continue;
243: return (dp);
244: }
245: }
246:
247: lseek(fdesc, addr, ptr)
248: int fdesc, ptr;
249: off_t addr;
250: {
251: register struct iob *io;
252:
253: #ifndef SMALL
254: if (ptr != L_SET) {
255: printf("Seek not from beginning of file\n");
256: errno = EOFFSET;
257: return (-1);
258: }
259: #endif
260: fdesc -= 3;
261: if (fdesc < 0 || fdesc >= NFILES ||
262: ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
263: errno = EBADF;
264: return (-1);
265: }
266: io->i_offset = addr;
267: io->i_bn = addr / DEV_BSIZE;
268: io->i_cc = 0;
269: return (0);
270: }
271:
272: getc(fdesc)
273: int fdesc;
274: {
275: register struct iob *io;
276: register struct fs *fs;
277: register char *p;
278: int c, lbn, off, size, diff;
279:
280:
281: if (fdesc >= 0 && fdesc <= 2)
282: return (getchar());
283: fdesc -= 3;
284: if (fdesc < 0 || fdesc >= NFILES ||
285: ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
286: errno = EBADF;
287: return (-1);
288: }
289: p = io->i_ma;
290: if (io->i_cc <= 0) {
291: if ((io->i_flgs & F_FILE) != 0) {
292: diff = io->i_ino.i_size - io->i_offset;
293: if (diff <= 0)
294: return (-1);
295: fs = &io->i_fs;
296: lbn = lblkno(fs, io->i_offset);
297: io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
298: off = blkoff(fs, io->i_offset);
299: size = blksize(fs, &io->i_ino, lbn);
300: } else {
301: io->i_bn = io->i_offset / DEV_BSIZE;
302: off = 0;
303: size = DEV_BSIZE;
304: }
305: io->i_ma = io->i_buf;
306: io->i_cc = size;
307: if (devread(io) < 0) {
308: errno = io->i_error;
309: return (-1);
310: }
311: if ((io->i_flgs & F_FILE) != 0) {
312: if (io->i_offset - off + size >= io->i_ino.i_size)
313: io->i_cc = diff + off;
314: io->i_cc -= off;
315: }
316: p = &io->i_buf[off];
317: }
318: io->i_cc--;
319: io->i_offset++;
320: c = (unsigned)*p++;
321: io->i_ma = p;
322: return (c);
323: }
324:
325: int errno;
326:
327: read(fdesc, buf, count)
328: int fdesc, count;
329: char *buf;
330: {
331: register i, size;
332: register struct iob *file;
333: register struct fs *fs;
334: int lbn, off;
335:
336: errno = 0;
337: if (fdesc >= 0 & fdesc <= 2) {
338: i = count;
339: do {
340: *buf = getchar();
341: } while (--i && *buf++ != '\n');
342: return (count - i);
343: }
344: fdesc -= 3;
345: if (fdesc < 0 || fdesc >= NFILES ||
346: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
347: errno = EBADF;
348: return (-1);
349: }
350: if ((file->i_flgs&F_READ) == 0) {
351: errno = EBADF;
352: return (-1);
353: }
354: #ifndef SMALL
355: if ((file->i_flgs & F_FILE) == 0) {
356: file->i_cc = count;
357: file->i_ma = buf;
358: file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
359: i = devread(file);
360: if (i < 0)
361: errno = file->i_error;
362: else
363: file->i_offset += i;
364: return (i);
365: }
366: #endif
367: if (file->i_offset+count > file->i_ino.i_size)
368: count = file->i_ino.i_size - file->i_offset;
369: if ((i = count) <= 0)
370: return (0);
371: /*
372: * While reading full blocks, do I/O into user buffer.
373: * Anything else uses getc().
374: */
375: fs = &file->i_fs;
376: while (i) {
377: off = blkoff(fs, file->i_offset);
378: lbn = lblkno(fs, file->i_offset);
379: size = blksize(fs, &file->i_ino, lbn);
380: if (off == 0 && size <= i) {
381: file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
382: file->i_boff;
383: file->i_cc = size;
384: file->i_ma = buf;
385: if (devread(file) < 0) {
386: errno = file->i_error;
387: return (-1);
388: }
389: file->i_offset += size;
390: file->i_cc = 0;
391: buf += size;
392: i -= size;
393: } else {
394: size -= off;
395: if (size > i)
396: size = i;
397: i -= size;
398: do {
399: *buf++ = getc(fdesc+3);
400: } while (--size);
401: }
402: }
403: return (count);
404: }
405:
406: #ifndef SMALL
407: write(fdesc, buf, count)
408: int fdesc, count;
409: char *buf;
410: {
411: register i;
412: register struct iob *file;
413:
414: errno = 0;
415: if (fdesc >= 0 && fdesc <= 2) {
416: i = count;
417: while (i--)
418: putchar(*buf++);
419: return (count);
420: }
421: fdesc -= 3;
422: if (fdesc < 0 || fdesc >= NFILES ||
423: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
424: errno = EBADF;
425: return (-1);
426: }
427: if ((file->i_flgs&F_WRITE) == 0) {
428: errno = EBADF;
429: return (-1);
430: }
431: file->i_cc = count;
432: file->i_ma = buf;
433: file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
434: i = devwrite(file);
435: file->i_offset += count;
436: if (i < 0)
437: errno = file->i_error;
438: return (i);
439: }
440: #endif
441:
442: int openfirst = 1;
443: u_int opendev; /* last device opened */
444: extern u_int bootdev;
445:
446: open(str, how)
447: char *str;
448: int how;
449: {
450: register char *t;
451: register int cnt;
452: register struct iob *file;
453: int fdesc, args[8], *argp;
454:
455: if (openfirst) {
456: for (cnt = 0; cnt < NFILES; cnt++)
457: iob[cnt].i_flgs = 0;
458: openfirst = 0;
459: }
460:
461: for (fdesc = 0;; fdesc++) {
462: if (fdesc == NFILES)
463: _stop("No more file slots");
464: if (iob[fdesc].i_flgs == 0) {
465: file = &iob[fdesc];
466: file->i_flgs |= F_ALLOC;
467: file->i_adapt = file->i_ctlr = file->i_unit =
468: file->i_part = 0;
469: break;
470: }
471: }
472:
473: for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
474: #ifndef SMALL
475: for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
476: if (isupper(*t))
477: *t = tolower(*t);
478: switch(*t) {
479: case '(': /* type(adapt, ctlr, drive, partition)file */
480: if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
481: goto bad;
482: for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
483: for (++t; isspace(*t); ++t);
484: if (*t == ')')
485: break;
486: if (!isdigit(*t))
487: goto badspec;
488: *argp++ = atoi(t);
489: for (++t; isdigit(*t); ++t);
490: if (*t != ',' && *t != ')' || cnt == 4)
491: goto badspec;
492: }
493: for (++t; isspace(*t); ++t);
494: argp -= 4;
495: file->i_adapt = *argp++;
496: file->i_ctlr = *argp++;
497: file->i_unit = *argp++;
498: file->i_part = *argp;
499: break;
500: case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */
501: for (t = str; *t != ':' && !isdigit(*t); ++t);
502: if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
503: goto bad;
504: if ((file->i_unit = getunit(t)) == -1)
505: goto bad;
506: for (; isdigit(*t); ++t);
507: if (*t >= 'a' && *t <= 'h')
508: file->i_part = *t++ - 'a';
509: if (*t != ':') {
510: errno = EOFFSET;
511: goto badspec;
512: }
513: for (++t; isspace(*t); ++t);
514: break;
515: case '/':
516: default: /* default bootstrap unit and device */
517: #else
518: {
519: #endif /* SMALL */
520: file->i_ino.i_dev = B_TYPE(bootdev);
521: file->i_adapt = B_ADAPTOR(bootdev);
522: file->i_ctlr = B_CONTROLLER(bootdev);
523: file->i_unit = B_UNIT(bootdev);
524: file->i_part = B_PARTITION(bootdev);
525: t = str;
526: }
527:
528: opendev = MAKEBOOTDEV(file->i_ino.i_dev, file->i_adapt, file->i_ctlr,
529: file->i_unit, file->i_part);
530:
531: if (errno = devopen(file))
532: goto bad;
533:
534: if (*t == '\0') {
535: file->i_flgs |= how + 1;
536: file->i_cc = 0;
537: file->i_offset = 0;
538: return (fdesc+3);
539: }
540: #ifndef SMALL
541: else if (how != 0) {
542: printf("Can't write files yet.. Sorry\n");
543: errno = EIO;
544: goto bad;
545: }
546: #endif
547: file->i_ma = (char *)(&file->i_fs);
548: file->i_cc = SBSIZE;
549: file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
550: file->i_offset = 0;
551: if (devread(file) < 0) {
552: errno = file->i_error;
553: printf("super block read error\n");
554: goto bad;
555: }
556: if ((cnt = find(t, file)) == 0) {
557: errno = ESRCH;
558: goto bad;
559: }
560: if (openi(cnt, file) < 0) {
561: errno = file->i_error;
562: goto bad;
563: }
564: file->i_offset = 0;
565: file->i_cc = 0;
566: file->i_flgs |= F_FILE | (how+1);
567: return (fdesc+3);
568:
569: #ifndef SMALL
570: badspec:
571: printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n");
572: #endif
573: bad:
574: file->i_flgs = 0;
575: return (-1);
576: }
577:
578: #ifndef SMALL
579: static
580: getdev(str, len)
581: register char *str;
582: int len;
583: {
584: register struct devsw *dp;
585: register int i;
586: char savedch = str[len];
587:
588: str[len] = '\0';
589: for (dp = devsw, i = 0; i < ndevs; dp++, i++)
590: if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
591: str[len] = savedch;
592: return (i);
593: }
594: printf("Unknown device\nKnown devices are:\n");
595: for (dp = devsw, i = 0; i < ndevs; dp++, i++)
596: if (dp->dv_name)
597: printf(" %s", dp->dv_name);
598: printf("\n");
599: errno = ENXIO;
600: return (-1);
601: }
602:
603: static
604: getunit(cp)
605: register char *cp;
606: {
607: int unit;
608:
609: unit = atoi(cp);
610: if ((u_int)unit > 255) {
611: printf("minor device number out of range (0-255)\n");
612: errno = EUNIT;
613: return (-1);
614: }
615: return (unit);
616: }
617: #endif /* SMALL */
618:
619: close(fdesc)
620: int fdesc;
621: {
622: struct iob *file;
623:
624: fdesc -= 3;
625: if (fdesc < 0 || fdesc >= NFILES ||
626: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
627: errno = EBADF;
628: return (-1);
629: }
630: if ((file->i_flgs&F_FILE) == 0)
631: devclose(file);
632: file->i_flgs = 0;
633: return (0);
634: }
635:
636: #ifndef SMALL
637: ioctl(fdesc, cmd, arg)
638: int fdesc, cmd;
639: char *arg;
640: {
641: register struct iob *file;
642: int error = 0;
643:
644: fdesc -= 3;
645: if (fdesc < 0 || fdesc >= NFILES ||
646: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
647: errno = EBADF;
648: return (-1);
649: }
650: switch (cmd) {
651:
652: case SAIOHDR:
653: file->i_flgs |= F_HDR;
654: break;
655:
656: case SAIOCHECK:
657: file->i_flgs |= F_CHECK;
658: break;
659:
660: case SAIOHCHECK:
661: file->i_flgs |= F_HCHECK;
662: break;
663:
664: case SAIONOBAD:
665: file->i_flgs |= F_NBSF;
666: break;
667:
668: case SAIODOBAD:
669: file->i_flgs &= ~F_NBSF;
670: break;
671:
672: default:
673: error = devioctl(file, cmd, arg);
674: break;
675: }
676: if (error < 0)
677: errno = file->i_error;
678: return (error);
679: }
680: #endif /* SMALL */
681:
682: exit()
683: {
684: _stop("Exit called");
685: }
686:
687: _stop(s)
688: char *s;
689: {
690: int i;
691:
692: for (i = 0; i < NFILES; i++)
693: if (iob[i].i_flgs != 0)
694: close(i);
695: printf("%s\n", s);
696: _rtt();
697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.