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