17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <fcall.h>
57dd7cddfSDavid du Colombier #include <bio.h>
67dd7cddfSDavid du Colombier #include <ndb.h>
77dd7cddfSDavid du Colombier #include <thread.h>
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier /*
107dd7cddfSDavid du Colombier * This fs presents a 1 level file system. It contains
118bc54264SDavid du Colombier * up to three files per console (xxx and xxxctl and xxxstat)
127dd7cddfSDavid du Colombier */
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier typedef struct Console Console;
157dd7cddfSDavid du Colombier typedef struct Fid Fid;
167dd7cddfSDavid du Colombier typedef struct Request Request;
177dd7cddfSDavid du Colombier typedef struct Reqlist Reqlist;
187dd7cddfSDavid du Colombier typedef struct Fs Fs;
197dd7cddfSDavid du Colombier
207dd7cddfSDavid du Colombier enum
217dd7cddfSDavid du Colombier {
227dd7cddfSDavid du Colombier /* last 5 bits of qid.path */
237dd7cddfSDavid du Colombier Textern= 0, /* fake parent of top level */
247dd7cddfSDavid du Colombier Ttopdir, /* top level directory */
257dd7cddfSDavid du Colombier Qctl,
267dd7cddfSDavid du Colombier Qstat,
277dd7cddfSDavid du Colombier Qdata,
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier Bufsize= 32*1024, /* chars buffered per reader */
307dd7cddfSDavid du Colombier Maxcons= 64, /* maximum consoles */
317dd7cddfSDavid du Colombier Nhash= 64, /* Fid hash buckets */
327dd7cddfSDavid du Colombier };
337dd7cddfSDavid du Colombier
349a747e4fSDavid du Colombier #define TYPE(x) (((ulong)x.path) & 0xf)
359a747e4fSDavid du Colombier #define CONS(x) ((((ulong)x.path) >> 4)&0xfff)
367dd7cddfSDavid du Colombier #define QID(c, x) (((c)<<4) | (x))
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier struct Request
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier Request *next;
417dd7cddfSDavid du Colombier Fid *fid;
427dd7cddfSDavid du Colombier Fs *fs;
437dd7cddfSDavid du Colombier Fcall f;
449a747e4fSDavid du Colombier uchar buf[1];
457dd7cddfSDavid du Colombier };
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier struct Reqlist
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier Lock;
507dd7cddfSDavid du Colombier Request *first;
517dd7cddfSDavid du Colombier Request *last;
527dd7cddfSDavid du Colombier };
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier struct Fid
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier Lock;
577dd7cddfSDavid du Colombier Fid *next; /* hash list */
587dd7cddfSDavid du Colombier Fid *cnext; /* list of Fid's on a console */
597dd7cddfSDavid du Colombier int fid;
607dd7cddfSDavid du Colombier int ref;
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier int attached;
637dd7cddfSDavid du Colombier int open;
649a747e4fSDavid du Colombier char *user;
658bc54264SDavid du Colombier char mbuf[Bufsize]; /* message */
668bc54264SDavid du Colombier int bufn;
678bc54264SDavid du Colombier int used;
687dd7cddfSDavid du Colombier Qid qid;
697dd7cddfSDavid du Colombier
707dd7cddfSDavid du Colombier Console *c;
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier char buf[Bufsize];
737dd7cddfSDavid du Colombier char *rp;
747dd7cddfSDavid du Colombier char *wp;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier Reqlist r; /* active read requests */
777dd7cddfSDavid du Colombier };
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier struct Console
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier Lock;
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier char *name;
847dd7cddfSDavid du Colombier char *dev;
857dd7cddfSDavid du Colombier int speed;
867dd7cddfSDavid du Colombier int cronly;
877dd7cddfSDavid du Colombier int ondemand; /* open only on demand */
888bc54264SDavid du Colombier int chat; /* chat consoles are special */
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier int pid; /* pid of reader */
917dd7cddfSDavid du Colombier
927dd7cddfSDavid du Colombier int fd;
937dd7cddfSDavid du Colombier int cfd;
947dd7cddfSDavid du Colombier int sfd;
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier Fid *flist; /* open fids to broadcast to */
977dd7cddfSDavid du Colombier };
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier struct Fs
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier Lock;
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier int fd; /* to kernel mount point */
1049a747e4fSDavid du Colombier int messagesize;
1057dd7cddfSDavid du Colombier Fid *hash[Nhash];
1067dd7cddfSDavid du Colombier Console *cons[Maxcons];
1077dd7cddfSDavid du Colombier int ncons;
1087dd7cddfSDavid du Colombier };
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier extern void console(Fs*, char*, char*, int, int, int);
1117dd7cddfSDavid du Colombier extern Fs* fsmount(char*);
1127dd7cddfSDavid du Colombier
1137dd7cddfSDavid du Colombier extern void fsreader(void*);
1147dd7cddfSDavid du Colombier extern void fsrun(void*);
1157dd7cddfSDavid du Colombier extern Fid* fsgetfid(Fs*, int);
1167dd7cddfSDavid du Colombier extern void fsputfid(Fs*, Fid*);
1179a747e4fSDavid du Colombier extern int fsdirgen(Fs*, Qid, int, Dir*, uchar*, int);
1187dd7cddfSDavid du Colombier extern void fsreply(Fs*, Request*, char*);
1197dd7cddfSDavid du Colombier extern void fskick(Fs*, Fid*);
1207dd7cddfSDavid du Colombier extern int fsreopen(Fs*, Console*);
1217dd7cddfSDavid du Colombier
1229a747e4fSDavid du Colombier extern void fsversion(Fs*, Request*, Fid*);
1237dd7cddfSDavid du Colombier extern void fsflush(Fs*, Request*, Fid*);
1249a747e4fSDavid du Colombier extern void fsauth(Fs*, Request*, Fid*);
1257dd7cddfSDavid du Colombier extern void fsattach(Fs*, Request*, Fid*);
1267dd7cddfSDavid du Colombier extern void fswalk(Fs*, Request*, Fid*);
1277dd7cddfSDavid du Colombier extern void fsclwalk(Fs*, Request*, Fid*);
1287dd7cddfSDavid du Colombier extern void fsopen(Fs*, Request*, Fid*);
1297dd7cddfSDavid du Colombier extern void fscreate(Fs*, Request*, Fid*);
1307dd7cddfSDavid du Colombier extern void fsread(Fs*, Request*, Fid*);
1317dd7cddfSDavid du Colombier extern void fswrite(Fs*, Request*, Fid*);
1327dd7cddfSDavid du Colombier extern void fsclunk(Fs*, Request*, Fid*);
1337dd7cddfSDavid du Colombier extern void fsremove(Fs*, Request*, Fid*);
1347dd7cddfSDavid du Colombier extern void fsstat(Fs*, Request*, Fid*);
1357dd7cddfSDavid du Colombier extern void fswstat(Fs*, Request*, Fid*);
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier void (*fcall[])(Fs*, Request*, Fid*) =
1397dd7cddfSDavid du Colombier {
1407dd7cddfSDavid du Colombier [Tflush] fsflush,
1419a747e4fSDavid du Colombier [Tversion] fsversion,
1429a747e4fSDavid du Colombier [Tauth] fsauth,
1437dd7cddfSDavid du Colombier [Tattach] fsattach,
1447dd7cddfSDavid du Colombier [Twalk] fswalk,
1457dd7cddfSDavid du Colombier [Topen] fsopen,
1467dd7cddfSDavid du Colombier [Tcreate] fscreate,
1477dd7cddfSDavid du Colombier [Tread] fsread,
1487dd7cddfSDavid du Colombier [Twrite] fswrite,
1497dd7cddfSDavid du Colombier [Tclunk] fsclunk,
1507dd7cddfSDavid du Colombier [Tremove] fsremove,
1517dd7cddfSDavid du Colombier [Tstat] fsstat,
1527dd7cddfSDavid du Colombier [Twstat] fswstat
1537dd7cddfSDavid du Colombier };
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier char Eperm[] = "permission denied";
1567dd7cddfSDavid du Colombier char Eexist[] = "file does not exist";
1577dd7cddfSDavid du Colombier char Enotdir[] = "not a directory";
1587dd7cddfSDavid du Colombier char Eisopen[] = "file already open";
1597dd7cddfSDavid du Colombier char Ebadcount[] = "bad read/write count";
1607dd7cddfSDavid du Colombier char Enofid[] = "no such fid";
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier char *consoledb = "/lib/ndb/consoledb";
1637dd7cddfSDavid du Colombier char *mntpt = "/mnt/consoles";
1647dd7cddfSDavid du Colombier
1659a747e4fSDavid du Colombier int messagesize = 8192+IOHDRSZ;
1669a747e4fSDavid du Colombier
1677dd7cddfSDavid du Colombier void
fatal(char * fmt,...)1687dd7cddfSDavid du Colombier fatal(char *fmt, ...)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier va_list arg;
1717dd7cddfSDavid du Colombier char buf[1024];
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier write(2, "consolefs: ", 10);
1747dd7cddfSDavid du Colombier va_start(arg, fmt);
1759a747e4fSDavid du Colombier vseprint(buf, buf+1024, fmt, arg);
1767dd7cddfSDavid du Colombier va_end(arg);
1777dd7cddfSDavid du Colombier write(2, buf, strlen(buf));
1787dd7cddfSDavid du Colombier write(2, "\n", 1);
1797dd7cddfSDavid du Colombier threadexitsall(fmt);
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier void*
emalloc(uint n)1847dd7cddfSDavid du Colombier emalloc(uint n)
1857dd7cddfSDavid du Colombier {
1867dd7cddfSDavid du Colombier void *p;
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier p = malloc(n);
1897dd7cddfSDavid du Colombier if(p == nil)
1907dd7cddfSDavid du Colombier fatal("malloc failed: %r");
1917dd7cddfSDavid du Colombier memset(p, 0, n);
1927dd7cddfSDavid du Colombier return p;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier
1957dd7cddfSDavid du Colombier int debug;
1967dd7cddfSDavid du Colombier Ndb *db;
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier /*
1997dd7cddfSDavid du Colombier * any request that can get queued for a delayed reply
2007dd7cddfSDavid du Colombier */
2017dd7cddfSDavid du Colombier Request*
allocreq(Fs * fs,int bufsize)2027dd7cddfSDavid du Colombier allocreq(Fs *fs, int bufsize)
2037dd7cddfSDavid du Colombier {
2047dd7cddfSDavid du Colombier Request *r;
2057dd7cddfSDavid du Colombier
2067dd7cddfSDavid du Colombier r = emalloc(sizeof(Request)+bufsize);
2077dd7cddfSDavid du Colombier r->fs = fs;
2087dd7cddfSDavid du Colombier r->next = nil;
2097dd7cddfSDavid du Colombier return r;
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier /*
2137dd7cddfSDavid du Colombier * for maintaining lists of requests
2147dd7cddfSDavid du Colombier */
2157dd7cddfSDavid du Colombier void
addreq(Reqlist * l,Request * r)2167dd7cddfSDavid du Colombier addreq(Reqlist *l, Request *r)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier lock(l);
2197dd7cddfSDavid du Colombier if(l->first == nil)
2207dd7cddfSDavid du Colombier l->first = r;
2217dd7cddfSDavid du Colombier else
2227dd7cddfSDavid du Colombier l->last->next = r;
2237dd7cddfSDavid du Colombier l->last = r;
2247dd7cddfSDavid du Colombier r->next = nil;
2257dd7cddfSDavid du Colombier unlock(l);
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier /*
2297dd7cddfSDavid du Colombier * remove the first request from a list of requests
2307dd7cddfSDavid du Colombier */
2317dd7cddfSDavid du Colombier Request*
remreq(Reqlist * l)2327dd7cddfSDavid du Colombier remreq(Reqlist *l)
2337dd7cddfSDavid du Colombier {
2347dd7cddfSDavid du Colombier Request *r;
2357dd7cddfSDavid du Colombier
2367dd7cddfSDavid du Colombier lock(l);
2377dd7cddfSDavid du Colombier r = l->first;
2387dd7cddfSDavid du Colombier if(r != nil)
2397dd7cddfSDavid du Colombier l->first = r->next;
2407dd7cddfSDavid du Colombier unlock(l);
2417dd7cddfSDavid du Colombier return r;
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier /*
2457dd7cddfSDavid du Colombier * remove a request with the given tag from a list of requests
2467dd7cddfSDavid du Colombier */
2477dd7cddfSDavid du Colombier Request*
remtag(Reqlist * l,int tag)2487dd7cddfSDavid du Colombier remtag(Reqlist *l, int tag)
2497dd7cddfSDavid du Colombier {
2507dd7cddfSDavid du Colombier Request *or, **ll;
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier lock(l);
2537dd7cddfSDavid du Colombier ll = &l->first;
2547dd7cddfSDavid du Colombier for(or = *ll; or; or = or->next){
2557dd7cddfSDavid du Colombier if(or->f.tag == tag){
2567dd7cddfSDavid du Colombier *ll = or->next;
2577dd7cddfSDavid du Colombier unlock(l);
2587dd7cddfSDavid du Colombier return or;
2597dd7cddfSDavid du Colombier }
2607dd7cddfSDavid du Colombier ll = &or->next;
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier unlock(l);
2637dd7cddfSDavid du Colombier return nil;
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier Qid
parentqid(Qid q)2677dd7cddfSDavid du Colombier parentqid(Qid q)
2687dd7cddfSDavid du Colombier {
2699a747e4fSDavid du Colombier if(q.type & QTDIR)
2709a747e4fSDavid du Colombier return (Qid){QID(0, Textern), 0, QTDIR};
2717dd7cddfSDavid du Colombier else
2729a747e4fSDavid du Colombier return (Qid){QID(0, Ttopdir), 0, QTDIR};
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier
2757dd7cddfSDavid du Colombier int
fsdirgen(Fs * fs,Qid parent,int i,Dir * d,uchar * buf,int nbuf)2769a747e4fSDavid du Colombier fsdirgen(Fs *fs, Qid parent, int i, Dir *d, uchar *buf, int nbuf)
2777dd7cddfSDavid du Colombier {
2789a747e4fSDavid du Colombier static char name[64];
2797dd7cddfSDavid du Colombier char *p;
2807dd7cddfSDavid du Colombier int xcons;
2817dd7cddfSDavid du Colombier
2829a747e4fSDavid du Colombier d->uid = d->gid = d->muid = "network";
2837dd7cddfSDavid du Colombier d->length = 0;
2847dd7cddfSDavid du Colombier d->atime = time(nil);
2857dd7cddfSDavid du Colombier d->mtime = d->atime;
2867dd7cddfSDavid du Colombier d->type = 'C';
2877dd7cddfSDavid du Colombier d->dev = '0';
2887dd7cddfSDavid du Colombier
2897dd7cddfSDavid du Colombier switch(TYPE(parent)){
2907dd7cddfSDavid du Colombier case Textern:
2917dd7cddfSDavid du Colombier if(i != 0)
2927dd7cddfSDavid du Colombier return -1;
2937dd7cddfSDavid du Colombier p = "consoles";
2949a747e4fSDavid du Colombier d->mode = DMDIR|0555;
2959a747e4fSDavid du Colombier d->qid.type = QTDIR;
2969a747e4fSDavid du Colombier d->qid.path = QID(0, Ttopdir);
2979a747e4fSDavid du Colombier d->qid.vers = 0;
2987dd7cddfSDavid du Colombier break;
2997dd7cddfSDavid du Colombier case Ttopdir:
3007dd7cddfSDavid du Colombier xcons = i/3;
3017dd7cddfSDavid du Colombier if(xcons >= fs->ncons)
3027dd7cddfSDavid du Colombier return -1;
3037dd7cddfSDavid du Colombier p = fs->cons[xcons]->name;
3047dd7cddfSDavid du Colombier switch(i%3){
3057dd7cddfSDavid du Colombier case 0:
306cb3cefd4SDavid du Colombier if(fs->cons[xcons]->cfd < 0)
307cb3cefd4SDavid du Colombier return 0;
3089a747e4fSDavid du Colombier snprint(name, sizeof name, "%sctl", p);
3097dd7cddfSDavid du Colombier p = name;
3109a747e4fSDavid du Colombier d->qid.type = QTFILE;
3119a747e4fSDavid du Colombier d->qid.path = QID(xcons, Qctl);
3129a747e4fSDavid du Colombier d->qid.vers = 0;
3137dd7cddfSDavid du Colombier break;
3147dd7cddfSDavid du Colombier case 1:
315cb3cefd4SDavid du Colombier if(fs->cons[xcons]->sfd < 0)
316cb3cefd4SDavid du Colombier return 0;
3179a747e4fSDavid du Colombier snprint(name, sizeof name, "%sstat", p);
3187dd7cddfSDavid du Colombier p = name;
3199a747e4fSDavid du Colombier d->qid.type = QTFILE;
3209a747e4fSDavid du Colombier d->qid.path = QID(xcons, Qstat);
3219a747e4fSDavid du Colombier d->qid.vers = 0;
3227dd7cddfSDavid du Colombier break;
3237dd7cddfSDavid du Colombier case 2:
3249a747e4fSDavid du Colombier d->qid.type = QTFILE;
3259a747e4fSDavid du Colombier d->qid.path = QID(xcons, Qdata);
3269a747e4fSDavid du Colombier d->qid.vers = 0;
3277dd7cddfSDavid du Colombier break;
3287dd7cddfSDavid du Colombier }
3297dd7cddfSDavid du Colombier d->mode = 0666;
3307dd7cddfSDavid du Colombier break;
3317dd7cddfSDavid du Colombier default:
3327dd7cddfSDavid du Colombier return -1;
3337dd7cddfSDavid du Colombier }
3349a747e4fSDavid du Colombier d->name = p;
3357dd7cddfSDavid du Colombier if(buf != nil)
3369a747e4fSDavid du Colombier return convD2M(d, buf, nbuf);
337cb3cefd4SDavid du Colombier return 1;
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier /*
3417dd7cddfSDavid du Colombier * mount the user interface and start a request processor
3427dd7cddfSDavid du Colombier */
3437dd7cddfSDavid du Colombier Fs*
fsmount(char * mntpt)3447dd7cddfSDavid du Colombier fsmount(char *mntpt)
3457dd7cddfSDavid du Colombier {
3467dd7cddfSDavid du Colombier Fs *fs;
3477dd7cddfSDavid du Colombier int pfd[2], srv;
3489a747e4fSDavid du Colombier char buf[32];
3497dd7cddfSDavid du Colombier int n;
3507dd7cddfSDavid du Colombier static void *v[2];
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier fs = emalloc(sizeof(Fs));
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier if(pipe(pfd) < 0)
3557dd7cddfSDavid du Colombier fatal("opening pipe: %r");
3567dd7cddfSDavid du Colombier
3577dd7cddfSDavid du Colombier /* start up the file system process */
3587dd7cddfSDavid du Colombier v[0] = fs;
3597dd7cddfSDavid du Colombier v[1] = pfd;
3607dd7cddfSDavid du Colombier proccreate(fsrun, v, 16*1024);
3617dd7cddfSDavid du Colombier
3627dd7cddfSDavid du Colombier /* Typically mounted before /srv exists */
3639a747e4fSDavid du Colombier if(access("#s/consoles", AEXIST) < 0){
3647dd7cddfSDavid du Colombier srv = create("#s/consoles", OWRITE, 0666);
3657dd7cddfSDavid du Colombier if(srv < 0)
3667dd7cddfSDavid du Colombier fatal("post: %r");
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier n = sprint(buf, "%d", pfd[1]);
3697dd7cddfSDavid du Colombier if(write(srv, buf, n) < 0)
3707dd7cddfSDavid du Colombier fatal("write srv: %r");
3717dd7cddfSDavid du Colombier
3727dd7cddfSDavid du Colombier close(srv);
3737dd7cddfSDavid du Colombier }
3747dd7cddfSDavid du Colombier
3759a747e4fSDavid du Colombier mount(pfd[1], -1, mntpt, MBEFORE, "");
3767dd7cddfSDavid du Colombier close(pfd[1]);
3777dd7cddfSDavid du Colombier return fs;
3787dd7cddfSDavid du Colombier }
3797dd7cddfSDavid du Colombier
3807dd7cddfSDavid du Colombier /*
3817dd7cddfSDavid du Colombier * reopen a console
3827dd7cddfSDavid du Colombier */
3837dd7cddfSDavid du Colombier int
fsreopen(Fs * fs,Console * c)3847dd7cddfSDavid du Colombier fsreopen(Fs* fs, Console *c)
3857dd7cddfSDavid du Colombier {
3867dd7cddfSDavid du Colombier char buf[128];
3877dd7cddfSDavid du Colombier static void *v[2];
3887dd7cddfSDavid du Colombier
3897dd7cddfSDavid du Colombier if(c->pid){
3907dd7cddfSDavid du Colombier if(postnote(PNPROC, c->pid, "reopen") != 0)
3917dd7cddfSDavid du Colombier fprint(2, "postnote failed: %r\n");
3927dd7cddfSDavid du Colombier c->pid = 0;
3937dd7cddfSDavid du Colombier }
3947dd7cddfSDavid du Colombier
3957dd7cddfSDavid du Colombier if(c->fd >= 0){
3967dd7cddfSDavid du Colombier close(c->fd);
3977dd7cddfSDavid du Colombier close(c->cfd);
3987dd7cddfSDavid du Colombier close(c->sfd);
3997dd7cddfSDavid du Colombier c->cfd = -1;
4007dd7cddfSDavid du Colombier c->fd = -1;
4017dd7cddfSDavid du Colombier c->sfd = -1;
4027dd7cddfSDavid du Colombier }
4037dd7cddfSDavid du Colombier
4047dd7cddfSDavid du Colombier if(c->flist == nil && c->ondemand)
4057dd7cddfSDavid du Colombier return 0;
4067dd7cddfSDavid du Colombier
4077dd7cddfSDavid du Colombier c->fd = open(c->dev, ORDWR);
4087dd7cddfSDavid du Colombier if(c->fd < 0)
4097dd7cddfSDavid du Colombier return -1;
4107dd7cddfSDavid du Colombier
4117dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%sctl", c->dev);
4127dd7cddfSDavid du Colombier c->cfd = open(buf, ORDWR);
4137dd7cddfSDavid du Colombier fprint(c->cfd, "b%d", c->speed);
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%sstat", c->dev);
4167dd7cddfSDavid du Colombier c->sfd = open(buf, OREAD);
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier v[0] = fs;
4197dd7cddfSDavid du Colombier v[1] = c;
4207dd7cddfSDavid du Colombier proccreate(fsreader, v, 16*1024);
4217dd7cddfSDavid du Colombier
4227dd7cddfSDavid du Colombier return 0;
4237dd7cddfSDavid du Colombier }
4247dd7cddfSDavid du Colombier
4257dd7cddfSDavid du Colombier void
change(Fs * fs,Console * c,int doreopen,int speed,int cronly,int ondemand)4267dd7cddfSDavid du Colombier change(Fs *fs, Console *c, int doreopen, int speed, int cronly, int ondemand)
4277dd7cddfSDavid du Colombier {
4287dd7cddfSDavid du Colombier lock(c);
4297dd7cddfSDavid du Colombier
4307dd7cddfSDavid du Colombier if(speed != c->speed){
4317dd7cddfSDavid du Colombier c->speed = speed;
4327dd7cddfSDavid du Colombier doreopen = 1;
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier if(ondemand != c->ondemand){
4357dd7cddfSDavid du Colombier c->ondemand = ondemand;
4367dd7cddfSDavid du Colombier doreopen = 1;
4377dd7cddfSDavid du Colombier }
4387dd7cddfSDavid du Colombier c->cronly = cronly;
4397dd7cddfSDavid du Colombier if(doreopen)
4407dd7cddfSDavid du Colombier fsreopen(fs, c);
4417dd7cddfSDavid du Colombier
4427dd7cddfSDavid du Colombier unlock(c);
4437dd7cddfSDavid du Colombier }
4447dd7cddfSDavid du Colombier
4457dd7cddfSDavid du Colombier /*
4467dd7cddfSDavid du Colombier * create a console interface
4477dd7cddfSDavid du Colombier */
4487dd7cddfSDavid du Colombier void
console(Fs * fs,char * name,char * dev,int speed,int cronly,int ondemand)4497dd7cddfSDavid du Colombier console(Fs* fs, char *name, char *dev, int speed, int cronly, int ondemand)
4507dd7cddfSDavid du Colombier {
4517dd7cddfSDavid du Colombier Console *c;
4527dd7cddfSDavid du Colombier char *x;
4537dd7cddfSDavid du Colombier int i, doreopen;
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier if(fs->ncons >= Maxcons)
4567dd7cddfSDavid du Colombier fatal("too many consoles, too little time");
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier doreopen = 0;
4597dd7cddfSDavid du Colombier for(i = 0; i < fs->ncons; i++){
4607dd7cddfSDavid du Colombier c = fs->cons[i];
4617dd7cddfSDavid du Colombier if(strcmp(name, c->name) == 0){
4627dd7cddfSDavid du Colombier if(strcmp(dev, c->dev) != 0){
4637dd7cddfSDavid du Colombier /* new device */
4647dd7cddfSDavid du Colombier x = c->dev;
4657dd7cddfSDavid du Colombier c->dev = strdup(dev);
4667dd7cddfSDavid du Colombier free(x);
4677dd7cddfSDavid du Colombier doreopen = 1;
4687dd7cddfSDavid du Colombier }
4697dd7cddfSDavid du Colombier change(fs, c, doreopen, speed, cronly, ondemand);
4707dd7cddfSDavid du Colombier return;
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier }
47314cc0f53SDavid du Colombier #ifdef sapedoesntlikethis
47414cc0f53SDavid du Colombier /*
47514cc0f53SDavid du Colombier * The code below prevents this from working. I can't
47614cc0f53SDavid du Colombier * think of scenarios where the code below actually helps
47714cc0f53SDavid du Colombier * Sape
47814cc0f53SDavid du Colombier *
47914cc0f53SDavid du Colombier * console=borneo dev=/dev/eia1
48014cc0f53SDavid du Colombier * speed=9600
48114cc0f53SDavid du Colombier * openondemand=1
48214cc0f53SDavid du Colombier * console=tottie dev=/dev/eia1
48314cc0f53SDavid du Colombier * speed=115200
48414cc0f53SDavid du Colombier * openondemand=1
48514cc0f53SDavid du Colombier */
4867dd7cddfSDavid du Colombier for(i = 0; i < fs->ncons; i++){
4877dd7cddfSDavid du Colombier c = fs->cons[i];
4887dd7cddfSDavid du Colombier if(strcmp(dev, c->dev) == 0){
4897dd7cddfSDavid du Colombier /* at least a rename */
4907dd7cddfSDavid du Colombier x = c->name;
4917dd7cddfSDavid du Colombier c->name = strdup(name);
4927dd7cddfSDavid du Colombier free(x);
4937dd7cddfSDavid du Colombier change(fs, c, doreopen, speed, cronly, ondemand);
4947dd7cddfSDavid du Colombier return;
4957dd7cddfSDavid du Colombier }
4967dd7cddfSDavid du Colombier }
49714cc0f53SDavid du Colombier #endif
4987dd7cddfSDavid du Colombier c = emalloc(sizeof(Console));
4997bd483b0SDavid du Colombier fs->cons[fs->ncons] = c;
5007bd483b0SDavid du Colombier fs->ncons++;
5017dd7cddfSDavid du Colombier c->name = strdup(name);
5027dd7cddfSDavid du Colombier c->dev = strdup(dev);
5038bc54264SDavid du Colombier if(strcmp(c->dev, "/dev/null") == 0)
5048bc54264SDavid du Colombier c->chat = 1;
5058bc54264SDavid du Colombier else
5068bc54264SDavid du Colombier c->chat = 0;
5077dd7cddfSDavid du Colombier c->fd = -1;
5087dd7cddfSDavid du Colombier c->cfd = -1;
5097dd7cddfSDavid du Colombier c->sfd = -1;
5107dd7cddfSDavid du Colombier change(fs, c, 1, speed, cronly, ondemand);
5117dd7cddfSDavid du Colombier }
5127dd7cddfSDavid du Colombier
5137dd7cddfSDavid du Colombier /*
5147dd7cddfSDavid du Colombier * buffer data from console to a client.
5157dd7cddfSDavid du Colombier * circular q with writer able to catch up to reader.
5167dd7cddfSDavid du Colombier * the reader may miss data but always sees an in order sequence.
5177dd7cddfSDavid du Colombier */
5187dd7cddfSDavid du Colombier void
fromconsole(Fid * f,char * p,int n)5197dd7cddfSDavid du Colombier fromconsole(Fid *f, char *p, int n)
5207dd7cddfSDavid du Colombier {
5217dd7cddfSDavid du Colombier char *rp, *wp, *ep;
5227dd7cddfSDavid du Colombier int pass;
5237dd7cddfSDavid du Colombier
5247dd7cddfSDavid du Colombier lock(f);
5257dd7cddfSDavid du Colombier rp = f->rp;
5267dd7cddfSDavid du Colombier wp = f->wp;
5277dd7cddfSDavid du Colombier ep = f->buf + sizeof(f->buf);
5287dd7cddfSDavid du Colombier pass = 0;
5297dd7cddfSDavid du Colombier while(n--){
5307dd7cddfSDavid du Colombier *wp++ = *p++;
5317dd7cddfSDavid du Colombier if(wp >= ep)
5327dd7cddfSDavid du Colombier wp = f->buf;
5337dd7cddfSDavid du Colombier if(rp == wp)
5347dd7cddfSDavid du Colombier pass = 1;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier f->wp = wp;
5377dd7cddfSDavid du Colombier
5387dd7cddfSDavid du Colombier /* we overtook the read pointer, push it up so readers always
5397dd7cddfSDavid du Colombier * see the tail of what was written
5407dd7cddfSDavid du Colombier */
5417dd7cddfSDavid du Colombier if(pass){
5427dd7cddfSDavid du Colombier wp++;
5437dd7cddfSDavid du Colombier if(wp >= ep)
5447dd7cddfSDavid du Colombier f->rp = f->buf;
5457dd7cddfSDavid du Colombier else
5467dd7cddfSDavid du Colombier f->rp = wp;
5477dd7cddfSDavid du Colombier }
5487dd7cddfSDavid du Colombier unlock(f);
5497dd7cddfSDavid du Colombier }
5507dd7cddfSDavid du Colombier
5517dd7cddfSDavid du Colombier /*
5527dd7cddfSDavid du Colombier * broadcast a list of members to all listeners
5537dd7cddfSDavid du Colombier */
5547dd7cddfSDavid du Colombier void
bcastmembers(Fs * fs,Console * c,char * msg,Fid * f)5557dd7cddfSDavid du Colombier bcastmembers(Fs *fs, Console *c, char *msg, Fid *f)
5567dd7cddfSDavid du Colombier {
5577dd7cddfSDavid du Colombier int n;
5587dd7cddfSDavid du Colombier Fid *fl;
5597dd7cddfSDavid du Colombier char buf[512];
5607dd7cddfSDavid du Colombier
5617dd7cddfSDavid du Colombier sprint(buf, "[%s%s", msg, f->user);
5629a747e4fSDavid du Colombier for(fl = c->flist; fl != nil && strlen(buf) + 64 < sizeof(buf); fl = fl->cnext){
5637dd7cddfSDavid du Colombier if(f == fl)
5647dd7cddfSDavid du Colombier continue;
5657dd7cddfSDavid du Colombier strcat(buf, ", ");
5667dd7cddfSDavid du Colombier strcat(buf, fl->user);
5677dd7cddfSDavid du Colombier }
5687dd7cddfSDavid du Colombier strcat(buf, "]\n");
5697dd7cddfSDavid du Colombier
5707dd7cddfSDavid du Colombier n = strlen(buf);
5717dd7cddfSDavid du Colombier for(fl = c->flist; fl; fl = fl->cnext){
5727dd7cddfSDavid du Colombier fromconsole(fl, buf, n);
5737dd7cddfSDavid du Colombier fskick(fs, fl);
5747dd7cddfSDavid du Colombier }
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier
5777dd7cddfSDavid du Colombier void
handler(void *,char * msg)5787dd7cddfSDavid du Colombier handler(void*, char *msg)
5797dd7cddfSDavid du Colombier {
5803b86f2f8SDavid du Colombier if(strstr(msg, "reopen") != nil ||
5813b86f2f8SDavid du Colombier strstr(msg, "write on closed pipe") != nil)
5827dd7cddfSDavid du Colombier noted(NCONT);
5837dd7cddfSDavid du Colombier noted(NDFLT);
5847dd7cddfSDavid du Colombier }
5857dd7cddfSDavid du Colombier
5867dd7cddfSDavid du Colombier /*
5877dd7cddfSDavid du Colombier * a process to read console output and broadcast it (one per console)
5887dd7cddfSDavid du Colombier */
5897dd7cddfSDavid du Colombier void
fsreader(void * v)5907dd7cddfSDavid du Colombier fsreader(void *v)
5917dd7cddfSDavid du Colombier {
5927dd7cddfSDavid du Colombier int n;
5937dd7cddfSDavid du Colombier Fid *fl;
5947dd7cddfSDavid du Colombier char buf[1024];
5957dd7cddfSDavid du Colombier Fs *fs;
5967dd7cddfSDavid du Colombier Console *c;
5977dd7cddfSDavid du Colombier void **a;
5987dd7cddfSDavid du Colombier
5997dd7cddfSDavid du Colombier a = v;
6007dd7cddfSDavid du Colombier fs = a[0];
6017dd7cddfSDavid du Colombier c = a[1];
6027dd7cddfSDavid du Colombier c->pid = getpid();
6037dd7cddfSDavid du Colombier notify(handler);
60465ae840eSDavid du Colombier if(c->chat)
60565ae840eSDavid du Colombier threadexits(nil);
6067dd7cddfSDavid du Colombier for(;;){
6077dd7cddfSDavid du Colombier n = read(c->fd, buf, sizeof(buf));
6087dd7cddfSDavid du Colombier if(n < 0)
6097dd7cddfSDavid du Colombier break;
6107dd7cddfSDavid du Colombier lock(c);
6117dd7cddfSDavid du Colombier for(fl = c->flist; fl; fl = fl->cnext){
6127dd7cddfSDavid du Colombier fromconsole(fl, buf, n);
6137dd7cddfSDavid du Colombier fskick(fs, fl);
6147dd7cddfSDavid du Colombier }
6157dd7cddfSDavid du Colombier unlock(c);
6167dd7cddfSDavid du Colombier }
6177dd7cddfSDavid du Colombier }
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier void
readdb(Fs * fs)6207dd7cddfSDavid du Colombier readdb(Fs *fs)
6217dd7cddfSDavid du Colombier {
6227dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
6237dd7cddfSDavid du Colombier char *dev, *cons;
6247dd7cddfSDavid du Colombier int cronly, speed, ondemand;
6257dd7cddfSDavid du Colombier
6267dd7cddfSDavid du Colombier ndbreopen(db);
6277dd7cddfSDavid du Colombier
6287dd7cddfSDavid du Colombier /* start a listener for each console */
6297dd7cddfSDavid du Colombier for(;;){
6307dd7cddfSDavid du Colombier t = ndbparse(db);
6317dd7cddfSDavid du Colombier if(t == nil)
6327dd7cddfSDavid du Colombier break;
6337dd7cddfSDavid du Colombier dev = nil;
6347dd7cddfSDavid du Colombier cons = nil;
6357dd7cddfSDavid du Colombier speed = 9600;
6367dd7cddfSDavid du Colombier cronly = 0;
6377dd7cddfSDavid du Colombier ondemand = 0;
6387dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){
6397dd7cddfSDavid du Colombier if(strcmp(nt->attr, "console") == 0)
6407dd7cddfSDavid du Colombier cons = nt->val;
6417dd7cddfSDavid du Colombier else if(strcmp(nt->attr, "dev") == 0)
6427dd7cddfSDavid du Colombier dev = nt->val;
6437dd7cddfSDavid du Colombier else if(strcmp(nt->attr, "speed") == 0)
6447dd7cddfSDavid du Colombier speed = atoi(nt->val);
6457dd7cddfSDavid du Colombier else if(strcmp(nt->attr, "cronly") == 0)
6467dd7cddfSDavid du Colombier cronly = 1;
6477dd7cddfSDavid du Colombier else if(strcmp(nt->attr, "openondemand") == 0)
6487dd7cddfSDavid du Colombier ondemand = 1;
6497dd7cddfSDavid du Colombier }
6507dd7cddfSDavid du Colombier if(dev != nil && cons != nil)
6517dd7cddfSDavid du Colombier console(fs, cons, dev, speed, cronly, ondemand);
6527dd7cddfSDavid du Colombier ndbfree(t);
6537dd7cddfSDavid du Colombier }
6547dd7cddfSDavid du Colombier }
6557dd7cddfSDavid du Colombier
6567dd7cddfSDavid du Colombier int dbmtime;
6577dd7cddfSDavid du Colombier
6587dd7cddfSDavid du Colombier /*
6597dd7cddfSDavid du Colombier * a request processor (one per Fs)
6607dd7cddfSDavid du Colombier */
6617dd7cddfSDavid du Colombier void
fsrun(void * v)6627dd7cddfSDavid du Colombier fsrun(void *v)
6637dd7cddfSDavid du Colombier {
6647dd7cddfSDavid du Colombier int n, t;
6657dd7cddfSDavid du Colombier Request *r;
6667dd7cddfSDavid du Colombier Fid *f;
6679a747e4fSDavid du Colombier Dir *d;
6687dd7cddfSDavid du Colombier void **a = v;
6697dd7cddfSDavid du Colombier Fs* fs;
6707dd7cddfSDavid du Colombier int *pfd;
6717dd7cddfSDavid du Colombier
6727dd7cddfSDavid du Colombier fs = a[0];
6737dd7cddfSDavid du Colombier pfd = a[1];
6747dd7cddfSDavid du Colombier fs->fd = pfd[0];
6753b86f2f8SDavid du Colombier notify(handler);
6767dd7cddfSDavid du Colombier for(;;){
6779a747e4fSDavid du Colombier d = dirstat(consoledb);
6789a747e4fSDavid du Colombier if(d != nil && d->mtime != dbmtime){
6799a747e4fSDavid du Colombier dbmtime = d->mtime;
6807dd7cddfSDavid du Colombier readdb(fs);
6817dd7cddfSDavid du Colombier }
6829a747e4fSDavid du Colombier free(d);
6839a747e4fSDavid du Colombier r = allocreq(fs, messagesize);
6849a747e4fSDavid du Colombier n = read9pmsg(fs->fd, r->buf, messagesize);
6857dd7cddfSDavid du Colombier if(n <= 0)
6867dd7cddfSDavid du Colombier fatal("unmounted");
6877dd7cddfSDavid du Colombier
6889a747e4fSDavid du Colombier if(convM2S(r->buf, n, &r->f) == 0){
6897dd7cddfSDavid du Colombier fprint(2, "can't convert %ux %ux %ux\n", r->buf[0],
6907dd7cddfSDavid du Colombier r->buf[1], r->buf[2]);
6917dd7cddfSDavid du Colombier free(r);
6927dd7cddfSDavid du Colombier continue;
6937dd7cddfSDavid du Colombier }
6947dd7cddfSDavid du Colombier
6957dd7cddfSDavid du Colombier
6967dd7cddfSDavid du Colombier f = fsgetfid(fs, r->f.fid);
6977dd7cddfSDavid du Colombier r->fid = f;
6987dd7cddfSDavid du Colombier if(debug)
6999a747e4fSDavid du Colombier fprint(2, "%F path %llux\n", &r->f, f->qid.path);
7007dd7cddfSDavid du Colombier
7017dd7cddfSDavid du Colombier t = r->f.type;
7027dd7cddfSDavid du Colombier r->f.type++;
7037dd7cddfSDavid du Colombier (*fcall[t])(fs, r, f);
7047dd7cddfSDavid du Colombier }
7057dd7cddfSDavid du Colombier }
7067dd7cddfSDavid du Colombier
7077dd7cddfSDavid du Colombier Fid*
fsgetfid(Fs * fs,int fid)7087dd7cddfSDavid du Colombier fsgetfid(Fs *fs, int fid)
7097dd7cddfSDavid du Colombier {
7107dd7cddfSDavid du Colombier Fid *f, *nf;
7117dd7cddfSDavid du Colombier
7127dd7cddfSDavid du Colombier lock(fs);
7137dd7cddfSDavid du Colombier for(f = fs->hash[fid%Nhash]; f; f = f->next){
7147dd7cddfSDavid du Colombier if(f->fid == fid){
7157dd7cddfSDavid du Colombier f->ref++;
7167dd7cddfSDavid du Colombier unlock(fs);
7177dd7cddfSDavid du Colombier return f;
7187dd7cddfSDavid du Colombier }
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier
7217dd7cddfSDavid du Colombier nf = emalloc(sizeof(Fid));
7227dd7cddfSDavid du Colombier nf->next = fs->hash[fid%Nhash];
7237dd7cddfSDavid du Colombier fs->hash[fid%Nhash] = nf;
7247dd7cddfSDavid du Colombier nf->fid = fid;
7257dd7cddfSDavid du Colombier nf->ref = 1;
7267dd7cddfSDavid du Colombier nf->wp = nf->buf;
7277dd7cddfSDavid du Colombier nf->rp = nf->wp;
7287dd7cddfSDavid du Colombier unlock(fs);
7297dd7cddfSDavid du Colombier return nf;
7307dd7cddfSDavid du Colombier }
7317dd7cddfSDavid du Colombier
7327dd7cddfSDavid du Colombier void
fsputfid(Fs * fs,Fid * f)7337dd7cddfSDavid du Colombier fsputfid(Fs *fs, Fid *f)
7347dd7cddfSDavid du Colombier {
7357dd7cddfSDavid du Colombier Fid **l, *nf;
7367dd7cddfSDavid du Colombier
7377dd7cddfSDavid du Colombier lock(fs);
7387dd7cddfSDavid du Colombier if(--f->ref > 0){
7397dd7cddfSDavid du Colombier unlock(fs);
7407dd7cddfSDavid du Colombier return;
7417dd7cddfSDavid du Colombier }
7427dd7cddfSDavid du Colombier for(l = &fs->hash[f->fid%Nhash]; nf = *l; l = &nf->next)
7437dd7cddfSDavid du Colombier if(nf == f){
7447dd7cddfSDavid du Colombier *l = f->next;
7457dd7cddfSDavid du Colombier break;
7467dd7cddfSDavid du Colombier }
7477dd7cddfSDavid du Colombier unlock(fs);
7489a747e4fSDavid du Colombier free(f->user);
7497dd7cddfSDavid du Colombier free(f);
7507dd7cddfSDavid du Colombier }
7517dd7cddfSDavid du Colombier
7527dd7cddfSDavid du Colombier void
fsauth(Fs * fs,Request * r,Fid *)7539a747e4fSDavid du Colombier fsauth(Fs *fs, Request *r, Fid*)
7547dd7cddfSDavid du Colombier {
7559a747e4fSDavid du Colombier fsreply(fs, r, "consolefs: authentication not required");
7567dd7cddfSDavid du Colombier }
7577dd7cddfSDavid du Colombier
7587dd7cddfSDavid du Colombier void
fsversion(Fs * fs,Request * r,Fid *)7599a747e4fSDavid du Colombier fsversion(Fs *fs, Request *r, Fid*)
7607dd7cddfSDavid du Colombier {
7619a747e4fSDavid du Colombier
7629a747e4fSDavid du Colombier if(r->f.msize < 256){
7639a747e4fSDavid du Colombier fsreply(fs, r, "message size too small");
7649a747e4fSDavid du Colombier return;
7659a747e4fSDavid du Colombier }
7669a747e4fSDavid du Colombier messagesize = r->f.msize;
7679a747e4fSDavid du Colombier if(messagesize > 8192+IOHDRSZ)
7689a747e4fSDavid du Colombier messagesize = 8192+IOHDRSZ;
7699a747e4fSDavid du Colombier r->f.msize = messagesize;
7709a747e4fSDavid du Colombier if(strncmp(r->f.version, "9P2000", 6) != 0){
7719a747e4fSDavid du Colombier fsreply(fs, r, "unrecognized 9P version");
7729a747e4fSDavid du Colombier return;
7739a747e4fSDavid du Colombier }
7749a747e4fSDavid du Colombier r->f.version = "9P2000";
7757dd7cddfSDavid du Colombier
7767dd7cddfSDavid du Colombier fsreply(fs, r, nil);
7777dd7cddfSDavid du Colombier }
7787dd7cddfSDavid du Colombier
7797dd7cddfSDavid du Colombier void
fsflush(Fs * fs,Request * r,Fid * f)7807dd7cddfSDavid du Colombier fsflush(Fs *fs, Request *r, Fid *f)
7817dd7cddfSDavid du Colombier {
7827dd7cddfSDavid du Colombier Request *or;
7837dd7cddfSDavid du Colombier
7847dd7cddfSDavid du Colombier or = remtag(&f->r, r->f.oldtag);
7857dd7cddfSDavid du Colombier if(or != nil){
7867dd7cddfSDavid du Colombier fsputfid(fs, or->fid);
7877dd7cddfSDavid du Colombier free(or);
7887dd7cddfSDavid du Colombier }
7897dd7cddfSDavid du Colombier fsreply(fs, r, nil);
7907dd7cddfSDavid du Colombier }
7917dd7cddfSDavid du Colombier
7927dd7cddfSDavid du Colombier void
fsattach(Fs * fs,Request * r,Fid * f)7937dd7cddfSDavid du Colombier fsattach(Fs *fs, Request *r, Fid *f)
7947dd7cddfSDavid du Colombier {
7959a747e4fSDavid du Colombier f->qid.type = QTDIR;
7969a747e4fSDavid du Colombier f->qid.path = QID(0, Ttopdir);
7979a747e4fSDavid du Colombier f->qid.vers = 0;
7987dd7cddfSDavid du Colombier
7997dd7cddfSDavid du Colombier if(r->f.uname[0])
8009a747e4fSDavid du Colombier f->user = strdup(r->f.uname);
8017dd7cddfSDavid du Colombier else
8029a747e4fSDavid du Colombier f->user = strdup("none");
8037dd7cddfSDavid du Colombier
8047dd7cddfSDavid du Colombier /* hold down the fid till the clunk */
8057dd7cddfSDavid du Colombier f->attached = 1;
8067dd7cddfSDavid du Colombier lock(fs);
8077dd7cddfSDavid du Colombier f->ref++;
8087dd7cddfSDavid du Colombier unlock(fs);
8097dd7cddfSDavid du Colombier
8107dd7cddfSDavid du Colombier r->f.qid = f->qid;
8117dd7cddfSDavid du Colombier fsreply(fs, r, nil);
8127dd7cddfSDavid du Colombier }
8137dd7cddfSDavid du Colombier
8147dd7cddfSDavid du Colombier void
fswalk(Fs * fs,Request * r,Fid * f)8157dd7cddfSDavid du Colombier fswalk(Fs *fs, Request *r, Fid *f)
8167dd7cddfSDavid du Colombier {
8177dd7cddfSDavid du Colombier char *name;
8187dd7cddfSDavid du Colombier Dir d;
819cb3cefd4SDavid du Colombier int i, n, nqid, nwname;
8209a747e4fSDavid du Colombier Qid qid, wqid[MAXWELEM];
8219a747e4fSDavid du Colombier Fid *nf;
8229a747e4fSDavid du Colombier char *err;
8237dd7cddfSDavid du Colombier
8247dd7cddfSDavid du Colombier if(f->attached == 0){
8257dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
8267dd7cddfSDavid du Colombier return;
8277dd7cddfSDavid du Colombier }
8287dd7cddfSDavid du Colombier
8299a747e4fSDavid du Colombier nf = nil;
8309a747e4fSDavid du Colombier if(r->f.fid != r->f.newfid){
8319a747e4fSDavid du Colombier nf = fsgetfid(fs, r->f.newfid);
8329a747e4fSDavid du Colombier nf->attached = f->attached;
8339a747e4fSDavid du Colombier nf->open = f->open;
8349a747e4fSDavid du Colombier nf->qid = f->qid;
8359a747e4fSDavid du Colombier nf->user = strdup(f->user);
8369a747e4fSDavid du Colombier nf->c = f->c;
8379a747e4fSDavid du Colombier nf->wp = nf->buf;
8389a747e4fSDavid du Colombier nf->rp = nf->wp;
8399a747e4fSDavid du Colombier f = nf;
8409a747e4fSDavid du Colombier }
8419a747e4fSDavid du Colombier
8429a747e4fSDavid du Colombier qid = f->qid;
8439a747e4fSDavid du Colombier err = nil;
8449a747e4fSDavid du Colombier nwname = r->f.nwname;
8459a747e4fSDavid du Colombier nqid = 0;
8469a747e4fSDavid du Colombier if(nwname > 0){
8479a747e4fSDavid du Colombier for(; err == nil && nqid < nwname; nqid++){
8489a747e4fSDavid du Colombier if(nqid >= MAXWELEM){
8499a747e4fSDavid du Colombier err = "too many name elements";
8509a747e4fSDavid du Colombier break;
8519a747e4fSDavid du Colombier }
8529a747e4fSDavid du Colombier name = r->f.wname[nqid];
8537dd7cddfSDavid du Colombier if(strcmp(name, "..") == 0)
8549a747e4fSDavid du Colombier qid = parentqid(qid);
8557dd7cddfSDavid du Colombier else if(strcmp(name, ".") != 0){
8567dd7cddfSDavid du Colombier for(i = 0; ; i++){
857cb3cefd4SDavid du Colombier n = fsdirgen(fs, qid, i, &d, nil, 0);
858cb3cefd4SDavid du Colombier if(n < 0){
8599a747e4fSDavid du Colombier err = Eexist;
8609a747e4fSDavid du Colombier break;
8617dd7cddfSDavid du Colombier }
862cb3cefd4SDavid du Colombier if(n > 0 && strcmp(name, d.name) == 0){
8639a747e4fSDavid du Colombier qid = d.qid;
8647dd7cddfSDavid du Colombier break;
8657dd7cddfSDavid du Colombier }
8667dd7cddfSDavid du Colombier }
8677dd7cddfSDavid du Colombier }
8689a747e4fSDavid du Colombier wqid[nqid] = qid;
8699a747e4fSDavid du Colombier }
8709a747e4fSDavid du Colombier if(nf != nil && nqid < nwname)
8719a747e4fSDavid du Colombier fsputfid(fs, nf);
8729a747e4fSDavid du Colombier if(nqid == nwname)
8739a747e4fSDavid du Colombier f->qid = qid;
8749a747e4fSDavid du Colombier }
8759a747e4fSDavid du Colombier
8769a747e4fSDavid du Colombier memmove(r->f.wqid, wqid, nqid*sizeof(Qid));
8779a747e4fSDavid du Colombier r->f.nwqid = nqid;
8789a747e4fSDavid du Colombier fsreply(fs, r, err);
8797dd7cddfSDavid du Colombier }
8807dd7cddfSDavid du Colombier
8817dd7cddfSDavid du Colombier int
ingroup(char * user,char * group)8827dd7cddfSDavid du Colombier ingroup(char *user, char *group)
8837dd7cddfSDavid du Colombier {
8847dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
8857dd7cddfSDavid du Colombier Ndbs s;
8867dd7cddfSDavid du Colombier
8877dd7cddfSDavid du Colombier t = ndbsearch(db, &s, "group", group);
8887dd7cddfSDavid du Colombier if(t == nil)
8897dd7cddfSDavid du Colombier return 0;
8907dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){
8917dd7cddfSDavid du Colombier if(strcmp(nt->attr, "uid") == 0)
8927dd7cddfSDavid du Colombier if(strcmp(nt->val, user) == 0)
8937dd7cddfSDavid du Colombier break;
8947dd7cddfSDavid du Colombier }
8957dd7cddfSDavid du Colombier ndbfree(t);
8967dd7cddfSDavid du Colombier return nt != nil;
8977dd7cddfSDavid du Colombier }
8987dd7cddfSDavid du Colombier
8997dd7cddfSDavid du Colombier int
userok(char * u,char * cname)9007dd7cddfSDavid du Colombier userok(char *u, char *cname)
9017dd7cddfSDavid du Colombier {
9027dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
9037dd7cddfSDavid du Colombier Ndbs s;
9047dd7cddfSDavid du Colombier
9057dd7cddfSDavid du Colombier t = ndbsearch(db, &s, "console", cname);
9067dd7cddfSDavid du Colombier if(t == nil)
9077dd7cddfSDavid du Colombier return 0;
9087dd7cddfSDavid du Colombier
9097dd7cddfSDavid du Colombier for(nt = t; nt; nt = nt->entry){
9107dd7cddfSDavid du Colombier if(strcmp(nt->attr, "uid") == 0)
9117dd7cddfSDavid du Colombier if(strcmp(nt->val, u) == 0)
9127dd7cddfSDavid du Colombier break;
9137dd7cddfSDavid du Colombier if(strcmp(nt->attr, "gid") == 0)
9147dd7cddfSDavid du Colombier if(ingroup(u, nt->val))
9157dd7cddfSDavid du Colombier break;
9167dd7cddfSDavid du Colombier }
9177dd7cddfSDavid du Colombier ndbfree(t);
9188bc54264SDavid du Colombier
9197dd7cddfSDavid du Colombier return nt != nil;
9207dd7cddfSDavid du Colombier }
9217dd7cddfSDavid du Colombier
9227dd7cddfSDavid du Colombier int m2p[] ={
9237dd7cddfSDavid du Colombier [OREAD] 4,
9247dd7cddfSDavid du Colombier [OWRITE] 2,
9257dd7cddfSDavid du Colombier [ORDWR] 6
9267dd7cddfSDavid du Colombier };
9277dd7cddfSDavid du Colombier
9288bc54264SDavid du Colombier /*
9298bc54264SDavid du Colombier * broadcast a message to all listeners
9308bc54264SDavid du Colombier */
9318bc54264SDavid du Colombier void
bcastmsg(Fs * fs,Console * c,char * msg,int n)9328bc54264SDavid du Colombier bcastmsg(Fs *fs, Console *c, char *msg, int n)
9338bc54264SDavid du Colombier {
9348bc54264SDavid du Colombier Fid *fl;
9358bc54264SDavid du Colombier
9368bc54264SDavid du Colombier for(fl = c->flist; fl; fl = fl->cnext){
9378bc54264SDavid du Colombier fromconsole(fl, msg, n);
9388bc54264SDavid du Colombier fskick(fs, fl);
9398bc54264SDavid du Colombier }
9408bc54264SDavid du Colombier }
9418bc54264SDavid du Colombier
9427dd7cddfSDavid du Colombier void
fsopen(Fs * fs,Request * r,Fid * f)9437dd7cddfSDavid du Colombier fsopen(Fs *fs, Request *r, Fid *f)
9447dd7cddfSDavid du Colombier {
9457dd7cddfSDavid du Colombier int mode;
9467dd7cddfSDavid du Colombier Console *c;
9477dd7cddfSDavid du Colombier
9487dd7cddfSDavid du Colombier if(f->attached == 0){
9497dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
9507dd7cddfSDavid du Colombier return;
9517dd7cddfSDavid du Colombier }
9527dd7cddfSDavid du Colombier
9537dd7cddfSDavid du Colombier if(f->open){
9547dd7cddfSDavid du Colombier fsreply(fs, r, Eisopen);
9557dd7cddfSDavid du Colombier return;
9567dd7cddfSDavid du Colombier }
9577dd7cddfSDavid du Colombier
9587dd7cddfSDavid du Colombier mode = r->f.mode & 3;
9597dd7cddfSDavid du Colombier
9609a747e4fSDavid du Colombier if((QTDIR & f->qid.type) && mode != OREAD){
9617dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
9627dd7cddfSDavid du Colombier return;
9637dd7cddfSDavid du Colombier }
9647dd7cddfSDavid du Colombier
9657dd7cddfSDavid du Colombier switch(TYPE(f->qid)){
9667dd7cddfSDavid du Colombier case Qdata:
9677dd7cddfSDavid du Colombier c = fs->cons[CONS(f->qid)];
9687dd7cddfSDavid du Colombier if(!userok(f->user, c->name)){
9697dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
9707dd7cddfSDavid du Colombier return;
9717dd7cddfSDavid du Colombier }
9727dd7cddfSDavid du Colombier f->rp = f->buf;
9737dd7cddfSDavid du Colombier f->wp = f->buf;
9747dd7cddfSDavid du Colombier f->c = c;
9757dd7cddfSDavid du Colombier lock(c);
9768bc54264SDavid du Colombier sprint(f->mbuf, "[%s] ", f->user);
9778bc54264SDavid du Colombier f->bufn = strlen(f->mbuf);
9788bc54264SDavid du Colombier f->used = 0;
9797dd7cddfSDavid du Colombier f->cnext = c->flist;
9807dd7cddfSDavid du Colombier c->flist = f;
9817dd7cddfSDavid du Colombier bcastmembers(fs, c, "+", f);
9827dd7cddfSDavid du Colombier if(c->pid == 0)
9837dd7cddfSDavid du Colombier fsreopen(fs, c);
9847dd7cddfSDavid du Colombier unlock(c);
9857dd7cddfSDavid du Colombier break;
9867dd7cddfSDavid du Colombier case Qctl:
9877dd7cddfSDavid du Colombier c = fs->cons[CONS(f->qid)];
9887dd7cddfSDavid du Colombier if(!userok(f->user, c->name)){
9897dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
9907dd7cddfSDavid du Colombier return;
9917dd7cddfSDavid du Colombier }
9927dd7cddfSDavid du Colombier f->c = c;
9937dd7cddfSDavid du Colombier break;
9947dd7cddfSDavid du Colombier case Qstat:
9957dd7cddfSDavid du Colombier c = fs->cons[CONS(f->qid)];
9967dd7cddfSDavid du Colombier if(!userok(f->user, c->name)){
9977dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
9987dd7cddfSDavid du Colombier return;
9997dd7cddfSDavid du Colombier }
10007dd7cddfSDavid du Colombier f->c = c;
10017dd7cddfSDavid du Colombier break;
10027dd7cddfSDavid du Colombier }
10037dd7cddfSDavid du Colombier
10047dd7cddfSDavid du Colombier f->open = 1;
10059a747e4fSDavid du Colombier r->f.iounit = messagesize-IOHDRSZ;
10067dd7cddfSDavid du Colombier r->f.qid = f->qid;
10077dd7cddfSDavid du Colombier fsreply(fs, r, nil);
10087dd7cddfSDavid du Colombier }
10097dd7cddfSDavid du Colombier
10107dd7cddfSDavid du Colombier void
fscreate(Fs * fs,Request * r,Fid *)10117dd7cddfSDavid du Colombier fscreate(Fs *fs, Request *r, Fid*)
10127dd7cddfSDavid du Colombier {
10137dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
10147dd7cddfSDavid du Colombier }
10157dd7cddfSDavid du Colombier
10167dd7cddfSDavid du Colombier void
fsread(Fs * fs,Request * r,Fid * f)10177dd7cddfSDavid du Colombier fsread(Fs *fs, Request *r, Fid *f)
10187dd7cddfSDavid du Colombier {
10199a747e4fSDavid du Colombier uchar *p, *e;
10209a747e4fSDavid du Colombier int i, m, off;
10219a747e4fSDavid du Colombier vlong offset;
10227dd7cddfSDavid du Colombier Dir d;
10239a747e4fSDavid du Colombier char sbuf[ERRMAX];
10247dd7cddfSDavid du Colombier
10257dd7cddfSDavid du Colombier if(f->attached == 0){
10267dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
10277dd7cddfSDavid du Colombier return;
10287dd7cddfSDavid du Colombier }
10297dd7cddfSDavid du Colombier
103022a127bbSDavid du Colombier if((int)r->f.count < 0){
10317dd7cddfSDavid du Colombier fsreply(fs, r, Ebadcount);
10327dd7cddfSDavid du Colombier return;
10337dd7cddfSDavid du Colombier }
10347dd7cddfSDavid du Colombier
10359a747e4fSDavid du Colombier if(QTDIR & f->qid.type){
10369a747e4fSDavid du Colombier p = r->buf + IOHDRSZ;
10379a747e4fSDavid du Colombier e = p + r->f.count;
10389a747e4fSDavid du Colombier offset = r->f.offset;
10399a747e4fSDavid du Colombier off = 0;
10409a747e4fSDavid du Colombier for(i=0; p<e; i++, off+=m){
10419a747e4fSDavid du Colombier m = fsdirgen(fs, f->qid, i, &d, p, e-p);
1042cb3cefd4SDavid du Colombier if(m < 0)
10437dd7cddfSDavid du Colombier break;
1044cb3cefd4SDavid du Colombier if(m > BIT16SZ && off >= offset)
10459a747e4fSDavid du Colombier p += m;
10467dd7cddfSDavid du Colombier }
10479a747e4fSDavid du Colombier r->f.data = (char*)r->buf + IOHDRSZ;
10489a747e4fSDavid du Colombier r->f.count = (char*)p - r->f.data;
10497dd7cddfSDavid du Colombier } else {
10507dd7cddfSDavid du Colombier switch(TYPE(f->qid)){
10517dd7cddfSDavid du Colombier case Qdata:
10527dd7cddfSDavid du Colombier addreq(&f->r, r);
10537dd7cddfSDavid du Colombier fskick(fs, f);
10547dd7cddfSDavid du Colombier return;
10557dd7cddfSDavid du Colombier case Qctl:
10569a747e4fSDavid du Colombier r->f.data = (char*)r->buf+IOHDRSZ;
10577dd7cddfSDavid du Colombier r->f.count = 0;
10587dd7cddfSDavid du Colombier break;
10597dd7cddfSDavid du Colombier case Qstat:
10607dd7cddfSDavid du Colombier if(r->f.count > sizeof(sbuf))
10617dd7cddfSDavid du Colombier r->f.count = sizeof(sbuf);
10629a747e4fSDavid du Colombier i = pread(f->c->sfd, sbuf, r->f.count, r->f.offset);
10637dd7cddfSDavid du Colombier if(i < 0){
10649a747e4fSDavid du Colombier errstr(sbuf, sizeof sbuf);
10657dd7cddfSDavid du Colombier fsreply(fs, r, sbuf);
10667dd7cddfSDavid du Colombier return;
10677dd7cddfSDavid du Colombier }
10687dd7cddfSDavid du Colombier r->f.data = sbuf;
10697dd7cddfSDavid du Colombier r->f.count = i;
10707dd7cddfSDavid du Colombier break;
10717dd7cddfSDavid du Colombier default:
10727dd7cddfSDavid du Colombier fsreply(fs, r, Eexist);
10737dd7cddfSDavid du Colombier return;
10747dd7cddfSDavid du Colombier }
10757dd7cddfSDavid du Colombier }
10767dd7cddfSDavid du Colombier fsreply(fs, r, nil);
10777dd7cddfSDavid du Colombier }
10787dd7cddfSDavid du Colombier
10797dd7cddfSDavid du Colombier void
fswrite(Fs * fs,Request * r,Fid * f)10807dd7cddfSDavid du Colombier fswrite(Fs *fs, Request *r, Fid *f)
10817dd7cddfSDavid du Colombier {
10828bc54264SDavid du Colombier int i, eol = 0;
10837dd7cddfSDavid du Colombier
10847dd7cddfSDavid du Colombier if(f->attached == 0){
10857dd7cddfSDavid du Colombier fsreply(fs, r, Enofid);
10867dd7cddfSDavid du Colombier return;
10877dd7cddfSDavid du Colombier }
10887dd7cddfSDavid du Colombier
108922a127bbSDavid du Colombier if((int)r->f.count < 0){
10907dd7cddfSDavid du Colombier fsreply(fs, r, Ebadcount);
10917dd7cddfSDavid du Colombier return;
10927dd7cddfSDavid du Colombier }
10937dd7cddfSDavid du Colombier
10949a747e4fSDavid du Colombier if(QTDIR & f->qid.type){
10957dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
10967dd7cddfSDavid du Colombier return;
10977dd7cddfSDavid du Colombier }
10987dd7cddfSDavid du Colombier
10997dd7cddfSDavid du Colombier switch(TYPE(f->qid)){
11007dd7cddfSDavid du Colombier default:
11017dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
11027dd7cddfSDavid du Colombier return;
11037dd7cddfSDavid du Colombier case Qctl:
11047dd7cddfSDavid du Colombier write(f->c->cfd, r->f.data, r->f.count);
11057dd7cddfSDavid du Colombier break;
11067dd7cddfSDavid du Colombier case Qdata:
11078bc54264SDavid du Colombier for(i = 0; i < r->f.count; i++){
11088bc54264SDavid du Colombier if(r->f.data[i] == '\n'){
11098bc54264SDavid du Colombier if(f->c->chat && f->used)
11108bc54264SDavid du Colombier eol = 1;
11117dd7cddfSDavid du Colombier if(f->c->cronly)
11127dd7cddfSDavid du Colombier r->f.data[i] = '\r';
11138bc54264SDavid du Colombier }
11148bc54264SDavid du Colombier else
11158bc54264SDavid du Colombier f->used = 1;
11168bc54264SDavid du Colombier }
11178bc54264SDavid du Colombier if(f->c->chat){
11188bc54264SDavid du Colombier fskick(fs, f);
11198bc54264SDavid du Colombier if(!f->used)
11208bc54264SDavid du Colombier break;
11218bc54264SDavid du Colombier
11228bc54264SDavid du Colombier if(f->bufn + r->f.count > Bufsize){
11238bc54264SDavid du Colombier r->f.count -= (f->bufn + r->f.count) % Bufsize;
11248bc54264SDavid du Colombier eol = 1;
11258bc54264SDavid du Colombier }
11268bc54264SDavid du Colombier strncat(f->mbuf, r->f.data, r->f.count);
11278bc54264SDavid du Colombier f->bufn += r->f.count;
11288bc54264SDavid du Colombier if(eol){
11298bc54264SDavid du Colombier bcastmsg(fs, f->c, f->mbuf, f->bufn);
11308bc54264SDavid du Colombier sprint(f->mbuf, "[%s] ", f->user);
11318bc54264SDavid du Colombier f->bufn = strlen(f->mbuf);
11328bc54264SDavid du Colombier f->used = 0;
11338bc54264SDavid du Colombier }
11348bc54264SDavid du Colombier }
11358bc54264SDavid du Colombier else
11367dd7cddfSDavid du Colombier write(f->c->fd, r->f.data, r->f.count);
11377dd7cddfSDavid du Colombier break;
11387dd7cddfSDavid du Colombier }
11397dd7cddfSDavid du Colombier fsreply(fs, r, nil);
11407dd7cddfSDavid du Colombier }
11417dd7cddfSDavid du Colombier
11427dd7cddfSDavid du Colombier void
fsclunk(Fs * fs,Request * r,Fid * f)11437dd7cddfSDavid du Colombier fsclunk(Fs *fs, Request *r, Fid *f)
11447dd7cddfSDavid du Colombier {
11457dd7cddfSDavid du Colombier Fid **l, *fl;
11467dd7cddfSDavid du Colombier Request *nr;
11477dd7cddfSDavid du Colombier
11487dd7cddfSDavid du Colombier if(f->open && TYPE(f->qid) == Qdata){
11497dd7cddfSDavid du Colombier while((nr = remreq(&f->r)) != nil){
11507dd7cddfSDavid du Colombier fsputfid(fs, f);
11517dd7cddfSDavid du Colombier free(nr);
11527dd7cddfSDavid du Colombier }
11537dd7cddfSDavid du Colombier
11547dd7cddfSDavid du Colombier lock(f->c);
11557dd7cddfSDavid du Colombier for(l = &f->c->flist; *l; l = &fl->cnext){
11567dd7cddfSDavid du Colombier fl = *l;
11577dd7cddfSDavid du Colombier if(fl == f){
11587dd7cddfSDavid du Colombier *l = fl->cnext;
11597dd7cddfSDavid du Colombier break;
11607dd7cddfSDavid du Colombier }
11617dd7cddfSDavid du Colombier }
11627dd7cddfSDavid du Colombier bcastmembers(fs, f->c, "-", f);
11637dd7cddfSDavid du Colombier if(f->c->ondemand && f->c->flist == nil)
11647dd7cddfSDavid du Colombier fsreopen(fs, f->c);
11657dd7cddfSDavid du Colombier unlock(f->c);
11667dd7cddfSDavid du Colombier }
11677dd7cddfSDavid du Colombier fsreply(fs, r, nil);
11687dd7cddfSDavid du Colombier fsputfid(fs, f);
11697dd7cddfSDavid du Colombier }
11707dd7cddfSDavid du Colombier
11717dd7cddfSDavid du Colombier void
fsremove(Fs * fs,Request * r,Fid *)11727dd7cddfSDavid du Colombier fsremove(Fs *fs, Request *r, Fid*)
11737dd7cddfSDavid du Colombier {
11747dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
11757dd7cddfSDavid du Colombier }
11767dd7cddfSDavid du Colombier
11777dd7cddfSDavid du Colombier void
fsstat(Fs * fs,Request * r,Fid * f)11787dd7cddfSDavid du Colombier fsstat(Fs *fs, Request *r, Fid *f)
11797dd7cddfSDavid du Colombier {
118022a127bbSDavid du Colombier int i, n;
11817dd7cddfSDavid du Colombier Qid q;
11827dd7cddfSDavid du Colombier Dir d;
11837dd7cddfSDavid du Colombier
11847dd7cddfSDavid du Colombier q = parentqid(f->qid);
11857dd7cddfSDavid du Colombier for(i = 0; ; i++){
11869a747e4fSDavid du Colombier r->f.stat = r->buf+IOHDRSZ;
118722a127bbSDavid du Colombier n = fsdirgen(fs, q, i, &d, r->f.stat, messagesize-IOHDRSZ);
118822a127bbSDavid du Colombier if(n < 0){
11897dd7cddfSDavid du Colombier fsreply(fs, r, Eexist);
11907dd7cddfSDavid du Colombier return;
11917dd7cddfSDavid du Colombier }
119222a127bbSDavid du Colombier r->f.nstat = n;
1193cb3cefd4SDavid du Colombier if(r->f.nstat > BIT16SZ && d.qid.path == f->qid.path)
11947dd7cddfSDavid du Colombier break;
11957dd7cddfSDavid du Colombier }
11967dd7cddfSDavid du Colombier fsreply(fs, r, nil);
11977dd7cddfSDavid du Colombier }
11987dd7cddfSDavid du Colombier
11997dd7cddfSDavid du Colombier void
fswstat(Fs * fs,Request * r,Fid *)12007dd7cddfSDavid du Colombier fswstat(Fs *fs, Request *r, Fid*)
12017dd7cddfSDavid du Colombier {
12027dd7cddfSDavid du Colombier fsreply(fs, r, Eperm);
12037dd7cddfSDavid du Colombier }
12047dd7cddfSDavid du Colombier
12057dd7cddfSDavid du Colombier void
fsreply(Fs * fs,Request * r,char * err)12067dd7cddfSDavid du Colombier fsreply(Fs *fs, Request *r, char *err)
12077dd7cddfSDavid du Colombier {
12087dd7cddfSDavid du Colombier int n;
12099a747e4fSDavid du Colombier uchar buf[8192+IOHDRSZ];
12107dd7cddfSDavid du Colombier
12117dd7cddfSDavid du Colombier if(err){
12127dd7cddfSDavid du Colombier r->f.type = Rerror;
12139a747e4fSDavid du Colombier r->f.ename = err;
12147dd7cddfSDavid du Colombier }
12159a747e4fSDavid du Colombier n = convS2M(&r->f, buf, messagesize);
12167dd7cddfSDavid du Colombier if(debug)
12179a747e4fSDavid du Colombier fprint(2, "%F path %llux n=%d\n", &r->f, r->fid->qid.path, n);
12187dd7cddfSDavid du Colombier fsputfid(fs, r->fid);
12199a747e4fSDavid du Colombier if(write(fs->fd, buf, n) != n)
12207dd7cddfSDavid du Colombier fatal("unmounted");
12217dd7cddfSDavid du Colombier free(r);
12227dd7cddfSDavid du Colombier }
12237dd7cddfSDavid du Colombier
12247dd7cddfSDavid du Colombier /*
12257dd7cddfSDavid du Colombier * called whenever input or a read request has been received
12267dd7cddfSDavid du Colombier */
12277dd7cddfSDavid du Colombier void
fskick(Fs * fs,Fid * f)12287dd7cddfSDavid du Colombier fskick(Fs *fs, Fid *f)
12297dd7cddfSDavid du Colombier {
12307dd7cddfSDavid du Colombier Request *r;
12317dd7cddfSDavid du Colombier char *p, *rp, *wp, *ep;
12327dd7cddfSDavid du Colombier int i;
12337dd7cddfSDavid du Colombier
12347dd7cddfSDavid du Colombier lock(f);
12357dd7cddfSDavid du Colombier while(f->rp != f->wp){
12367dd7cddfSDavid du Colombier r = remreq(&f->r);
12377dd7cddfSDavid du Colombier if(r == nil)
12387dd7cddfSDavid du Colombier break;
12399a747e4fSDavid du Colombier p = (char*)r->buf;
12407dd7cddfSDavid du Colombier rp = f->rp;
12417dd7cddfSDavid du Colombier wp = f->wp;
12427dd7cddfSDavid du Colombier ep = &f->buf[Bufsize];
12437dd7cddfSDavid du Colombier for(i = 0; i < r->f.count && rp != wp; i++){
12447dd7cddfSDavid du Colombier *p++ = *rp++;
12457dd7cddfSDavid du Colombier if(rp >= ep)
12467dd7cddfSDavid du Colombier rp = f->buf;
12477dd7cddfSDavid du Colombier }
12487dd7cddfSDavid du Colombier f->rp = rp;
12499a747e4fSDavid du Colombier r->f.data = (char*)r->buf;
12509a747e4fSDavid du Colombier r->f.count = p - (char*)r->buf;
12517dd7cddfSDavid du Colombier fsreply(fs, r, nil);
12527dd7cddfSDavid du Colombier }
12537dd7cddfSDavid du Colombier unlock(f);
12547dd7cddfSDavid du Colombier }
12557dd7cddfSDavid du Colombier
12567dd7cddfSDavid du Colombier void
usage(void)12577dd7cddfSDavid du Colombier usage(void)
12587dd7cddfSDavid du Colombier {
12597dd7cddfSDavid du Colombier fprint(2, "usage: consolefs [-d] [-m mount-point] [-c console-db]\n");
12607dd7cddfSDavid du Colombier threadexitsall("usage");
12617dd7cddfSDavid du Colombier }
12627dd7cddfSDavid du Colombier
12637dd7cddfSDavid du Colombier void
threadmain(int argc,char ** argv)12647dd7cddfSDavid du Colombier threadmain(int argc, char **argv)
12657dd7cddfSDavid du Colombier {
1266*8498559bSDavid du Colombier rfork(RFNOTEG);
12679a747e4fSDavid du Colombier fmtinstall('F', fcallfmt);
12687dd7cddfSDavid du Colombier
12697dd7cddfSDavid du Colombier ARGBEGIN{
12707dd7cddfSDavid du Colombier case 'd':
12717dd7cddfSDavid du Colombier debug++;
12727dd7cddfSDavid du Colombier break;
12737dd7cddfSDavid du Colombier case 'c':
12747dd7cddfSDavid du Colombier consoledb = ARGF();
12757dd7cddfSDavid du Colombier if(consoledb == nil)
12767dd7cddfSDavid du Colombier usage();
12777dd7cddfSDavid du Colombier break;
12787dd7cddfSDavid du Colombier case 'm':
12797dd7cddfSDavid du Colombier mntpt = ARGF();
12807dd7cddfSDavid du Colombier if(mntpt == nil)
12817dd7cddfSDavid du Colombier usage();
12827dd7cddfSDavid du Colombier break;
12837dd7cddfSDavid du Colombier }ARGEND;
12847dd7cddfSDavid du Colombier
12857dd7cddfSDavid du Colombier db = ndbopen(consoledb);
12867dd7cddfSDavid du Colombier if(db == nil)
12877dd7cddfSDavid du Colombier fatal("can't open %s: %r", consoledb);
12887dd7cddfSDavid du Colombier
12897dd7cddfSDavid du Colombier fsmount(mntpt);
12907dd7cddfSDavid du Colombier }
1291