#include <u.h>#include <libc.h>#include <thread.h>#include <sunrpc.h>#include <nfs3.h>#include <diskfs.h>#include "ffs.h" #define BADBNO ((u64int)~0ULL) #define checkcg 0#define debug 0 static int checkfsblk(Fsblk*);static int checkcgblk(Cgblk*);static Block *ffsblockread(Fsys*, u64int);static int ffssync(Fsys*);static void ffsclose(Fsys*); static u64int ffsxfileblock(Fsys *fs, Nfs3Handle *h, u64int offset);static Nfs3Status ffsroot(Fsys*, Nfs3Handle*);static Nfs3Status ffsgetattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*);static Nfs3Status ffslookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*);static Nfs3Status ffsreadfile(Fsys*, SunAuthUnix *au, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*);static Nfs3Status ffsreadlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link);static Nfs3Status ffsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*);static Nfs3Status ffsaccess(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr); Fsys*fsysopenffs(Disk *disk, u32int bs, u64int off){ Ffs *fs; Fsys *fsys; fsys = emalloc(sizeof(Fsys)); fs = emalloc(sizeof(Ffs)); fs->disk = disk; fsys->priv = fs; fsys->type = "ffs"; fsys->_readblock = ffsblockread; fsys->_sync = ffssync; fsys->_root = ffsroot; fsys->_getattr = ffsgetattr; fsys->_access = ffsaccess; fsys->_lookup = ffslookup; fsys->_readfile = ffsreadfile; fsys->_readlink = ffsreadlink; fsys->_readdir = ffsreaddir; fsys->_close = ffsclose; fsys->fileblock = ffsxfileblock; if(ffssync(fsys) < 0) goto error; return fsys; error: ffsclose(fsys); return nil;} static Cgblk*ffscylgrp(Ffs *fs, u32int i, Block **pb){ Block *b; Cgblk *cg; if(i >= fs->ncg) return nil; b = diskread(fs->disk, fs->blocksize, (u64int)fs->cg[i].cgblkno*fs->blocksize); if(b == nil) return nil; cg = (Cgblk*)b->data; if(checkcgblk(cg) < 0){fprint(2, "checkcgblk %d %lud: %r\n", i, (ulong)fs->cg[i].cgblkno); blockput(b); return nil; } *pb = b; return cg;} static intffssync(Fsys *fsys){ int i; int off[] = { SBOFF, SBOFF2, SBOFFPIGGY }; Block *b, *cgb; Cgblk *cgblk; Cylgrp *cg; Disk *disk; Ffs *fs; Fsblk *fsblk; fs = fsys->priv; disk = fs->disk; /* * Read super block. */ b = nil; for(i=0; i<nelem(off); i++){ if((b = diskread(disk, SBSIZE, off[i])) == nil) goto error; fsblk = (Fsblk*)b->data; // fprint(2, "offset of magic: %ld\n", offsetof(Fsblk, magic)); if((fs->ufs = checkfsblk(fsblk)) > 0) goto okay; blockput(b); b = nil; } goto error; okay: fs->blocksize = fsblk->blocksize; fs->nblock = (fsblk->nfrag+fsblk->fragsperblock-1) / fsblk->fragsperblock; fs->fragsize = fsblk->fragsize; fs->fragspergroup = fsblk->fragspergroup; fs->fragsperblock = fsblk->fragsperblock; fs->inosperblock = fsblk->inosperblock; fs->inospergroup = fsblk->inospergroup; fs->nfrag = fsblk->nfrag; fs->ndfrag = fsblk->ndfrag; /* * used to use * fs->blockspergroup = (u64int)fsblk->_cylspergroup * * fsblk->secspercyl * BYTESPERSEC / fsblk->blocksize; * for UFS1, but this should work for both UFS1 and UFS2 */ fs->blockspergroup = (u64int)fsblk->fragspergroup / fsblk->fragsperblock; fs->ncg = fsblk->ncg; fsys->blocksize = fs->blocksize; fsys->nblock = fs->nblock; if(debug) fprint(2, "ffs %lld %d-byte blocks, %d cylinder groups\n", fs->nblock, fs->blocksize, fs->ncg); if(debug) fprint(2, "\tinospergroup %d perblock %d blockspergroup %lld\n", fs->inospergroup, fs->inosperblock, fs->blockspergroup); if(fs->cg == nil) fs->cg = emalloc(fs->ncg*sizeof(Cylgrp)); for(i=0; i<fs->ncg; i++){ cg = &fs->cg[i]; if(fs->ufs == 2) cg->bno = (u64int)fs->blockspergroup*i; else cg->bno = fs->blockspergroup*i + fsblk->_cgoffset * (i & ~fsblk->_cgmask); cg->cgblkno = cg->bno + fsblk->cfragno/fs->fragsperblock; cg->ibno = cg->bno + fsblk->ifragno/fs->fragsperblock; cg->dbno = cg->bno + fsblk->dfragno/fs->fragsperblock; if(checkcg){ if((cgb = diskread(disk, fs->blocksize, (u64int)cg->cgblkno*fs->blocksize)) == nil) goto error; cgblk = (Cgblk*)cgb->data; if(checkcgblk(cgblk) < 0){ blockput(cgb); goto error; } if(cgblk->nfrag % fs->fragsperblock && i != fs->ncg-1){ werrstr("fractional number of blocks in non-last cylinder group %d", cgblk->nfrag); blockput(cgb); goto error; } /* cg->nfrag = cgblk->nfrag; */ /* cg->nblock = (cgblk->nfrag+fs->fragsperblock-1) / fs->fragsperblock; */ /* fprint(2, "cg #%d: cgblk %lud, %d blocks, %d inodes\n", cgblk->num, (ulong)cg->cgblkno, cg->nblock, cg->nino); */ } } blockput(b); return 0; error: blockput(b); return -1;} static voidffsclose(Fsys *fsys){ Ffs *fs; fs = fsys->priv; if(fs->cg) free(fs->cg); free(fs); free(fsys);} static intcheckfsblk(Fsblk *super){// fprint(2, "ffs magic 0x%ux\n", super->magic); if(super->magic == FSMAGIC){ super->time = super->_time; super->nfrag = super->_nfrag; super->ndfrag = super->_ndfrag; super->flags = super->_flags; return 1; } if(super->magic == FSMAGIC2){ return 2; } werrstr("bad super block"); return -1;} static intcheckcgblk(Cgblk *cg){ if(cg->magic != CGMAGIC){ werrstr("bad cylinder group block"); return -1; } return 0;} /* * Read block #bno from the disk, zeroing unused data. * If there is no data whatsoever, it's okay to return nil. */int nskipx;static Block*ffsblockread(Fsys *fsys, u64int bno){ int i, o; u8int *fmap; int frag, fsize, avail; Block *b; Cgblk *cgblk; Ffs *fs; fs = fsys->priv; i = bno / fs->blockspergroup; o = bno % fs->blockspergroup; if(i >= fs->ncg) return nil; if((cgblk = ffscylgrp(fs, i, &b)) == nil) return nil; fmap = (u8int*)cgblk+cgblk->fmapoff; frag = fs->fragsperblock; switch(frag){ default: sysfatal("bad frag"); case 8: avail = fmap[o]; break; case 4: avail = (fmap[o>>1] >> ((o&1)*4)) & 0xF; break; case 2: avail = (fmap[o>>2] >> ((o&3)*2)) & 0x3; break; case 1: avail = (fmap[o>>3] >> (o&7)) & 0x1; break; } blockput(b); if(avail == ((1<<frag)-1)){nskipx++; return nil;} if((b = diskread(fs->disk, fs->blocksize, bno*fs->blocksize)) == nil){ fprint(2, "diskread failed!!!\n"); return nil; } fsize = fs->fragsize; for(i=0; i<frag; i++) if(avail & (1<<i)) memset(b->data + fsize*i, 0, fsize); return b;} static Block*ffsdatablock(Ffs *fs, u64int bno, int size){ int fsize; u64int diskaddr; Block *b; if(bno == 0) return nil; fsize = size; if(fsize < fs->fragsize) fsize = fs->fragsize; if(bno >= fs->nfrag){ fprint(2, "ffs: request for block %#lux; nfrag %#llux\n", (ulong)bno, fs->nfrag); return nil; } diskaddr = (u64int)bno*fs->fragsize; b = diskread(fs->disk, fsize, diskaddr); if(b == nil){ fprint(2, "ffs: disk i/o at %#llux for %#ux: %r\n", diskaddr, fsize); return nil; } if(b->len < fsize){ fprint(2, "ffs: disk i/o at %#llux for %#ux got %#ux\n", diskaddr, fsize, b->len); blockput(b); return nil; } return b;} static u64intifetch(Ffs *fs, u64int bno, u32int off){ Block *b; if(bno == BADBNO) return BADBNO; b = ffsdatablock(fs, bno, fs->blocksize); if(b == nil) return BADBNO; if(fs->ufs == 2) bno = ((u64int*)b->data)[off]; else bno = ((u32int*)b->data)[off]; blockput(b); return bno;} static u64intffsfileblockno(Ffs *fs, Inode *ino, u64int bno){ int ppb; if(bno < NDADDR){ if(debug) fprint(2, "ffsfileblock %lud: direct %#lux\n", (ulong)bno, (ulong)ino->db[bno]); return ino->db[bno]; } bno -= NDADDR; ppb = fs->blocksize/4; if(bno < ppb) /* single indirect */ return ifetch(fs, ino->ib[0], bno); bno -= ppb; if(bno < ppb*ppb) return ifetch(fs, ifetch(fs, ino->ib[1], bno/ppb), bno%ppb); bno -= ppb*ppb; if(bno/ppb/ppb/ppb == 0) /* bno < ppb*ppb*ppb w/o overflow */ return ifetch(fs, ifetch(fs, ifetch(fs, ino->ib[2], bno/ppb/ppb), (bno/ppb)%ppb), bno%ppb); fprint(2, "ffsfileblock %llud: way too big\n", bno+NDADDR+ppb+ppb*ppb); return BADBNO;} static Block*ffsfileblock(Ffs *fs, Inode *ino, u64int bno, int size){ u64int b; b = ffsfileblockno(fs, ino, bno); if(b == ~0) return nil; return ffsdatablock(fs, b, size);} /* * NFS handles are 4-byte inode number. */static voidmkhandle(Nfs3Handle *h, u64int ino){ h->h[0] = ino >> 24; h->h[1] = ino >> 16; h->h[2] = ino >> 8; h->h[3] = ino; h->len = 4;} static u32intbyte2u32(uchar *p){ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];} static u64int lastiaddr; /* debugging */ static voidinode1to2(Inode1 *i1, Inode *i2){ int i; memset(i2, 0, sizeof *i2); i2->mode = i1->mode; i2->nlink = i1->nlink; i2->size = i1->size; i2->atime = i1->atime; i2->atimensec = i1->atimensec; i2->mtime = i1->mtime; i2->mtimensec = i1->mtimensec; i2->ctime = i1->ctime; i2->ctimensec = i1->ctimensec; for(i=0; i<NDADDR; i++) i2->db[i] = i1->db[i]; for(i=0; i<NIADDR; i++) i2->ib[i] = i1->ib[i]; i2->flags = i1->flags; i2->nblock = i1->nblock; i2->gen = i1->gen; i2->uid = i1->uid; i2->gid = i1->gid;} static Nfs3Statushandle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino){ int i; u32int ioff; u32int inum; u64int iaddr; Block *b; Cylgrp *cg; Inode1 ino1; if(h->len != 4) return Nfs3ErrBadHandle; inum = byte2u32(h->h); if(pinum) *pinum = inum; if(debug) print("inum %d...", (int)inum); /* fetch inode from disk */ i = inum / fs->inospergroup; ioff = inum % fs->inospergroup; if(debug)print("cg %d off %d...", i, (int)ioff); if(i >= fs->ncg) return Nfs3ErrBadHandle; cg = &fs->cg[i]; if(debug) print("cg->ibno %lld ufs %d...", cg->ibno, fs->ufs); iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize; ioff = ioff%fs->inosperblock; if((b = diskread(fs->disk, fs->blocksize, iaddr)) == nil) return Nfs3ErrIo; if(fs->ufs == 2){ *ino = ((Inode*)b->data)[ioff]; lastiaddr = iaddr+ioff*sizeof(Inode); }else{ ino1 = ((Inode1*)b->data)[ioff]; inode1to2(&ino1, ino); lastiaddr = iaddr+ioff*sizeof(Inode1); } blockput(b); return Nfs3Ok;} static Nfs3Statusffsroot(Fsys *fsys, Nfs3Handle *h){ USED(fsys); mkhandle(h, 2); return Nfs3Ok;} static Nfs3Statusino2attr(Ffs *fs, Inode *ino, u32int inum, Nfs3Attr *attr){ u32int rdev; attr->type = -1; switch(ino->mode&IFMT){ case IFIFO: attr->type = Nfs3FileFifo; break; case IFCHR: attr->type = Nfs3FileChar; break; case IFDIR: attr->type = Nfs3FileDir; break; case IFBLK: attr->type = Nfs3FileBlock; break; case IFREG: attr->type = Nfs3FileReg; break; case IFLNK: attr->type = Nfs3FileSymlink; break; case IFSOCK: attr->type = Nfs3FileSocket; break; case IFWHT:Lines 1–500 of 907. Load more
#include <u.h> #include <libc.h> #include <thread.h> #include <sunrpc.h> #include <nfs3.h> #include <diskfs.h> #include "ffs.h" #define BADBNO ((u64int)~0ULL) #define checkcg 0 #define debug 0 static int checkfsblk(Fsblk*); static int checkcgblk(Cgblk*); static Block *ffsblockread(Fsys*, u64int); static int ffssync(Fsys*); static void ffsclose(Fsys*); static u64int ffsxfileblock(Fsys *fs, Nfs3Handle *h, u64int offset); static Nfs3Status ffsroot(Fsys*, Nfs3Handle*); static Nfs3Status ffsgetattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*); static Nfs3Status ffslookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*); static Nfs3Status ffsreadfile(Fsys*, SunAuthUnix *au, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*); static Nfs3Status ffsreadlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link); static Nfs3Status ffsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*); static Nfs3Status ffsaccess(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr); Fsys* fsysopenffs(Disk *disk, u32int bs, u64int off) { Ffs *fs; Fsys *fsys; fsys = emalloc(sizeof(Fsys)); fs = emalloc(sizeof(Ffs)); fs->disk = disk; fsys->priv = fs; fsys->type = "ffs"; fsys->_readblock = ffsblockread; fsys->_sync = ffssync; fsys->_root = ffsroot; fsys->_getattr = ffsgetattr; fsys->_access = ffsaccess; fsys->_lookup = ffslookup; fsys->_readfile = ffsreadfile; fsys->_readlink = ffsreadlink; fsys->_readdir = ffsreaddir; fsys->_close = ffsclose; fsys->fileblock = ffsxfileblock; if(ffssync(fsys) < 0) goto error; return fsys; error: ffsclose(fsys); return nil; } static Cgblk* ffscylgrp(Ffs *fs, u32int i, Block **pb) { Block *b; Cgblk *cg; if(i >= fs->ncg) return nil; b = diskread(fs->disk, fs->blocksize, (u64int)fs->cg[i].cgblkno*fs->blocksize); if(b == nil) return nil; cg = (Cgblk*)b->data; if(checkcgblk(cg) < 0){ fprint(2, "checkcgblk %d %lud: %r\n", i, (ulong)fs->cg[i].cgblkno); blockput(b); return nil; } *pb = b; return cg; } static int ffssync(Fsys *fsys) { int i; int off[] = { SBOFF, SBOFF2, SBOFFPIGGY }; Block *b, *cgb; Cgblk *cgblk; Cylgrp *cg; Disk *disk; Ffs *fs; Fsblk *fsblk; fs = fsys->priv; disk = fs->disk; /* * Read super block. */ b = nil; for(i=0; i<nelem(off); i++){ if((b = diskread(disk, SBSIZE, off[i])) == nil) goto error; fsblk = (Fsblk*)b->data; // fprint(2, "offset of magic: %ld\n", offsetof(Fsblk, magic)); if((fs->ufs = checkfsblk(fsblk)) > 0) goto okay; blockput(b); b = nil; } goto error; okay: fs->blocksize = fsblk->blocksize; fs->nblock = (fsblk->nfrag+fsblk->fragsperblock-1) / fsblk->fragsperblock; fs->fragsize = fsblk->fragsize; fs->fragspergroup = fsblk->fragspergroup; fs->fragsperblock = fsblk->fragsperblock; fs->inosperblock = fsblk->inosperblock; fs->inospergroup = fsblk->inospergroup; fs->nfrag = fsblk->nfrag; fs->ndfrag = fsblk->ndfrag; /* * used to use * fs->blockspergroup = (u64int)fsblk->_cylspergroup * * fsblk->secspercyl * BYTESPERSEC / fsblk->blocksize; * for UFS1, but this should work for both UFS1 and UFS2 */ fs->blockspergroup = (u64int)fsblk->fragspergroup / fsblk->fragsperblock; fs->ncg = fsblk->ncg; fsys->blocksize = fs->blocksize; fsys->nblock = fs->nblock; if(debug) fprint(2, "ffs %lld %d-byte blocks, %d cylinder groups\n", fs->nblock, fs->blocksize, fs->ncg); if(debug) fprint(2, "\tinospergroup %d perblock %d blockspergroup %lld\n", fs->inospergroup, fs->inosperblock, fs->blockspergroup); if(fs->cg == nil) fs->cg = emalloc(fs->ncg*sizeof(Cylgrp)); for(i=0; i<fs->ncg; i++){ cg = &fs->cg[i]; if(fs->ufs == 2) cg->bno = (u64int)fs->blockspergroup*i; else cg->bno = fs->blockspergroup*i + fsblk->_cgoffset * (i & ~fsblk->_cgmask); cg->cgblkno = cg->bno + fsblk->cfragno/fs->fragsperblock; cg->ibno = cg->bno + fsblk->ifragno/fs->fragsperblock; cg->dbno = cg->bno + fsblk->dfragno/fs->fragsperblock; if(checkcg){ if((cgb = diskread(disk, fs->blocksize, (u64int)cg->cgblkno*fs->blocksize)) == nil) goto error; cgblk = (Cgblk*)cgb->data; if(checkcgblk(cgblk) < 0){ blockput(cgb); goto error; } if(cgblk->nfrag % fs->fragsperblock && i != fs->ncg-1){ werrstr("fractional number of blocks in non-last cylinder group %d", cgblk->nfrag); blockput(cgb); goto error; } /* cg->nfrag = cgblk->nfrag; */ /* cg->nblock = (cgblk->nfrag+fs->fragsperblock-1) / fs->fragsperblock; */ /* fprint(2, "cg #%d: cgblk %lud, %d blocks, %d inodes\n", cgblk->num, (ulong)cg->cgblkno, cg->nblock, cg->nino); */ } } blockput(b); return 0; error: blockput(b); return -1; } static void ffsclose(Fsys *fsys) { Ffs *fs; fs = fsys->priv; if(fs->cg) free(fs->cg); free(fs); free(fsys); } static int checkfsblk(Fsblk *super) { // fprint(2, "ffs magic 0x%ux\n", super->magic); if(super->magic == FSMAGIC){ super->time = super->_time; super->nfrag = super->_nfrag; super->ndfrag = super->_ndfrag; super->flags = super->_flags; return 1; } if(super->magic == FSMAGIC2){ return 2; } werrstr("bad super block"); return -1; } static int checkcgblk(Cgblk *cg) { if(cg->magic != CGMAGIC){ werrstr("bad cylinder group block"); return -1; } return 0; } /* * Read block #bno from the disk, zeroing unused data. * If there is no data whatsoever, it's okay to return nil. */ int nskipx; static Block* ffsblockread(Fsys *fsys, u64int bno) { int i, o; u8int *fmap; int frag, fsize, avail; Block *b; Cgblk *cgblk; Ffs *fs; fs = fsys->priv; i = bno / fs->blockspergroup; o = bno % fs->blockspergroup; if(i >= fs->ncg) return nil; if((cgblk = ffscylgrp(fs, i, &b)) == nil) return nil; fmap = (u8int*)cgblk+cgblk->fmapoff; frag = fs->fragsperblock; switch(frag){ default: sysfatal("bad frag"); case 8: avail = fmap[o]; break; case 4: avail = (fmap[o>>1] >> ((o&1)*4)) & 0xF; break; case 2: avail = (fmap[o>>2] >> ((o&3)*2)) & 0x3; break; case 1: avail = (fmap[o>>3] >> (o&7)) & 0x1; break; } blockput(b); if(avail == ((1<<frag)-1)) { nskipx++; return nil; } if((b = diskread(fs->disk, fs->blocksize, bno*fs->blocksize)) == nil){ fprint(2, "diskread failed!!!\n"); return nil; } fsize = fs->fragsize; for(i=0; i<frag; i++) if(avail & (1<<i)) memset(b->data + fsize*i, 0, fsize); return b; } static Block* ffsdatablock(Ffs *fs, u64int bno, int size) { int fsize; u64int diskaddr; Block *b; if(bno == 0) return nil; fsize = size; if(fsize < fs->fragsize) fsize = fs->fragsize; if(bno >= fs->nfrag){ fprint(2, "ffs: request for block %#lux; nfrag %#llux\n", (ulong)bno, fs->nfrag); return nil; } diskaddr = (u64int)bno*fs->fragsize; b = diskread(fs->disk, fsize, diskaddr); if(b == nil){ fprint(2, "ffs: disk i/o at %#llux for %#ux: %r\n", diskaddr, fsize); return nil; } if(b->len < fsize){ fprint(2, "ffs: disk i/o at %#llux for %#ux got %#ux\n", diskaddr, fsize, b->len); blockput(b); return nil; } return b; } static u64int ifetch(Ffs *fs, u64int bno, u32int off) { Block *b; if(bno == BADBNO) return BADBNO; b = ffsdatablock(fs, bno, fs->blocksize); if(b == nil) return BADBNO; if(fs->ufs == 2) bno = ((u64int*)b->data)[off]; else bno = ((u32int*)b->data)[off]; blockput(b); return bno; } static u64int ffsfileblockno(Ffs *fs, Inode *ino, u64int bno) { int ppb; if(bno < NDADDR){ if(debug) fprint(2, "ffsfileblock %lud: direct %#lux\n", (ulong)bno, (ulong)ino->db[bno]); return ino->db[bno]; } bno -= NDADDR; ppb = fs->blocksize/4; if(bno < ppb) /* single indirect */ return ifetch(fs, ino->ib[0], bno); bno -= ppb; if(bno < ppb*ppb) return ifetch(fs, ifetch(fs, ino->ib[1], bno/ppb), bno%ppb); bno -= ppb*ppb; if(bno/ppb/ppb/ppb == 0) /* bno < ppb*ppb*ppb w/o overflow */ return ifetch(fs, ifetch(fs, ifetch(fs, ino->ib[2], bno/ppb/ppb), (bno/ppb)%ppb), bno%ppb); fprint(2, "ffsfileblock %llud: way too big\n", bno+NDADDR+ppb+ppb*ppb); return BADBNO; } static Block* ffsfileblock(Ffs *fs, Inode *ino, u64int bno, int size) { u64int b; b = ffsfileblockno(fs, ino, bno); if(b == ~0) return nil; return ffsdatablock(fs, b, size); } /* * NFS handles are 4-byte inode number. */ static void mkhandle(Nfs3Handle *h, u64int ino) { h->h[0] = ino >> 24; h->h[1] = ino >> 16; h->h[2] = ino >> 8; h->h[3] = ino; h->len = 4; } static u32int byte2u32(uchar *p) { return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; } static u64int lastiaddr; /* debugging */ static void inode1to2(Inode1 *i1, Inode *i2) { int i; memset(i2, 0, sizeof *i2); i2->mode = i1->mode; i2->nlink = i1->nlink; i2->size = i1->size; i2->atime = i1->atime; i2->atimensec = i1->atimensec; i2->mtime = i1->mtime; i2->mtimensec = i1->mtimensec; i2->ctime = i1->ctime; i2->ctimensec = i1->ctimensec; for(i=0; i<NDADDR; i++) i2->db[i] = i1->db[i]; for(i=0; i<NIADDR; i++) i2->ib[i] = i1->ib[i]; i2->flags = i1->flags; i2->nblock = i1->nblock; i2->gen = i1->gen; i2->uid = i1->uid; i2->gid = i1->gid; } static Nfs3Status handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino) { int i; u32int ioff; u32int inum; u64int iaddr; Block *b; Cylgrp *cg; Inode1 ino1; if(h->len != 4) return Nfs3ErrBadHandle; inum = byte2u32(h->h); if(pinum) *pinum = inum; if(debug) print("inum %d...", (int)inum); /* fetch inode from disk */ i = inum / fs->inospergroup; ioff = inum % fs->inospergroup; if(debug)print("cg %d off %d...", i, (int)ioff); if(i >= fs->ncg) return Nfs3ErrBadHandle; cg = &fs->cg[i]; if(debug) print("cg->ibno %lld ufs %d...", cg->ibno, fs->ufs); iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize; ioff = ioff%fs->inosperblock; if((b = diskread(fs->disk, fs->blocksize, iaddr)) == nil) return Nfs3ErrIo; if(fs->ufs == 2){ *ino = ((Inode*)b->data)[ioff]; lastiaddr = iaddr+ioff*sizeof(Inode); }else{ ino1 = ((Inode1*)b->data)[ioff]; inode1to2(&ino1, ino); lastiaddr = iaddr+ioff*sizeof(Inode1); } blockput(b); return Nfs3Ok; } static Nfs3Status ffsroot(Fsys *fsys, Nfs3Handle *h) { USED(fsys); mkhandle(h, 2); return Nfs3Ok; } static Nfs3Status ino2attr(Ffs *fs, Inode *ino, u32int inum, Nfs3Attr *attr) { u32int rdev; attr->type = -1; switch(ino->mode&IFMT){ case IFIFO: attr->type = Nfs3FileFifo; break; case IFCHR: attr->type = Nfs3FileChar; break; case IFDIR: attr->type = Nfs3FileDir; break; case IFBLK: attr->type = Nfs3FileBlock; break; case IFREG: attr->type = Nfs3FileReg; break; case IFLNK: attr->type = Nfs3FileSymlink; break; case IFSOCK: attr->type = Nfs3FileSocket; break; case IFWHT: