Commiting changes to fs2.c and request.c. Not commiting required changes to other files yet.

This commit is contained in:
Kris Maglione 2006-06-15 02:48:31 -04:00
parent 87eb4561ce
commit ad38c92e9f
2 changed files with 303 additions and 209 deletions

View File

@ -1,28 +1,41 @@
/* So, here's the begining of my idea of fs.c. Before you think it, yes, it's
* still braindamaged. I'm certain that more simplicification is possible, but
* my brain seems fried every time I try to work it out. Think of this a draft
* in preparation for a draft. The basic idea here is to keep everything regarding
* to directory structure in one place. Everything should be done in lookup_file,
* including finding all files in a dir for a stat and finding files to walk to,
* as well as associating a file with a pointer and id.
*
* I think that I could possibly save quite a few lines of code in lookup_file
* with a function to create the FileId struct and push it onto the list. We'll see.
* I need to sleep on it some more.
*
* Comments are, of course, welcome, but if you don't see where I'm going with this,
* I don't know of how much help they'll be.
*
* This, btw, doesn't compile due to a lack of header files for cext_emallocz,
* Client, lbar, etc.
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "wm.h"
P9Srv p9srv = {
.open= fs_open,
.walk= fs_walk,
.read= fs_read,
.stat= fs_stat,
.write= fs_write,
.attach=fs_attach,
.create=fs_create,
.remove=fs_remove
};
#define QID(t, i) (((long long)((t)&0xFF)<<32)|((i)&0xFFFFFFFF))
#define TYPE(q) ((q)>>32&0xFF)
#define ID(q) ((q)&0xFFFFFFFF)
static char Enoperm[] = "permission denied";
static char Enofile[] = "file not found";
//static char Efidinuse[] = "fid in use";
//static char Enomode[] = "mode not supported";
//static char Enofunc[] = "function not supported";
//static char Enocommand[] = "command not supported";
//static char Ebadvalue[] = "bad value";
enum { FsRoot, FsDClient, FsDClients, FsDLBar,
FsDRBar, FsDSClient, FsDTag, FsDTags,
FsFBar, FsFCNorm, FsFCSel, FsFCctl,
FsFCindex, FsFColRules, FsFEvent, FsFFont,
FsFKeys, FsFRctl, FsFTagRules, FsFTctl,
FsFTindex, FsFprops, RsFFont
};
typedef struct Dirtab Dirtab; typedef struct Dirtab Dirtab;
struct Dirtab struct Dirtab
{ {
@ -32,26 +45,21 @@ struct Dirtab
unsigned int perm; unsigned int perm;
}; };
#define nil ((void *)0)
#define QID(t, i) (((long long)((t)&0xFF)<<32)|((i)&0xFFFFFFFF)) typedef struct FileId FileId;
#define TYPE(q) ((q)>>32&0xFF) struct FileId {
#define ID(q) ((q)&0xFFFFFFFF) FileId *next;
void *ref;
enum { DMDIR, DMAPPEND, QTDIR, QTFILE, QTAPPEND }; unsigned int id;
enum { FsRoot, FsDClient, FsDClients, FsDLBar, unsigned int index;
FsDRBar, FsDSClient, FsDTag, FsDTags, Dirtab tab;
FsFBar, FsFCNorm, FsFCSel, FsFCctl,
FsFCindex, FsFColRules, FsFEvent, FsFFont,
FsFKeys, FsFRctl, FsFTagRules, FsFTctl,
FsFTindex, FsFprops, RsFFont
}; };
Dirtab *dirtab[] = static void dostat(Stat *s, unsigned int len, FileId *f);
{ FileId *free_fileid = nil;
[FsRoot] (Dirtab [])
{{".", QTDIR, FsRoot, 0500|DMDIR }, static Dirtab
dirtabroot[]= {{".", QTDIR, FsRoot, 0500|DMDIR },
{"rbar", QTDIR, FsDRBar, 0700|DMDIR }, {"rbar", QTDIR, FsDRBar, 0700|DMDIR },
{"lbar", QTDIR, FsDLBar, 0700|DMDIR }, {"lbar", QTDIR, FsDLBar, 0700|DMDIR },
{"client", QTDIR, FsDClients, 0500|DMDIR }, {"client", QTDIR, FsDClients, 0500|DMDIR },
@ -65,52 +73,40 @@ Dirtab *dirtab[] =
{"normcolors", QTFILE, FsFCNorm, 0600 }, {"normcolors", QTFILE, FsFCNorm, 0600 },
{"selcolors", QTFILE, FsFCSel, 0600 }, {"selcolors", QTFILE, FsFCSel, 0600 },
{nil}}, {nil}},
[FsDRBar] (Dirtab []) dirtabclient[]= {{".", QTFILE, FsDClient, 0500|DMDIR },
{{".", QTDIR, FsDRBar, 0700|DMDIR },
{"", QTFILE, FsFBar, 0600 },
{nil}},
[FsDLBar] (Dirtab [])
{{".", QTDIR, FsDRBar, 0700|DMDIR },
{"", QTFILE, FsFBar, 0600 },
{nil}},
[FsDClients] (Dirtab [])
{{".", QTDIR, FsDClients, 0500|DMDIR },
{"", QTDIR, FsDClient, 0500|DMDIR },
{nil}},
[FsDClient] (Dirtab [])
{{".", QTFILE, FsDClient, 0500|DMDIR },
{"ctl", QTAPPEND, FsFCctl, 0200|DMAPPEND }, {"ctl", QTAPPEND, FsFCctl, 0200|DMAPPEND },
{"props", QTFILE, FsFprops, 0400 }, {"props", QTFILE, FsFprops, 0400 },
{nil}}, {nil}},
[FsDSClient] (Dirtab []) dirtabsclient[]={{".", QTDIR, FsDClient, 0500|DMDIR },
{{".", QTDIR, FsDClient, 0500|DMDIR },
{"ctl", QTAPPEND, FsFCctl, 0200|DMAPPEND }, {"ctl", QTAPPEND, FsFCctl, 0200|DMAPPEND },
{"index", QTFILE, FsFCindex, 0400 }, {"index", QTFILE, FsFCindex, 0400 },
{"props", QTFILE, FsFprops, 0400 }, {"props", QTFILE, FsFprops, 0400 },
{nil}}, {nil}},
[FsDTags] (Dirtab []) dirtabbar[]= {{".", QTDIR, FsDRBar, 0700|DMDIR },
{{".", QTDIR, FsDTags, 0500|DMDIR }, {"", QTFILE, FsFBar, 0600 },
{nil}},
dirtabclients[]={{".", QTDIR, FsDClients, 0500|DMDIR },
{"", QTDIR, FsDClient, 0500|DMDIR },
{nil}},
dirtabtags[]= {{".", QTDIR, FsDTags, 0500|DMDIR },
{"", QTDIR, FsDTag, 0500|DMDIR }, {"", QTDIR, FsDTag, 0500|DMDIR },
{nil}}, {nil}},
[FsDTag] (Dirtab []) dirtabtag[]= {{".", QTDIR, FsDTag, 0500|DMDIR },
{{".", QTDIR, FsDTag, 0500|DMDIR },
{"ctl", QTAPPEND, FsFTctl, 0200|DMAPPEND }, {"ctl", QTAPPEND, FsFTctl, 0200|DMAPPEND },
{"index", QTFILE, FsFTindex, 0400 }, {"index", QTFILE, FsFTindex, 0400 },
{nil}} {nil}};
static Dirtab *dirtab[] = {
[FsRoot] dirtabroot,
[FsDRBar] dirtabbar,
[FsDLBar] dirtabbar,
[FsDClients] dirtabclients,
[FsDClient] dirtabclient,
[FsDSClient] dirtabsclient,
[FsDTags] dirtabtags,
[FsDTag] dirtabtag
}; };
typedef struct FileId FileId; static FileId *
struct FileId {
FileId *next;
void *ref;
unsigned int id;
unsigned int index;
Dirtab tab;
};
FileId *free_fileid = nil;
FileId *
get_file() { get_file() {
FileId *temp; FileId *temp;
if(!free_fileid) { if(!free_fileid) {
@ -126,17 +122,20 @@ get_file() {
return temp; return temp;
} }
void static void
free_file(FileId *f) { free_file(FileId *f) {
free(f->tab.name); free(f->tab.name);
f->next = free_fileid; f->next = free_fileid;
free_fileid = f; free_fileid = f;
} }
FileId * static FileId *
lookup_file(FileId *parent, char *name) lookup_file(FileId *parent, char *name)
{ {
unsigned int i; unsigned int i, id;
Client *c;
View *v;
Bar *b;
if(!(parent->tab.perm & DMDIR)) if(!(parent->tab.perm & DMDIR))
return nil; return nil;
@ -160,10 +159,10 @@ lookup_file(FileId *parent, char *name)
temp->ref = rbar; temp->ref = rbar;
break; break;
case FsFColRules: case FsFColRules:
temp->ref = crules; temp->ref = vrule;
break; break;
case FsFTagRules: case FsFTagRules:
temp->ref = trules; temp->ref = trule;
break; break;
} }
if(name) if(name)
@ -172,9 +171,8 @@ lookup_file(FileId *parent, char *name)
if(!*dir->name) { /* strlen(dir->name) == 0 */ if(!*dir->name) { /* strlen(dir->name) == 0 */
switch(parent->tab.type) { switch(parent->tab.type) {
case FsDClients: case FsDClients:
Client *c;
if(!name || !strncmp(name, "sel", 4)) { if(!name || !strncmp(name, "sel", 4)) {
if(sel && sel->sel && (c = sel->sel->sel->client)) { if((c = sel_client())) {
temp = get_file(); temp = get_file();
*last = temp; *last = temp;
last = &temp->next; last = &temp->next;
@ -184,33 +182,28 @@ lookup_file(FileId *parent, char *name)
temp->tab = *dirtab[FsDSClient]; temp->tab = *dirtab[FsDSClient];
temp->tab.name = strdup("sel"); temp->tab.name = strdup("sel");
} }
if(name)
goto LastItem;
}else{ }else{
if(name) { if(name) {
i = (unsigned int)strtol(name, &name, 10); id = (unsigned int)strtol(name, &name, 10);
if(*name) if(*name)
continue; continue;
} }
for(c=client; c; c=c->next) { for(c=client; c; c=c->next) {
if(!name || c->index == i) { if(name && c->id != id)
temp = get_file(); continue;
*last = temp; temp = get_file();
last = &temp->next; *last = temp;
temp->ref = c; last = &temp->next;
temp->id = c->id; temp->ref = c;
temp->tab = *dirtab[FsDClient]; temp->id = c->id;
asprintf(&temp->tab.name, "%d", c->index); temp->tab = *dirtab[FsDClient];
if(name) asprintf(&temp->tab.name, "%d", i);
goto LastItem; if(name)
} goto LastItem;
} }
if(name)
goto LastItem; /* label doesn't exist */
} }
case FsDTags: case FsDTags:
View *v;
if(!name || !strncmp(name, "sel", 4)) { if(!name || !strncmp(name, "sel", 4)) {
if(sel) { if(sel) {
temp = get_file(); temp = get_file();
@ -221,25 +214,20 @@ lookup_file(FileId *parent, char *name)
temp->tab = *dirtab[FsDTag]; temp->tab = *dirtab[FsDTag];
temp->tab.name = strdup("sel"); temp->tab.name = strdup("sel");
} }
if(name)
goto LastItem;
}else{ }else{
for(v=view; v; v=v->next) { for(v=view; v; v=v->next) {
if(!name || !strcmp(name, v->name)) { if(name && strcmp(name, v->name))
temp = get_file(); continue;
*last = temp; temp = get_file();
last = &temp->next; *last = temp;
temp->rev = v; last = &temp->next;
temp->id = v->id; temp->ref = v;
temp->name = strdup(v->name); temp->id = v->id;
if(name) temp->tab.name = strdup(v->name);
goto LastItem;
}
} }
} }
case FsDRBar: case FsDRBar:
case FsDLBar: case FsDLBar:
Bar *b;
for(b=parent->ref; b; b=b->next) { for(b=parent->ref; b; b=b->next) {
if(!name || strcmp(name, b->name)) { if(!name || strcmp(name, b->name)) {
temp = get_file(); temp = get_file();
@ -248,10 +236,12 @@ lookup_file(FileId *parent, char *name)
temp->ref = b; temp->ref = b;
temp->id = b->id; temp->id = b->id;
temp->tab = dirtab[FsDRBar][1]; temp->tab = dirtab[FsDRBar][1];
temp->tab.name = strdup(bar->name); temp->tab.name = strdup(b->name);
} }
} }
} }
if(name)
goto LastItem;
} }
} }
LastItem: LastItem:
@ -259,6 +249,7 @@ LastItem:
return ret; return ret;
} }
/* XXX This leaks FileIds */
void void
fs_walk(Req *r) { fs_walk(Req *r) {
FileId *f = r->fid->aux, *nf, **fi; FileId *f = r->fid->aux, *nf, **fi;
@ -268,13 +259,14 @@ fs_walk(Req *r) {
if(!strncmp(r->ifcall.wname[i], "..", 3)) { if(!strncmp(r->ifcall.wname[i], "..", 3)) {
if(f->next) f=f->next; if(f->next) f=f->next;
}else{ }else{
nf = lookup_file(f, r->ircall.wname[i]); nf = lookup_file(f, r->ifcall.wname[i]);
if(!nf) if(!nf)
break; break;
nf->next = f; nf->next = f;
f = nf; f = nf;
} }
r->ofcall.wqid[i] = QID(f->tab.type, f->id); r->ofcall.wqid[i].type = f->tab.qtype;
r->ofcall.wqid[i].path = QID(f->tab.type, f->id);
} }
if(i < r->ifcall.nwname) { if(i < r->ifcall.nwname) {
for(; f != r->fid->aux; f=nf) { for(; f != r->fid->aux; f=nf) {
@ -284,40 +276,45 @@ fs_walk(Req *r) {
respond(r, Enofile); respond(r, Enofile);
} }
r->newfid->aux = f;
if(r->ifcall.fid != r->ifcall.newfid) { if(r->ifcall.fid != r->ifcall.newfid) {
r->newfid.aux = f; for(fi=(void *)&r->newfid->aux;
for(fi=&r->newfid.aux; *fi != r->fid.aux; fi=&(*fi)->next); *fi != r->fid->aux;
fi=&(*fi)->next);
for(; *fi; fi=&(*fi)->next) { for(; *fi; fi=&(*fi)->next) {
nf = get_file(); nf = get_file();
*nf = **fi; *nf = **fi;
*fi = nf; *fi = nf;
} }
}else }
r->fid.aux = f;
r->fid.qid = r->ofcall.qid = r->ofcall.nwqid[i-1]; if(r->ifcall.nwname == 0)
r->newfid->qid = r->fid->qid;
else
r->newfid->qid = r->ofcall.wqid[i-1];
r->ofcall.nwqid = i; r->ofcall.nwqid = i;
r->fid.aux = f; respond(r, nil);
respond(r);
} }
/* All of this stat stuf is ugly. */ /* All of this stat stuf is ugly. */
void void
fs_stat(Req *r) { fs_stat(Req *r) {
Stat s; Stat s;
int size = IXP_MAX_STAT; int size;
void *buf = cext_emallocz(size); unsigned char *buf;
r->ofcall.stat = buf;
dostat(&s, 0, r->fid->aux); dostat(&s, 0, r->fid->aux);
r->ofcall.nstat = size = ixp_sizeof_stat(&s);
buf = cext_emallocz(size);
r->ofcall.stat = buf;
ixp_pack_stat(&buf, &size, &s); ixp_pack_stat(&buf, &size, &s);
r->ofcall.nstat = IXP_MAX_STAT - size; respond(r, nil);
respond(r);
} }
void void
fs_read(Req *r) { fs_read(Req *r) {
void *buf; unsigned char *buf;
unsigned int n, offset = 0; unsigned int n, offset = 0;
int size; int size;
FileId *f = r->fid->aux, *tf; FileId *f = r->fid->aux, *tf;
@ -325,16 +322,17 @@ fs_read(Req *r) {
if(f->tab.perm & DMDIR) { if(f->tab.perm & DMDIR) {
Stat s; Stat s;
offset = 0; offset = 0;
size = r->ifcall->count; size = r->ifcall.count;
buf = cext_emallocz(size); buf = cext_emallocz(size);
f.ofcall.data = buf; r->ofcall.data = buf;
f = lookup_file(f, nil); f = lookup_file(f, nil);
for(; f; f=f->next) { /* f->tab.name == "."; goto next */
for(f=f->next; f; f=f->next) {
dostat(&s, 0, f); dostat(&s, 0, f);
n = ixp_sizeof_stat(s); n = ixp_sizeof_stat(&s);
offset += n; offset += n;
if(offset >= f->ifcall.offset) { if(offset >= r->ifcall.offset) {
if(size < n) if(size < n)
break; break;
ixp_pack_stat(&buf, &size, &s); ixp_pack_stat(&buf, &size, &s);
@ -346,25 +344,66 @@ fs_read(Req *r) {
free_file(tf); free_file(tf);
} }
f.ofcall.size = f.ifcall.size - size; r->ofcall.count = r->ifcall.count - size;
respond(f, nil); respond(r, nil);
}else{ }else{
} }
} }
void void
fs_attach(Req *r) {
FileId *f = cext_emallocz(sizeof(FileId));
f->tab = dirtab[FsRoot][0];
f->tab.name = strdup("/");
r->fid->aux = f;
r->fid->qid.type = f->tab.qtype;
r->fid->qid.path = QID(f->tab.type, 0);
r->ofcall.qid = r->fid->qid;
respond(r, nil);
}
void
fs_remove(Req *r) {
respond(r, "not implemented");
}
void
fs_write(Req *r) {
respond(r, "not implemented");
}
void
fs_open(Req *r) {
if(!r->ifcall.mode == OREAD)
respond(r, Enoperm);
r->fid->omode = OREAD;
respond(r, nil);
}
void
fs_create(Req *r) {
respond(r, "not implemented");
}
void
write_event(char *buf) {
return;
}
static void
dostat(Stat *s, unsigned int len, FileId *f) { dostat(Stat *s, unsigned int len, FileId *f) {
s->type = 0; s->type = 0;
s->dev = 0; s->dev = 0;
s->qid.path = QID(f->tab.type, f->id); s->qid.path = QID(f->tab.type, f->id);
s->qid.vers = 0; s->qid.version = 0;
s->qid.type = f->tab.qtype; s->qid.type = f->tab.qtype;
s->mode = f->tab.perm; s->mode = f->tab.perm;
s->atime = clock; s->atime = time(nil);
s->mtime = clock; s->mtime = time(nil);
s->length = len; s->length = len;
s->name = f->tab.name; s->name = f->tab.name;
s->uid = user; /* XXX This genenv should be called once */
s->gid = user; s->uid = getenv("USER");
s->muid = user; s->gid = getenv("USER");
s->muid = getenv("USER");
} }

View File

@ -1,73 +1,89 @@
enum { TAG_BUCKETS = 64; #include <stdlib.h>
FID_BUCKETS = 64; } #include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include "ixp.h"
typedef struct Fid { static void ixp_handle_req(Req *r);
unsigned long fid;
unsigned char omode;
char *uid;
Qid qid;
void *aux;
/* Implementation specific */ void *
/* Do not use */ createfid(Intmap *map, int fid) {
Fid *f = cext_emallocz(sizeof(Fid));
unsigned long ofid; f->fid = fid;
} Fid; f->omode = -1;
f->map = map;
struct IXPConn { if(caninsertkey(map, fid, f))
IXPConn *next; return f;
IXPServer *srv; free(f);
void *aux; return nil;
int fd; }
void (*read) (IXPConn *); int
void (*close) (IXPConn *); destroyfid(Intmap *map, unsigned long fid) {
}; Fid *f;
if(!(f = deletekey(map, fid)))
struct P9Conn { return 0;
free(f);
return 1;
} }
Req * static char
ixp_server_receive_req(IXPConn *c) Eduptag[] = "tag in use",
Edupfid[] = "fid in use",
Enofunc[] = "function not implemented",
Ebotch[] = "9P protocol botch",
Enofile[] = "the requested file does not exist",
Enofid[] = "fid does not exist",
Enotdir[] = "not a directory",
Eisdir[] = "cannot perform operation on a directory";
enum { TAG_BUCKETS = 64,
FID_BUCKETS = 64 };
typedef struct P9Conn {
Intmap tagmap;
void *taghash[TAG_BUCKETS];
Intmap fidmap;
void *fidhash[FID_BUCKETS];
P9Srv *srv;
unsigned int msize;
unsigned char *buf;
} P9Conn;
void
ixp_server_handle_fcall(IXPConn *c)
{ {
Fcall fcall; Fcall fcall;
P9Client *pc = c->aux; P9Conn *pc = c->aux;
Req *req; Req *req;
unsigned int msize; unsigned int msize;
char *errstr = nil; char *errstr = nil;
if(!(msize = ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &errstr))) if(!(msize = ixp_recv_message(c->fd, pc->buf, pc->msize, &errstr)))
goto Fail; goto Fail;
if(!(msize = ixp_msg2fcall(&fcall, msg, IXP_MAX_MSG))) if(!(msize = ixp_msg2fcall(&fcall, pc->buf, IXP_MAX_MSG)))
goto Fail; goto Fail;
req = cext_emallocz(sizeof(Req)); req = cext_emallocz(sizeof(Req));
req->conn = c; req->conn = c;
req->ifcall = fcall; req->ifcall = fcall;
if(lookupkey(pc->tagmap, fcall->tag)) { if(lookupkey(&pc->tagmap, fcall.tag))
respond(req, Edupdag); return respond(req, Eduptag);
return nil;
}
insertkey(pc->tagmap, fcall.id, req); insertkey(&pc->tagmap, fcall.tag, req);
return req; return ixp_handle_req(req);
Fail: Fail:
ixp_close_conn(c); ixp_server_close_conn(c);
return nil;
} }
void static void
ixp_handle_fcall(IXPConn *c) ixp_handle_req(Req *r)
{ {
Req *r; P9Conn *pc = r->conn->aux;
unsigned int msize; P9Srv *srv = pc->srv;
P9Conn *pc = c->aux;
if(!(r = ixp_server_receive_fcall(c, &fcall))) switch(r->ifcall.type) {
return;
switch(r->ifcall.id) {
default: default:
respond(r, Enofunc); respond(r, Enofunc);
break; break;
@ -84,18 +100,18 @@ ixp_handle_fcall(IXPConn *c)
respond(r, nil); respond(r, nil);
break; break;
case TATTACH: case TATTACH:
if(!(r->fid = createfid(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = createfid(&pc->fidmap, r->ifcall.fid)))
return respond(r, Edupfid); return respond(r, Edupfid);
/* attach is a required function */ /* attach is a required function */
srv->attach(r); srv->attach(r);
break; break;
case TCLUNK: case TCLUNK:
if(!destroyfid(pc, r->ifcall.fid)) if(!destroyfid(&pc->fidmap, r->ifcall.fid))
return respond(r, Enofid); return respond(r, Enofid);
respond(r, nil); respond(r, nil);
break; break;
case TCREATE: case TCREATE:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if(r->fid->omode != -1) if(r->fid->omode != -1)
return respond(r, Ebotch); return respond(r, Ebotch);
@ -106,54 +122,56 @@ ixp_handle_fcall(IXPConn *c)
pc->srv->create(r); pc->srv->create(r);
break; break;
case TOPEN: case TOPEN:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if((r->fid.qid.type&QTDIR) && (r->fcall.mode|ORCLOSE) != (OREAD|ORCLOSE)) if((r->fid->qid.type&QTDIR) && (r->ifcall.mode|ORCLOSE) != (OREAD|ORCLOSE))
return respond(r, Eisdir); return respond(r, Eisdir);
r->ofcall.qid = r->fid.qid; r->ofcall.qid = r->fid->qid;
if(!pc->srv->open) if(!pc->srv->open)
return respond(r, Enofunc); return respond(r, Enofunc);
pc->srv->open(r); pc->srv->open(r);
break; break;
case TREAD: case TREAD:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if(r->fid.omode == -1) if(r->fid->omode == -1)
return respond(r, Ebotch); return respond(r, Ebotch);
if(!pc->srv->read) if(!pc->srv->read)
return respond(r, Enofunc); return respond(r, Enofunc);
pc->srv->read(r); pc->srv->read(r);
break; break;
case TREMOVE: case TREMOVE:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if(!pc->srv->remove) if(!pc->srv->remove)
return respond(r, Enofunc); return respond(r, Enofunc);
pc->src->remove(r); pc->srv->remove(r);
break; break;
case TSTAT: case TSTAT:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if(!pc->srv->stat) if(!pc->srv->stat)
return respond(r, Enofunc); return respond(r, Enofunc);
pc->srv->stat(r); pc->srv->stat(r);
break; break;
case TWALK: case TWALK:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if(r->fid->omode != -1) if(r->fid->omode != -1)
return respond(r, "cannot walk from an open fid"); return respond(r, "cannot walk from an open fid");
if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR)) if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR))
return respond(r, Enotdir); return respond(r, Enotdir);
if((r->ifcall.fid != r->ifcall.newfid) && if((r->ifcall.fid != r->ifcall.newfid)) {
!(r->newfid = createfid(pc->fid_hash, r->ifcall.newfid))) if(!(r->newfid = createfid(&pc->fidmap, r->ifcall.newfid)))
return respond(r, Edupfid); return respond(r, Edupfid);
}else
r->newfid = r->fid;
if(!pc->srv->walk) if(!pc->srv->walk)
return respond(r, Enofunc); return respond(r, Enofunc);
pc->srv->walk(r); pc->srv->walk(r);
break; break;
case TWRITE: case TWRITE:
if(!(r->fid = lookupkey(pc->fid_hash, r->ifcall.fid))) if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid); return respond(r, Enofid);
if((r->fid->omode&3) != OWRITE && (r->fid->omode&3) != ORDWR) if((r->fid->omode&3) != OWRITE && (r->fid->omode&3) != ORDWR)
return respond(r, "write on fid not opened for writing"); return respond(r, "write on fid not opened for writing");
@ -170,7 +188,8 @@ respond(Req *r, char *error) {
P9Conn *pc = r->conn->aux; P9Conn *pc = r->conn->aux;
switch(r->ifcall.type) { switch(r->ifcall.type) {
default: default:
cext_assert(!"Respond called on unsupported fcall type"); if(!error)
cext_assert(!"Respond called on unsupported fcall type");
break; break;
case TVERSION: case TVERSION:
cext_assert(!error); cext_assert(!error);
@ -180,7 +199,7 @@ respond(Req *r, char *error) {
break; break;
case TATTACH: case TATTACH:
if(error) if(error)
destroyfid(r->fid); destroyfid(r->fid->map, r->fid->fid);
break; break;
case TOPEN: case TOPEN:
case TCREATE: case TCREATE:
@ -191,12 +210,12 @@ respond(Req *r, char *error) {
break; break;
case TWALK: case TWALK:
if(error || r->ofcall.nwqid < r->ifcall.nwname) { if(error || r->ofcall.nwqid < r->ifcall.nwname) {
if(r->ifcall.fid != r->ifcall.newfid) if(r->ifcall.fid != r->ifcall.newfid && r->newfid)
destroyfid(r->newfid); destroyfid(r->newfid->map, r->newfid->fid);
if(!error && r->ofcall.nwqid == 0) if(!error && r->ofcall.nwqid == 0)
error = Enofile; error = Enofile;
}else{ }else{
if(f->ofcall.nwqid == 0) if(r->ofcall.nwqid == 0)
r->newfid->qid = r->fid->qid; r->newfid->qid = r->fid->qid;
else else
r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1]; r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1];
@ -219,14 +238,46 @@ respond(Req *r, char *error) {
r->ofcall.ename = error; r->ofcall.ename = error;
} }
ixp_server_respond_fcall(r->conn, r->ofcall); /* XXX Check if conn is still open */
ixp_server_respond_fcall(r->conn, &r->ofcall);
deletekey(pc->tag_pool, r->tag);; switch(r->ofcall.type) {
case RSTAT:
free(r->ofcall.stat);
break;
case RREAD:
free(r->ofcall.data);
break;
}
switch(r->ifcall.type) {
case TWALK:
free(r->ifcall.wname[0]);
break;
case TWRITE:
free(r->ifcall.data);
}
deletekey(&pc->tagmap, r->ifcall.tag);;
free(r); free(r);
} }
void static void
ixp_void_request(void *r) {
/* generate flush request */
}
static void
ixp_void_fid(void *f) {
/* generate clunk request */
}
static void
ixp_cleanup_conn(IXPConn *c) { ixp_cleanup_conn(IXPConn *c) {
P9Conn *pc = c->aux;
freemap(&pc->tagmap, ixp_void_request);
freemap(&pc->fidmap, ixp_void_fid);
free(pc->buf);
free(pc);
} }
void void
@ -238,8 +289,12 @@ serve_9pcon(IXPConn *c) {
P9Conn *pc = cext_emallocz(sizeof(P9Conn)); P9Conn *pc = cext_emallocz(sizeof(P9Conn));
pc->srv = c->aux; pc->srv = c->aux;
initmap(&pc->tagmap, TAG_BUCKETS, &pc->tag_hash); /* XXX */
initmap(&pc->fidmap, FID_BUCKETS, &pc->fid_hash); pc->msize = 1024;
pc->buf = cext_emallocz(pc->msize);
ixp_server_open_conn(c->srv, fd, pc, ixp_handle_fcall, ixp_cleanup_conn); initmap(&pc->tagmap, TAG_BUCKETS, &pc->taghash);
initmap(&pc->fidmap, FID_BUCKETS, &pc->fidhash);
ixp_server_open_conn(c->srv, fd, pc, ixp_server_handle_fcall, ixp_cleanup_conn);
} }