/* * (C) 1983 UniSoft Corp. of Berkeley CA * * UniPlus Source Code. This program is proprietary * with Unisoft Corporation and is not to be reproduced * or used in any manner except as authorized in * writing by Unisoft. */ /* These routines expect getchar and putchar to be defined elsewhere */ #include #include #include #include #include #include #include #include devread(io) register struct iob *io; { register n; # ifdef DEBUG if (debug & D_INOUT) printf("Entering devread()\n"); if (debug & D_RW) printf("dev %d/%d Read block %d. %d bytes into 0x%x\n", io->i_device, io->i_unit, io->i_bn, io->i_cc, io->i_ma); # endif n = (*devsw[io->i_device].dv_strategy)(io,READ); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving devread()\n"); # endif return(n); } devwrite(io) register struct iob *io; { # ifdef DEBUG if (debug & D_INOUT) printf("Entering devwrite()\n"); # endif return( (*devsw[io->i_device].dv_strategy)(io, WRITE) ); } devopen(io) register struct iob *io; { # ifdef DEBUG if (debug & D_INOUT) printf("Entering devopen()\n"); # endif return((*devsw[io->i_device].dv_open)(io)); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving devopen()\n"); # endif } devclose(io) register struct iob *io; { # ifdef DEBUG if (debug & D_INOUT) printf("Entering devclose()\n"); # endif (*devsw[io->i_device].dv_close)(io); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving devclose()\n"); # endif } ino_t dlook(); int openi(n,io) register struct iob *io; { register struct dinode *dp; register dev = io->i_Fsdev; # ifdef DEBUG if (debug & D_INOUT) printf("Entering openi, inode=%d\n", n); # endif io->i_offset = 0; io->i_bn = io->i_boff; io->i_bn += (daddr_t)FsLTOP(dev, (FsITOD(dev, n))); io->i_cc = FsBSIZE(dev); io->i_ma = io->i_buf; if (devread(io) != io->i_cc) return(-1); # ifdef DEBUG if (debug & D_RW) printf("Read block %d: %d inodes\n", io->i_bn, FsINOPB(dev)); # endif dp = (struct dinode *)io->i_buf; dp += FsITOO(dev, 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_addr, (char *)dp->di_addr, NADDR); # ifdef DEBUG if (debug & D_RW) printf("inode %d, mode 0%o, size %d\n", io->i_ino.i_number, io->i_ino.i_mode, io->i_ino.i_size); if (debug & D_INOUT) printf("Leaving openi\n"); # endif return(0); } static find(path, file) register char *path; register struct iob *file; { register char *q; register char c; register n; # ifdef DEBUG if (debug & D_INOUT) printf("Entering find: path=%s\n", path); # endif if (path==NULL || *path=='\0') { printf("find: null path\n"); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving find\n"); # endif return(0); } if (openi(2, file) < 0) { printf("find: can't read inode 2\n"); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving find\n"); # endif return(0); } 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; if (openi(n, file) < 0) { printf("find: can't read inode %d\n", n); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving find\n"); # endif return(0); } *q = c; path = q; continue; } else { printf("%s not found\n",path); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving find\n"); # endif return(0); } } # ifdef DEBUG if (debug & D_INOUT) printf("Leaving find: n = %d\n", n); # endif return(n); } static daddr_t sbmap(io, bn) register struct iob *io; daddr_t bn; { register i, j; register struct inode *ip = &io->i_ino; register dev = io->i_Fsdev; int sh; daddr_t nb, *bap; # ifdef DEBUG if (debug & D_INOUT) printf("Entering sbmap\n"); # endif 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_addr[i]; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving sbmap\n"); # endif 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 += FsNSHIFT(dev); nb <<= FsNSHIFT(dev); if(bn < nb) break; bn -= nb; } if(j == 0) { printf("bn ovf %D\n",bn); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving sbmap\n"); # endif return((daddr_t)0); } /* * fetch the address from the inode */ nb = ip->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 = FsLTOP(dev, nb) + io->i_boff; io->i_ma = b[j]; io->i_cc = FsBSIZE(dev); if (devread(io) < io->i_cc) { printf("sbmap: can't read block %d\n", nb); return((daddr_t)0); } blknos[j] = nb; } bap = (daddr_t *)b[j]; sh -= FsNSHIFT(dev); i = (bn>>sh) & FsNMASK(dev); nb = bap[i]; if(nb == 0) { printf("bn void %D\n",bn); return((daddr_t)0); } } # ifdef DEBUG if (debug & D_INOUT) printf("Leaving sbmap\n"); # endif return(nb); } static ino_t dlook(s, io) char *s; register struct iob *io; { register struct direct *dp; register struct inode *ip = &io->i_ino; register dev = io->i_Fsdev; register daddr_t bn; register n, dc; int dpb; # ifdef DEBUG if (debug & D_INOUT) printf("Entering dlook\n"); # endif if (s==NULL || *s=='\0') return(0); if ((ip->i_mode&IFMT)!=IFDIR) { printf("not a directory\n"); printf("mode %o, loc 0%o\n",ip->i_mode,ip); return(0); } n = ip->i_size/sizeof(struct direct); if (n==0) { printf("zero length directory\n"); return(0); } dpb = FsBSIZE(dev)/sizeof(struct direct); dc = dpb; bn = (daddr_t)0; while(n--) { if (++dc >= dpb) { io->i_bn = FsLTOP(dev, sbmap(io, bn++)) + io->i_boff; io->i_ma = io->i_buf; io->i_cc = FsBSIZE(dev); if (devread(io) < io->i_cc) { printf("dlook: can't read block %d\n", bn-1); return(0); } dp = (struct direct *)io->i_buf; dc = 0; } if (match(s, dp->d_name)) { # ifdef DEBUG if (debug & D_INOUT) printf("Leaving dlook: ino = %d\n", dp->d_ino); # endif return(dp->d_ino); } dp++; } # ifdef DEBUG if (debug & D_INOUT) printf("Leaving dlook\n"); # endif return(0); } static match(s1,s2) register char *s1,*s2; { register cc; # ifdef DEBUG if (debug & D_INOUT) printf("Match: '%s' '%s'\n", s1, s2); # endif 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; # ifdef DEBUG if (debug & D_INOUT) printf("Entering lseek\n"); # endif 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) { # ifdef DEBUG if (debug & D_INOUT) { printf("Leaving lseek: -1\n"); printf("\tfdesc=%d io->i_flgs=0x%x\n", fdesc, io->i_flgs); } # endif return(-1); } io->i_offset = addr; io->i_bn = addr/PBSIZE + io->i_boff; io->i_cc = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving lseek: 0\n"); # endif return(0); } /* if tape mark encountered, set flag (in driver) */ int tapemark; getc(fdesc) int fdesc; { register struct iob *io; register char *p; register dev; register c; register off; register daddr_t bn; # ifdef DEBUG_GC printf("Entering getc\n"); # endif if (fdesc >= 0 && fdesc <= 2) { c = getchar(); # ifdef DEBUG_GC printf("Leaving getc: c = 0%o\n", c & 0x7f); # endif return(c); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { # ifdef DEBUG_GC printf("Leaving getc\n"); # endif return(-1); } p = io->i_ma; if (io->i_cc <= 0) { dev = io->i_Fsdev; bn = io->i_offset/(off_t)FsBSIZE(dev); if (io->i_flgs&F_FILE) io->i_bn = FsLTOP(dev, sbmap(io, bn)) + io->i_boff; else io->i_bn = FsLTOP(dev, bn) + io->i_boff; io->i_ma = io->i_buf; io->i_cc = FsBSIZE(dev); tapemark=0; if (devread(io) < io->i_cc) { io->i_cc = 0; if (!tapemark) printf("getc: can't read block %d\n", bn); return(-1); } if (io->i_flgs&F_FILE) { off = io->i_offset % (off_t)FsBSIZE(dev); if (io->i_offset+(FsBSIZE(dev)-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) { # ifdef DEBUG_GC printf("Leaving getc:io->i_cc <= 0\n"); # endif return(-1); } } else { off = 0; if(tapemark) { # ifdef DEBUG_GC printf("Leaving getc:tapemark\n"); # endif io->i_cc = 0; return(-1); } } p = &io->i_buf[off]; } io->i_cc--; io->i_offset++; c = (unsigned)*p++ & 0xFF; io->i_ma = p; # ifdef DEBUG_GC printf("Leaving getc at end: c = 0%o\n", c & 0x7f); # endif return(c); } getw(fdesc) int fdesc; { register char *cp; register w, i; int val; for (i = 0, val = 0, cp = (char *)&val; i < sizeof(val); i++) { w = getc(fdesc); if (w < 0) { if (i == 0) return(-1); else break; } *cp++ = w; } return(val); } read(fdesc, buf, count) int fdesc; char *buf; int count; { register i; register struct iob *file; # ifdef DEBUG if (debug & D_INOUT) printf("Entering read\n"); # endif if (fdesc >= 0 && fdesc <= 2) { i = count; do { *buf = getchar(); } while (--i && *buf++ != '\n'); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read:1\n"); # endif return(count - i); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read:2\n"); # endif return(-1); } if ((file->i_flgs&F_READ) == 0) { # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read:3\n"); # endif return(-1); } if ((file->i_flgs&F_FILE) == 0) { file->i_cc = count; file->i_ma = buf; if ((i = devread(file)) < 0) { # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read: devread failed\n"); # endif return(i); } file->i_bn += (i+PBSIZE-1) >> PBSHIFT; file->i_offset += i; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read:4\n"); # endif return(i); } if (file->i_offset+count > file->i_ino.i_size) count = file->i_ino.i_size - file->i_offset; if ((i = count) <= 0) { # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read:5\n"); # endif return(0); } do { *buf++ = getc(fdesc+3); } while (--i); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving read:6\n"); # endif return(count); } write(fdesc, buf, count) int fdesc; char *buf; int count; { register i; register struct iob *file; # ifdef DEBUG if (debug & D_INOUT) printf("Entering write\n"); # endif 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; if ((i = devwrite(file)) < 0) return(i); file->i_bn += (i+PBSIZE-1) >> PBSHIFT; file->i_offset += i; return(i); } finit() { register int i; for (i = 0; i < NFILES; i++) iob[i].i_flgs = 0; } readsb(file) register struct iob *file; { register struct filsys *fp; file->i_offset = 0; file->i_bn = SUPERB + file->i_boff; file->i_cc = PBSIZE; file->i_ma = file->i_buf; if (devread(file) < PBSIZE) { printf("readsb: can't read superblock\n"); return(-1); } fp = (struct filsys *)file->i_buf; if ((fp->s_magic == FsMAGIC) && (fp->s_type == Fs2b)) file->i_Fsdev = Fs2BLK; else file->i_Fsdev = 0; #ifdef DEBUG if ((fp->s_magic == FsMAGIC) && (fp->s_type == Fs2b)) printf("readsb: 1K-byte block filesystem\n"); else printf("readsb: 512-byte block filesystem\n"); #endif DEBUG return(0); } 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(); # ifdef DEBUG if (debug & D_INOUT) printf("Entering open\n"); # endif if (first) { finit(); 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; goto out; } *cp++ = '\0'; for (dp = devsw; dp->dv_name; dp++) { if (match(str, dp->dv_name)) goto gotdev; } printf("Unknown device.\n"); out: printf("Valid devices are\n"); for (dp = devsw; dp->dv_name; dp++) printf(" %s\n", dp->dv_name); file->i_flgs = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open\n"); # endif return(-1); gotdev: *(cp-1) = '('; file->i_device = dp-devsw; file->i_unit = atol(cp); for (;;) { if (*cp == ',') break; if (*cp++) continue; } if (file->i_unit < 0 || file->i_unit > 255) { printf("Bad unit specifier\n"); file->i_flgs = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open\n"); # endif return(-1); } if (*cp++ != ',') { badoff: printf("Missing offset specification\n"); file->i_flgs = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open\n"); # endif return(-1); } file->i_boff = atol(cp); for (;;) { if (*cp == ')') break; if (*cp++) continue; goto badoff; } if(devopen(file) < 0) return (-1); if (*++cp == '\0') { file->i_flgs |= how+1; file->i_Fsdev = 0; /* treat raw disk as 512-byte blk fs */ file->i_offset = 0; file->i_bn = file->i_boff; file->i_cc = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open:1\n"); # endif return(fdesc+3); } if (readsb(file) < 0) { file->i_flgs = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open:2\n"); # endif return(-1); } if ((i = find(cp, file)) == 0) { file->i_flgs = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open:3\n"); # endif return(-1); } if (how != 0) { printf("Can't write files yet.. Sorry\n"); file->i_flgs = 0; return(-1); } if (openi(i, file) < 0) { printf("open: can't read inode %d\n", i); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open:4\n"); # endif return(-1); } file->i_offset = 0; file->i_cc = 0; file->i_flgs |= F_FILE | (how+1); # ifdef DEBUG if (debug & D_INOUT) printf("Leaving open:5\n"); # endif return(fdesc+3); } close(fdesc) int fdesc; { struct iob *file; # ifdef DEBUG if (debug & D_INOUT) printf("Entering close\n"); # endif fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { # ifdef DEBUG if (debug & D_INOUT) printf("Leaving close:1\n"); # endif return(-1); } if ((file->i_flgs&F_FILE) == 0) devclose(file); file->i_flgs = 0; # ifdef DEBUG if (debug & D_INOUT) printf("Leaving close:2\n"); # endif return(0); } exit() { # ifdef DEBUG if (debug & D_INOUT) printf("Entering exit\n"); # endif _stop("Exit called"); } _stop(s) char *s; { # ifdef DEBUG if (debug & D_INOUT) printf("Entering stop\n"); # endif printf("%s\n", s); for (;;); }