+#include <sys/param.h>
+#include <sys/ino.h>
+#include <sys/inode.h>
+#include <sys/filsys.h>
+#include <sys/dir.h>
+#include "saio.h"
+
+ino_t dlook();
+
+static
+openi(n,io)
+register struct iob *io;
+{
+ register struct dinode *dp;
+
+ io->i_offset = 0;
+ io->i_bn = fsbtodb(itod(n)) + io->i_boff;
+ io->i_cc = BSIZE;
+ io->i_ma = io->i_buf;
+ devread(io);
+
+ dp = (struct dinode *)io->i_buf;
+ dp = &dp[itoo(n)];
+ io->i_ino.i_number = n;
+ io->i_ino.i_mode = dp->di_mode;
+ io->i_ino.i_size = dp->di_size;
+ l3tol((char *)io->i_ino.i_un.i_addr, (char *)dp->di_addr, NADDR);
+}
+
+static
+find(path, file)
+register char *path;
+struct iob *file;
+{
+ register char *q;
+ char c;
+ int n;
+
+ if (path==NULL || *path=='\0') {
+ printf("null path\n");
+ return(0);
+ }
+
+ openi((ino_t) ROOTINO, file);
+ while (*path) {
+ while (*path == '/')
+ path++;
+ q = path;
+ while(*q != '/' && *q != '\0')
+ q++;
+ c = *q;
+ *q = '\0';
+
+ if ((n=dlook(path, file))!=0) {
+ if (c=='\0')
+ break;
+ openi(n, file);
+ *q = c;
+ path = q;
+ continue;
+ } else {
+ printf("%s not found\n",path);
+ return(0);
+ }
+ }
+ return(n);
+}
+
+static daddr_t
+sbmap(io, bn)
+register struct iob *io;
+daddr_t bn;
+{
+ register i;
+ register struct inode *ip;
+ int j, sh;
+ daddr_t nb, *bap;
+ int ibn = bn;
+
+ ip = &io->i_ino;
+ if(bn < 0) {
+ printf("bn negative\n");
+ return((daddr_t)0);
+ }
+
+ /*
+ * blocks 0..NADDR-4 are direct blocks
+ */
+ if(bn < NADDR-3) {
+ i = bn;
+ nb = ip->i_un.i_addr[i];
+ return(nb);
+ }
+
+ /*
+ * addresses NADDR-3, NADDR-2, and NADDR-1
+ * have single, double, triple indirect blocks.
+ * the first step is to determine
+ * how many levels of indirection.
+ */
+ sh = 0;
+ nb = 1;
+ bn -= NADDR-3;
+ for(j=3; j>0; j--) {
+ sh += NSHIFT;
+ nb <<= NSHIFT;
+ if(bn < nb)
+ break;
+ bn -= nb;
+ }
+ if(j == 0) {
+ printf("bn ovf %D\n",bn);
+ return((daddr_t)0);
+ }
+
+ /*
+ * fetch the address from the inode
+ */
+ nb = ip->i_un.i_addr[NADDR-j];
+ if(nb == 0) {
+ printf("bn void %D\n",bn);
+ return((daddr_t)0);
+ }
+
+ /*
+ * fetch through the indirect blocks
+ */
+ for(; j<=3; j++) {
+ if (blknos[j] != nb) {
+ io->i_bn = fsbtodb(nb) + io->i_boff;
+ io->i_ma = b[j];
+ io->i_cc = BSIZE;
+ devread(io);
+ bap = (daddr_t *)b[j];
+ blknos[j] = nb;
+ }
+ bap = (daddr_t *)b[j];
+ sh -= NSHIFT;
+ i = (bn>>sh) & NMASK;
+ nb = bap[i];
+ if(nb == 0) {
+ printf("bn void %D\n",bn);
+ return((daddr_t)0);
+ }
+ }
+ return(nb);
+}
+
+static ino_t
+dlook(s, io)
+char *s;
+register struct iob *io;
+{
+ register struct direct *dp;
+ register struct inode *ip;
+ daddr_t bn;
+ int n,dc;
+
+ if (s==NULL || *s=='\0')
+ return(0);
+ ip = &io->i_ino;
+ if ((ip->i_mode&IFMT)!=IFDIR) {
+ printf("not a directory\n");
+ return(0);
+ }
+
+ n = ip->i_size/sizeof(struct direct);
+
+ if (n==0) {
+ printf("zero length directory\n");
+ return(0);
+ }
+
+ dc = BSIZE;
+ bn = (daddr_t)0;
+ while(n--) {
+ if (++dc >= BSIZE/sizeof(struct direct)) {
+ io->i_bn = fsbtodb(sbmap(io, bn++)) + io->i_boff;
+ io->i_ma = io->i_buf;
+ io->i_cc = BSIZE;
+ devread(io);
+ dp = (struct direct *)io->i_buf;
+ dc = 0;
+ }
+
+ if (match(s, dp->d_name))
+ return(dp->d_ino);
+ dp++;
+ }
+ return(0);
+}
+
+static
+match(s1,s2)
+register char *s1,*s2;
+{
+ register cc;
+
+ cc = DIRSIZ;
+ while (cc--) {
+ if (*s1 != *s2)
+ return(0);
+ if (*s1++ && *s2++)
+ continue; else
+ return(1);
+ }
+ return(1);
+}
+
+lseek(fdesc, addr, ptr)
+int fdesc;
+off_t addr;
+int ptr;
+{
+ register struct iob *io;
+
+ if (ptr != 0) {
+ printf("Seek not from beginning of file\n");
+ return(-1);
+ }
+ fdesc -= 3;
+ if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
+ return(-1);
+ io->i_offset = addr;
+ io->i_bn = fsbtodb(addr/BSIZE) + io->i_boff;
+ io->i_cc = 0;
+ return(0);
+}
+
+getc(fdesc)
+int fdesc;
+{
+ register struct iob *io;
+ register char *p;
+ register c;
+ int off;
+
+
+ if (fdesc >= 0 && fdesc <= 2)
+ return(getchar());
+ fdesc -= 3;
+ if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
+ return(-1);
+ p = io->i_ma;
+ if (io->i_cc <= 0) {
+ io->i_bn = fsbtodb(io->i_offset/(off_t)BSIZE);
+ if (io->i_flgs&F_FILE)
+ io->i_bn = fsbtodb(sbmap(io, dbtofsb(io->i_bn))) + io->i_boff;
+ io->i_ma = io->i_buf;
+ io->i_cc = BSIZE;
+ devread(io);
+ if (io->i_flgs&F_FILE) {
+ off = io->i_offset % (off_t)BSIZE;
+ if (io->i_offset+(BSIZE-off) >= io->i_ino.i_size)
+ io->i_cc = io->i_ino.i_size - io->i_offset + off;
+ io->i_cc -= off;
+ if (io->i_cc <= 0)
+ return(-1);
+ } else
+ off = 0;
+ p = &io->i_buf[off];
+ }
+ io->i_cc--;
+ io->i_offset++;
+ c = (unsigned)*p++;
+ io->i_ma = p;
+ return(c);
+}
+/* does this port?
+getw(fdesc)
+int fdesc;
+{
+ register w,i;
+ register char *cp;
+ int val;
+
+ for (i = 0, val = 0, cp = &val; i < sizeof(val); i++) {
+ w = getc(fdesc);
+ if (w < 0) {
+ if (i == 0)
+ return(-1);
+ else
+ return(val);
+ }
+ *cp++ = w;
+ }
+ return(val);
+}
+*/
+
+read(fdesc, buf, count)
+int fdesc;
+char *buf;
+int count;
+{
+ register i;
+ register struct iob *file;
+
+ if (fdesc >= 0 & fdesc <= 2) {
+ i = count;
+ do {
+ *buf = getchar();
+ } while (--i && *buf++ != '\n');
+ return(count - i);
+ }
+ fdesc -= 3;
+ if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
+ return(-1);
+ if ((file->i_flgs&F_READ) == 0)
+ return(-1);
+ if ((file->i_flgs&F_FILE) == 0) {
+ file->i_cc = count;
+ file->i_ma = buf;
+ i = devread(file);
+ file->i_bn += CLSIZE;
+ return(i);
+ }
+ else {
+ if (file->i_offset+count > file->i_ino.i_size)
+ count = file->i_ino.i_size - file->i_offset;
+ if ((i = count) <= 0)
+ return(0);
+ do {
+ *buf++ = getc(fdesc+3);
+ } while (--i);
+ return(count);
+ }
+}
+
+write(fdesc, buf, count)
+int fdesc;
+char *buf;
+int count;
+{
+ register i;
+ register struct iob *file;
+
+ if (fdesc >= 0 && fdesc <= 2) {
+ i = count;
+ while (i--)
+ putchar(*buf++);
+ return(count);
+ }
+ fdesc -= 3;
+ if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
+ return(-1);
+ if ((file->i_flgs&F_WRITE) == 0)
+ return(-1);
+ file->i_cc = count;
+ file->i_ma = buf;
+ i = devwrite(file);
+ file->i_bn += CLSIZE;
+ return(i);
+}
+
+open(str, how)
+char *str;
+int how;
+{
+ register char *cp;
+ int i;
+ register struct iob *file;
+ register struct devsw *dp;
+ int fdesc;
+ static first = 1;
+ long atol();
+
+ if (first) {
+ for (i = 0; i < NFILES; i++)
+ iob[i].i_flgs = 0;
+ first = 0;
+ }
+
+ for (fdesc = 0; fdesc < NFILES; fdesc++)
+ if (iob[fdesc].i_flgs == 0)
+ goto gotfile;
+ _stop("No more file slots");
+gotfile:
+ (file = &iob[fdesc])->i_flgs |= F_ALLOC;
+
+ for (cp = str; *cp && *cp != '('; cp++)
+ ;
+ if (*cp != '(') {
+ printf("Bad device\n");
+ file->i_flgs = 0;
+ return(-1);
+ }
+ *cp++ = '\0';
+ for (dp = devsw; dp->dv_name; dp++) {
+ if (match(str, dp->dv_name))
+ goto gotdev;
+ }
+ printf("Unknown device\n");
+ file->i_flgs = 0;
+ return(-1);
+gotdev:
+ *(cp-1) = '(';
+ file->i_ino.i_dev = dp-devsw;
+ file->i_unit = *cp++ - '0';
+ if (file->i_unit < 0 || file->i_unit > 7) {
+ printf("Bad unit specifier\n");
+ file->i_flgs = 0;
+ return(-1);
+ }
+ if (*cp++ != ',') {
+badoff:
+ printf("Missing offset specification\n");
+ file->i_flgs = 0;
+ return(-1);
+ }
+ file->i_boff = atol(cp);
+ for (;;) {
+ if (*cp == ')')
+ break;
+ if (*cp++)
+ continue;
+ goto badoff;
+ }
+ devopen(file);
+ if (*++cp == '\0') {
+ file->i_flgs |= how+1;
+ file->i_cc = 0;
+ file->i_offset = 0;
+ return(fdesc+3);
+ }
+ if ((i = find(cp, file)) == 0) {
+ file->i_flgs = 0;
+ return(-1);
+ }
+ if (how != 0) {
+ printf("Can't write files yet.. Sorry\n");
+ file->i_flgs = 0;
+ return(-1);
+ }
+ openi(i, file);
+ file->i_offset = 0;
+ file->i_cc = 0;
+ file->i_flgs |= F_FILE | (how+1);
+ return(fdesc+3);
+}
+
+close(fdesc)
+int fdesc;
+{
+ struct iob *file;
+
+ fdesc -= 3;
+ if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
+ return(-1);
+ if ((file->i_flgs&F_FILE) == 0)
+ devclose(file);
+ file->i_flgs = 0;
+ return(0);
+}
+
+exit()
+{
+ _stop("Exit called");
+}
+
+_stop(s)
+char *s;
+{
+ printf("%s\n", s);
+ _rtt();
+}
+
+trap(ps)
+int ps;
+{
+ printf("Trap %o\n", ps);
+ for (;;)
+ ;
+}