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