#include "dat.h" #include "fns.h" #include "error.h" typedef struct Join Join; struct Join { Chan *c; Join *next; }; enum { Qdir, Qjoinfile, }; Dirtab joindir[] = { ".", {Qdir,0,QTDIR}, 0, DMDIR|0500, "new", {Qjoinfile}, 0, 0660, }; static void joinfree(Join *j) { if(j == nil) return; joinfree(j->next); cclose(j->c); free(j); } static Chan* joinattach(char *spec) { return devattach('δ', spec); } static Walkqid* joinwalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, joindir, nelem(joindir), devgen); } static int joinstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, joindir, nelem(joindir), devgen); } static Chan* joinopen(Chan *c, int omode) { return devopen(c, omode, joindir, nelem(joindir), devgen); } static void joinclose(Chan *c) { joinfree(c->aux); c->aux = nil; } static long joinread(Chan *c, void *va, long n, vlong off) { Join *j; long l; if(c->qid.type == QTDIR) return devdirread(c, va, n, joindir, nelem(joindir), devgen); l = 0; while(c->aux != nil) { j = c->aux; l = devtab[j->c->type]->read(j->c, va, n, off); if(l != 0) break; c->aux = j->next; cclose(j->c); free(j); } return l; } static long joinwrite(Chan *c, void *va, long n, vlong off) { char buf[32]; int fd; Chan *jc; Join *j; Join *nj; if(c->qid.type == QTDIR) error(Eisdir); if(n >= sizeof buf+1) error(Ebadarg); memmove(buf, va, n); buf[n] = 0; fd = atoi(buf); jc = fdtochan(up->env->fgrp, fd, -1, 0, 1); nj = malloc(sizeof nj[0]); nj->c = jc; nj->next = nil; if(c->aux == nil) { c->aux = nj; } else { for(j = c->aux; j->next != nil; j = j->next) {} j->next = nj; } return n; } Dev joindevtab = { 'δ', "join", devinit, joinattach, joinwalk, joinstat, joinopen, devcreate, joinclose, joinread, devbread, joinwrite, devbwrite, devremove, devwstat, };