|
|
1.1 root 1: /*
2: * @(#)sys.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
3: */
4:
5: /*
6: * Basic file system reading code for standalone I/O system.
7: * Simulates a primitive UNIX I/O system (read(), write(), open(), etc).
8: * Does not attempt writes to file systems, tho writing to whole devices
9: * is supported, when the driver supports it.
10: */
11:
12: #include "param.h"
13: #include "saio.h"
14: #include "../h/dir.h"
15: #include "../h/time.h"
16: #include "../h/vnode.h"
17: #include "../ufs/fs.h"
18: #include "../ufs/inode.h"
19: /*
20: * This struct keeps track of an open file in the standalone I/O system.
21: *
22: * It includes an IOB for device addess, an inode, a buffer for reading
23: * indirect blocks and inodes, and a buffer for the superblock of the
24: * file system (if any).
25: */
26: struct iob {
27: struct saioreq i_si; /* I/O request block for this file */
28: struct inode i_ino; /* Inode for this file */
29: char i_buf[MAXBSIZE];/* Buffer for reading inodes & dirs */
30: union {
31: struct fs ui_fs; /* Superblock for file system */
32: char dummy[SBSIZE];
33: } i_un;
34: };
35: #define i_flgs i_si.si_flgs
36: #define i_boottab i_si.si_boottab
37: #define i_devdata i_si.si_devdata
38: #define i_ctlr i_si.si_ctlr
39: #define i_unit i_si.si_unit
40: #define i_boff i_si.si_boff
41: #define i_cyloff i_si.si_cyloff
42: #define i_offset i_si.si_offset
43: #define i_bn i_si.si_bn
44: #define i_ma i_si.si_ma
45: #define i_cc i_si.si_cc
46: #define i_fs i_un.ui_fs
47:
48: /* These are the pools of buffers, iob's, etc. */
49: #define NBUFS (NIADDR+1) /* NOT! a variable */
50: char b[NBUFS][MAXBSIZE];
51: daddr_t blknos[NBUFS];
52: struct iob iob[NFILES];
53:
54: ino_t dlook();
55:
56: struct dirstuff {
57: int loc;
58: struct iob *io;
59: };
60:
61: static
62: openi(n,io)
63: ino_t n;
64: register struct iob *io;
65: {
66: register struct dinode *dp;
67:
68: io->i_offset = 0;
69: io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n));
70: io->i_cc = io->i_fs.fs_bsize;
71: io->i_ma = io->i_buf;
72: /* FIXME: this call to devread() does not check for errors! */
73: devread(&io->i_si);
74: dp = (struct dinode *)io->i_buf;
75: io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
76: }
77:
78: static ino_t
79: find(path, file)
80: register char *path;
81: struct iob *file;
82: {
83: register char *q;
84: char c;
85: ino_t n;
86:
87: if (path==NULL || *path=='\0') {
88: printf("null path\n");
89: return(0);
90: }
91:
92: openi((ino_t) ROOTINO, file);
93: while (*path) {
94: while (*path == '/')
95: path++;
96: q = path;
97: while(*q != '/' && *q != '\0')
98: q++;
99: c = *q;
100: *q = '\0';
101:
102: if ((n=dlook(path, file))!=0) {
103: if (c=='\0')
104: break;
105: openi(n, file);
106: *q = c;
107: path = q;
108: continue;
109: } else {
110: printf("%s not found\n",path);
111: return(0);
112: }
113: }
114: return(n);
115: }
116:
117: static daddr_t
118: sbmap(io, bn)
119: register struct iob *io;
120: daddr_t bn;
121: {
122: register struct inode *ip;
123: register int i, j, sh;
124: register daddr_t nb, *bap;
125:
126: ip = &io->i_ino;
127:
128: /*
129: * blocks 0..NDADDR are direct blocks
130: */
131: if(bn < NDADDR) {
132: nb = ip->i_db[bn];
133: return(nb);
134: }
135:
136: #ifndef BOOTBLOCK
137: /*
138: * addresses NIADDR have single and double indirect blocks.
139: * the first step is to determine how many levels of indirection.
140: */
141: sh = 1;
142: bn -= NDADDR;
143: for (j = NIADDR; j > 0; j--) {
144: sh *= NINDIR(&io->i_fs);
145: if (bn < sh)
146: break;
147: bn -= sh;
148: }
149: if (j == 0) {
150: printf("bn ovf %D\n", bn);
151: return ((daddr_t)0);
152: }
153:
154: /*
155: * fetch the first indirect block address from the inode
156: */
157: nb = ip->i_ib[NIADDR - j];
158: if (nb == 0) {
159: printf("bn void %D\n",bn);
160: return((daddr_t)0);
161: }
162:
163: /*
164: * fetch through the indirect blocks
165: */
166: for (; j <= NIADDR; j++) {
167: if (blknos[j] != nb) {
168: io->i_bn = fsbtodb(&io->i_fs, nb);
169: io->i_ma = b[j];
170: io->i_cc = io->i_fs.fs_bsize;
171: if (devread(&io->i_si) != io->i_cc)
172: return((daddr_t)0);
173: blknos[j] = nb;
174: }
175: bap = (daddr_t *)b[j];
176: sh /= NINDIR(&io->i_fs);
177: i = (bn / sh) % NINDIR(&io->i_fs);
178: nb = bap[i];
179: if(nb == 0) {
180: printf("bn void %D\n",bn);
181: return((daddr_t)0);
182: }
183: }
184: return(nb);
185: #else BOOTBLOCK
186: return((daddr_t)0);
187: #endif BOOTBLOCK
188: }
189:
190: static ino_t
191: dlook(s, io)
192: char *s;
193: register struct iob *io;
194: {
195: register struct direct *dp;
196: register struct inode *ip;
197: struct dirstuff dirp;
198: register int len;
199:
200: ip = &io->i_ino;
201: #ifndef BOOTBLOCK
202: if (s == NULL || *s == '\0')
203: return(0);
204: if ((ip->i_mode&IFMT) != IFDIR) {
205: printf("not a directory\n");
206: return(0);
207: }
208: if (ip->i_size == 0) {
209: printf("zero length directory\n");
210: return(0);
211: }
212: #endif
213: len = strlen(s);
214: dirp.loc = 0;
215: dirp.io = io;
216: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
217: if(dp->d_ino == 0)
218: continue;
219: if (dp->d_namlen == len && !strcmp(s, dp->d_name))
220: return(dp->d_ino);
221: #ifndef BOOTBLOCK
222: /* Allow "*" to print all names at that level, w/out match */
223: if (!strcmp(s, "*"))
224: printf("%s\n", dp->d_name);
225: #endif
226: }
227: return(0);
228: }
229:
230: /*
231: * get next entry in a directory.
232: */
233: struct direct *
234: readdir(dirp)
235: register struct dirstuff *dirp;
236: {
237: register struct direct *dp;
238: register struct iob *io;
239: register daddr_t lbn, d;
240: register int off;
241:
242: io = dirp->io;
243: for(;;) {
244: if (dirp->loc >= io->i_ino.i_size)
245: return NULL;
246: off = blkoff(&io->i_fs, dirp->loc);
247: if (off == 0) {
248: lbn = lblkno(&io->i_fs, dirp->loc);
249: d = sbmap(io, lbn);
250: if(d == 0)
251: return NULL;
252: io->i_bn = fsbtodb(&io->i_fs, d);
253: io->i_ma = io->i_buf;
254: io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
255: if (devread(&io->i_si) != io->i_cc)
256: return NULL;
257: }
258: dp = (struct direct *)(io->i_buf + off);
259: dirp->loc += dp->d_reclen;
260: if (dp->d_ino == 0)
261: continue;
262: return (dp);
263: }
264: }
265:
266: lseek(fdesc, addr, ptr)
267: int fdesc;
268: register off_t addr;
269: int ptr;
270: {
271: register struct iob *io;
272:
273: #ifndef BOOTBLOCK
274: fdesc -= 3;
275: if (fdesc < 0 || fdesc >= NFILES ||
276: ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0)
277: return(-1);
278: #else
279: io = &iob[fdesc - 3];
280: #endif
281: io->i_si.si_flgs &= ~F_EOF;
282: io->i_offset = addr;
283: io->i_bn = addr / DEV_BSIZE;
284: io->i_cc = 0;
285: return(0);
286: }
287:
288: /* FIXME: possibly make this static and pass iob, eliminating assorted tests? */
289: getc(fdesc)
290: int fdesc;
291: {
292: register struct iob *io;
293: register struct fs *fs;
294: register char *p;
295: register int c, off, size, diff;
296: register daddr_t lbn;
297:
298:
299: #ifndef BOOTBLOCK
300: if (fdesc >= 0 && fdesc <= 2)
301: return(getchar());
302: fdesc -= 3;
303: if (fdesc < 0 || fdesc >= NFILES ||
304: ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
305: return(-1);
306: #else
307: io = &iob[fdesc -= 3];
308: #endif
309: p = io->i_ma;
310: if (io->i_cc <= 0) {
311: if ((io->i_flgs & F_FILE) != 0) {
312: diff = io->i_ino.i_size - io->i_offset;
313: if (diff <= 0)
314: return (-1);
315: fs = &io->i_fs;
316: lbn = lblkno(fs, io->i_offset);
317: io->i_bn = fsbtodb(fs, sbmap(io, lbn));
318: off = blkoff(fs, io->i_offset);
319: size = blksize(fs, &io->i_ino, lbn);
320: } else {
321: io->i_bn = io->i_offset / DEV_BSIZE;
322: off = 0;
323: size = DEV_BSIZE;
324: }
325: io->i_ma = io->i_buf;
326: io->i_cc = size;
327: if (devread(&io->i_si) != io->i_cc) /* Trap errors */
328: return(-1);
329: if ((io->i_flgs & F_FILE) != 0) {
330: if (io->i_offset - off + size >= io->i_ino.i_size)
331: io->i_cc = diff + off;
332: io->i_cc -= off;
333: }
334: p = &io->i_buf[off];
335: }
336: io->i_cc--;
337: io->i_offset++;
338: c = (unsigned)*p++;
339: io->i_ma = p;
340: return(c);
341: }
342:
343:
344: read(fdesc, buf, count)
345: int fdesc;
346: register char *buf;
347: int count;
348: {
349: register i,j;
350: register struct iob *file;
351:
352: #ifndef BOOTBLOCK
353: if (fdesc >= 0 && fdesc <= 2) {
354: i = count;
355: do {
356: *buf = getchar();
357: } while (--i && *buf++ != '\n');
358: return(count - i);
359: }
360: fdesc -= 3;
361: if (fdesc < 0 || fdesc >= NFILES ||
362: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
363: return(-1);
364: if ((file->i_flgs&F_READ) == 0)
365: return(-1);
366: fdesc += 3;
367: #else BOOTBLOCK
368: file = &iob[fdesc - 3];
369: #endif BOOTBLOCK
370: if ((file->i_flgs & F_FILE) == 0) {
371: file->i_cc = count;
372: file->i_ma = buf;
373: file->i_bn = (file->i_offset / DEV_BSIZE);
374: i = devread(&file->i_si);
375: file->i_offset += count;
376: return(i);
377: } else {
378: if (file->i_offset+count > file->i_ino.i_size)
379: count = file->i_ino.i_size - file->i_offset;
380: if ((i = count) <= 0)
381: return(0);
382: #ifdef BOOTBLOCK
383: do {
384: *buf++ = getc(fdesc);
385: } while (--i);
386: #else BOOTBLOCK
387: while (i > 0) {
388: if ((j = file->i_cc) <= 0) {
389: *buf++ = getc(fdesc);
390: i--;
391: } else {
392: if (i < j)
393: j = i;
394: bcopy(file->i_ma, buf, (unsigned)j);
395: buf += j;
396: file->i_ma += j;
397: file->i_offset += j;
398: file->i_cc -= j;
399: i -= j;
400: }
401: }
402: #endif BOOTBLOCK
403: return(count);
404: }
405: }
406:
407: #ifndef BOOTBLOCK
408: write(fdesc, buf, count)
409: int fdesc;
410: char *buf;
411: int count;
412: {
413: register i;
414: register struct iob *file;
415:
416: if (fdesc >= 0 && fdesc <= 2) {
417: i = count;
418: while (i--)
419: putchar(*buf++);
420: return(count);
421: }
422: fdesc -= 3;
423: if (fdesc < 0 || fdesc >= NFILES ||
424: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
425: return(-1);
426: if ((file->i_flgs&F_WRITE) == 0)
427: return(-1);
428: if (count % DEV_BSIZE)
429: printf("count=%d?\n", count);
430: file->i_cc = count;
431: file->i_ma = buf;
432: file->i_bn = (file->i_offset / DEV_BSIZE);
433: i = devwrite(&file->i_si);
434: file->i_offset += count;
435: return(i);
436: }
437: #endif BOOTBLOCK
438:
439: /*
440: * Open a file on a physical device, or open the device itself.
441: *
442: * The device is identified by a struct bootparam which gives pointers
443: * to the struct boottab, containing the device open, strategy and close
444: * routines; and the device parameters such as controller #, unit #, etc.
445: *
446: * If *str == 0, the device is opened, else the named file in the file
447: * system on the device is opened.
448: */
449: int
450: physopen(bp, str, how)
451: register struct bootparam *bp;
452: char *str;
453: int how;
454: {
455: int fdesc;
456: register struct iob *file;
457:
458: #ifdef BOOTBLOCK
459: fdesc = 0;
460: file = &iob[0];
461: file->i_flgs |= F_ALLOC;
462: #else BOOTBLOCK
463: fdesc = getiob(); /* Allocate an IOB */
464: file = &iob[fdesc];
465: #endif BOOTBLOCK
466:
467: file->i_boottab = bp->bp_boottab; /* Record pointer to boot table */
468: file->i_ctlr = bp->bp_ctlr;
469: file->i_unit = bp->bp_unit;
470: file->i_boff = bp->bp_part;
471: file->i_ino.i_dev = 0; /* Call it device 0 for chuckles */
472:
473: return(openfile(fdesc, file, str, how));
474: }
475:
476: #ifndef BOOTBLOCK
477:
478: int openfirst = 1;
479:
480: /*
481: * Allocate an IOB for a newly opened file.
482: */
483: int
484: getiob()
485: {
486: register int fdesc;
487:
488: if (openfirst) {
489: openfirst = 0;
490: for (fdesc = 0; fdesc < NFILES; fdesc++)
491: iob[fdesc].i_flgs = 0;
492: }
493:
494: for (fdesc = 0; fdesc < NFILES; fdesc++)
495: if (iob[fdesc].i_flgs == 0)
496: goto gotfile;
497: _stop("No more file slots");
498: gotfile:
499: (&iob[fdesc])->i_flgs |= F_ALLOC;
500: return fdesc;
501: }
502:
503: /* Hex string scanner for open() */
504: static char *
505: openhex(p, ip)
506: register char *p;
507: int *ip;
508: {
509: register int ac = 0;
510:
511: while (*p) {
512: if (*p >= '0' && *p <= '9')
513: ac = (ac<<4) + (*p - '0');
514: else if (*p >= 'a' && *p <= 'f')
515: ac = (ac<<4) + (*p - 'a' + 10);
516: else if (*p >= 'A' && *p <= 'F')
517: ac = (ac<<4) + (*p - 'A' + 10);
518: else
519: break;
520: p++;
521: }
522: if (*p == ',')
523: p++;
524: *ip = ac;
525: return (p);
526: }
527:
528: /*
529: * Open a device or file-in-file-system-on-device.
530: */
531: int
532: open(str, how)
533: char *str;
534: int how;
535: {
536: register char *cp;
537: register struct iob *file;
538: register struct boottab *dp;
539: register struct boottab **tablep;
540: int fdesc;
541: long atol();
542:
543: extern struct boottab *(devsw[]);
544:
545: fdesc = getiob(); /* Allocate an IOB */
546: file = &iob[fdesc];
547:
548: for (cp = str; *cp && *cp != '('; cp++)
549: ;
550: if (*cp++ != '(') {
551: file->i_flgs = 0;
552: goto badsyntax;
553: }
554: for (tablep = devsw; 0 != (dp = *tablep); tablep++) {
555: if (str[0] == dp->b_dev[0] && str[1] == dp->b_dev[1])
556: goto gotdev;
557: }
558: printf("Unknown device: %c%c; known devices:\n", str[0], str[1]);
559: for (tablep = devsw; 0 != (dp = *tablep); tablep++)
560: printf(" %s\n", dp->b_desc);
561: file->i_flgs = 0;
562: return(-1);
563: gotdev:
564: file->i_boottab = dp; /* Record pointer to boot table */
565: file->i_ino.i_dev = tablep-devsw;
566: #ifdef sun
567: cp = openhex(cp, &file->i_ctlr);
568: #endif
569: cp = openhex(cp, &file->i_unit);
570: cp = openhex(cp, (int *)&file->i_boff);
571: if (*cp == '\0') goto doit;
572: if (*cp != ')') {
573: badsyntax:
574: printf("%s: bad syntax, try dev(ctlr,unit,part)name\n", str);
575: return -1;
576: }
577: do
578: cp++;
579: while (*cp == ' ');
580:
581: doit:
582: return(openfile(fdesc, file, cp, how));
583: }
584: #endif NOOPEN
585:
586:
587: /*
588: * File processing for open call
589: */
590: openfile(fdesc, file, cp, how)
591: int fdesc;
592: struct iob *file;
593: char *cp;
594: int how;
595: {
596: ino_t ino;
597:
598: if (devopen(&file->i_si)) {
599: file->i_flgs = 0;
600: return(-1); /* if devopen fails, open fails */
601: }
602:
603: if (*cp == '\0') { /* Opening a device */
604: file->i_flgs |= how+1;
605: file->i_cc = 0;
606: file->i_offset = 0;
607: return(fdesc+3);
608: }
609: /* Opening a file system; read the superblock. */
610: file->i_ma = (char *)(&file->i_fs);
611: file->i_cc = SBSIZE;
612: file->i_bn = SBLOCK;
613: file->i_offset = 0;
614: if (devread(&file->i_si) != SBSIZE) {
615: file->i_flgs = 0;
616: return(-1);
617: }
618: #ifndef BOOTBLOCK
619: if (file->i_fs.fs_magic != FS_MAGIC) {
620: printf("Not a file system\n");
621: return(-1);
622: }
623: #endif
624: if ((ino = find(cp, file)) == 0) {
625: file->i_flgs = 0;
626: return(-1);
627: }
628: #ifndef BOOTBLOCK
629: if (how != 0) {
630: printf("Can't write files yet.. Sorry\n");
631: file->i_flgs = 0;
632: return(-1);
633: }
634: #endif
635: openi(ino, file);
636: file->i_offset = 0;
637: file->i_cc = 0;
638: file->i_flgs |= F_FILE | (how+1);
639: return(fdesc+3);
640: }
641:
642:
643: close(fdesc)
644: int fdesc;
645: {
646: register struct iob *file;
647:
648: fdesc -= 3;
649: if (fdesc < 0 || fdesc >= NFILES ||
650: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
651: return(-1);
652: devclose(&file->i_si); /* For a file-in-filesys or for raw dev */
653: file->i_flgs = 0;
654: return(0);
655: }
656:
657: exit()
658: {
659: _stop((char *)0);
660: }
661:
662: _stop(s)
663: char *s;
664: {
665: register int i;
666:
667: for (i = 0; i < NFILES; i++)
668: if (iob[i].i_flgs != 0)
669: close(i);
670: if (s) printf("%s\n", s);
671: _exit();
672: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.