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