#include <u.h>#include <libc.h>#include <thread.h>#include <sunrpc.h>#include <nfs3.h>#include <diskfs.h>#include "ext2.h" static void parsedirent(Dirent*, uchar*);static void parseinode(Inode*, uchar*);static void parsegroup(Group*, uchar*);static void parsesuper(Super*, uchar*); #define debug 0 static int ext2sync(Fsys*);static void ext2close(Fsys*);static Block* ext2blockread(Fsys*, u64int); static Nfs3Status ext2root(Fsys*, Nfs3Handle*);static Nfs3Status ext2getattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*);static Nfs3Status ext2lookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*);static Nfs3Status ext2readfile(Fsys*, SunAuthUnix *au, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*);static Nfs3Status ext2readlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link);static Nfs3Status ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*);static Nfs3Status ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr); Fsys*fsysopenext2(Disk *disk, u32int bs, u64int off){ Ext2 *fs; Fsys *fsys; fsys = emalloc(sizeof(Fsys)); fs = emalloc(sizeof(Ext2)); fs->disk = disk; fsys->priv = fs; fs->fsys = fsys; fsys->type = "ext2"; fsys->_readblock = ext2blockread; fsys->_sync = ext2sync; fsys->_root = ext2root; fsys->_getattr = ext2getattr; fsys->_access = ext2access; fsys->_lookup = ext2lookup; fsys->_readfile = ext2readfile; fsys->_readlink = ext2readlink; fsys->_readdir = ext2readdir; fsys->_close = ext2close; if(ext2sync(fsys) < 0) goto error; return fsys; error: ext2close(fsys); return nil;} static voidext2close(Fsys *fsys){ Ext2 *fs; fs = fsys->priv; free(fs); free(fsys);} static intext2group(Ext2 *fs, u32int i, Group *g){ Block *b; u64int addr; if(i >= fs->ngroup) return -1; addr = fs->groupaddr + i/fs->descperblock; b = diskread(fs->disk, fs->blocksize, addr*fs->blocksize); if(b == nil) return -1; parsegroup(g, b->data+i%fs->descperblock*GroupSize); blockput(b); return 0;} static Block*ext2blockread(Fsys *fsys, u64int vbno){ Block *bitb; Group g; uchar *bits; u32int bno, boff, bitblock; u64int bitpos; Ext2 *fs; fs = fsys->priv; if(vbno >= fs->nblock) return nil; bno = vbno; if(bno != vbno) return nil; /* if(bno < fs->firstblock) return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize);*/ if(bno < fs->firstblock) return nil; bno -= fs->firstblock; if(ext2group(fs, bno/fs->blockspergroup, &g) < 0){ if(debug) fprint(2, "loading group: %r..."); return nil; }/* if(debug) fprint(2, "ext2 group %d: bitblock=%ud inodebitblock=%ud inodeaddr=%ud freeblocks=%ud freeinodes=%ud useddirs=%ud\n", (int)(bno/fs->blockspergroup), g.bitblock, g.inodebitblock, g.inodeaddr, g.freeblockscount, g.freeinodescount, g.useddirscount); if(debug) fprint(2, "group %d bitblock=%d...", bno/fs->blockspergroup, g.bitblock);*/ bitblock = g.bitblock; bitpos = (u64int)bitblock*fs->blocksize; if((bitb = diskread(fs->disk, fs->blocksize, bitpos)) == nil){ if(debug) fprint(2, "loading bitblock: %r..."); return nil; } bits = bitb->data; boff = bno%fs->blockspergroup; if((bits[boff>>3] & (1<<(boff&7))) == 0){ if(debug) fprint(2, "block %d not allocated in group %d: bitblock %d/%lld bits[%d] = %#x\n", boff, bno/fs->blockspergroup, (int)bitblock, bitpos, boff>>3, bits[boff>>3]); blockput(bitb); return nil; } blockput(bitb); bno += fs->firstblock; return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize);} static Block*ext2datablock(Ext2 *fs, u32int bno, int size){ USED(size); return ext2blockread(fs->fsys, bno);} static Block*ext2fileblock(Ext2 *fs, Inode *ino, u32int bno, int size){ int ppb; Block *b; u32int *a; u32int obno, pbno; obno = bno; if(bno < NDIRBLOCKS){ if(debug) fprint(2, "fileblock %d -> %d...", bno, ino->block[bno]); return ext2datablock(fs, ino->block[bno], size); } bno -= NDIRBLOCKS; ppb = fs->blocksize/4; /* one indirect */ if(bno < ppb){ b = ext2datablock(fs, ino->block[INDBLOCK], fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; bno = a[bno]; blockput(b); return ext2datablock(fs, bno, size); } bno -= ppb; /* one double indirect */ if(bno < ppb*ppb){ b = ext2datablock(fs, ino->block[DINDBLOCK], fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; pbno = a[bno/ppb]; bno = bno%ppb; blockput(b); b = ext2datablock(fs, pbno, fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; bno = a[bno]; blockput(b); return ext2datablock(fs, bno, size); } bno -= ppb*ppb; /* one triple indirect */ if(bno < ppb*ppb*ppb){ b = ext2datablock(fs, ino->block[TINDBLOCK], fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; pbno = a[bno/(ppb*ppb)]; bno = bno%(ppb*ppb); blockput(b); b = ext2datablock(fs, pbno, fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; pbno = a[bno/ppb]; bno = bno%ppb; blockput(b); b = ext2datablock(fs, pbno, fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; bno = a[bno]; blockput(b); return ext2datablock(fs, bno, size); } fprint(2, "ext2fileblock %ud: too big\n", obno); return nil;} static intchecksuper(Super *super){ if(super->magic != SUPERMAGIC){ werrstr("bad magic 0x%ux wanted 0x%ux", super->magic, SUPERMAGIC); return -1; } return 0;} static intext2sync(Fsys *fsys){ int i; Group g; Block *b; Super super; Ext2 *fs; Disk *disk; fs = fsys->priv; disk = fs->disk; if((b = diskread(disk, SBSIZE, SBOFF)) == nil) return -1; parsesuper(&super, b->data); blockput(b); if(checksuper(&super) < 0) return -1; fs->blocksize = MINBLOCKSIZE<<super.logblocksize; fs->nblock = super.nblock; fs->ngroup = (super.nblock+super.blockspergroup-1) / super.blockspergroup; fs->inospergroup = super.inospergroup; fs->blockspergroup = super.blockspergroup; if(super.revlevel >= 1) fs->inosize = super.inosize; else fs->inosize = 128; fs->inosperblock = fs->blocksize / fs->inosize; if(fs->blocksize == SBOFF) fs->groupaddr = 2; else fs->groupaddr = 1; fs->descperblock = fs->blocksize / GroupSize; fs->firstblock = super.firstdatablock; fsys->blocksize = fs->blocksize; fsys->nblock = fs->nblock; if(debug) fprint(2, "ext2 %d %d-byte blocks, first data block %d, %d groups of %d\n", fs->nblock, fs->blocksize, fs->firstblock, fs->ngroup, fs->blockspergroup); if(0){ for(i=0; i<fs->ngroup; i++) if(ext2group(fs, i, &g) >= 0) fprint(2, "grp %d: bitblock=%d\n", i, g.bitblock); } return 0;} 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 Nfs3Statushandle2ino(Ext2 *fs, Nfs3Handle *h, u32int *pinum, Inode *ino){ int i; uint ioff; u32int inum; u32int addr; Block *b; Group g; if(h->len != 4) return Nfs3ErrBadHandle; inum = byte2u32(h->h); if(pinum) *pinum = inum; i = (inum-1) / fs->inospergroup; if(i >= fs->ngroup) return Nfs3ErrBadHandle; ioff = (inum-1) % fs->inospergroup; if(ext2group(fs, i, &g) < 0) return Nfs3ErrIo; addr = g.inodeaddr + ioff/fs->inosperblock; if((b = diskread(fs->disk, fs->blocksize, (u64int)addr*fs->blocksize)) == nil) return Nfs3ErrIo; parseinode(ino, b->data+fs->inosize*(ioff%fs->inosperblock)); blockput(b); return Nfs3Ok;} static Nfs3Statusext2root(Fsys *fsys, Nfs3Handle *h){ USED(fsys); mkhandle(h, ROOTINODE); return Nfs3Ok;} static u64intinosize(Inode* ino){ u64int size; size = ino->size; if((ino->mode&IFMT)==IFREG) size |= (u64int)ino->diracl << 32; return size;} static Nfs3Statusino2attr(Ext2 *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: default: return Nfs3ErrBadHandle; } attr->mode = ino->mode&07777; attr->nlink = ino->nlink; attr->uid = ino->uid; attr->gid = ino->gid; attr->size = inosize(ino); attr->used = (u64int)ino->nblock*fs->blocksize; if(attr->type==Nfs3FileBlock || attr->type==Nfs3FileChar){ rdev = ino->block[0]; attr->major = (rdev>>8)&0xFF; attr->minor = rdev & 0xFFFF00FF; }else{ attr->major = 0; attr->minor = 0; } attr->fsid = 0; attr->fileid = inum; attr->atime.sec = ino->atime; attr->atime.nsec = 0; attr->mtime.sec = ino->mtime; attr->mtime.nsec = 0; attr->ctime.sec = ino->ctime; attr->ctime.nsec = 0; return Nfs3Ok;} static intingroup(SunAuthUnix *au, uint gid){ int i; for(i=0; i<au->ng; i++) if(au->g[i] == gid) return 1; return 0;} static Nfs3Statusinoperm(Inode *ino, SunAuthUnix *au, int need){ int have; if(allowall) return Nfs3Ok; have = ino->mode&0777; if(ino->uid == au->uid) have >>= 6; else if(ino->gid == au->gid || ingroup(au, ino->gid)) have >>= 3; if((have&need) != need) return Nfs3ErrNotOwner; /* really EPERM */ return Nfs3Ok;} static Nfs3Statusext2getattr(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, Nfs3Attr *attr){ Inode ino; u32int inum; Ext2 *fs; Nfs3Status ok; fs = fsys->priv; if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok) return ok; USED(au); /* anyone can getattr */ return ino2attr(fs, &ino, inum, attr);} static Nfs3Statusext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr){ int have; Inode ino; u32int inum; Ext2 *fs; Nfs3Status ok; fs = fsys->priv; if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok) return ok; have = ino.mode&0777; if(ino.uid == au->uid) have >>= 6; else if(ino.gid == au->gid || ingroup(au, ino.gid)) have >>= 3; *got = 0; if((want&Nfs3AccessRead) && (have&AREAD)) *got |= Nfs3AccessRead; if((want&Nfs3AccessLookup) && (ino.mode&IFMT)==IFDIR && (have&AEXEC)) *got |= Nfs3AccessLookup; if((want&Nfs3AccessExecute) && (ino.mode&IFMT)!=IFDIR && (have&AEXEC)) *got |= Nfs3AccessExecute; return ino2attr(fs, &ino, inum, attr);} Lines 1–500 of 886. Load more
#include <u.h> #include <libc.h> #include <thread.h> #include <sunrpc.h> #include <nfs3.h> #include <diskfs.h> #include "ext2.h" static void parsedirent(Dirent*, uchar*); static void parseinode(Inode*, uchar*); static void parsegroup(Group*, uchar*); static void parsesuper(Super*, uchar*); #define debug 0 static int ext2sync(Fsys*); static void ext2close(Fsys*); static Block* ext2blockread(Fsys*, u64int); static Nfs3Status ext2root(Fsys*, Nfs3Handle*); static Nfs3Status ext2getattr(Fsys*, SunAuthUnix *au, Nfs3Handle*, Nfs3Attr*); static Nfs3Status ext2lookup(Fsys*, SunAuthUnix *au, Nfs3Handle*, char*, Nfs3Handle*); static Nfs3Status ext2readfile(Fsys*, SunAuthUnix *au, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*); static Nfs3Status ext2readlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link); static Nfs3Status ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*); static Nfs3Status ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr); Fsys* fsysopenext2(Disk *disk, u32int bs, u64int off) { Ext2 *fs; Fsys *fsys; fsys = emalloc(sizeof(Fsys)); fs = emalloc(sizeof(Ext2)); fs->disk = disk; fsys->priv = fs; fs->fsys = fsys; fsys->type = "ext2"; fsys->_readblock = ext2blockread; fsys->_sync = ext2sync; fsys->_root = ext2root; fsys->_getattr = ext2getattr; fsys->_access = ext2access; fsys->_lookup = ext2lookup; fsys->_readfile = ext2readfile; fsys->_readlink = ext2readlink; fsys->_readdir = ext2readdir; fsys->_close = ext2close; if(ext2sync(fsys) < 0) goto error; return fsys; error: ext2close(fsys); return nil; } static void ext2close(Fsys *fsys) { Ext2 *fs; fs = fsys->priv; free(fs); free(fsys); } static int ext2group(Ext2 *fs, u32int i, Group *g) { Block *b; u64int addr; if(i >= fs->ngroup) return -1; addr = fs->groupaddr + i/fs->descperblock; b = diskread(fs->disk, fs->blocksize, addr*fs->blocksize); if(b == nil) return -1; parsegroup(g, b->data+i%fs->descperblock*GroupSize); blockput(b); return 0; } static Block* ext2blockread(Fsys *fsys, u64int vbno) { Block *bitb; Group g; uchar *bits; u32int bno, boff, bitblock; u64int bitpos; Ext2 *fs; fs = fsys->priv; if(vbno >= fs->nblock) return nil; bno = vbno; if(bno != vbno) return nil; /* if(bno < fs->firstblock) return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize); */ if(bno < fs->firstblock) return nil; bno -= fs->firstblock; if(ext2group(fs, bno/fs->blockspergroup, &g) < 0){ if(debug) fprint(2, "loading group: %r..."); return nil; } /* if(debug) fprint(2, "ext2 group %d: bitblock=%ud inodebitblock=%ud inodeaddr=%ud freeblocks=%ud freeinodes=%ud useddirs=%ud\n", (int)(bno/fs->blockspergroup), g.bitblock, g.inodebitblock, g.inodeaddr, g.freeblockscount, g.freeinodescount, g.useddirscount); if(debug) fprint(2, "group %d bitblock=%d...", bno/fs->blockspergroup, g.bitblock); */ bitblock = g.bitblock; bitpos = (u64int)bitblock*fs->blocksize; if((bitb = diskread(fs->disk, fs->blocksize, bitpos)) == nil){ if(debug) fprint(2, "loading bitblock: %r..."); return nil; } bits = bitb->data; boff = bno%fs->blockspergroup; if((bits[boff>>3] & (1<<(boff&7))) == 0){ if(debug) fprint(2, "block %d not allocated in group %d: bitblock %d/%lld bits[%d] = %#x\n", boff, bno/fs->blockspergroup, (int)bitblock, bitpos, boff>>3, bits[boff>>3]); blockput(bitb); return nil; } blockput(bitb); bno += fs->firstblock; return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize); } static Block* ext2datablock(Ext2 *fs, u32int bno, int size) { USED(size); return ext2blockread(fs->fsys, bno); } static Block* ext2fileblock(Ext2 *fs, Inode *ino, u32int bno, int size) { int ppb; Block *b; u32int *a; u32int obno, pbno; obno = bno; if(bno < NDIRBLOCKS){ if(debug) fprint(2, "fileblock %d -> %d...", bno, ino->block[bno]); return ext2datablock(fs, ino->block[bno], size); } bno -= NDIRBLOCKS; ppb = fs->blocksize/4; /* one indirect */ if(bno < ppb){ b = ext2datablock(fs, ino->block[INDBLOCK], fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; bno = a[bno]; blockput(b); return ext2datablock(fs, bno, size); } bno -= ppb; /* one double indirect */ if(bno < ppb*ppb){ b = ext2datablock(fs, ino->block[DINDBLOCK], fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; pbno = a[bno/ppb]; bno = bno%ppb; blockput(b); b = ext2datablock(fs, pbno, fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; bno = a[bno]; blockput(b); return ext2datablock(fs, bno, size); } bno -= ppb*ppb; /* one triple indirect */ if(bno < ppb*ppb*ppb){ b = ext2datablock(fs, ino->block[TINDBLOCK], fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; pbno = a[bno/(ppb*ppb)]; bno = bno%(ppb*ppb); blockput(b); b = ext2datablock(fs, pbno, fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; pbno = a[bno/ppb]; bno = bno%ppb; blockput(b); b = ext2datablock(fs, pbno, fs->blocksize); if(b == nil) return nil; a = (u32int*)b->data; bno = a[bno]; blockput(b); return ext2datablock(fs, bno, size); } fprint(2, "ext2fileblock %ud: too big\n", obno); return nil; } static int checksuper(Super *super) { if(super->magic != SUPERMAGIC){ werrstr("bad magic 0x%ux wanted 0x%ux", super->magic, SUPERMAGIC); return -1; } return 0; } static int ext2sync(Fsys *fsys) { int i; Group g; Block *b; Super super; Ext2 *fs; Disk *disk; fs = fsys->priv; disk = fs->disk; if((b = diskread(disk, SBSIZE, SBOFF)) == nil) return -1; parsesuper(&super, b->data); blockput(b); if(checksuper(&super) < 0) return -1; fs->blocksize = MINBLOCKSIZE<<super.logblocksize; fs->nblock = super.nblock; fs->ngroup = (super.nblock+super.blockspergroup-1) / super.blockspergroup; fs->inospergroup = super.inospergroup; fs->blockspergroup = super.blockspergroup; if(super.revlevel >= 1) fs->inosize = super.inosize; else fs->inosize = 128; fs->inosperblock = fs->blocksize / fs->inosize; if(fs->blocksize == SBOFF) fs->groupaddr = 2; else fs->groupaddr = 1; fs->descperblock = fs->blocksize / GroupSize; fs->firstblock = super.firstdatablock; fsys->blocksize = fs->blocksize; fsys->nblock = fs->nblock; if(debug) fprint(2, "ext2 %d %d-byte blocks, first data block %d, %d groups of %d\n", fs->nblock, fs->blocksize, fs->firstblock, fs->ngroup, fs->blockspergroup); if(0){ for(i=0; i<fs->ngroup; i++) if(ext2group(fs, i, &g) >= 0) fprint(2, "grp %d: bitblock=%d\n", i, g.bitblock); } return 0; } 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 Nfs3Status handle2ino(Ext2 *fs, Nfs3Handle *h, u32int *pinum, Inode *ino) { int i; uint ioff; u32int inum; u32int addr; Block *b; Group g; if(h->len != 4) return Nfs3ErrBadHandle; inum = byte2u32(h->h); if(pinum) *pinum = inum; i = (inum-1) / fs->inospergroup; if(i >= fs->ngroup) return Nfs3ErrBadHandle; ioff = (inum-1) % fs->inospergroup; if(ext2group(fs, i, &g) < 0) return Nfs3ErrIo; addr = g.inodeaddr + ioff/fs->inosperblock; if((b = diskread(fs->disk, fs->blocksize, (u64int)addr*fs->blocksize)) == nil) return Nfs3ErrIo; parseinode(ino, b->data+fs->inosize*(ioff%fs->inosperblock)); blockput(b); return Nfs3Ok; } static Nfs3Status ext2root(Fsys *fsys, Nfs3Handle *h) { USED(fsys); mkhandle(h, ROOTINODE); return Nfs3Ok; } static u64int inosize(Inode* ino) { u64int size; size = ino->size; if((ino->mode&IFMT)==IFREG) size |= (u64int)ino->diracl << 32; return size; } static Nfs3Status ino2attr(Ext2 *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: default: return Nfs3ErrBadHandle; } attr->mode = ino->mode&07777; attr->nlink = ino->nlink; attr->uid = ino->uid; attr->gid = ino->gid; attr->size = inosize(ino); attr->used = (u64int)ino->nblock*fs->blocksize; if(attr->type==Nfs3FileBlock || attr->type==Nfs3FileChar){ rdev = ino->block[0]; attr->major = (rdev>>8)&0xFF; attr->minor = rdev & 0xFFFF00FF; }else{ attr->major = 0; attr->minor = 0; } attr->fsid = 0; attr->fileid = inum; attr->atime.sec = ino->atime; attr->atime.nsec = 0; attr->mtime.sec = ino->mtime; attr->mtime.nsec = 0; attr->ctime.sec = ino->ctime; attr->ctime.nsec = 0; return Nfs3Ok; } static int ingroup(SunAuthUnix *au, uint gid) { int i; for(i=0; i<au->ng; i++) if(au->g[i] == gid) return 1; return 0; } static Nfs3Status inoperm(Inode *ino, SunAuthUnix *au, int need) { int have; if(allowall) return Nfs3Ok; have = ino->mode&0777; if(ino->uid == au->uid) have >>= 6; else if(ino->gid == au->gid || ingroup(au, ino->gid)) have >>= 3; if((have&need) != need) return Nfs3ErrNotOwner; /* really EPERM */ return Nfs3Ok; } static Nfs3Status ext2getattr(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, Nfs3Attr *attr) { Inode ino; u32int inum; Ext2 *fs; Nfs3Status ok; fs = fsys->priv; if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok) return ok; USED(au); /* anyone can getattr */ return ino2attr(fs, &ino, inum, attr); } static Nfs3Status ext2access(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr) { int have; Inode ino; u32int inum; Ext2 *fs; Nfs3Status ok; fs = fsys->priv; if((ok = handle2ino(fs, h, &inum, &ino)) != Nfs3Ok) return ok; have = ino.mode&0777; if(ino.uid == au->uid) have >>= 6; else if(ino.gid == au->gid || ingroup(au, ino.gid)) have >>= 3; *got = 0; if((want&Nfs3AccessRead) && (have&AREAD)) *got |= Nfs3AccessRead; if((want&Nfs3AccessLookup) && (ino.mode&IFMT)==IFDIR && (have&AEXEC)) *got |= Nfs3AccessLookup; if((want&Nfs3AccessExecute) && (ino.mode&IFMT)!=IFDIR && (have&AEXEC)) *got |= Nfs3AccessExecute; return ino2attr(fs, &ino, inum, attr); }