|  | #include <stdlib.h> | 
|  | #include <stdio.h> | 
|  | #include <parlib.h> | 
|  | #include <unistd.h> | 
|  | #include <signal.h> | 
|  | #include <fcntl.h> | 
|  | #include <nixip.h> | 
|  | #include <dir.h> | 
|  | #include <ndb.h> | 
|  | #include <fcall.h> | 
|  |  | 
|  | static | 
|  | uint8_t* | 
|  | pstring(uint8_t *p, char *s) | 
|  | { | 
|  | unsigned int n; | 
|  |  | 
|  | if(s == NULL){ | 
|  | PBIT16(p, 0); | 
|  | p += BIT16SZ; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | n = strlen(s); | 
|  | /* | 
|  | * We are moving the string before the length, | 
|  | * so you can S2M a struct into an existing message | 
|  | */ | 
|  | memmove(p + BIT16SZ, s, n); | 
|  | PBIT16(p, n); | 
|  | p += n + BIT16SZ; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | static | 
|  | uint8_t* | 
|  | pqid(uint8_t *p, struct qid *q) | 
|  | { | 
|  | PBIT8(p, q->type); | 
|  | p += BIT8SZ; | 
|  | PBIT32(p, q->vers); | 
|  | p += BIT32SZ; | 
|  | PBIT64(p, q->path); | 
|  | p += BIT64SZ; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | static | 
|  | unsigned int | 
|  | stringsz(char *s) | 
|  | { | 
|  | if(s == NULL) | 
|  | return BIT16SZ; | 
|  |  | 
|  | return BIT16SZ+strlen(s); | 
|  | } | 
|  |  | 
|  | unsigned int | 
|  | sizeS2M(struct fcall *f) | 
|  | { | 
|  | unsigned int n; | 
|  | int i; | 
|  |  | 
|  | n = 0; | 
|  | n += BIT32SZ;	/* size */ | 
|  | n += BIT8SZ;	/* type */ | 
|  | n += BIT16SZ;	/* tag */ | 
|  |  | 
|  | switch(f->type) | 
|  | { | 
|  | default: | 
|  | return 0; | 
|  |  | 
|  | case Tversion: | 
|  | n += BIT32SZ; | 
|  | n += stringsz(f->version); | 
|  | break; | 
|  |  | 
|  | case Tflush: | 
|  | n += BIT16SZ; | 
|  | break; | 
|  |  | 
|  | case Tauth: | 
|  | n += BIT32SZ; | 
|  | n += stringsz(f->uname); | 
|  | n += stringsz(f->aname); | 
|  | break; | 
|  |  | 
|  | case Tattach: | 
|  | n += BIT32SZ; | 
|  | n += BIT32SZ; | 
|  | n += stringsz(f->uname); | 
|  | n += stringsz(f->aname); | 
|  | break; | 
|  |  | 
|  | case Twalk: | 
|  | n += BIT32SZ; | 
|  | n += BIT32SZ; | 
|  | n += BIT16SZ; | 
|  | for(i=0; i<f->nwname; i++) | 
|  | n += stringsz(f->wname[i]); | 
|  | break; | 
|  |  | 
|  | case Topen: | 
|  | n += BIT32SZ; | 
|  | n += BIT8SZ; | 
|  | break; | 
|  |  | 
|  | case Tcreate: | 
|  | n += BIT32SZ; | 
|  | n += stringsz(f->name); | 
|  | n += BIT32SZ; | 
|  | n += BIT8SZ; | 
|  | break; | 
|  |  | 
|  | case Tread: | 
|  | n += BIT32SZ; | 
|  | n += BIT64SZ; | 
|  | n += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Twrite: | 
|  | n += BIT32SZ; | 
|  | n += BIT64SZ; | 
|  | n += BIT32SZ; | 
|  | n += f->count; | 
|  | break; | 
|  |  | 
|  | case Tclunk: | 
|  | case Tremove: | 
|  | n += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Tstat: | 
|  | n += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Twstat: | 
|  | n += BIT32SZ; | 
|  | n += BIT16SZ; | 
|  | n += f->nstat; | 
|  | break; | 
|  | /* | 
|  | */ | 
|  |  | 
|  | case Rversion: | 
|  | n += BIT32SZ; | 
|  | n += stringsz(f->version); | 
|  | break; | 
|  |  | 
|  | case Rerror: | 
|  | n += stringsz(f->ename); | 
|  | break; | 
|  |  | 
|  | case Rflush: | 
|  | break; | 
|  |  | 
|  | case Rauth: | 
|  | n += QIDSZ; | 
|  | break; | 
|  |  | 
|  | case Rattach: | 
|  | n += QIDSZ; | 
|  | break; | 
|  |  | 
|  | case Rwalk: | 
|  | n += BIT16SZ; | 
|  | n += f->nwqid*QIDSZ; | 
|  | break; | 
|  |  | 
|  | case Ropen: | 
|  | case Rcreate: | 
|  | n += QIDSZ; | 
|  | n += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Rread: | 
|  | n += BIT32SZ; | 
|  | n += f->count; | 
|  | break; | 
|  |  | 
|  | case Rwrite: | 
|  | n += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Rclunk: | 
|  | break; | 
|  |  | 
|  | case Rremove: | 
|  | break; | 
|  |  | 
|  | case Rstat: | 
|  | n += BIT16SZ; | 
|  | n += f->nstat; | 
|  | break; | 
|  |  | 
|  | case Rwstat: | 
|  | break; | 
|  | } | 
|  | return n; | 
|  | } | 
|  |  | 
|  | unsigned int | 
|  | convS2M(struct fcall *f, uint8_t *ap, unsigned int nap) | 
|  | { | 
|  | uint8_t *p; | 
|  | unsigned int i, size; | 
|  |  | 
|  | size = sizeS2M(f); | 
|  | if(size == 0) | 
|  | return 0; | 
|  | if(size > nap) | 
|  | return 0; | 
|  |  | 
|  | p = (uint8_t*)ap; | 
|  |  | 
|  | PBIT32(p, size); | 
|  | p += BIT32SZ; | 
|  | PBIT8(p, f->type); | 
|  | p += BIT8SZ; | 
|  | PBIT16(p, f->tag); | 
|  | p += BIT16SZ; | 
|  |  | 
|  | switch(f->type) | 
|  | { | 
|  | default: | 
|  | return 0; | 
|  |  | 
|  | case Tversion: | 
|  | PBIT32(p, f->msize); | 
|  | p += BIT32SZ; | 
|  | p = pstring(p, f->version); | 
|  | break; | 
|  |  | 
|  | case Tflush: | 
|  | PBIT16(p, f->oldtag); | 
|  | p += BIT16SZ; | 
|  | break; | 
|  |  | 
|  | case Tauth: | 
|  | PBIT32(p, f->afid); | 
|  | p += BIT32SZ; | 
|  | p  = pstring(p, f->uname); | 
|  | p  = pstring(p, f->aname); | 
|  | break; | 
|  |  | 
|  | case Tattach: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | PBIT32(p, f->afid); | 
|  | p += BIT32SZ; | 
|  | p  = pstring(p, f->uname); | 
|  | p  = pstring(p, f->aname); | 
|  | break; | 
|  |  | 
|  | case Twalk: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | PBIT32(p, f->newfid); | 
|  | p += BIT32SZ; | 
|  | PBIT16(p, f->nwname); | 
|  | p += BIT16SZ; | 
|  | if(f->nwname > MAXWELEM) | 
|  | return 0; | 
|  | for(i=0; i<f->nwname; i++) | 
|  | p = pstring(p, f->wname[i]); | 
|  | break; | 
|  |  | 
|  | case Topen: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | PBIT8(p, f->mode); | 
|  | p += BIT8SZ; | 
|  | break; | 
|  |  | 
|  | case Tcreate: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | p = pstring(p, f->name); | 
|  | PBIT32(p, f->perm); | 
|  | p += BIT32SZ; | 
|  | PBIT8(p, f->mode); | 
|  | p += BIT8SZ; | 
|  | break; | 
|  |  | 
|  | case Tread: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | PBIT64(p, f->offset); | 
|  | p += BIT64SZ; | 
|  | PBIT32(p, f->count); | 
|  | p += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Twrite: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | PBIT64(p, f->offset); | 
|  | p += BIT64SZ; | 
|  | PBIT32(p, f->count); | 
|  | p += BIT32SZ; | 
|  | memmove(p, f->data, f->count); | 
|  | p += f->count; | 
|  | break; | 
|  |  | 
|  | case Tclunk: | 
|  | case Tremove: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Tstat: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Twstat: | 
|  | PBIT32(p, f->fid); | 
|  | p += BIT32SZ; | 
|  | PBIT16(p, f->nstat); | 
|  | p += BIT16SZ; | 
|  | memmove(p, f->stat, f->nstat); | 
|  | p += f->nstat; | 
|  | break; | 
|  | /* | 
|  | */ | 
|  |  | 
|  | case Rversion: | 
|  | PBIT32(p, f->msize); | 
|  | p += BIT32SZ; | 
|  | p = pstring(p, f->version); | 
|  | break; | 
|  |  | 
|  | case Rerror: | 
|  | p = pstring(p, f->ename); | 
|  | break; | 
|  |  | 
|  | case Rflush: | 
|  | break; | 
|  |  | 
|  | case Rauth: | 
|  | p = pqid(p, &f->aqid); | 
|  | break; | 
|  |  | 
|  | case Rattach: | 
|  | p = pqid(p, &f->qid); | 
|  | break; | 
|  |  | 
|  | case Rwalk: | 
|  | PBIT16(p, f->nwqid); | 
|  | p += BIT16SZ; | 
|  | if(f->nwqid > MAXWELEM) | 
|  | return 0; | 
|  | for(i=0; i<f->nwqid; i++) | 
|  | p = pqid(p, &f->wqid[i]); | 
|  | break; | 
|  |  | 
|  | case Ropen: | 
|  | case Rcreate: | 
|  | p = pqid(p, &f->qid); | 
|  | PBIT32(p, f->iounit); | 
|  | p += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Rread: | 
|  | PBIT32(p, f->count); | 
|  | p += BIT32SZ; | 
|  | memmove(p, f->data, f->count); | 
|  | p += f->count; | 
|  | break; | 
|  |  | 
|  | case Rwrite: | 
|  | PBIT32(p, f->count); | 
|  | p += BIT32SZ; | 
|  | break; | 
|  |  | 
|  | case Rclunk: | 
|  | break; | 
|  |  | 
|  | case Rremove: | 
|  | break; | 
|  |  | 
|  | case Rstat: | 
|  | PBIT16(p, f->nstat); | 
|  | p += BIT16SZ; | 
|  | memmove(p, f->stat, f->nstat); | 
|  | p += f->nstat; | 
|  | break; | 
|  |  | 
|  | case Rwstat: | 
|  | break; | 
|  | } | 
|  | if(size != p-ap) | 
|  | return 0; | 
|  | return size; | 
|  | } |