libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

commit 96a8beff61bd0b2a676224d7e5899f9a7a8ec4a5
parent e9f62eb246537af265d7ed98eb696d95abd2e6ec
Author: Kris Maglione <jg@suckless.org>
Date:   Sun, 11 Oct 2009 20:14:21 -0400

Fix segfault when clients clunk files with pending requests. Cleanup, etc.

Diffstat:
include/ixp_srvutil.h | 20++++++++++----------
libixp/srv_util.c | 440++++++++++++++++++++++++++++++++++++++++---------------------------------------
2 files changed, 235 insertions(+), 225 deletions(-)

diff --git a/include/ixp_srvutil.h b/include/ixp_srvutil.h @@ -1,30 +1,30 @@ typedef struct IxpDirtab IxpDirtab; typedef struct IxpFileId IxpFileId; -typedef struct IxpPLink IxpPLink; +typedef struct IxpPendingLink IxpPendingLink; typedef struct IxpPending IxpPending; typedef struct IxpQueue IxpQueue; -typedef struct IxpRLink IxpRLink; +typedef struct IxpRequestLink IxpRequestLink; typedef IxpFileId* (*IxpLookupFn)(IxpFileId*, char*); -struct IxpPLink { - IxpPLink* next; - IxpPLink* prev; +struct IxpPendingLink { + IxpPendingLink* next; + IxpPendingLink* prev; IxpFid* fid; IxpQueue* queue; IxpPending* pending; }; -struct IxpRLink { - IxpRLink* next; - IxpRLink* prev; +struct IxpRequestLink { + IxpRequestLink* next; + IxpRequestLink* prev; Ixp9Req* req; }; struct IxpPending { - IxpRLink req; - IxpPLink fids; + IxpRequestLink req; + IxpPendingLink fids; }; struct IxpDirtab { diff --git a/libixp/srv_util.c b/libixp/srv_util.c @@ -37,25 +37,25 @@ static IxpFileId* free_fileid; */ IxpFileId* ixp_srv_getfile(void) { - IxpFileId *f; + IxpFileId *file; int i; if(!free_fileid) { i = 15; - f = emallocz(i * sizeof *f); + file = emallocz(i * sizeof *file); for(; i; i--) { - f->next = free_fileid; - free_fileid = f++; + file->next = free_fileid; + free_fileid = file++; } } - f = free_fileid; - free_fileid = f->next; - f->p = nil; - f->volatil = 0; - f->nref = 1; - f->next = nil; - f->pending = false; - return f; + file = free_fileid; + free_fileid = file->next; + file->p = nil; + file->volatil = 0; + file->nref = 1; + file->next = nil; + file->pending = false; + return file; } /** @@ -82,37 +82,37 @@ ixp_srv_clonefiles(IxpFileId *f) { } void -ixp_srv_readbuf(Ixp9Req *r, char *buf, uint len) { +ixp_srv_readbuf(Ixp9Req *req, char *buf, uint len) { - if(r->ifcall.io.offset >= len) + if(req->ifcall.io.offset >= len) return; - len -= r->ifcall.io.offset; - if(len > r->ifcall.io.count) - len = r->ifcall.io.count; - r->ofcall.io.data = emalloc(len); - memcpy(r->ofcall.io.data, buf + r->ifcall.io.offset, len); - r->ofcall.io.count = len; + len -= req->ifcall.io.offset; + if(len > req->ifcall.io.count) + len = req->ifcall.io.count; + req->ofcall.io.data = emalloc(len); + memcpy(req->ofcall.io.data, buf + req->ifcall.io.offset, len); + req->ofcall.io.count = len; } void -ixp_srv_writebuf(Ixp9Req *r, char **buf, uint *len, uint max) { - IxpFileId *f; +ixp_srv_writebuf(Ixp9Req *req, char **buf, uint *len, uint max) { + IxpFileId *file; char *p; uint offset, count; - f = r->fid->aux; + file = req->fid->aux; - offset = r->ifcall.io.offset; - if(f->tab.perm & DMAPPEND) + offset = req->ifcall.io.offset; + if(file->tab.perm & DMAPPEND) offset = *len; - if(offset > *len || r->ifcall.io.count == 0) { - r->ofcall.io.count = 0; + if(offset > *len || req->ifcall.io.count == 0) { + req->ofcall.io.count = 0; return; } - count = r->ifcall.io.count; + count = req->ifcall.io.count; if(max && (offset + count > max)) count = max - offset; @@ -121,8 +121,8 @@ ixp_srv_writebuf(Ixp9Req *r, char **buf, uint *len, uint max) { *buf = erealloc(*buf, *len + 1); p = *buf; - memcpy(p+offset, r->ifcall.io.data, count); - r->ofcall.io.count = count; + memcpy(p+offset, req->ifcall.io.data, count); + req->ofcall.io.count = count; p[offset+count] = '\0'; } @@ -131,33 +131,33 @@ ixp_srv_writebuf(Ixp9Req *r, char **buf, uint *len, uint max) { * removing any new line from its end. */ void -ixp_srv_data2cstring(Ixp9Req *r) { +ixp_srv_data2cstring(Ixp9Req *req) { char *p, *q; uint i; - i = r->ifcall.io.count; - p = r->ifcall.io.data; + i = req->ifcall.io.count; + p = req->ifcall.io.data; if(i && p[i - 1] == '\n') i--; q = memchr(p, '\0', i); if(q) i = q - p; - p = erealloc(r->ifcall.io.data, i+1); + p = erealloc(req->ifcall.io.data, i+1); p[i] = '\0'; - r->ifcall.io.data = p; + req->ifcall.io.data = p; } char* -ixp_srv_writectl(Ixp9Req *r, char* (*fn)(void*, IxpMsg*)) { +ixp_srv_writectl(Ixp9Req *req, char* (*fn)(void*, IxpMsg*)) { char *err, *s, *p, c; - IxpFileId *f; - IxpMsg m; + IxpFileId *file; + IxpMsg msg; - f = r->fid->aux; + file = req->fid->aux; - ixp_srv_data2cstring(r); - s = r->ifcall.io.data; + ixp_srv_data2cstring(req); + s = req->ifcall.io.data; err = nil; c = *s; @@ -170,8 +170,8 @@ ixp_srv_writectl(Ixp9Req *r, char* (*fn)(void*, IxpMsg*)) { c = *p; *p = '\0'; - m = ixp_message(s, p-s, 0); - s = fn(f->p, &m); + msg = ixp_message(s, p-s, 0); + s = fn(file->p, &msg); if(s) err = s; s = p + 1; @@ -180,262 +180,272 @@ ixp_srv_writectl(Ixp9Req *r, char* (*fn)(void*, IxpMsg*)) { } void -ixp_pending_respond(Ixp9Req *r) { - IxpFileId *f; - IxpPLink *p; - IxpRLink *rl; - IxpQueue *q; - - f = r->fid->aux; - p = f->p; - assert(f->pending); +ixp_pending_respond(Ixp9Req *req) { + IxpFileId *file; + IxpPendingLink *p; + IxpRequestLink *req_link; + IxpQueue *queue; + + file = req->fid->aux; + assert(file->pending); + p = file->p; if(p->queue) { - q = p->queue; - p->queue = q->link; - r->ofcall.io.data = q->dat; - r->ofcall.io.count = q->len; - if(r->aux) { - rl = r->aux; - rl->next->prev = rl->prev; - rl->prev->next = rl->next; - free(rl); + queue = p->queue; + p->queue = queue->link; + req->ofcall.io.data = queue->dat; + req->ofcall.io.count = queue->len; + if(req->aux) { + req_link = req->aux; + req_link->next->prev = req_link->prev; + req_link->prev->next = req_link->next; + free(req_link); } - respond(r, nil); - free(q); + respond(req, nil); + free(queue); }else { - rl = emallocz(sizeof *rl); - rl->req = r; - rl->next = &p->pending->req; - rl->prev = rl->next->prev; - rl->next->prev = rl; - rl->prev->next = rl; - r->aux = rl; + req_link = emallocz(sizeof *req_link); + req_link->req = req; + req_link->next = &p->pending->req; + req_link->prev = req_link->next->prev; + req_link->next->prev = req_link; + req_link->prev->next = req_link; + req->aux = req_link; } } void -ixp_pending_write(IxpPending *p, char *dat, long n) { - IxpRLink rl; - IxpQueue **qp, *q; - IxpPLink *pp; - IxpRLink *rp; +ixp_pending_write(IxpPending *pending, char *dat, long n) { + IxpRequestLink req_link; + IxpQueue **qp, *queue; + IxpPendingLink *pp; + IxpRequestLink *rp; if(n == 0) return; - if(p->req.next == nil) { - p->req.next = &p->req; - p->req.prev = &p->req; - p->fids.prev = &p->fids; - p->fids.next = &p->fids; + if(pending->req.next == nil) { + pending->req.next = &pending->req; + pending->req.prev = &pending->req; + pending->fids.prev = &pending->fids; + pending->fids.next = &pending->fids; } - for(pp=p->fids.next; pp != &p->fids; pp=pp->next) { + for(pp=pending->fids.next; pp != &pending->fids; pp=pp->next) { for(qp=&pp->queue; *qp; qp=&qp[0]->link) ; - q = emallocz(sizeof *q); - q->dat = emalloc(n); - memcpy(q->dat, dat, n); - q->len = n; - *qp = q; + queue = emallocz(sizeof *queue); + queue->dat = emalloc(n); + memcpy(queue->dat, dat, n); + queue->len = n; + *qp = queue; } - rl.next = &rl; - rl.prev = &rl; - if(p->req.next != &p->req) { - rl.next = p->req.next; - rl.prev = p->req.prev; - p->req.prev = &p->req; - p->req.next = &p->req; + + req_link.next = &req_link; + req_link.prev = &req_link; + if(pending->req.next != &pending->req) { + req_link.next = pending->req.next; + req_link.prev = pending->req.prev; + pending->req.prev = &pending->req; + pending->req.next = &pending->req; } - rl.prev->next = &rl; - rl.next->prev = &rl; - while((rp = rl.next) != &rl) + req_link.prev->next = &req_link; + req_link.next->prev = &req_link; + + while((rp = req_link.next) != &req_link) ixp_pending_respond(rp->req); } void -ixp_pending_pushfid(IxpPending *p, IxpFid *f) { - IxpPLink *pl; - IxpFileId *fi; - - if(p->req.next == nil) { - p->req.next = &p->req; - p->req.prev = &p->req; - p->fids.prev = &p->fids; - p->fids.next = &p->fids; +ixp_pending_pushfid(IxpPending *pending, IxpFid *fid) { + IxpPendingLink *pend_link; + IxpFileId *file; + + if(pending->req.next == nil) { + pending->req.next = &pending->req; + pending->req.prev = &pending->req; + pending->fids.prev = &pending->fids; + pending->fids.next = &pending->fids; } - fi = f->aux; - pl = emallocz(sizeof *pl); - pl->fid = f; - pl->pending = p; - pl->next = &p->fids; - pl->prev = pl->next->prev; - pl->next->prev = pl; - pl->prev->next = pl; - fi->pending = true; - fi->p = pl; + file = fid->aux; + pend_link = emallocz(sizeof *pend_link); + pend_link->fid = fid; + pend_link->pending = pending; + pend_link->next = &pending->fids; + pend_link->prev = pend_link->next->prev; + pend_link->next->prev = pend_link; + pend_link->prev->next = pend_link; + file->pending = true; + file->p = pend_link; } -void -ixp_pending_flush(Ixp9Req *r) { - Ixp9Req *or; - IxpFileId *f; - IxpRLink *rl; - - or = r->oldreq; - f = or->fid->aux; - if(f->pending) { - rl = or->aux; - if(rl) { - rl->prev->next = rl->next; - rl->next->prev = rl->prev; - free(rl); +static void +pending_flush(Ixp9Req *req) { + IxpFileId *file; + IxpRequestLink *req_link; + + file = req->fid->aux; + if(file->pending) { + req_link = req->aux; + if(req_link) { + req_link->prev->next = req_link->next; + req_link->next->prev = req_link->prev; + free(req_link); } } } +void +ixp_pending_flush(Ixp9Req *req) { + + pending_flush(req->oldreq); +} + bool -ixp_pending_clunk(Ixp9Req *r) { - IxpPending *p; - IxpFileId *f; - IxpPLink *pl; - IxpRLink *rl; - IxpQueue *qu; +ixp_pending_clunk(Ixp9Req *req) { + IxpPending *pending; + IxpPendingLink *pend_link; + IxpRequestLink *req_link; + Ixp9Req *r; + IxpFileId *file; + IxpQueue *queue; bool more; - f = r->fid->aux; - pl = f->p; + file = req->fid->aux; + pend_link = file->p; - p = pl->pending; - for(rl=p->req.next; rl != &p->req; rl=rl->next) - if(rl->req->fid == pl->fid) { - respond(r, "fid in use"); - return true; + pending = pend_link->pending; + for(req_link=pending->req.next; req_link != &pending->req;) { + r = req_link->req; + req_link = req_link->next; + if(r->fid == pend_link->fid) { + pending_flush(r); + respond(r, "interrupted"); } + } - pl->prev->next = pl->next; - pl->next->prev = pl->prev; + pend_link->prev->next = pend_link->next; + pend_link->next->prev = pend_link->prev; - while((qu = pl->queue)) { - pl->queue = qu->link; - free(qu->dat); - free(qu); + while((queue = pend_link->queue)) { + pend_link->queue = queue->link; + free(queue->dat); + free(queue); } - more = (pl->pending->fids.next == &pl->pending->fids); - free(pl); - respond(r, nil); + more = (pend_link->pending->fids.next == &pend_link->pending->fids); + free(pend_link); + respond(req, nil); return more; } bool -ixp_srv_verifyfile(IxpFileId *f, IxpLookupFn lookup) { - IxpFileId *nf; +ixp_srv_verifyfile(IxpFileId *file, IxpLookupFn lookup) { + IxpFileId *tfile; int ret; - if(!f->next) + if(!file->next) return true; ret = false; - if(ixp_srv_verifyfile(f->next, lookup)) { - nf = lookup(f->next, f->tab.name); - if(nf) { - if(!nf->volatil || nf->p == f->p) + if(ixp_srv_verifyfile(file->next, lookup)) { + tfile = lookup(file->next, file->tab.name); + if(tfile) { + if(!tfile->volatil || tfile->p == file->p) ret = true; - ixp_srv_freefile(nf); + ixp_srv_freefile(tfile); } } return ret; } void -ixp_srv_readdir(Ixp9Req *r, IxpLookupFn lookup, void (*dostat)(IxpStat*, IxpFileId*)) { - IxpMsg m; - IxpFileId *f, *tf; - IxpStat s; +ixp_srv_readdir(Ixp9Req *req, IxpLookupFn lookup, void (*dostat)(IxpStat*, IxpFileId*)) { + IxpMsg msg; + IxpFileId *file, *tfile; + IxpStat stat; char *buf; ulong size, n; uvlong offset; - f = r->fid->aux; + file = req->fid->aux; - size = r->ifcall.io.count; - if(size > r->fid->iounit) - size = r->fid->iounit; + size = req->ifcall.io.count; + if(size > req->fid->iounit) + size = req->fid->iounit; buf = emallocz(size); - m = ixp_message(buf, size, MsgPack); + msg = ixp_message(buf, size, MsgPack); - f = lookup(f, nil); - tf = f; - /* Note: The first f is ".", so we skip it. */ + file = lookup(file, nil); + tfile = file; + /* Note: The first file is ".", so we skip it. */ offset = 0; - for(f=f->next; f; f=f->next) { - dostat(&s, f); - n = ixp_sizeof_stat(&s); - if(offset >= r->ifcall.io.offset) { + for(file=file->next; file; file=file->next) { + dostat(&stat, file); + n = ixp_sizeof_stat(&stat); + if(offset >= req->ifcall.io.offset) { if(size < n) break; - ixp_pstat(&m, &s); + ixp_pstat(&msg, &stat); size -= n; } offset += n; } - while((f = tf)) { - tf=tf->next; - ixp_srv_freefile(f); + while((file = tfile)) { + tfile=tfile->next; + ixp_srv_freefile(file); } - r->ofcall.io.count = m.pos - m.data; - r->ofcall.io.data = m.data; - respond(r, nil); + req->ofcall.io.count = msg.pos - msg.data; + req->ofcall.io.data = msg.data; + respond(req, nil); } void -ixp_srv_walkandclone(Ixp9Req *r, IxpLookupFn lookup) { - IxpFileId *f, *nf; +ixp_srv_walkandclone(Ixp9Req *req, IxpLookupFn lookup) { + IxpFileId *file, *tfile; int i; - f = r->fid->aux; - ixp_srv_clonefiles(f); - for(i=0; i < r->ifcall.twalk.nwname; i++) { - if(!strcmp(r->ifcall.twalk.wname[i], "..")) { - if(f->next) { - nf=f; - f=f->next; - ixp_srv_freefile(nf); + file = req->fid->aux; + ixp_srv_clonefiles(file); + for(i=0; i < req->ifcall.twalk.nwname; i++) { + if(!strcmp(req->ifcall.twalk.wname[i], "..")) { + if(file->next) { + tfile=file; + file=file->next; + ixp_srv_freefile(tfile); } }else{ - nf = lookup(f, r->ifcall.twalk.wname[i]); - if(!nf) + tfile = lookup(file, req->ifcall.twalk.wname[i]); + if(!tfile) break; - assert(!nf->next); - if(strcmp(r->ifcall.twalk.wname[i], ".")) { - nf->next = f; - f = nf; + assert(!tfile->next); + if(strcmp(req->ifcall.twalk.wname[i], ".")) { + tfile->next = file; + file = tfile; } } - r->ofcall.rwalk.wqid[i].type = f->tab.qtype; - r->ofcall.rwalk.wqid[i].path = QID(f->tab.type, f->id); + req->ofcall.rwalk.wqid[i].type = file->tab.qtype; + req->ofcall.rwalk.wqid[i].path = QID(file->tab.type, file->id); } /* There should be a way to do this on freefid() */ - if(i < r->ifcall.twalk.nwname) { - while((nf = f)) { - f=f->next; - ixp_srv_freefile(nf); + if(i < req->ifcall.twalk.nwname) { + while((tfile = file)) { + file=file->next; + ixp_srv_freefile(tfile); } - respond(r, Enofile); + respond(req, Enofile); return; } - /* Remove refs for r->fid if no new fid */ - if(r->ifcall.hdr.fid == r->ifcall.twalk.newfid) { - nf = r->fid->aux; - r->fid->aux = f; - while((f = nf)) { - nf = nf->next; - ixp_srv_freefile(f); + /* Remove refs for req->fid if no new fid */ + if(req->ifcall.hdr.fid == req->ifcall.twalk.newfid) { + tfile = req->fid->aux; + req->fid->aux = file; + while((file = tfile)) { + tfile = tfile->next; + ixp_srv_freefile(file); } }else - r->newfid->aux = f; - r->ofcall.rwalk.nwqid = i; - respond(r, nil); + req->newfid->aux = file; + req->ofcall.rwalk.nwqid = i; + respond(req, nil); }