devmntloop.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       devmntloop.c (2782B)
       ---
            1 /*
            2  * Clumsy hack to be able to create mountable files in /srv that
            3  * correspond to certain directories, kind of like an in-kernel exportfs:
            4  *
            5  *        fd = open("#~/mntloop", ORDWR);
            6  *        fprint(fd, "/mnt/foo");
            7  *        sfd = create("/srv/foo", ORDWR, 0666);
            8  *        fprint(sfd, "%d", fd);
            9  *        close(sfd);
           10  *        close(fd);
           11  *
           12  * is almost equivalent to
           13  *
           14  *        srvfs /mnt/foo foo
           15  *
           16  * but avoids the translation to 9P and back when you later
           17  * mount /srv/foo.  There are a few inaccuracies compared
           18  * to what srvfs does:
           19  *
           20  *         binds and mounts inside the tree rooted at /mnt/foo
           21  *        in the original name space are not present when a
           22  *        different name space mounts /srv/foo.
           23  *
           24  *        if the exported tree is a kernel device, then the kernel
           25  *        device will use the name of the user who mounted /srv/foo
           26  *        (not the name of the user who exported it) for permissions checks.
           27  *
           28  * This is all so that we can provide a /srv/boot file even if the
           29  * root is from a kernel device.  It's not intended for general use.
           30  */
           31 
           32 #include        "u.h"
           33 #include        "lib.h"
           34 #include        "mem.h"
           35 #include        "dat.h"
           36 #include        "fns.h"
           37 #include        "error.h"
           38 
           39 enum {
           40         Qdir = 0,
           41         Qmntloop = 1
           42 };
           43 
           44 static Chan*
           45 mntloopattach(char *spec)
           46 {
           47         Chan *c;
           48         c = devattach('~', spec);
           49         mkqid(&c->qid, Qdir, 0, QTDIR);
           50         return c;
           51 }
           52 
           53 static Dirtab dir[] = {
           54         "#~",        {Qdir, 0, QTDIR},        0,        DMDIR|0555,
           55         "mntloop",        {Qmntloop, 0, 0},        0,        0666,
           56 };
           57 
           58 static int
           59 mntloopgen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp)
           60 {
           61         if(s == DEVDOTDOT){
           62                 devdir(c, c->qid, "#~", 0, eve, DMDIR|0555, dp);
           63                 return 1;
           64         }
           65         
           66         return devgen(c, name, dir, nelem(dir), s, dp);
           67 }
           68 
           69 static Walkqid*
           70 mntloopwalk(Chan *c, Chan *nc, char **name, int nname)
           71 {
           72         return devwalk(c, nc, name, nname, nil, 0, mntloopgen);
           73 }
           74 
           75 static int
           76 mntloopstat(Chan *c, uchar *dp, int n)
           77 {
           78         return devstat(c, dp, n, nil, 0, mntloopgen);
           79 }
           80 
           81 static Chan*
           82 mntloopopen(Chan *c, int omode)
           83 {
           84         return devopen(c, omode, nil, 0, mntloopgen);
           85 }
           86 
           87 static void
           88 mntloopclose(Chan *c)
           89 {
           90         if(c->aux)
           91                 cclose(c->aux);
           92 }
           93 
           94 static long
           95 mntloopread(Chan *c, void *va, long n, vlong off)
           96 {
           97         error(Egreg);
           98         return -1;
           99 }
          100 
          101 static long
          102 mntloopwrite(Chan *c, void *va, long n, vlong off)
          103 {
          104         char *p;
          105         Chan *nc;
          106 
          107         if(c->aux || off != 0 || n >= BY2PG)
          108                 error(Ebadarg);
          109 
          110         p = smalloc(n+1);
          111         memmove(p, va, n);
          112         p[n] = 0;
          113         if(waserror()){
          114                 free(p);
          115                 nexterror();
          116         }
          117         nc = namec(p, Atodir, 0, 0);
          118         free(p);
          119         poperror();
          120         lock(&c->ref.lk);
          121         if(c->aux){
          122                 unlock(&c->ref.lk);
          123                 cclose(nc);
          124                 error(Ebadarg);
          125         }
          126         c->aux = nc;
          127         unlock(&c->ref.lk);
          128         return n;
          129 }
          130 
          131 Dev mntloopdevtab = {        /* known to mntattach */
          132         '~',
          133         "mntloop",
          134         
          135         devreset,
          136         devinit,
          137         devshutdown,
          138         mntloopattach,
          139         mntloopwalk,
          140         mntloopstat,
          141         mntloopopen,
          142         devcreate,
          143         mntloopclose,
          144         mntloopread,
          145         devbread,
          146         mntloopwrite,
          147         devbwrite,
          148         devremove,
          149         devwstat,
          150 };
          151