diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/ext2srv/ext2fs.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ext2srv/ext2fs.c')
-rwxr-xr-x | sys/src/cmd/ext2srv/ext2fs.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/sys/src/cmd/ext2srv/ext2fs.c b/sys/src/cmd/ext2srv/ext2fs.c new file mode 100755 index 000000000..458b56bfc --- /dev/null +++ b/sys/src/cmd/ext2srv/ext2fs.c @@ -0,0 +1,348 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "dat.h" +#include "fns.h" + +#define thdr r->ifcall +#define rhdr r->ofcall + +extern int errno; + +static void +response(Req *r) +{ + char *err; + + if (errno) { + err = xerrstr(errno); + chat("%s\n", err); + respond(r, err); + } else { + chat("OK\n"); + respond(r, nil); + } +} + +static void +rattach(Req *r) +{ + Xfs *xf; + Xfile *root; + + chat("attach(fid=%d,uname=\"%s\",aname=\"%s\",afid=\"%d\")...", + thdr.fid, thdr.uname, thdr.aname, thdr.afid); + + errno = 0; + root = xfile(r->fid, Clean); + if(!root){ + errno = Enomem; + goto error; + } + root->xf = xf = getxfs(thdr.aname); + if(!xf) + goto error; + + /* now attach root inode */ + if( get_inode(root, EXT2_ROOT_INODE) < 0 ) + goto error; + + r->fid->qid.type = QTDIR; + r->fid->qid.vers = 0; + root->xf->rootqid = r->fid->qid; + root->pinbr = EXT2_ROOT_INODE; + root->root = 1; + rhdr.qid = r->fid->qid; + +error: + response(r); +} +static char * +rclone(Fid *fid, Fid *newfid) +{ + Xfile *of = xfile(fid, Asis); + Xfile *nf = xfile(newfid, Clean); + + chat("clone(fid=%d,newfid=%d)...", fid->fid, newfid->fid); + errno = 0; + if(!of) + errno = Eio; + else if(!nf) + errno = Enomem; + else{ + Xfile *next = nf->next; + *nf = *of; + nf->next = next; + nf->fid = newfid->fid; + nf->root = 0; + } + chat("%s\n", errno? xerrstr(errno) : "OK"); + return errno ? xerrstr(errno) : 0; +} +static char * +rwalk1(Fid *fid, char *name, Qid *qid) +{ + Xfile *f=xfile(fid, Asis); + int nr, sinbr = 0; + + chat("walk1(fid=%d,name=\"%s\")...", fid->fid, name); + errno = 0; + if( !f ){ + chat("no xfile..."); + goto error; + } + if( !(fid->qid.type & QTDIR) ){ + chat("qid.type=0x%x...", fid->qid.type); + goto error; + } + sinbr = f->pinbr; + if( name == 0 || name[0] == 0 || !strcmp(name, ".") ){ + *qid = fid->qid; + goto ok; + }else if( !strcmp(name, "..") ){ + if( fid->qid.path == f->xf->rootqid.path ){ + chat("walkup from root..."); + *qid = fid->qid; + goto ok; + } + if( get_inode(f, f->pinbr) < 0 ) + goto error; + if( f->pinbr == EXT2_ROOT_INODE ){ + *qid = f->xf->rootqid; + f->pinbr = EXT2_ROOT_INODE; + } else { + *qid = (Qid){f->pinbr,0,QTDIR}; + f->inbr = f->pinbr; + if( (nr = get_file(f, "..")) < 0 ) + goto error; + f->pinbr = nr; + } + }else{ + f->pinbr = f->inbr; + if( (nr = get_file(f, name)) < 0 ) + goto error; + if( get_inode(f, nr) < 0 ) + goto error; + *qid = (Qid){nr,0,0}; + if( nr == EXT2_ROOT_INODE ) + *qid = f->xf->rootqid; + else if( S_ISDIR(getmode(f)) ) + qid->type = QTDIR; + /*strcpy(f->name, thdr.name);*/ + } +ok: + chat("OK\n"); + return 0; +error: + f->pinbr = sinbr; + chat("%s\n", xerrstr(Enonexist)); + return xerrstr(Enonexist); +} +static void +rstat(Req *r) +{ + Xfile *f=xfile(r->fid, Asis); + + chat("stat(fid=%d)...", thdr.fid); + errno = 0; + if( !f ) + errno = Eio; + else{ + dostat(r->fid->qid, f, &r->d); + } + response(r); +} +static void +rwstat(Req *r) +{ + Xfile *f=xfile(r->fid, Asis); + + chat("wstat(fid=%d)...", thdr.fid); + errno = 0; + if( !f ) + errno = Eio; + else + dowstat(f, &r->d); + response(r); +} +static void +rread(Req *r) +{ + Xfile *f; + int nr; + + chat("read(fid=%d,offset=%lld,count=%d)...", + thdr.fid, thdr.offset, thdr.count); + errno = 0; + if ( !(f=xfile(r->fid, Asis)) ) + goto error; + if( r->fid->qid.type & QTDIR ){ + nr = readdir(f, r->rbuf, thdr.offset, thdr.count); + }else + nr = readfile(f, r->rbuf, thdr.offset, thdr.count); + + if(nr >= 0){ + rhdr.count = nr; + chat("rcnt=%d...OK\n", nr); + respond(r, nil); + return; + } +error: + errno = Eio; + response(r); +} +static void +rwrite(Req *r) +{ + Xfile *f; int nr; + + chat("write(fid=%d,offset=%lld,count=%d)...", + thdr.fid, thdr.offset, thdr.count); + + errno = 0; + if (!(f=xfile(r->fid, Asis)) ){ + errno = Eio; + goto error; + } + if( !S_ISREG(getmode(f)) ){ + errno = Elink; + goto error; + } + nr = writefile(f, thdr.data, thdr.offset, thdr.count); + if(nr >= 0){ + rhdr.count = nr; + chat("rcnt=%d...OK\n", nr); + respond(r, nil); + return; + } + errno = Eio; +error: + response(r); +} +static void +destroyfid(Fid *fid) +{ + chat("destroy(fid=%d)\n", fid->fid); + xfile(fid, Clunk); + /*syncbuf(xf);*/ +} +static void +ropen(Req *r) +{ + Xfile *f; + + chat("open(fid=%d,mode=%d)...", thdr.fid, thdr.mode); + + errno = 0; + f = xfile(r->fid, Asis); + if( !f ){ + errno = Eio; + goto error; + } + + if(thdr.mode & OTRUNC){ + if( !S_ISREG(getmode(f)) ){ + errno = Eperm; + goto error; + } + if(truncfile(f) < 0){ + goto error; + } + } + chat("f->qid=0x%8.8lux...", r->fid->qid.path); + rhdr.qid = r->fid->qid; +error: + response(r); +} +static void +rcreate(Req *r) +{ + Xfile *f; + int inr, perm; + + chat("create(fid=%d,name=\"%s\",perm=%uo,mode=%d)...", + thdr.fid, thdr.name, thdr.perm, thdr.mode); + + errno = 0; + if(strcmp(thdr.name, ".") == 0 || strcmp(thdr.name, "..") == 0){ + errno = Eperm; + goto error; + } + f = xfile(r->fid, Asis); + if( !f ){ + errno = Eio; + goto error; + } + if( strlen(thdr.name) > EXT2_NAME_LEN ){ + chat("name too long ..."); + errno = Elongname; + goto error; + } + + /* create */ + errno = 0; + if( thdr.perm & DMDIR ){ + perm = (thdr.perm & ~0777) | + (getmode(f) & thdr.perm & 0777); + perm |= S_IFDIR; + inr = create_dir(f, thdr.name, perm); + }else{ + perm = (thdr.perm & (~0777|0111)) | + (getmode(f) & thdr.perm & 0666); + perm |= S_IFREG; + inr = create_file(f, thdr.name, perm); + + } + if( inr < 0 ) + goto error; + + /* fill with new inode */ + f->pinbr = f->inbr; + if( get_inode(f, inr) < 0 ){ + errno = Eio; + goto error; + } + r->fid->qid = (Qid){inr, 0, 0}; + if( S_ISDIR(getmode(f)) ) + r->fid->qid.type |= QTDIR; + chat("f->qid=0x%8.8lux...", r->fid->qid.path); + rhdr.qid = r->fid->qid; +error: + response(r); +} +static void +rremove(Req *r) +{ + Xfile *f=xfile(r->fid, Asis); + + chat("remove(fid=%d) ...", thdr.fid); + + errno = 0; + if(!f){ + errno = Eio; + goto error; + } + + /* check permission here !!!!*/ + + unlink(f); + +error: + response(r); +} + +Srv ext2srv = { + .destroyfid = destroyfid, + .attach = rattach, + .stat = rstat, + .wstat = rwstat, + .clone = rclone, + .walk1 = rwalk1, + .open = ropen, + .read = rread, + .write = rwrite, + .create = rcreate, + .remove = rremove, +}; |