|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)sys.c 7.2 (Berkeley) 7/1/90
21: */
22:
23: #include "saio.h"
24: #include "ufs/dir.h"
25: #ifndef SMALL
26: #include "sys/stat.h"
27: #endif
28:
29: ino_t dlook();
30:
31: struct dirstuff {
32: int loc;
33: struct iob *io;
34: };
35:
36: static
37: openi(n, io)
38: register struct iob *io;
39: {
40: register struct dinode *dp;
41: int cc;
42:
43: io->i_offset = 0;
44: io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
45: io->i_cc = io->i_fs.fs_bsize;
46: io->i_ma = io->i_buf;
47: cc = devread(io);
48: dp = (struct dinode *)io->i_buf;
49: io->i_ino = dp[itoo(&io->i_fs, n)];
50: return (cc);
51: }
52:
53: static
54: find(path, file)
55: register char *path;
56: struct iob *file;
57: {
58: register char *q;
59: char c;
60: int n;
61:
62: if (path==NULL || *path=='\0') {
63: printf("null path\n");
64: return (0);
65: }
66:
67: if (openi((ino_t) ROOTINO, file) < 0) {
68: printf("can't read root inode\n");
69: return (0);
70: }
71: while (*path) {
72: while (*path == '/')
73: path++;
74: q = path;
75: while(*q != '/' && *q != '\0')
76: q++;
77: c = *q;
78: *q = '\0';
79: if (q == path) path = "." ; /* "/" means "/." */
80:
81: if ((n = dlook(path, file)) != 0) {
82: if (c == '\0')
83: break;
84: if (openi(n, file) < 0)
85: return (0);
86: *q = c;
87: path = q;
88: continue;
89: } else {
90: printf("%s: not found\n", path);
91: return (0);
92: }
93: }
94: return (n);
95: }
96:
97: static daddr_t
98: sbmap(io, bn)
99: register struct iob *io;
100: daddr_t bn;
101: {
102: register struct dinode *ip;
103: int i, j, sh;
104: daddr_t nb, *bap;
105:
106: ip = &io->i_ino;
107: if (bn < 0) {
108: printf("bn negative\n");
109: return ((daddr_t)0);
110: }
111:
112: /*
113: * blocks 0..NDADDR are direct blocks
114: */
115: if(bn < NDADDR) {
116: nb = ip->di_db[bn];
117: return (nb);
118: }
119:
120: /*
121: * addresses NIADDR have single and double indirect blocks.
122: * the first step is to determine how many levels of indirection.
123: */
124: sh = 1;
125: bn -= NDADDR;
126: for (j = NIADDR; j > 0; j--) {
127: sh *= NINDIR(&io->i_fs);
128: if (bn < sh)
129: break;
130: bn -= sh;
131: }
132: if (j == 0) {
133: printf("bn ovf %D\n", bn);
134: return ((daddr_t)0);
135: }
136:
137: /*
138: * fetch the first indirect block address from the inode
139: */
140: nb = ip->di_ib[NIADDR - j];
141: if (nb == 0) {
142: printf("bn void %D\n",bn);
143: return ((daddr_t)0);
144: }
145:
146: /*
147: * fetch through the indirect blocks
148: */
149: for (; j <= NIADDR; j++) {
150: if (blknos[j] != nb) {
151: io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
152: io->i_ma = b[j];
153: io->i_cc = io->i_fs.fs_bsize;
154: if (devread(io) != io->i_fs.fs_bsize) {
155: if (io->i_error)
156: errno = io->i_error;
157: printf("bn %D: read error\n", io->i_bn);
158: return ((daddr_t)0);
159: }
160: blknos[j] = nb;
161: }
162: bap = (daddr_t *)b[j];
163: sh /= NINDIR(&io->i_fs);
164: i = (bn / sh) % NINDIR(&io->i_fs);
165: nb = bap[i];
166: if(nb == 0) {
167: printf("bn void %D\n",bn);
168: return ((daddr_t)0);
169: }
170: }
171: return (nb);
172: }
173:
174: static ino_t
175: dlook(s, io)
176: char *s;
177: register struct iob *io;
178: {
179: register struct direct *dp;
180: struct direct *readdir();
181: register struct dinode *ip;
182: struct dirstuff dirp;
183: int len;
184:
185: if (s == NULL || *s == '\0')
186: return (0);
187: ip = &io->i_ino;
188: if ((ip->di_mode&IFMT) != IFDIR) {
189: printf("not a directory\n");
190: printf("%s: not a directory\n", s);
191: return (0);
192: }
193: if (ip->di_size == 0) {
194: printf("%s: zero length directory\n", s);
195: return (0);
196: }
197: len = strlen(s);
198: dirp.loc = 0;
199: dirp.io = io;
200: for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
201: if(dp->d_ino == 0)
202: continue;
203: if (dp->d_namlen == len && !strcmp(s, dp->d_name))
204: return (dp->d_ino);
205: }
206: return (0);
207: }
208:
209: /*
210: * get next entry in a directory.
211: */
212: struct direct *
213: readdir(dirp)
214: register struct dirstuff *dirp;
215: {
216: register struct direct *dp;
217: register struct iob *io;
218: daddr_t lbn, d;
219: int off;
220:
221: io = dirp->io;
222: for(;;) {
223: if (dirp->loc >= io->i_ino.di_size)
224: return (NULL);
225: off = blkoff(&io->i_fs, dirp->loc);
226: if (off == 0) {
227: lbn = lblkno(&io->i_fs, dirp->loc);
228: d = sbmap(io, lbn);
229: if(d == 0)
230: return NULL;
231: io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
232: io->i_ma = io->i_buf;
233: io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
234: if (devread(io) < 0) {
235: errno = io->i_error;
236: printf("bn %D: directory read error\n",
237: io->i_bn);
238: return (NULL);
239: }
240: }
241: dp = (struct direct *)(io->i_buf + off);
242: dirp->loc += dp->d_reclen;
243: if (dp->d_ino == 0)
244: continue;
245: return (dp);
246: }
247: }
248:
249: lseek(fdesc, addr, ptr)
250: int fdesc, ptr;
251: off_t addr;
252: {
253: register struct iob *io;
254:
255: #ifndef SMALL
256: if (ptr != 0) {
257: printf("Seek not from beginning of file\n");
258: errno = EOFFSET;
259: return (-1);
260: }
261: #endif SMALL
262: fdesc -= 3;
263: if (fdesc < 0 || fdesc >= NFILES ||
264: ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
265: errno = EBADF;
266: return (-1);
267: }
268: io->i_offset = addr;
269: io->i_bn = addr / DEV_BSIZE;
270: io->i_cc = 0;
271: return (0);
272: }
273:
274: getc(fdesc)
275: int fdesc;
276: {
277: register struct iob *io;
278: register struct fs *fs;
279: register char *p;
280: int c, lbn, off, size, diff;
281:
282:
283: if (fdesc >= 0 && fdesc <= 2)
284: return (getchar());
285: fdesc -= 3;
286: if (fdesc < 0 || fdesc >= NFILES ||
287: ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
288: errno = EBADF;
289: return (-1);
290: }
291: p = io->i_ma;
292: if (io->i_cc <= 0) {
293: if ((io->i_flgs & F_FILE) != 0) {
294: diff = io->i_ino.di_size - io->i_offset;
295: if (diff <= 0)
296: return (-1);
297: fs = &io->i_fs;
298: lbn = lblkno(fs, io->i_offset);
299: io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
300: off = blkoff(fs, io->i_offset);
301: size = dblksize(fs, &io->i_ino, lbn);
302: } else {
303: io->i_bn = io->i_offset / DEV_BSIZE;
304: off = 0;
305: size = DEV_BSIZE;
306: }
307: io->i_ma = io->i_buf;
308: io->i_cc = size;
309: if (devread(io) < 0) {
310: errno = io->i_error;
311: return (-1);
312: }
313: if ((io->i_flgs & F_FILE) != 0) {
314: if (io->i_offset - off + size >= io->i_ino.di_size)
315: io->i_cc = diff + off;
316: io->i_cc -= off;
317: }
318: p = &io->i_buf[off];
319: }
320: io->i_cc--;
321: io->i_offset++;
322: c = (unsigned)*p++;
323: io->i_ma = p;
324: return (c);
325: }
326:
327: int errno;
328:
329: read(fdesc, buf, count)
330: int fdesc, count;
331: char *buf;
332: {
333: register i, size;
334: register struct iob *file;
335: register struct fs *fs;
336: int lbn, off;
337:
338: errno = 0;
339: if (fdesc >= 0 & fdesc <= 2) {
340: i = count;
341: do {
342: *buf = getchar();
343: } while (--i && *buf++ != '\n');
344: return (count - i);
345: }
346: fdesc -= 3;
347: if (fdesc < 0 || fdesc >= NFILES ||
348: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
349: errno = EBADF;
350: return (-1);
351: }
352: if ((file->i_flgs&F_READ) == 0) {
353: errno = EBADF;
354: return (-1);
355: }
356: #ifndef SMALL
357: if ((file->i_flgs & F_FILE) == 0) {
358: file->i_cc = count;
359: file->i_ma = buf;
360: file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
361: i = devread(file);
362: file->i_offset += count;
363: if (i < 0)
364: errno = file->i_error;
365: return (i);
366: }
367: #endif SMALL
368: if (file->i_offset+count > file->i_ino.di_size)
369: count = file->i_ino.di_size - file->i_offset;
370: if ((i = count) <= 0)
371: return (0);
372: /*
373: * While reading full blocks, do I/O into user buffer.
374: * Anything else uses getc().
375: */
376: fs = &file->i_fs;
377: while (i) {
378: off = blkoff(fs, file->i_offset);
379: lbn = lblkno(fs, file->i_offset);
380: size = dblksize(fs, &file->i_ino, lbn);
381: if (off == 0 && size <= i) {
382: file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
383: file->i_boff;
384: file->i_cc = size;
385: file->i_ma = buf;
386: if (devread(file) < 0) {
387: errno = file->i_error;
388: return (-1);
389: }
390: file->i_offset += size;
391: file->i_cc = 0;
392: buf += size;
393: i -= size;
394: } else {
395: size -= off;
396: if (size > i)
397: size = i;
398: i -= size;
399: do {
400: *buf++ = getc(fdesc+3);
401: } while (--size);
402: }
403: }
404: return (count);
405: }
406:
407: #ifndef SMALL
408: write(fdesc, buf, count)
409: int fdesc, count;
410: char *buf;
411: {
412: register i;
413: register struct iob *file;
414:
415: errno = 0;
416: if (fdesc >= 0 && fdesc <= 2) {
417: i = count;
418: while (i--)
419: putchar(0, *buf++);
420: return (count);
421: }
422: fdesc -= 3;
423: if (fdesc < 0 || fdesc >= NFILES ||
424: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
425: errno = EBADF;
426: return (-1);
427: }
428: if ((file->i_flgs&F_WRITE) == 0) {
429: errno = EBADF;
430: return (-1);
431: }
432: file->i_cc = count;
433: file->i_ma = buf;
434: file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
435: i = devwrite(file);
436: file->i_offset += count;
437: if (i < 0)
438: errno = file->i_error;
439: return (i);
440: }
441: #endif SMALL
442:
443: int openfirst = 1;
444: #ifdef notyet
445: int opendev; /* last device opened; for boot to set bootdev */
446: extern int bootdev;
447: #endif notyet
448:
449: open(str, how)
450: char *str;
451: int how;
452: {
453: register char *cp;
454: int i;
455: register struct iob *file;
456: register struct devsw *dp;
457: int fdesc;
458: long atol();
459:
460: if (openfirst) {
461: for (i = 0; i < NFILES; i++)
462: iob[i].i_flgs = 0;
463: openfirst = 0;
464: }
465:
466: for (fdesc = 0; fdesc < NFILES; fdesc++)
467: if (iob[fdesc].i_flgs == 0)
468: goto gotfile;
469: _stop("No more file slots");
470: gotfile:
471: (file = &iob[fdesc])->i_flgs |= F_ALLOC;
472:
473: #ifdef notyet
474: for (cp = str; *cp && *cp != '/' && *cp != ':'; cp++)
475: ;
476: if (*cp != ':') {
477: /* default bootstrap unit and device */
478: file->i_dev = bootdev;
479: cp = str;
480: } else {
481: # define isdigit(n) ((n>='0') && (n<='9'))
482: /*
483: * syntax for possible device name:
484: * <alpha-string><digit-string><letter>:
485: */
486: for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
487: ;
488: for (dp = devsw; dp->dv_name; dp++) {
489: if (!strncmp(str, dp->dv_name,cp-str))
490: goto gotdev;
491: }
492: printf("unknown device\n");
493: file->i_flgs = 0;
494: errno = EDEV;
495: return (-1);
496: gotdev:
497: i = 0;
498: while (*cp >= '0' && *cp <= '9')
499: i = i * 10 + *cp++ - '0';
500: if (i < 0 || i > 255) {
501: printf("minor device number out of range (0-255)\n");
502: file->i_flgs = 0;
503: errno = EUNIT;
504: return (-1);
505: }
506: if (*cp >= 'a' && *cp <= 'h') {
507: if (i > 31) {
508: printf("unit number out of range (0-31)\n");
509: file->i_flgs = 0;
510: errno = EUNIT;
511: return (-1);
512: }
513: i = make_minor(i, *cp++ - 'a');
514: }
515:
516: if (*cp++ != ':') {
517: printf("incorrect device specification\n");
518: file->i_flgs = 0;
519: errno = EOFFSET;
520: return (-1);
521: }
522: opendev = file->i_dev = makedev(dp-devsw, i);
523: }
524: file->i_boff = 0;
525: devopen(file);
526: if (cp != str && *cp == '\0') {
527: file->i_flgs |= how+1;
528: file->i_cc = 0;
529: file->i_offset = 0;
530: return (fdesc+3);
531: }
532: #else notyet
533: for (cp = str; *cp && *cp != '('; cp++)
534: ;
535: if (*cp != '(') {
536: printf("Bad device\n");
537: file->i_flgs = 0;
538: errno = EDEV;
539: return (-1);
540: }
541: *cp = '\0';
542: for (dp = devsw; dp->dv_name; dp++)
543: if (!strcmp(str, dp->dv_name))
544: break;
545: *cp++ = '(';
546: if (dp->dv_name == NULL) {
547: printf("Unknown device\n");
548: file->i_flgs = 0;
549: errno = ENXIO;
550: return (-1);
551: }
552: file->i_dev = dp-devsw;
553: file->i_unit = *cp++ - '0';
554: if (*cp >= '0' && *cp <= '9')
555: file->i_unit = file->i_unit * 10 + *cp++ - '0';
556: if (file->i_unit < 0 || file->i_unit > 63) {
557: printf("Bad unit specifier\n");
558: file->i_flgs = 0;
559: errno = EUNIT;
560: return (-1);
561: }
562: if (*cp++ != ',') {
563: badoff:
564: printf("Missing offset specification\n");
565: file->i_flgs = 0;
566: errno = EOFFSET;
567: return (-1);
568: }
569: file->i_boff = atol(cp);
570: for (;;) {
571: if (*cp == ')')
572: break;
573: if (*cp++)
574: continue;
575: goto badoff;
576: }
577: devopen(file);
578: if (*++cp == '\0') {
579: file->i_flgs |= how+1;
580: file->i_cc = 0;
581: file->i_offset = 0;
582: return (fdesc+3);
583: }
584: #endif notyet
585: file->i_ma = (char *)(&file->i_fs);
586: file->i_cc = SBSIZE;
587: file->i_bn = SBLOCK + file->i_boff;
588: file->i_offset = 0;
589: if (devread(file) < 0) {
590: errno = file->i_error;
591: printf("super block read error\n");
592: return (-1);
593: }
594: if ((i = find(cp, file)) == 0) {
595: file->i_flgs = 0;
596: errno = ESRCH;
597: return (-1);
598: }
599: #ifndef SMALL
600: if (how != 0) {
601: printf("Can't write files yet.. Sorry\n");
602: file->i_flgs = 0;
603: errno = EIO;
604: return (-1);
605: }
606: #endif SMALL
607: if (openi(i, file) < 0) {
608: errno = file->i_error;
609: return (-1);
610: }
611: file->i_offset = 0;
612: file->i_cc = 0;
613: file->i_flgs |= F_FILE | (how+1);
614: return (fdesc+3);
615: }
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: exit()
635: {
636: _stop("Exit called");
637: }
638:
639: _stop(s)
640: char *s;
641: {
642: static int stopped = 0;
643: int i;
644:
645: if (!stopped) {
646: stopped++;
647: for (i = 0; i < NFILES; i++)
648: if (iob[i].i_flgs != 0)
649: close(i);
650: }
651: printf("%s\n", s);
652: _rtt();
653: }
654:
655: #ifndef SMALL
656: ioctl(fdesc, cmd, arg)
657: int fdesc, cmd;
658: char *arg;
659: {
660: register struct iob *file;
661: int error = 0;
662:
663: fdesc -= 3;
664: if (fdesc < 0 || fdesc >= NFILES ||
665: ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
666: errno = EBADF;
667: return (-1);
668: }
669: switch (cmd) {
670:
671: case SAIOHDR:
672: file->i_flgs |= F_HDR;
673: break;
674:
675: case SAIOCHECK:
676: file->i_flgs |= F_CHECK;
677: break;
678:
679: case SAIOHCHECK:
680: file->i_flgs |= F_HCHECK;
681: break;
682:
683: case SAIONOBAD:
684: file->i_flgs |= F_NBSF;
685: break;
686:
687: case SAIODOBAD:
688: file->i_flgs &= ~F_NBSF;
689: break;
690:
691: default:
692: error = devioctl(file, cmd, arg);
693: break;
694: }
695: if (error < 0)
696: errno = file->i_error;
697: return (error);
698: }
699:
700: extern char end;
701: static caddr_t theend = 0;
702:
703: caddr_t
704: brk(addr)
705: char *addr;
706: {
707: char stkloc;
708:
709: if (theend == (caddr_t)0)
710: theend = &end;
711: if (addr > &stkloc || addr < &end)
712: return((caddr_t)-1);
713: if (addr > theend)
714: bzero(theend, addr-theend);
715: theend = addr;
716: return(0);
717: }
718:
719: caddr_t
720: sbrk(incr)
721: int incr;
722: {
723: caddr_t obrk, brk();
724:
725: if (theend == (caddr_t)0)
726: theend = &end;
727: obrk = theend;
728: if (brk(theend+incr) == (caddr_t)-1)
729: return((caddr_t)-1);
730: return(obrk);
731: }
732:
733: getpagesize()
734: {
735: return(NBPG);
736: }
737:
738: getdtablesize()
739: {
740: return(NFILES);
741: }
742:
743: fstat(fdesc, sb)
744: struct stat *sb;
745: {
746: register struct iob *io;
747:
748: fdesc -= 3;
749: if (fdesc < 0 || fdesc >= NFILES ||
750: ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
751: errno = EBADF;
752: return (-1);
753: }
754: /* only important stuff */
755: sb->st_mode = io->i_ino.di_mode;
756: sb->st_uid = io->i_ino.di_uid;
757: sb->st_gid = io->i_ino.di_gid;
758: sb->st_size = io->i_ino.di_size;
759: return (0);
760: }
761:
762: stat(str, sb)
763: {
764: /* the easy way */
765: int f, rv = 0;
766:
767: f = open(str, 0);
768: if (f < 0 || fstat(f, sb) < 0)
769: rv = -1;
770: (void) close(f);
771: return(rv);
772: }
773:
774: #endif SMALL
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.