ref: 38f2878c44f584d472560c9a426d01cdd3fb99cb
parent: 8eef000ed6e16e02354e6798f227223cc38b2d42
author: B. Wilson <x@wilsonb.com>
date: Wed Jun 18 02:07:10 EDT 2025
Add sanity check tests
--- a/ridefs.c
+++ b/ridefs.c
@@ -19,30 +19,15 @@
/* internal use */
char *user;
- char *pres; /* previous result */
+ char *pres; /* previous result */
+ char *rinfo;
+ char *qctl;
long time0;
int id;
- int oio; /* io opened */
- int iopid; /* read/write fork */
- int fd; /* data */
- int cfd; /* ctl */
-
- /* id reply info */
- int Rapiversion;
- int Rport;
- int Rpid;
- char *Ripaddress;
- char *Rvendor;
- char *Rlanguage;
- char *Rversion;
- char *Rmachine;
- char *Rarch;
- char *Rproject;
- char *Rprocess;
- char *Ruser;
- char *Rtoken;
- char *Rdate;
- char *Rplatform;
+ int oio; /* io opened */
+ int iopid; /* read/write fork */
+ int fd; /* data */
+ int cfd; /* ctl */
};
enum {
@@ -52,6 +37,7 @@
Qclient,
Qctl,
Qio,
+ Qrinfo,
QCOUNT
};
@@ -62,6 +48,7 @@
nil,
"ctl",
"io",
+ "rinfo",
};
struct Rfid {
@@ -70,12 +57,13 @@
int client;
};
-#define RIDESRV_VERS 0
+#define VERSION 0
static Client *cpool;
static char *mtpt;
static char *service;
static char *net;
static char *user;
+static char *qrctl;
static ulong umask;
static long bufsz;
static long time0;
@@ -103,12 +91,52 @@
char*
estrdup(char *s){
+ if(s == nil)
+ return nil;
+
s = estrdup9p(s);
setrealloctag(s, getcallerpc(&s));
return s;
}
+Client*
+clientref(int i){
+ if(i < 0 || i > nclients)
+ return nil;
+ return &cpool[i];
+}
+
int
+genqrctl(void){
+ sprintf(qrctl,
+ "version %i\n"
+ "bufsz %u\n"
+ "nclients %u\n"
+ "debug %i\n"
+ "timeout %i\n"
+ "umask 0%hlo\n",
+ VERSION, bufsz, nclients,
+ debug, timeout, umask);
+
+ return strlen(qrctl);
+}
+
+int
+genqctl(int client){
+ Client *c;
+
+ c = clientref(client);
+ sprintf(c->qctl,
+ "%i\n"
+ "connect %s\n"
+ "timeout %i\n"
+ "umask 0%hlo\n",
+ client, c->addr, c->timeout, c->umask);
+
+ return strlen(c->qctl);
+}
+
+int
mkclient(void){
Client *c;
int i;
@@ -116,7 +144,7 @@
for(i = 0; i < nclients; i++)
if(cpool[i].ref == 0)
break;
- if(i == nelem(cpool))
+ if(i == nclients)
return -1;
c = &cpool[i];
@@ -126,18 +154,12 @@
c->umask = umask;
c->user = estrdup(getuser());
c->time0 = time(0);
+ c->qctl = ecalloc(bufsz);
+ genqctl(i);
return i;
}
-Client*
-clientref(int i){
- if(i < 0 || i > nclients)
- return nil;
-
- return &cpool[i];
-}
-
void
rmclient(int i){
Client *c;
@@ -146,20 +168,10 @@
if(c == nil || decref(c))
return;
- if(c->Ripaddress) free(c->Ripaddress);
- if(c->Rvendor) free(c->Rvendor);
- if(c->Rlanguage) free(c->Rlanguage);
- if(c->Rversion) free(c->Rversion);
- if(c->Rmachine) free(c->Rmachine);
- if(c->Rarch) free(c->Rarch);
- if(c->Rproject) free(c->Rproject);
- if(c->Rprocess) free(c->Rprocess);
- if(c->Ruser) free(c->Ruser);
- if(c->Rtoken) free(c->Rtoken);
- if(c->Rdate) free(c->Rdate);
- if(c->Rplatform) free(c->Rplatform);
-
if(c->user) free(c->user);
+ if(c->pres) free(c->pres);
+ if(c->qctl) free(c->qctl);
+ if(c->rinfo) free(c->rinfo);
if(c->fd) close(c->fd);
if(c->cfd) close(c->cfd);
@@ -167,9 +179,9 @@
}
static void
-mkqid(Qid *q, int k, Client *c){
- q->vers = RIDESRV_VERS;
- q->path = ((u64int)c->id<<32) | k&0xffffffff;
+mkqid(Qid *q, int k, int client){
+ q->vers = VERSION;
+ q->path = ((u64int)client<<32) | k&0xffffffff;
switch(k){
case Qroot:
@@ -225,7 +237,7 @@
char *
rideinit(int client){
int fd;
- char *addr, *pld, *s;
+ char *addr, *buf, *s, *e;
Client *c;
JSON *j;
JSONEl *d;
@@ -237,26 +249,26 @@
c = clientref(client);
c->fd = fd;
- pld = ecalloc(bufsz);
- if(0 > readmsg(fd, pld, bufsz))
+ buf = ecalloc(bufsz);
+ if(0 > readmsg(fd, buf, bufsz))
return "failed to read handshake";
- if(0 != strcmp(pld, "SupportedProtocols=2"))
+ if(0 != strcmp(buf, "SupportedProtocols=2"))
return "unrecognized protocol";
- free(pld);
+ free(buf);
- pld = "UsingProtocol=2";
- if(0 > writemsg(fd, pld, strlen(pld)))
+ buf = "UsingProtocol=2";
+ if(0 > writemsg(fd, buf, strlen(buf)))
return "failed to write handshake";
- pld = "[\"Identify\",{\"apiVersion\":1,\"identity\":1}]";
- if(0 > writemsg(fd, pld, strlen(pld)))
+ buf = "[\"Identify\",{\"apiVersion\":1,\"identity\":1}]";
+ if(0 > writemsg(fd, buf, strlen(buf)))
return "failed to send identification message";
- pld = ecalloc(bufsz);
- if(0 > readmsg(fd, pld, bufsz))
+ buf = ecalloc(bufsz);
+ if(0 > readmsg(fd, buf, bufsz))
return "failed to receive identification message";
- j = jsonparse(pld);
- free(pld);
+ j = jsonparse(buf);
+ free(buf);
if(j == nil || j->t != JSONArray || nil == j->first)
return "unrecognized reply";
if(nil == (s = jsonstr(j->first->val)) || 0 != strcmp(s, "ReplyIdentify"))
@@ -264,51 +276,31 @@
if(nil == (d = j->first->next) || d->val->t != JSONObject)
return "malformed identification reply";
- c->Rapiversion = jsonbyname(d->val, "apiVersion")->n;
- c->Rport = jsonbyname(d->val, "Port")->n;
- c->Rpid = jsonbyname(d->val, "pid")->n;
- c->Ripaddress = estrdup(jsonstr(jsonbyname(d->val, "IPAddress")));
- c->Rvendor = estrdup(jsonstr(jsonbyname(d->val, "Vendor")));
- c->Rlanguage = estrdup(jsonstr(jsonbyname(d->val, "Language")));
- c->Rversion = estrdup(jsonstr(jsonbyname(d->val, "version")));
- c->Rmachine = estrdup(jsonstr(jsonbyname(d->val, "Machine")));
- c->Rarch = estrdup(jsonstr(jsonbyname(d->val, "arch")));
- c->Rproject = estrdup(jsonstr(jsonbyname(d->val, "Project")));
- c->Rprocess = estrdup(jsonstr(jsonbyname(d->val, "Process")));
- c->Ruser = estrdup(jsonstr(jsonbyname(d->val, "User")));
- c->Rtoken = estrdup(jsonstr(jsonbyname(d->val, "token")));
- c->Rdate = estrdup(jsonstr(jsonbyname(d->val, "date")));
- c->Rplatform = estrdup(jsonstr(jsonbyname(d->val, "platform")));
+ c->rinfo = s = ecalloc(bufsz);
+ buf = ecalloc(bufsz);
+ e = s + bufsz-1;
+ for(; d != nil; d = d->next){
+ switch(d->val->t){
+ case JSONBool:
+ case JSONNumber:
+ sprintf(buf, "%s %i\n", d->name, d->val->n); break;
+ case JSONString:
+ sprintf(buf, "%s %s\n", d->name, d->val->s); break;
+ }
+ s = strecpy(s, e, buf);
+ }
+ free(buf);
jsonfree(j);
return nil;
}
-
long
-readqrctl(char **buf){
- char *b;
-
- b = ecalloc(bufsz);
- sprintf(b,
- "version %i\n"
- "bufsz %u\n"
- "nclients %u\n"
- "debug %i\n"
- "timeout %i\n"
- "umask %o\n",
- RIDESRV_VERS, bufsz, nclients,
- debug, timeout, umask);
-
- *buf = b;
- return strlen(b);
-}
-
-long
-writeqrctl(char *b, long n){
+writeqrctl(char *b, long){
char *s;
- char *sep = " ";
+ char sep[7];
+ sprintf(sep, " \t\n\f\r\v");
for(s = strtok(b, sep); s != nil; s = strtok(nil, sep)){
if(strcmp(s, "bufsz") == 0)
bufsz = strtoul(strtok(nil, sep), nil, 0);
@@ -323,53 +315,18 @@
}
cpool = erealloc(cpool, nclients*sizeof(*cpool));
+ genqrctl();
- return n;
+ return strlen(qrctl);
}
long
-readqctl(char **buf, Client *c){
- char *b, r[1024];
+writeqctl(char *b, long n, int client){
+ Client *c;
+ char *s, sep[7];
- b = ecalloc(bufsz);
- sprintf(b,
- "connect %s\n",
- "timeout %i\n",
- "umask %l",
- c->addr, c->timeout, c->umask);
- if(c->oio){
- sprintf(r,
- "Rapiversion %i\n"
- "Rport %i\n"
- "Rpid %i\n"
- "Ripaddress %s\n"
- "Rvendor %s\n"
- "Rlanguage %s\n"
- "Rversion %s\n"
- "Rmachine %s\n"
- "Rarch %s\n"
- "Rproject %s\n"
- "Rprocess %s\n"
- "Ruser %s\n"
- "Rtoken %s\n"
- "Rdate %s\n"
- "Rplatform %s\n",
- c->Rapiversion, c->Rport, c->Rpid, c->Ripaddress,
- c->Rvendor, c->Rlanguage, c->Rversion, c->Rmachine,
- c->Rarch, c->Rproject, c->Rprocess, c->Ruser,
- c->Rtoken, c->Rdate, c->Rplatform);
- strcpy(b, r);
- }
-
- *buf = b;
- return strlen(b);
-}
-
-long
-writeqctl(char *b, long n, Client *c){
- char *s, *sep;
-
- sep = " ";
+ c = clientref(client);
+ sprintf(sep, " \t\n\f\r\v");
for(s = strtok(b, sep); s != nil; s = strtok(nil, sep)){
if(strcmp(s, "connect") == 0)
c->addr = estrdup(strtok(nil, sep));
@@ -379,20 +336,18 @@
c->umask = strtoul(strtok(nil, sep), nil, 0);
}
+ genqctl(client);
+
return n;
}
long
-readqio(char **buf, Client *c){
- *buf = estrdup(c->pres);
- return strlen(*buf);
-}
-
-long
-writeqio(char *b, long, Client *c){
+writeqio(char *b, long, int client){
+ Client *c;
char *pld, *e, *p, *z;
long sz;
+ c = clientref(client);
pld = z = ecalloc(bufsz);
e = pld + bufsz - 1;
sz = -1;
@@ -414,42 +369,53 @@
}
void
-mkdirent(Dir *d, int kind, Client *c){
- char *nm, *buf;
+mkdirent(Dir *d, int kind, int client){
+ Client *c;
+ char *nm;
- mkqid(&d->qid, kind, c);
+ memset(d, 0, sizeof(*d));
+ mkqid(&d->qid, kind, client);
d->mode = 0444 & umask;
if(nil != (nm = nametab[kind]))
- d->name = nm;
+ d->name = estrdup(nm);
+ if(kind == Qclient){
+ nm = ecalloc(bufsz);
+ sprintf(nm, "%i", client);
+ d->name = estrdup(nm);
+ }
+ if(d->qid.type & QTDIR)
+ d->mode |= DMDIR | 0111;
- buf = ecalloc(bufsz);
+ c = clientref(client);
switch(kind){
+ case Qrctl: d->mode = 0666 & umask; break;
+ case Qctl:
+ case Qio: d->mode = 0666 & c->umask; break;
+ }
+
+ switch(kind){
case Qroot:
- d->mode = 0777 & umask;
case Qrctl:
+ case Qclone:
d->atime = d->mtime = time0;
d->uid = estrdup(user);
d->gid = estrdup(user);
d->muid = estrdup(user);
break;
- case Qclient:
- d->mode = 0777 & c->umask;
- sprintf(buf, "%i", c->id);
- d->name = estrdup(buf);
default:
d->atime = d->mtime = c->time0;
d->uid = estrdup(c->user);
d->gid = estrdup(c->user);
d->muid = estrdup(c->user);
+ break;
}
switch(kind){
- case Qrctl: d->length = readqrctl(&buf);
- case Qctl: d->length = readqctl(&buf, c);
- case Qio: d->length = readqio(&buf, c);
+ case Qrctl: d->length = strlen(qrctl); break;
+ case Qctl: d->length = strlen(c->qctl); break;
+ case Qio: d->length = c->pres == nil ? 0 : strlen(c->pres); break;
+ case Qrinfo: d->length = c->rinfo == nil ? 0 : strlen(c->rinfo); break;
}
-
- free(buf);
}
int
@@ -459,7 +425,7 @@
i += Qroot + 1;
if(i < Qclient){
- mkdirent(d, i, nil);
+ mkdirent(d, i, -1);
} else {
i -= Qclient;
if(i == 0)
@@ -468,7 +434,7 @@
if(j == nclients)
return -1;
n++;
- mkdirent(d, Qclient, clientref(j));
+ mkdirent(d, Qclient, j);
}
return 0;
@@ -476,26 +442,26 @@
int
genqclient(int i, Dir *d, void *aux){
- Client *c;
+ int client;
- c = aux;
+ client = (vlong)aux;
i += Qclient + 1;
if(i >= QCOUNT)
return -1;
- mkdirent(d, i, c);
+ mkdirent(d, i, client);
return 0;
}
-
static void
fsdestroyfid(Fid *fid){
Rfid *f;
f = fid->aux;
- if(-1 < f->client){
- rmclient(f->client);
- free(f);
- }
+ if(f == nil)
+ return;
+
+ rmclient(f->client);
+ free(f);
}
static void
@@ -513,11 +479,12 @@
static void
fsattach(Req *r){
Rfid *f;
-
+
f = ecalloc(sizeof(*f));
f->kind = Qroot;
+ f->client = -1;
- mkqid(&r->fid->qid, f->kind, nil);
+ mkqid(&r->fid->qid, f->kind, f->client);
r->fid->aux = f;
r->ofcall.qid = r->fid->qid;
@@ -542,9 +509,8 @@
}
f->kind = Qctl;
- c = clientref(f->client);
- mkqid(&r->ofcall.qid, f->kind, c);
+ mkqid(&r->ofcall.qid, f->kind, f->client);
r->fid->qid = r->ofcall.qid;
respond(r, nil);
@@ -574,6 +540,8 @@
c->iopid = pid;
}
break;
+ default:
+ respond(r, nil);
}
}
@@ -582,23 +550,22 @@
Rfid *f;
Client *c;
char *buf;
- long n;
buf = nil;
- n = -1;
f = r->fid->aux;
c = clientref(f->client);
switch(f->kind){
case Qroot: dirread9p(r, genqroot, nil); break;
- case Qrctl: n = readqrctl(&buf); break;
+ case Qrctl: buf = estrdup(qrctl); break;
case Qclone: respond(r, "read prohibited"); return;
- case Qclient: dirread9p(r, genqclient, c); break;
- case Qctl: n = readqctl(&buf, c); break;
- case Qio: n = readqio(&buf, c); break;
+ case Qclient: dirread9p(r, genqclient, (void*)f->client); break;
+ case Qctl: buf = estrdup(c->qctl); break;
+ case Qio: buf = estrdup(c->pres); break;
+ case Qrinfo: buf = estrdup(c->rinfo); break;
}
if(buf != nil){
- readbuf(r, buf, n);
+ readbuf(r, buf, strlen(buf));
free(buf);
}
@@ -610,28 +577,32 @@
Rfid *f;
Client *c;
int pid;
+ char *d, *err;
+ long n;
+ d = r->ifcall.data;
+ n = r->ifcall.count;
f = r->fid->aux;
c = clientref(f->client);
+ err = nil;
switch(f->kind){
case Qrctl:
- r->ofcall.count = writeqrctl(r->ifcall.data, r->ifcall.count);
+ r->ofcall.count = writeqrctl(d, n);
break;
case Qctl:
- r->ofcall.count = writeqctl(r->ifcall.data, r->ifcall.count, c);
+ r->ofcall.count = writeqctl(d, n, f->client);
break;
case Qio:
switch(pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
case 0:
alarm(c->timeout);
- r->ofcall.count = writeqio(r->ifcall.data, r->ifcall.count, c);
+ r->ofcall.count = writeqio(d, n, f->client);
alarm(0);
c->iopid = 0;
- respond(r, nil);
break;
case -1:
- respond(r, "failed to send command");
+ err = "failed to fork write";
break;
default:
c->iopid = pid;
@@ -638,18 +609,21 @@
}
break;
default:
- respond(r, "write prohibited"); return;
+ err = "write prohibited";
}
+
+ respond(r, err);
}
static void
fsflush(Req *r){
+ Req *o;
Rfid *f;
Client *c;
- f = r->fid->aux;
- c = clientref(f->client);
-
+ if(o = r->oldreq)
+ if(f = o->fid->aux)
+ if(c = clientref(f->client))
if(0 < c->iopid){
postnote(PNPROC, c->iopid, "interrupt");
respond(r, "interrupted");
@@ -661,11 +635,9 @@
static void
fsstat(Req *r){
Rfid *f;
- Client *c;
f = r->fid->aux;
- c = clientref(f->client);
- mkdirent(&r->d, f->kind, c);
+ mkdirent(&r->d, f->kind, f->client);
respond(r, nil);
}
@@ -700,9 +672,10 @@
break;
if(i == Qclient){
n = strtol(name, &nend, 10);
- if(*nend == 0 && nil != (c = clientref(n)) && c->ref != 0){
- f->client = n;
+ c = clientref(n);
+ if(*nend == 0 && c != nil && c->ref != 0){
incref(c);
+ f->client = n;
break;
}
}
@@ -711,7 +684,7 @@
return "directory entry not found";
f->kind = i;
}
- mkqid(qid, f->kind, clientref(n));
+ mkqid(qid, f->kind, n);
fid->qid = *qid;
return nil;
}
@@ -727,7 +700,7 @@
f = ecalloc(sizeof(*f));
memmove(f, o, sizeof(*f));
- if(-1 < f->client)
+ if(f->client > -1)
incref(clientref(f->client));
newfid->aux = f;
@@ -755,12 +728,13 @@
void
main(int argc, char **argv){
- timeout = 10000;
+ user = getuser();
mtpt = "/mnt/ride";
- bufsz = 4096;
umask = 0755;
+ bufsz = 4096;
time0 = time(0);
nclients = 256;
+ timeout = 10000;
ARGBEGIN{
case 'D': chatty9p++; break;
@@ -773,6 +747,23 @@
}ARGEND
cpool = ecalloc(nclients*sizeof(*cpool));
+ qrctl = ecalloc(bufsz);
+ genqrctl();
+
+ if(debug)
+ fprintf(stderr,
+ "ridefs:\n"
+ "\tchatty9p = %i\n"
+ "\tdebug = %i\n"
+ "\ttimeout = %i\n"
+ "\tmtpt = %s\n"
+ "\tservice = %s\n"
+ "\tnet = %s\n"
+ "\tfs = %p\n"
+ "\tcpool = %p\n",
+ chatty9p, debug, timeout,
+ mtpt, service, net,
+ &fs, cpool);
rfork(RFNOTEG);
postmountsrv(&fs, service, mtpt, MREPL);
--- /dev/null
+++ b/test
@@ -1,0 +1,51 @@
+#!/bin/rc
+
+fn fail{ echo $1; exit $1}
+
+./6.out $* ||
+ fail 'Crashed at startup'
+
+cd /mnt/ride ||
+ fail 'Not mounted'
+
+ls . >/dev/null ||
+ fail 'Mountpoint not readable'
+
+cat ctl >/dev/null ||
+ fail 'Could not read ctl'
+
+ot=`{grep timeout ctl}
+echo 'timeout 5000' >ctl ||
+ fail 'Could not write ctl'
+
+nt=`{grep timeout ctl}
+~ $nt(2) 5000 ||
+ fail 'Written and read ctl values differ'
+echo timeout $ot(2) >ctl
+
+cat clone >/dev/null ||
+ fail 'Could not clone'
+
+<clone {
+ cd `{read} ||
+ fail 'Could not cd to client'
+
+ cat ctl >/dev/null ||
+ fail 'Could not read client ctl'
+
+ ot=`{grep timeout ctl}
+ echo 'timeout 5000' >ctl ||
+ fail 'Could not write client ctl'
+
+ nt=`{grep timeout ctl}
+ ~ $nt(2) 5000 ||
+ fail 'Written and read client ctl values differ'
+ echo timeout $ot(2) >ctl
+
+ cd .. ||
+ fail 'Could not cd out of client directory'
+}
+
+n=`{read clone}
+ls -d $n >[2]/dev/null &&
+ fail 'Did not clean up closed client'
--
⑨