commit b5b00caa66a47bd61c29c52a93b64e03dfc84162
parent 3a5ee74f2e3589f7d64f2753c9451b9c23b40d24
Author: Kris Maglione <bsdaemon@wmii.de>
Date: Fri, 16 Jun 2006 02:34:15 -0400
More fixes/improvements to fs2.c/libixp; for whatever reason, I'm commiting these files and not the tree again.
Diffstat:
| cmd/wm/fs2.c | | | 238 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
| libixp/request.c | | | 61 | ++++++++++++++++++++++++++++++++----------------------------- |
2 files changed, 232 insertions(+), 67 deletions(-)
diff --git a/cmd/wm/fs2.c b/cmd/wm/fs2.c
@@ -10,6 +10,7 @@ P9Srv p9srv = {
.read= fs_read,
.stat= fs_stat,
.write= fs_write,
+ .clunk= fs_clunk,
.attach=fs_attach,
.create=fs_create,
.remove=fs_remove,
@@ -22,26 +23,27 @@ P9Srv p9srv = {
#define TYPE(q) ((q)>>32&0xFF)
#define ID(q) ((q)&0xFFFFFFFF)
-static char Enoperm[] = "permission denied";
-static char Enofile[] = "file not found";
+static char
+ Enoperm[] = "permission denied",
+ Enofile[] = "file not found",
+ Eisdir[] = "file is a directory",
+ Ebadvalue[] = "bad value",
+ Enocommand[] = "command not supported";
//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
+ FsFBar, FsFBorder, FsFCNorm, FsFCSel,
+ FsFCctl, FsFCindex, FsFColRules, FsFEvent,
+ FsFFont, FsFKeys, FsFRctl, FsFTagRules,
+ FsFTctl, FsFTindex, FsFprops, RsFFont
};
typedef struct Dirtab Dirtab;
-struct Dirtab
-{
+struct Dirtab {
char *name;
unsigned char qtype;
unsigned int type;
@@ -51,7 +53,14 @@ struct Dirtab
typedef struct FileId FileId;
struct FileId {
FileId *next;
- void *ref;
+ union {
+ void *ref;
+ Bar *bar;
+ View *view;
+ Client *client;
+ Rules *rule;
+ Color *col;
+ };
unsigned int id;
unsigned int index;
Dirtab tab;
@@ -70,13 +79,14 @@ dirtabroot[]= {{".", QTDIR, FsRoot, 0500|DMDIR },
{"client", QTDIR, FsDClients, 0500|DMDIR },
{"tag", QTDIR, FsDTags, 0500|DMDIR },
{"ctl", QTAPPEND, FsFRctl, 0600|DMAPPEND },
+ {"border", QTFILE, FsFBorder, 0600 },
{"colrules", QTFILE, FsFColRules, 0600 },
- {"tagrules", QTFILE, FsFTagRules, 0600 },
+ {"event", QTFILE, FsFEvent, 0600 },
{"font", QTFILE, FsFFont, 0600 },
{"keys", QTFILE, FsFKeys, 0600 },
- {"event", QTFILE, FsFEvent, 0600 },
{"normcolors", QTFILE, FsFCNorm, 0600 },
{"selcolors", QTFILE, FsFCSel, 0600 },
+ {"tagrules", QTFILE, FsFTagRules, 0600 },
{nil}},
dirtabclients[]={{".", QTDIR, FsDClients, 0500|DMDIR },
{"", QTDIR, FsDClient, 0500|DMDIR },
@@ -131,6 +141,7 @@ get_file() {
temp = free_fileid;
free_fileid = temp->next;
temp->nref = 1;
+ temp->next = nil;
return temp;
}
@@ -153,10 +164,12 @@ free_file(FileId *f) {
free_fileid = f;
}
+/* This function's name belies it's true purpose. It increases
+ * the reference count of the FileId list */
static void
clone_files(FileId *f) {
for(; f; f=f->next)
- f->nref++;
+ cext_assert(f->nref++);
}
/* All lookups and directory organization should be performed through
@@ -164,15 +177,19 @@ clone_files(FileId *f) {
static FileId *
lookup_file(FileId *parent, char *name)
{
- unsigned int i, id;
+ FileId *ret, *file, **last;
+ Dirtab *dir;
Client *c;
View *v;
Bar *b;
+ unsigned int i, id;
if(!(parent->tab.perm & DMDIR))
return nil;
- Dirtab *dir = dirtab[parent->tab.type];
- FileId *ret = nil, *file, **last = &ret;
+
+ dir = dirtab[parent->tab.type];
+ last = &ret;
+ ret = nil;
for(; dir->name; dir++) {
/* Dynamic dirs */
@@ -245,7 +262,7 @@ lookup_file(FileId *parent, char *name)
if(!name || !strcmp(name, dir->name)) {
file = push_file(&last);
file->id = 0;
- file->ref = nil;
+ file->ref = parent->ref;
file->tab = *dir;
/* Special considerations: */
@@ -257,10 +274,16 @@ lookup_file(FileId *parent, char *name)
file->ref = rbar;
break;
case FsFColRules:
- file->ref = vrule;
+ file->ref = &def.colrules;
break;
case FsFTagRules:
- file->ref = trule;
+ file->ref = &def.tagrules;
+ break;
+ case FsFCSel:
+ file->ref = &def.selcolor;
+ break;
+ case FsFCNorm:
+ file->ref = &def.normcolor;
break;
}
if(name) goto LastItem;
@@ -275,9 +298,11 @@ LastItem:
void
fs_walk(Req *r) {
- FileId *f = r->fid->aux, *nf;
+ FileId *f, *nf;
int i;
+ f = r->fid->aux;
+
clone_files(f);
for(i=0; i < r->ifcall.nwname; i++) {
if(!strncmp(r->ifcall.wname[i], "..", 3)) {
@@ -296,8 +321,7 @@ fs_walk(Req *r) {
r->ofcall.wqid[i].type = f->tab.qtype;
r->ofcall.wqid[i].path = QID(f->tab.type, f->id);
}
- /* XXX: This will not be necessary once a free_fid
- * function is implemented */
+ /* There should be a way to do this on freefid() */
if(i < r->ifcall.nwname) {
while((nf = f)) {
f=f->next;
@@ -339,6 +363,20 @@ fs_stat(Req *r) {
respond(r, nil);
}
+static void
+write_buf(Req *r, void *buf, unsigned int len) {
+ if(r->ifcall.offset >= len)
+ return;
+
+ len -= r->ifcall.offset;
+ if(len > r->ifcall.count)
+ len = r->ifcall.count;
+ /* XXX: mallocz is not really needed here */
+ r->ofcall.data = cext_emallocz(len);
+ memcpy(r->ofcall.data, buf + r->ifcall.offset, len);
+ r->ofcall.count = len;
+}
+
/* This should probably be factored out like lookup_file
* so we can use it to get size for stats and not write
* data anywhere. -KM */
@@ -346,9 +384,12 @@ fs_stat(Req *r) {
void
fs_read(Req *r) {
unsigned char *buf;
- unsigned int n, offset = 0;
+ FileId *f, *tf;
+ unsigned int n, offset;
int size;
- FileId *f = r->fid->aux, *tf;
+
+ offset = 0;
+ f = r->fid->aux;
if(f->tab.perm & DMDIR) {
Stat s;
@@ -370,21 +411,47 @@ fs_read(Req *r) {
offset += n;
}
- while((f = tf)) {
- tf = tf->next;
+ for(; f; f = tf) {
+ tf = f->next;
free_file(f);
}
r->ofcall.count = r->ifcall.count - size;
respond(r, nil);
}else{
- /* Read normal files */
+ switch(f->tab.type) {
+ case FsFprops:
+ write_buf(r, (void *)f->client->props, strlen(f->client->props));
+ return respond(r, nil);
+ case FsFCSel:
+ case FsFCNorm:
+ write_buf(r, (void *)f->col->string, strlen(f->col->string));
+ return respond(r, nil);
+ case FsFColRules:
+ case FsFTagRules:
+ write_buf(r, (void *)f->rule->string, f->rule->size);
+ return respond(r, nil);
+ case FsFKeys:
+ write_buf(r, (void *)def.keys, def.keyssz);
+ return respond(r, nil);
+ case FsFFont:
+ write_buf(r, (void *)def.font, strlen(def.font));
+ return respond(r, nil);
+ case FsFBorder:
+ asprintf((void *)&r->ofcall.data, "%d", def.border);
+ if(!r->ifcall.offset)
+ r->ofcall.count = strlen(r->ofcall.data);
+ return respond(r, nil);
+ }
+ /* XXX: This should be taken care of by open */
+ /* should probably be an assertion in the future */
+ respond(r, Enoperm);
}
}
void
fs_attach(Req *r) {
- FileId *f = cext_emallocz(sizeof(FileId));
+ FileId *f = get_file();
f->tab = dirtab[FsRoot][0];
f->tab.name = strdup("/");
r->fid->aux = f;
@@ -394,22 +461,22 @@ fs_attach(Req *r) {
respond(r, nil);
}
-/* fs_* functions below here are yet to be properly implemented */
+/* XXX: fs_* functions below here are yet to be properly implemented */
void
fs_open(Req *r) {
- if(!r->ifcall.mode == OREAD)
- respond(r, Enoperm);
- r->fid->omode = OREAD;
+ /* XXX */
+ r->ofcall.mode = r->ifcall.mode;
respond(r, nil);
}
void
fs_freefid(Fid *f) {
- FileId *id = f->aux, *tid;
- while((tid = id)) {
- id = id->next;
- free_file(tid);
+ FileId *id, *tid;
+
+ for(id=f->aux; id; id = tid) {
+ tid = id->next;
+ free_file(id);
}
}
@@ -419,8 +486,103 @@ fs_remove(Req *r) {
}
void
+fs_clunk(Req *r) {
+ Client *c;
+ FileId *f = r->fid->aux;
+
+ switch(r->ifcall.type) {
+ case FsFTagRules:
+ update_rules(&f->rule->rule, f->rule->string);
+ /* no break */
+ case FsFColRules:
+ for(c=client; c; c=c->next)
+ apply_rules(c);
+ update_views();
+ break;
+ }
+ respond(r, nil);
+}
+
+void
+write_to_buf(Req *r, void *buf, unsigned int *len, unsigned int max) {
+ unsigned int offset, count;
+
+ offset = (r->fid->omode&OAPPEND) ? *len : r->ifcall.offset;
+ if(offset > *len || r->ifcall.count == 0) {
+ r->ofcall.count = 0;
+ return;
+ }
+
+ count = r->ifcall.count;
+ if(max && (count > max - offset))
+ count = max - offset;
+
+ if(r->fid->omode&OTRUNC || (offset + count > *len))
+ *len = offset + count;
+
+ if(max == 0) {
+ *(void **)buf = realloc(*(void **)buf, *len);
+ cext_assert(*(void **)buf);
+ buf = *(void **)buf;
+ }
+
+ memcpy(buf + offset, r->ifcall.data, count);
+}
+
+void
fs_write(Req *r) {
- respond(r, "not implemented");
+ FileId *f;
+ char *buf;
+ unsigned int i;
+
+ f = r->fid->aux;
+ if(f->tab.perm & DMDIR) {
+ respond(r, Eisdir);
+ }else{
+ switch(f->tab.type) {
+ case FsFColRules:
+ case FsFTagRules:
+ write_to_buf(r, &f->rule->string, &f->rule->size, 0);
+ return respond(r, nil);
+ case FsFKeys:
+ write_to_buf(r, &def.keys, &def.keyssz, 0);
+ return respond(r, nil);
+ case FsFFont:
+ i=strlen(def.font);
+ write_to_buf(r, &def.font, &i, 0);
+ return respond(r, nil);
+ case FsFBorder:
+ /* fix me! */
+ buf = realloc(r->ifcall.data, r->ifcall.count + 1);
+ cext_assert(buf);
+ buf[r->ifcall.count] = '\0';
+ i = (unsigned int)strtol(r->ifcall.data, &buf, 10);
+ if(*buf)
+ return respond(r, Ebadvalue);
+ def.border = i;
+ return respond(r, nil);
+ case FsFCSel:
+ case FsFCNorm:
+ if((r->ifcall.count != 23) ||
+ (3 != sscanf(r->ifcall.data, "#%06x #%06x #%06x", &i,&i,&i)))
+ return respond(r, Ebadvalue);
+ r->ofcall.count = 23;
+ bcopy(r->ifcall.data, f->col->string, 23);
+ blitz_loadcolor(&f->col->col, f->col->string);
+ draw_clients();
+ return respond(r, nil);
+ case FsFRctl:
+ if(!strncmp(r->ifcall.data, "quit", 5))
+ srv.running = 0;
+ else if(!strncmp(buf, "view ", 5))
+ select_view(&r->ifcall.data[5]);
+ else
+ return respond(r, Enocommand);
+ r->ofcall.msize = r->ifcall.msize;
+ return respond(r, nil);
+ }
+ respond(r, Enoperm);
+ }
}
void
diff --git a/libixp/request.c b/libixp/request.c
@@ -6,26 +6,6 @@
static void ixp_handle_req(Req *r);
-void *
-createfid(Intmap *map, int fid) {
- Fid *f = cext_emallocz(sizeof(Fid));
- f->fid = fid;
- f->omode = -1;
- f->map = map;
- if(caninsertkey(map, fid, f))
- return f;
- free(f);
- return nil;
-}
-int
-destroyfid(Intmap *map, unsigned long fid) {
- Fid *f;
- if(!(f = deletekey(map, fid)))
- return 0;
- free(f);
- return 1;
-}
-
static char
Eduptag[] = "tag in use",
Edupfid[] = "fid in use",
@@ -49,10 +29,33 @@ typedef struct P9Conn {
unsigned char *buf;
} P9Conn;
+void *
+createfid(Intmap *map, int fid) {
+ Fid *f = cext_emallocz(sizeof(Fid));
+ f->fid = fid;
+ f->omode = -1;
+ f->map = map;
+ if(caninsertkey(map, fid, f))
+ return f;
+ free(f);
+ return nil;
+}
+
+int
+destroyfid(P9Conn *pc, unsigned long fid) {
+ Fid *f;
+ if(!(f = deletekey(&pc->fidmap, fid)))
+ return 0;
+ if(pc->srv->freefid)
+ pc->srv->freefid(f);
+ free(f);
+ return 1;
+}
+
void
ixp_server_handle_fcall(IXPConn *c)
{
- Fcall fcall;
+ Fcall fcall = {0};
P9Conn *pc = c->aux;
Req *req;
unsigned int msize;
@@ -82,7 +85,6 @@ ixp_handle_req(Req *r)
{
P9Conn *pc = r->conn->aux;
P9Srv *srv = pc->srv;
- Fid *f;
switch(r->ifcall.type) {
default:
@@ -107,12 +109,11 @@ ixp_handle_req(Req *r)
srv->attach(r);
break;
case TCLUNK:
- if(!(f=deletekey(&pc->fidmap, r->ifcall.fid)))
+ if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid);
- if(pc->srv->freefid)
- pc->srv->freefid(f);
- free(f);
- respond(r, nil);
+ if(!srv->clunk)
+ return respond(r, nil);
+ srv->clunk(r);
break;
case TCREATE:
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
@@ -204,7 +205,7 @@ respond(Req *r, char *error) {
break;
case TATTACH:
if(error)
- destroyfid(r->fid->map, r->fid->fid);
+ destroyfid(pc, r->fid->fid);
free(r->ifcall.uname);
free(r->ifcall.aname);
break;
@@ -220,7 +221,7 @@ respond(Req *r, char *error) {
case TWALK:
if(error || r->ofcall.nwqid < r->ifcall.nwname) {
if(r->ifcall.fid != r->ifcall.newfid && r->newfid)
- destroyfid(r->newfid->map, r->newfid->fid);
+ destroyfid(pc, r->newfid->fid);
if(!error && r->ofcall.nwqid == 0)
error = Enofile;
}else{
@@ -235,6 +236,8 @@ respond(Req *r, char *error) {
free(r->ifcall.data);
break;
case TCLUNK:
+ destroyfid(pc, r->fid->fid);
+ break;
case TREAD:
case TREMOVE:
case TSTAT: