libixp

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

commit 96b9a8724da808efe7a2883d96e5b26966ec1752
parent 1520e87502657f38c075aab3bbca7d66c105f322
Author: Kris Maglione <jg@suckless.org>
Date:   Mon, 25 Aug 2008 11:30:45 -0400

Create ixp_srvutils—convenience functions and structures from wmii's fs.c.  Bump API version.

Diffstat:
include/Makefile | 3++-
include/ixp.h | 2+-
include/ixp_srvutil.h | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libixp/Makefile | 1+
libixp/srv_util.c | 418+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libixp/transport.c | 4++--
libixp/util.c | 6+++---
util/compile | 1+
util/link | 1+
9 files changed, 498 insertions(+), 7 deletions(-)

diff --git a/include/Makefile b/include/Makefile @@ -2,7 +2,8 @@ ROOT= .. include ${ROOT}/mk/hdr.mk include ${ROOT}/mk/ixp.mk -HFILES = ixp.h +HFILES = ixp.h \ + ixp_srvutil.h install: ${HFILES:.h=.install} diff --git a/include/ixp.h b/include/ixp.h @@ -7,7 +7,7 @@ #include <sys/types.h> #include <sys/select.h> -#define IXP_API 93 +#define IXP_API 97 /* Gunk */ #if defined(IXP_NEEDAPI) && IXP_API < IXP_NEEDAPI diff --git a/include/ixp_srvutil.h b/include/ixp_srvutil.h @@ -0,0 +1,69 @@ + +typedef struct IxpDirtab IxpDirtab; +typedef struct IxpFileId IxpFileId; +typedef struct IxpPLink IxpPLink; +typedef struct IxpPending IxpPending; +typedef struct IxpQueue IxpQueue; +typedef struct IxpRLink IxpRLink; + +typedef IxpFileId* (*IxpLookupFn)(IxpFileId*, char*); + +struct IxpPLink { + IxpPLink* next; + IxpPLink* prev; + IxpFid* fid; + IxpQueue* queue; + IxpPending* pending; +}; + +struct IxpRLink { + IxpRLink* next; + IxpRLink* prev; + Ixp9Req* req; +}; + +struct IxpPending { + IxpRLink req; + IxpPLink fids; +}; + +struct IxpDirtab { + char* name; + uchar qtype; + uint type; + uint perm; + uint flags; +}; + +struct IxpFileId { + IxpFileId* next; + IxpFileIdU p; + bool pending; + uint id; + uint index; + IxpDirtab tab; + ushort nref; + uchar volatil; +}; + +enum { + FLHide = 1, +}; + +bool ixp_pending_clunk(Ixp9Req*); +void ixp_pending_flush(Ixp9Req*); +void ixp_pending_pushfid(IxpPending*, IxpFid*); +void ixp_pending_respond(Ixp9Req*); +void ixp_pending_write(IxpPending*, char*, long); +void ixp_srv_clonefiles(IxpFileId*); +void ixp_srv_data2cstring(Ixp9Req*); +void ixp_srv_freefile(IxpFileId*); +void ixp_srv_readbuf(Ixp9Req*, char*, uint); +void ixp_srv_readdir(Ixp9Req*, IxpLookupFn, void (*)(IxpStat*, IxpFileId*)); +bool ixp_srv_verifyfile(IxpFileId*, IxpLookupFn); +void ixp_srv_walkandclone(Ixp9Req*, IxpLookupFn); +void ixp_srv_writebuf(Ixp9Req*, char**, uint*, uint); +char* ixp_srv_writectl(Ixp9Req*, char* (*)(void*, IxpMsg*)); +IxpFileId* ixp_srv_getfile(void); + + diff --git a/libixp/Makefile b/libixp/Makefile @@ -12,6 +12,7 @@ OBJ = client \ request \ rpc \ server \ + srv_util \ socket \ thread \ timer \ diff --git a/libixp/srv_util.c b/libixp/srv_util.c @@ -0,0 +1,418 @@ +/* Copyright ©2006-2008 Kris Maglione <fbsdaemon at gmail dot com> + * See LICENSE file for license details. + */ +#include <assert.h> +#include <ctype.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "ixp_local.h" + +typedef void* IxpFileIdU; + +static char + Enofile[] = "file not found"; + +#include "ixp_srvutil.h" + +struct IxpQueue { + IxpQueue* link; + char* dat; + long len; +}; + +/* Macros */ +#define QID(t, i) (((vlong)((t)&0xFF)<<32)|((i)&0xFFFFFFFF)) + +/* Global Vars */ +/***************/ +static IxpFileId* free_fileid; + +/* Utility Functions */ +IxpFileId* +ixp_srv_getfile(void) { + IxpFileId *f; + int i; + + if(!free_fileid) { + i = 15; + f = emallocz(i * sizeof *f); + for(; i; i--) { + f->next = free_fileid; + free_fileid = f++; + } + } + f = free_fileid; + free_fileid = f->next; + f->p = nil; + f->volatil = 0; + f->nref = 1; + f->next = nil; + f->pending = false; + return f; +} + +void +ixp_srv_freefile(IxpFileId *f) { + if(--f->nref) + return; + free(f->tab.name); + f->next = free_fileid; + free_fileid = f; +} + +/* Increase the reference counts of the IxpFileId list */ +void +ixp_srv_clonefiles(IxpFileId *f) { + for(; f; f=f->next) + assert(f->nref++); +} + +/* This should be moved to libixp */ +void +ixp_srv_readbuf(Ixp9Req *r, char *buf, uint len) { + + if(r->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; +} + +/* This should be moved to libixp */ +void +ixp_srv_writebuf(Ixp9Req *r, char **buf, uint *len, uint max) { + IxpFileId *f; + char *p; + uint offset, count; + + f = r->fid->aux; + + offset = r->ifcall.io.offset; + if(f->tab.perm & DMAPPEND) + offset = *len; + + if(offset > *len || r->ifcall.io.count == 0) { + r->ofcall.io.count = 0; + return; + } + + count = r->ifcall.io.count; + if(max && (offset + count > max)) + count = max - offset; + + *len = offset + count; + if(max == 0) + *buf = erealloc(*buf, *len + 1); + p = *buf; + + memcpy(p+offset, r->ifcall.io.data, count); + r->ofcall.io.count = count; + p[offset+count] = '\0'; +} + +void +ixp_srv_data2cstring(Ixp9Req *r) { + char *p, *q; + uint i; + + i = r->ifcall.io.count; + p = r->ifcall.io.data; + q = memchr(p, '\0', i); + if(i && p[i - 1] == '\n') + i--; + if(q && q-p < i) + i = q-p; + + p = erealloc(r->ifcall.io.data, i+1); + p[i] = '\0'; + r->ifcall.io.data = p; +} + +char* +ixp_srv_writectl(Ixp9Req *r, char* (*fn)(void*, IxpMsg*)) { + char *err, *s, *p, c; + IxpFileId *f; + IxpMsg m; + + f = r->fid->aux; + + ixp_srv_data2cstring(r); + s = r->ifcall.io.data; + + err = nil; + c = *s; + while(c != '\0') { + while(*s == '\n') + s++; + p = s; + while(*p != '\0' && *p != '\n') + p++; + c = *p; + *p = '\0'; + + m = ixp_message(s, p-s, 0); + s = fn(f->p, &m); + if(s) + err = s; + s = p + 1; + } + return err; +} + +void +ixp_pending_respond(Ixp9Req *r) { + IxpFileId *f; + IxpPLink *p; + IxpRLink *rl; + IxpQueue *q; + + f = r->fid->aux; + p = f->p; + assert(f->pending); + 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); + } + respond(r, nil); + free(q); + }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; + } +} + +void +ixp_pending_write(IxpPending *p, char *dat, long n) { + IxpRLink rl; + IxpQueue **qp, *q; + IxpPLink *pp; + IxpRLink *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; + } + + for(pp=p->fids.next; pp != &p->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; + } + 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; + } + rl.prev->next = &rl; + rl.next->prev = &rl; + while((rp = rl.next) != &rl) + 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; + } + + 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; +} + +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); + } + } +} + +bool +ixp_pending_clunk(Ixp9Req *r) { + IxpFileId *f; + IxpPLink *pl; + IxpQueue *qu; + bool more; + + f = r->fid->aux; + pl = f->p; + pl->prev->next = pl->next; + pl->next->prev = pl->prev; + while((qu = pl->queue)) { + pl->queue = qu->link; + free(qu->dat); + free(qu); + } + more = (pl->pending->fids.next == &pl->pending->fids); + free(pl); + respond(r, nil); + return more; +} + +bool +ixp_srv_verifyfile(IxpFileId *f, IxpLookupFn lookup) { + IxpFileId *nf; + int ret; + + if(!f->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) + ret = true; + ixp_srv_freefile(nf); + } + } + return ret; +} + +void +ixp_srv_readdir(Ixp9Req *r, IxpLookupFn lookup, void (*dostat)(IxpStat*, IxpFileId*)) { + IxpMsg m; + IxpFileId *f, *tf; + IxpStat s; + char *buf; + ulong size, n; + uvlong offset; + + f = r->fid->aux; + + size = r->ifcall.io.count; + if(size > r->fid->iounit) + size = r->fid->iounit; + buf = emallocz(size); + m = ixp_message(buf, size, MsgPack); + + f = lookup(f, nil); + tf = f; + /* Note: f->tab.name == "." 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) { + if(size < n) + break; + ixp_pstat(&m, &s); + size -= n; + } + offset += n; + } + while((f = tf)) { + tf=tf->next; + ixp_srv_freefile(f); + } + r->ofcall.io.count = m.pos - m.data; + r->ofcall.io.data = m.data; + respond(r, nil); +} + +void +ixp_srv_walkandclone(Ixp9Req *r, IxpLookupFn lookup) { + IxpFileId *f, *nf; + 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); + } + }else{ + nf = lookup(f, r->ifcall.twalk.wname[i]); + if(!nf) + break; + assert(!nf->next); + if(strcmp(r->ifcall.twalk.wname[i], ".")) { + nf->next = f; + f = nf; + } + } + r->ofcall.rwalk.wqid[i].type = f->tab.qtype; + r->ofcall.rwalk.wqid[i].path = QID(f->tab.type, f->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); + } + respond(r, 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); + } + }else + r->newfid->aux = f; + r->ofcall.rwalk.nwqid = i; + respond(r, nil); +} + diff --git a/libixp/transport.c b/libixp/transport.c @@ -41,7 +41,7 @@ readn(int fd, IxpMsg *msg, uint count) { if(r == -1 && errno == EINTR) continue; if(r == 0) { - werrstr("broken pipe: %r"); + werrstr("broken pipe: %s", ixp_errbuf()); return count - num; } num -= r; @@ -59,7 +59,7 @@ ixp_sendmsg(int fd, IxpMsg *msg) { if(r < 1) { if(errno == EINTR) continue; - werrstr("broken pipe: %r"); + werrstr("broken pipe: %s", ixp_errbuf()); return 0; } msg->pos += r; diff --git a/libixp/util.c b/libixp/util.c @@ -51,7 +51,7 @@ rmkdir(char *path, int mode) { *p = '\0'; ret = mkdir(path, mode); if((ret == -1) && (errno != EEXIST)) { - ixp_werrstr("Can't create path '%s': %r", path); + ixp_werrstr("Can't create path '%s': %s", path, ixp_errbuf()); return 0; } *p = c; @@ -84,11 +84,11 @@ ns_display(void) { if(!rmkdir(path, 0700)) ; else if(stat(path, &st)) - ixp_werrstr("Can't stat ns_path '%s': %r", path); + ixp_werrstr("Can't stat ns_path '%s': %s", path, ixp_errbuf()); else if(getuid() != st.st_uid) ixp_werrstr("ns_path '%s' exists but is not owned by you", path); else if((st.st_mode & 077) && chmod(path, st.st_mode & ~077)) - ixp_werrstr("Namespace path '%s' exists, but has wrong permissions: %r", path); + ixp_werrstr("Namespace path '%s' exists, but has wrong permissions: %s", path, ixp_errbuf()); else return path; free(path); diff --git a/util/compile b/util/compile @@ -11,6 +11,7 @@ echo CC $($bin/cleanname ${BASE}$outfile) [ -n "$noisycc" ] && echo $CC -o $outfile $CFLAGS $@ $CC -o $outfile $CFLAGS $@ >$xtmp 2>&1 status=$? +[ $? -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2 base=$(echo $BASE | sed 's/,/\\,/g') re='\([^[:space:]/]*\..:[0-9]\)' diff --git a/util/link b/util/link @@ -24,6 +24,7 @@ echo LD "$($bin/cleanname ${BASE}$outfile)" [ -n "$noisycc" ] && echo $LD -o $outfile $ofiles $LDFLAGS $args $LD -o $outfile $ofiles $LDFLAGS $args >$xtmp 2>&1 status=$? +[ $? -eq 0 ] || $LD -o $outfile $ofiles $LDFLAGS $args >&2 sed 's/.*: In function `[^:]*: *//' $xtmp | egrep . | egrep -v 'is almost always misused|is dangerous, better use|in statically linked applications requires at runtime'