Anyway, it's here:
        % mk install
        % watchfs main.c

"cat /n/watch/ctl" will block until a change has been made
to /n/watch/data/main.c.

KNOWN BUGS:
        - it doesn't care about Tflush yet.
        - it only accepts files in the current directory.


# To unbundle, run this file
echo mkfile
sed 's/.//' >mkfile <<'//GO.SYSIN DD mkfile'
-</$objtype/mkfile
-BIN=$home/bin/$objtype
-
-TARG=watchfs
-OFILES=\
-       main.$O\
-
-</sys/src/cmd/mkone
//GO.SYSIN DD mkfile
echo main.c
sed 's/.//' >main.c <<'//GO.SYSIN DD main.c'
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include <thread.h>
-#include <9p.h>
-
-int dbg;
-
-char *uname;
-Channel *cctl, *cctlwait;
-Channel *pctl, *pctlwait;
-Channel *creq;
-
-typedef struct Watchfile       Watchfile;
-struct Watchfile {
-       Ref;
-       Qid qid;
-       int fd;
-       char *name;
-       int dirty;
-};
-
-Watchfile wtab[10];
-int nw;
-
-void wtopen(Req*);
-void wtread(Req*);
-void wtwrite(Req*);
-void wtdestroyfid(Fid*);
-void takedown(Srv*);
-
-enum{
-       Qdata= 0,
-       Qctl= 1,
-
-       STACK = 8192,
-};
-
-int chatty9p;
-Srv fs = {
-       .open= wtopen,
-       .read= wtread,
-       .write= wtwrite,
-       .destroyfid = wtdestroyfid,
-       .end= takedown,
-};
-
-static void
-dumpQid(Dir *d)
-{
-       ulong path;
-       path = d->qid.path;
-       fprint(2, "name=%s qid=%lux\n", d->name, path);
-}
-
-static void
-dumpWF(void)
-{
-       int i;
-
-       for(i=0; i<nw; i++)
-               fprint(2, "dumpWF: %s %llud\n", wtab[i].name, wtab[i].qid.path);
-}      
-
-Watchfile *
-findtab(ulong path)
-{
-       int i;
-       for(i=0; i<nw; i++)
-               if(wtab[i].qid.path == path)
-                       return &wtab[i];
-       return nil;
-}
-
-void
-wtopen(Req *r)
-{
-       ulong path;
-       Watchfile *wf;
-
-       path = r->fid->qid.path;
-       switch(path){
-       case Qctl:
-       case Qdata:
-               respond(r, nil);
-               return;
-       }
-
-       /* data/... */
-       wf = findtab(path);
-       if(wf == nil){
-               respond(r, "no file");
-               return;
-       }
-       if(dbg)
-               fprint(2, "wtopen: %s %ld fd %d\n", wf->name, wf->ref, wf->fd);
-
-       incref(wf);
-       if(wf->fd < 0){
-               wf->fd = open(wf->name, r->ifcall.mode);
-               wf->dirty = 0;
-       }
-       if(r->ifcall.mode&OTRUNC)
-               r->fid->file->length = 0;
-       respond(r, nil);
-}
-
-void
-wtread(Req *r)
-{
-       char buf[512];
-       int n;
-       ulong path;
-       Watchfile *wf;
-
-       path = r->fid->qid.path;
-       switch(path){
-       case Qdata:
-       case Qctl:
-               sendp(creq, r);
-               return;
-       }
-
-       /* data/... */
-       wf = findtab(r->fid->qid.path);
-       if(wf == nil){
-               respond(r, "no such qid");
-               return;
-       }
-       if(wf->fd < 0){
-               respond(r, "no fd");
-               return;
-       }
-       if(dbg)
-               fprint(2, "wtread: %s ref %ld fd %d\n", wf->name, wf->ref, 
wf->fd);
-       n = pread(wf->fd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
-       if(n < 0){
-               rerrstr(buf, sizeof buf);
-               respond(r, buf);
-               return;
-       }
-       r->ofcall.count = n;
-       respond(r, nil);
-}
-
-void
-wtwrite(Req *r)
-{
-       char buf[512];
-       int n;
-       ulong path;
-       vlong offset;
-       Watchfile *wf;
-
-       path = r->fid->qid.path;
-       offset = r->ifcall.offset;
-
-       switch(path){
-       case Qdata:
-       case Qctl:
-               snprint(buf, sizeof buf, "not yet %lux", path);
-               respond(r, buf);
-               return;
-       }
-
-       /* data/... */
-       wf = findtab(path);
-       if(wf == nil){
-               respond(r, "no such qid");
-               return;
-       }
-       if(dbg)
-               fprint(2, "wtwrite: %s ref %ld fd %d\n", wf->name, wf->ref, 
wf->fd);
-
-       if(wf->fd < 0){
-               respond(r, "no fd");
-               return;
-       }
-
-       n = pwrite(wf->fd, r->ifcall.data, r->ifcall.count, r->ifcall.offset);
-       if(n < 0){
-               rerrstr(buf, sizeof buf);
-               respond(r, buf);
-               return;
-       }
-       if(n+offset >= r->fid->file->length)
-               r->fid->file->length = n+offset;
-       wf->dirty++;
-       r->ofcall.count = n;
-       respond(r, nil);
-
-}
-
-void
-wtdestroyfid(Fid *fid)
-{
-       ulong path;
-       Watchfile *wf;
-
-       path = fid->qid.path;
-       wf = findtab(path);
-       if(wf == nil)
-               return;
-
-       if(dbg)
-               fprint(2, "wtdestroyfid: %s ref %ld fd %d\n", wf->name, 
wf->ref, wf->fd);
-
-       if(wf->fd >= 0){
-               if(decref(wf) == 0){
-                       if(wf->dirty){
-                               sendp(cctl, wf);
-                               recvp(cctlwait);
-                       }
-                       close(wf->fd);
-                       wf->fd = -1;
-                       wf->dirty = 0;
-               }
-       }
-}
-
-Tree *
-inittree(char **argv)
-{
-       Tree *tree;
-       File *df;
-
-       tree = alloctree(uname, uname, DMDIR|0555, nil);
-       df = createfile(tree->root, "data", uname, DMDIR|0555, nil);
-       createfile(tree->root, "ctl", uname, 0660, nil);
-
-       for(;*argv;argv++){
-               File *f;
-               Dir *d;
-               d = dirstat(*argv);
-               if(d == nil)
-                       continue;
-               if(dbg)
-                       fprint(2, "dir: name %s len %lld\n", d->name, 
d->length);
-               f = createfile(df, *argv, uname, 0660, nil);
-               wtab[nw].qid = f->qid;
-               wtab[nw].name = estrdup9p(*argv);
-               wtab[nw].fd = -1;
-               f->length = d->length;
-               nw++;
-       }
-
-       return tree;
-}
-
-static void
-pollthread(void*)
-{
-       for(;;){
-               sleep(1);
-       }
-}
-
-static void
-ctlthread(void*)
-{
-       int i, np = 0;
-       Alt a[4];
-       Req *r, *rtab[10];
-       Watchfile *wf;
-
-       threadsetname("ctlthread");
-
-       a[0].op = CHANRCV;
-       a[0].c = creq;
-       a[0].v = &r;
-       a[1].op = CHANRCV;
-       a[1].c = cctl;
-       a[1].v = &wf;
-       a[2].op = CHANRCV;
-       a[2].c = pctl;
-       a[2].v = &wf;
-       a[3].op = CHANEND;
-
-       for(;;){
-               switch(alt(a)){
-               case 0: /* creq: someone tries to read ctl */
-                       rtab[np++] = r;
-                       break;
-
-               case 1: /* cctl: ready to serve ctl */
-                       for(i=0; i<np; i++){
-                               r = rtab[i];
-                               snprint(r->ofcall.data, r->ifcall.count,
-                                       "%s %llud\n", wf->name, wf->qid.path);
-                               r->ofcall.count = strlen(r->ofcall.data);
-                               respond(r, nil);
-                       }
-                       np = 0;
-                       sendp(cctlwait, 0);
-                       break;
-
-               case 2: /* pctl: poll says modified */
-                       for(i=0; i<np; i++){
-                               r = rtab[i];
-                               snprint(r->ofcall.data, r->ifcall.count,
-                                       "%s %llud\n", wf->name, wf->qid.path);
-                               r->ofcall.count = strlen(r->ofcall.data);
-                               respond(r, nil);
-                       }
-                       np = 0;
-                       sendp(pctlwait, 0);
-                       break;
-
-               default:
-                       break;
-               }
-       }
-}
-
-void
-initctl(void)
-{
-       cctl = chancreate(sizeof(void*), 0);
-       cctlwait = chancreate(sizeof(void*), 0);
-       pctl = chancreate(sizeof(void*), 0);
-       pctlwait = chancreate(sizeof(void*), 0);
-       creq = chancreate(sizeof(void*), 0);
-       procrfork(ctlthread, nil, STACK, RFNAMEG);
-       procrfork(pollthread, nil, STACK, RFNAMEG);
-}
-
-void
-usage(void)
-{
-       fprint(2, "usage:  watchfs files...\n");
-}
-
-void
-threadmain(int argc, char *argv[])
-{
-
-       ARGBEGIN{
-       case 'd':
-               dbg++;
-               break;
-       case 'D':
-               chatty9p++;
-               break;
-       }ARGEND;
-
-       uname = getuser();
-
-       fs.tree = inittree(&argv[0]);
-       if(dbg)
-               dumpWF();
-
-       initctl();
-       threadpostmountsrv(&fs, nil, "/n/watch", MREPL|MCREATE);
-       threadexits(0);
-}
-
-void
-takedown(Srv*)
-{
-       threadexitsall("done");
-}
-
-
-
-
//GO.SYSIN DD main.c


Reply via email to