Blame


1 5551e51d 2006-07-23 devnull #include "a.h"
2 5551e51d 2006-07-23 devnull
3 5551e51d 2006-07-23 devnull int fusefd;
4 5551e51d 2006-07-23 devnull int fuseeof;
5 5551e51d 2006-07-23 devnull int fusebufsize;
6 5551e51d 2006-07-23 devnull int fusemaxwrite;
7 5551e51d 2006-07-23 devnull FuseMsg *fusemsglist;
8 be8b4b39 2006-08-01 devnull Lock fusemsglock;
9 5551e51d 2006-07-23 devnull
10 143cdf57 2006-07-26 devnull int mountfuse(char *mtpt);
11 143cdf57 2006-07-26 devnull void unmountfuse(char *mtpt);
12 143cdf57 2006-07-26 devnull
13 5551e51d 2006-07-23 devnull FuseMsg*
14 5551e51d 2006-07-23 devnull allocfusemsg(void)
15 5551e51d 2006-07-23 devnull {
16 5551e51d 2006-07-23 devnull FuseMsg *m;
17 5551e51d 2006-07-23 devnull void *vbuf;
18 fa325e9b 2020-01-10 cross
19 be8b4b39 2006-08-01 devnull lock(&fusemsglock);
20 5551e51d 2006-07-23 devnull if((m = fusemsglist) != nil){
21 5551e51d 2006-07-23 devnull fusemsglist = m->next;
22 be8b4b39 2006-08-01 devnull unlock(&fusemsglock);
23 5551e51d 2006-07-23 devnull return m;
24 5551e51d 2006-07-23 devnull }
25 be8b4b39 2006-08-01 devnull unlock(&fusemsglock);
26 5551e51d 2006-07-23 devnull m = emalloc(sizeof(*m) + fusebufsize);
27 5551e51d 2006-07-23 devnull vbuf = m+1;
28 5551e51d 2006-07-23 devnull m->buf = vbuf;
29 5551e51d 2006-07-23 devnull m->nbuf = 0;
30 5551e51d 2006-07-23 devnull m->hdr = vbuf;
31 5551e51d 2006-07-23 devnull m->tx = m->hdr+1;
32 5551e51d 2006-07-23 devnull return m;
33 5551e51d 2006-07-23 devnull }
34 5551e51d 2006-07-23 devnull
35 5551e51d 2006-07-23 devnull void
36 5551e51d 2006-07-23 devnull freefusemsg(FuseMsg *m)
37 5551e51d 2006-07-23 devnull {
38 be8b4b39 2006-08-01 devnull lock(&fusemsglock);
39 5551e51d 2006-07-23 devnull m->next = fusemsglist;
40 5551e51d 2006-07-23 devnull fusemsglist = m;
41 be8b4b39 2006-08-01 devnull unlock(&fusemsglock);
42 5551e51d 2006-07-23 devnull }
43 5551e51d 2006-07-23 devnull
44 5551e51d 2006-07-23 devnull FuseMsg*
45 5551e51d 2006-07-23 devnull readfusemsg(void)
46 5551e51d 2006-07-23 devnull {
47 5551e51d 2006-07-23 devnull FuseMsg *m;
48 869875b4 2008-07-04 rsc int n, nn;
49 fa325e9b 2020-01-10 cross
50 5551e51d 2006-07-23 devnull m = allocfusemsg();
51 5551e51d 2006-07-23 devnull /*
52 5551e51d 2006-07-23 devnull * The FUSE kernel device apparently guarantees
53 5551e51d 2006-07-23 devnull * that this read will return exactly one message.
54 5551e51d 2006-07-23 devnull * You get an error return if you ask for just the
55 5551e51d 2006-07-23 devnull * length (first 4 bytes).
56 5551e51d 2006-07-23 devnull * FUSE returns an ENODEV error, not EOF,
57 5551e51d 2006-07-23 devnull * when the connection is unmounted.
58 5551e51d 2006-07-23 devnull */
59 112744e5 2018-03-23 0intro do{
60 112744e5 2018-03-23 0intro errno = 0;
61 112744e5 2018-03-23 0intro n = read(fusefd, m->buf, fusebufsize);
62 112744e5 2018-03-23 0intro }while(n < 0 && errno == EINTR);
63 112744e5 2018-03-23 0intro if(n < 0){
64 5551e51d 2006-07-23 devnull if(errno != ENODEV)
65 5551e51d 2006-07-23 devnull sysfatal("readfusemsg: %r");
66 5551e51d 2006-07-23 devnull }
67 5551e51d 2006-07-23 devnull if(n <= 0){
68 5551e51d 2006-07-23 devnull fuseeof = 1;
69 5551e51d 2006-07-23 devnull freefusemsg(m);
70 5551e51d 2006-07-23 devnull return nil;
71 5551e51d 2006-07-23 devnull }
72 5551e51d 2006-07-23 devnull m->nbuf = n;
73 143cdf57 2006-07-26 devnull
74 143cdf57 2006-07-26 devnull /*
75 143cdf57 2006-07-26 devnull * FreeBSD FUSE sends a short length in the header
76 143cdf57 2006-07-26 devnull * for FUSE_INIT even though the actual read length
77 143cdf57 2006-07-26 devnull * is correct.
78 143cdf57 2006-07-26 devnull */
79 143cdf57 2006-07-26 devnull if(n == sizeof(*m->hdr)+sizeof(struct fuse_init_in)
80 143cdf57 2006-07-26 devnull && m->hdr->opcode == FUSE_INIT && m->hdr->len < n)
81 143cdf57 2006-07-26 devnull m->hdr->len = n;
82 143cdf57 2006-07-26 devnull
83 5551e51d 2006-07-23 devnull if(m->hdr->len != n)
84 5551e51d 2006-07-23 devnull sysfatal("readfusemsg: got %d wanted %d",
85 5551e51d 2006-07-23 devnull n, m->hdr->len);
86 143cdf57 2006-07-26 devnull m->hdr->len -= sizeof(*m->hdr);
87 fa325e9b 2020-01-10 cross
88 5551e51d 2006-07-23 devnull /*
89 5551e51d 2006-07-23 devnull * Paranoia.
90 5551e51d 2006-07-23 devnull * Make sure lengths are long enough.
91 5551e51d 2006-07-23 devnull * Make sure string arguments are NUL terminated.
92 5551e51d 2006-07-23 devnull * (I don't trust the kernel module.)
93 5551e51d 2006-07-23 devnull */
94 5551e51d 2006-07-23 devnull switch(m->hdr->opcode){
95 5551e51d 2006-07-23 devnull default:
96 5551e51d 2006-07-23 devnull /*
97 5551e51d 2006-07-23 devnull * Could sysfatal here, but can also let message go
98 5551e51d 2006-07-23 devnull * and assume higher-level code will return an
99 5551e51d 2006-07-23 devnull * "I don't know what you mean" error and recover.
100 5551e51d 2006-07-23 devnull */
101 5551e51d 2006-07-23 devnull break;
102 5551e51d 2006-07-23 devnull case FUSE_LOOKUP:
103 5551e51d 2006-07-23 devnull case FUSE_UNLINK:
104 5551e51d 2006-07-23 devnull case FUSE_RMDIR:
105 5551e51d 2006-07-23 devnull case FUSE_REMOVEXATTR:
106 5551e51d 2006-07-23 devnull /* just a string */
107 5551e51d 2006-07-23 devnull if(((char*)m->tx)[m->hdr->len-1] != 0)
108 5551e51d 2006-07-23 devnull bad:
109 5551e51d 2006-07-23 devnull sysfatal("readfusemsg: bad message");
110 5551e51d 2006-07-23 devnull break;
111 5551e51d 2006-07-23 devnull case FUSE_FORGET:
112 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_forget_in))
113 5551e51d 2006-07-23 devnull goto bad;
114 5551e51d 2006-07-23 devnull break;
115 5551e51d 2006-07-23 devnull case FUSE_GETATTR:
116 5551e51d 2006-07-23 devnull break;
117 5551e51d 2006-07-23 devnull case FUSE_SETATTR:
118 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_setattr_in))
119 5551e51d 2006-07-23 devnull goto bad;
120 5551e51d 2006-07-23 devnull break;
121 5551e51d 2006-07-23 devnull case FUSE_READLINK:
122 5551e51d 2006-07-23 devnull break;
123 5551e51d 2006-07-23 devnull case FUSE_SYMLINK:
124 5551e51d 2006-07-23 devnull /* two strings */
125 5551e51d 2006-07-23 devnull if(((char*)m->tx)[m->hdr->len-1] != 0
126 5551e51d 2006-07-23 devnull || memchr(m->tx, 0, m->hdr->len-1) == 0)
127 5551e51d 2006-07-23 devnull goto bad;
128 fa325e9b 2020-01-10 cross break;
129 5551e51d 2006-07-23 devnull case FUSE_MKNOD:
130 5551e51d 2006-07-23 devnull if(m->hdr->len <= sizeof(struct fuse_mknod_in)
131 5551e51d 2006-07-23 devnull || ((char*)m->tx)[m->hdr->len-1] != 0)
132 5551e51d 2006-07-23 devnull goto bad;
133 5551e51d 2006-07-23 devnull break;
134 5551e51d 2006-07-23 devnull case FUSE_MKDIR:
135 5551e51d 2006-07-23 devnull if(m->hdr->len <= sizeof(struct fuse_mkdir_in)
136 5551e51d 2006-07-23 devnull || ((char*)m->tx)[m->hdr->len-1] != 0)
137 5551e51d 2006-07-23 devnull goto bad;
138 5551e51d 2006-07-23 devnull break;
139 5551e51d 2006-07-23 devnull case FUSE_RENAME:
140 5551e51d 2006-07-23 devnull /* a struct and two strings */
141 5551e51d 2006-07-23 devnull if(m->hdr->len <= sizeof(struct fuse_rename_in)
142 5551e51d 2006-07-23 devnull || ((char*)m->tx)[m->hdr->len-1] != 0
143 5551e51d 2006-07-23 devnull || memchr((uchar*)m->tx+sizeof(struct fuse_rename_in), 0, m->hdr->len-sizeof(struct fuse_rename_in)-1) == 0)
144 5551e51d 2006-07-23 devnull goto bad;
145 5551e51d 2006-07-23 devnull break;
146 5551e51d 2006-07-23 devnull case FUSE_LINK:
147 5551e51d 2006-07-23 devnull if(m->hdr->len <= sizeof(struct fuse_link_in)
148 5551e51d 2006-07-23 devnull || ((char*)m->tx)[m->hdr->len-1] != 0)
149 5551e51d 2006-07-23 devnull goto bad;
150 5551e51d 2006-07-23 devnull break;
151 5551e51d 2006-07-23 devnull case FUSE_OPEN:
152 5551e51d 2006-07-23 devnull case FUSE_OPENDIR:
153 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_open_in))
154 5551e51d 2006-07-23 devnull goto bad;
155 5551e51d 2006-07-23 devnull break;
156 5551e51d 2006-07-23 devnull case FUSE_READ:
157 5551e51d 2006-07-23 devnull case FUSE_READDIR:
158 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_read_in))
159 5551e51d 2006-07-23 devnull goto bad;
160 5551e51d 2006-07-23 devnull break;
161 5551e51d 2006-07-23 devnull case FUSE_WRITE:
162 5551e51d 2006-07-23 devnull /* no strings, but check that write length is sane */
163 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_write_in)+((struct fuse_write_in*)m->tx)->size)
164 5551e51d 2006-07-23 devnull goto bad;
165 5551e51d 2006-07-23 devnull break;
166 5551e51d 2006-07-23 devnull case FUSE_STATFS:
167 5551e51d 2006-07-23 devnull break;
168 5551e51d 2006-07-23 devnull case FUSE_RELEASE:
169 5551e51d 2006-07-23 devnull case FUSE_RELEASEDIR:
170 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_release_in))
171 5551e51d 2006-07-23 devnull goto bad;
172 5551e51d 2006-07-23 devnull break;
173 5551e51d 2006-07-23 devnull case FUSE_FSYNC:
174 5551e51d 2006-07-23 devnull case FUSE_FSYNCDIR:
175 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_fsync_in))
176 5551e51d 2006-07-23 devnull goto bad;
177 5551e51d 2006-07-23 devnull break;
178 5551e51d 2006-07-23 devnull case FUSE_SETXATTR:
179 869875b4 2008-07-04 rsc /* struct, one string, and one binary blob */
180 869875b4 2008-07-04 rsc if(m->hdr->len <= sizeof(struct fuse_setxattr_in))
181 869875b4 2008-07-04 rsc goto bad;
182 869875b4 2008-07-04 rsc nn = ((struct fuse_setxattr_in*)m->tx)->size;
183 869875b4 2008-07-04 rsc if(m->hdr->len < sizeof(struct fuse_setxattr_in)+nn+1)
184 869875b4 2008-07-04 rsc goto bad;
185 869875b4 2008-07-04 rsc if(((char*)m->tx)[m->hdr->len-nn-1] != 0)
186 5551e51d 2006-07-23 devnull goto bad;
187 5551e51d 2006-07-23 devnull break;
188 5551e51d 2006-07-23 devnull case FUSE_GETXATTR:
189 5551e51d 2006-07-23 devnull /* struct and one string */
190 5551e51d 2006-07-23 devnull if(m->hdr->len <= sizeof(struct fuse_getxattr_in)
191 5551e51d 2006-07-23 devnull || ((char*)m->tx)[m->hdr->len-1] != 0)
192 5551e51d 2006-07-23 devnull goto bad;
193 5551e51d 2006-07-23 devnull break;
194 5551e51d 2006-07-23 devnull case FUSE_LISTXATTR:
195 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_getxattr_in))
196 5551e51d 2006-07-23 devnull goto bad;
197 5551e51d 2006-07-23 devnull break;
198 5551e51d 2006-07-23 devnull case FUSE_FLUSH:
199 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_flush_in))
200 5551e51d 2006-07-23 devnull goto bad;
201 5551e51d 2006-07-23 devnull break;
202 5551e51d 2006-07-23 devnull case FUSE_INIT:
203 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_init_in))
204 5551e51d 2006-07-23 devnull goto bad;
205 5551e51d 2006-07-23 devnull break;
206 5551e51d 2006-07-23 devnull case FUSE_ACCESS:
207 5551e51d 2006-07-23 devnull if(m->hdr->len < sizeof(struct fuse_access_in))
208 5551e51d 2006-07-23 devnull goto bad;
209 5551e51d 2006-07-23 devnull break;
210 5551e51d 2006-07-23 devnull case FUSE_CREATE:
211 5551e51d 2006-07-23 devnull if(m->hdr->len <= sizeof(struct fuse_open_in)
212 5551e51d 2006-07-23 devnull || ((char*)m->tx)[m->hdr->len-1] != 0)
213 5551e51d 2006-07-23 devnull goto bad;
214 5551e51d 2006-07-23 devnull break;
215 5551e51d 2006-07-23 devnull }
216 5551e51d 2006-07-23 devnull if(debug)
217 5551e51d 2006-07-23 devnull fprint(2, "FUSE -> %G\n", m->hdr, m->tx);
218 5551e51d 2006-07-23 devnull return m;
219 5551e51d 2006-07-23 devnull }
220 5551e51d 2006-07-23 devnull
221 5551e51d 2006-07-23 devnull /*
222 fa325e9b 2020-01-10 cross * Reply to FUSE request m using additonal
223 5551e51d 2006-07-23 devnull * argument buffer arg of size narg bytes.
224 5551e51d 2006-07-23 devnull * Perhaps should free the FuseMsg here?
225 5551e51d 2006-07-23 devnull */
226 5551e51d 2006-07-23 devnull void
227 5551e51d 2006-07-23 devnull replyfuse(FuseMsg *m, void *arg, int narg)
228 5551e51d 2006-07-23 devnull {
229 5551e51d 2006-07-23 devnull struct iovec vec[2];
230 5551e51d 2006-07-23 devnull struct fuse_out_header hdr;
231 5551e51d 2006-07-23 devnull int nvec;
232 fa325e9b 2020-01-10 cross
233 5551e51d 2006-07-23 devnull hdr.len = sizeof hdr + narg;
234 5551e51d 2006-07-23 devnull hdr.error = 0;
235 5551e51d 2006-07-23 devnull hdr.unique = m->hdr->unique;
236 5551e51d 2006-07-23 devnull if(debug)
237 5551e51d 2006-07-23 devnull fprint(2, "FUSE <- %#G\n", m->hdr, &hdr, arg);
238 5551e51d 2006-07-23 devnull
239 5551e51d 2006-07-23 devnull vec[0].iov_base = &hdr;
240 5551e51d 2006-07-23 devnull vec[0].iov_len = sizeof hdr;
241 5551e51d 2006-07-23 devnull nvec = 1;
242 5551e51d 2006-07-23 devnull if(arg && narg){
243 5551e51d 2006-07-23 devnull vec[1].iov_base = arg;
244 5551e51d 2006-07-23 devnull vec[1].iov_len = narg;
245 5551e51d 2006-07-23 devnull nvec++;
246 5551e51d 2006-07-23 devnull }
247 6f61477d 2008-07-24 rsc writev(fusefd, vec, nvec);
248 be8b4b39 2006-08-01 devnull freefusemsg(m);
249 5551e51d 2006-07-23 devnull }
250 5551e51d 2006-07-23 devnull
251 5551e51d 2006-07-23 devnull /*
252 5551e51d 2006-07-23 devnull * Reply to FUSE request m with errno e.
253 5551e51d 2006-07-23 devnull */
254 5551e51d 2006-07-23 devnull void
255 5551e51d 2006-07-23 devnull replyfuseerrno(FuseMsg *m, int e)
256 5551e51d 2006-07-23 devnull {
257 5551e51d 2006-07-23 devnull struct fuse_out_header hdr;
258 fa325e9b 2020-01-10 cross
259 5551e51d 2006-07-23 devnull hdr.len = sizeof hdr;
260 5551e51d 2006-07-23 devnull hdr.error = -e; /* FUSE sends negative errnos. */
261 5551e51d 2006-07-23 devnull hdr.unique = m->hdr->unique;
262 5551e51d 2006-07-23 devnull if(debug)
263 5551e51d 2006-07-23 devnull fprint(2, "FUSE <- %#G\n", m->hdr, &hdr, 0);
264 6f61477d 2008-07-24 rsc write(fusefd, &hdr, sizeof hdr);
265 be8b4b39 2006-08-01 devnull freefusemsg(m);
266 5551e51d 2006-07-23 devnull }
267 5551e51d 2006-07-23 devnull
268 5551e51d 2006-07-23 devnull void
269 5551e51d 2006-07-23 devnull replyfuseerrstr(FuseMsg *m)
270 5551e51d 2006-07-23 devnull {
271 5551e51d 2006-07-23 devnull replyfuseerrno(m, errstr2errno());
272 5551e51d 2006-07-23 devnull }
273 5551e51d 2006-07-23 devnull
274 5551e51d 2006-07-23 devnull char *fusemtpt;
275 5551e51d 2006-07-23 devnull void
276 5551e51d 2006-07-23 devnull unmountatexit(void)
277 5551e51d 2006-07-23 devnull {
278 5551e51d 2006-07-23 devnull if(fusemtpt)
279 5551e51d 2006-07-23 devnull unmountfuse(fusemtpt);
280 5551e51d 2006-07-23 devnull }
281 5551e51d 2006-07-23 devnull
282 5551e51d 2006-07-23 devnull void
283 5551e51d 2006-07-23 devnull initfuse(char *mtpt)
284 5551e51d 2006-07-23 devnull {
285 5551e51d 2006-07-23 devnull FuseMsg *m;
286 5551e51d 2006-07-23 devnull struct fuse_init_in *tx;
287 5551e51d 2006-07-23 devnull struct fuse_init_out rx;
288 5551e51d 2006-07-23 devnull
289 5551e51d 2006-07-23 devnull fusemtpt = mtpt;
290 5551e51d 2006-07-23 devnull
291 5551e51d 2006-07-23 devnull /*
292 5551e51d 2006-07-23 devnull * The 4096 is for the message headers.
293 5551e51d 2006-07-23 devnull * It's a lot, but it's what the FUSE libraries ask for.
294 5551e51d 2006-07-23 devnull */
295 5551e51d 2006-07-23 devnull fusemaxwrite = getpagesize();
296 5551e51d 2006-07-23 devnull fusebufsize = 4096 + fusemaxwrite;
297 5551e51d 2006-07-23 devnull
298 5551e51d 2006-07-23 devnull if((fusefd = mountfuse(mtpt)) < 0)
299 5551e51d 2006-07-23 devnull sysfatal("mountfuse: %r");
300 5551e51d 2006-07-23 devnull
301 5551e51d 2006-07-23 devnull if((m = readfusemsg()) == nil)
302 5551e51d 2006-07-23 devnull sysfatal("readfusemsg: %r");
303 5551e51d 2006-07-23 devnull if(m->hdr->opcode != FUSE_INIT)
304 5551e51d 2006-07-23 devnull sysfatal("fuse: expected FUSE_INIT (26) got %d", m->hdr->opcode);
305 5551e51d 2006-07-23 devnull tx = m->tx;
306 5551e51d 2006-07-23 devnull
307 5551e51d 2006-07-23 devnull /*
308 5551e51d 2006-07-23 devnull * Complain if the kernel is too new.
309 5551e51d 2006-07-23 devnull * We could forge ahead, but at least the one time I tried,
310 fa325e9b 2020-01-10 cross * the kernel rejected the newer version by making the
311 5551e51d 2006-07-23 devnull * writev fail in replyfuse, which is a much more confusing
312 fa325e9b 2020-01-10 cross * error message. In the future, might be nice to try to
313 5551e51d 2006-07-23 devnull * support older versions that differ only slightly.
314 5551e51d 2006-07-23 devnull */
315 fa325e9b 2020-01-10 cross if(tx->major < FUSE_KERNEL_VERSION
316 5551e51d 2006-07-23 devnull || (tx->major == FUSE_KERNEL_VERSION && tx->minor < FUSE_KERNEL_MINOR_VERSION))
317 5551e51d 2006-07-23 devnull sysfatal("fuse: too kernel version %d.%d older than program version %d.%d",
318 5551e51d 2006-07-23 devnull tx->major, tx->minor, FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
319 5551e51d 2006-07-23 devnull
320 5551e51d 2006-07-23 devnull memset(&rx, 0, sizeof rx);
321 5551e51d 2006-07-23 devnull rx.major = FUSE_KERNEL_VERSION;
322 5551e51d 2006-07-23 devnull rx.minor = FUSE_KERNEL_MINOR_VERSION;
323 5551e51d 2006-07-23 devnull rx.max_write = fusemaxwrite;
324 5551e51d 2006-07-23 devnull replyfuse(m, &rx, sizeof rx);
325 5551e51d 2006-07-23 devnull }
326 5551e51d 2006-07-23 devnull
327 5551e51d 2006-07-23 devnull /*
328 5551e51d 2006-07-23 devnull * Print FUSE messages. Assuming it is installed as %G,
329 5551e51d 2006-07-23 devnull * use %G with hdr, arg arguments to format a request,
330 5551e51d 2006-07-23 devnull * and %#G with reqhdr, hdr, arg arguments to format a response.
331 5551e51d 2006-07-23 devnull * The reqhdr is necessary in the %#G form because the
332 5551e51d 2006-07-23 devnull * response does not contain an opcode tag.
333 5551e51d 2006-07-23 devnull */
334 5551e51d 2006-07-23 devnull int
335 5551e51d 2006-07-23 devnull fusefmt(Fmt *fmt)
336 5551e51d 2006-07-23 devnull {
337 5551e51d 2006-07-23 devnull struct fuse_in_header *hdr = va_arg(fmt->args, void*);
338 5551e51d 2006-07-23 devnull if((fmt->flags&FmtSharp) == 0){ /* "%G", hdr, arg */
339 5551e51d 2006-07-23 devnull void *a = va_arg(fmt->args, void*);
340 5551e51d 2006-07-23 devnull fmtprint(fmt, "len %d unique %#llux uid %d gid %d pid %d ",
341 5551e51d 2006-07-23 devnull hdr->len, hdr->unique, hdr->uid, hdr->gid, hdr->pid);
342 5551e51d 2006-07-23 devnull
343 5551e51d 2006-07-23 devnull switch(hdr->opcode){
344 5551e51d 2006-07-23 devnull default: {
345 5551e51d 2006-07-23 devnull fmtprint(fmt, "??? opcode %d", hdr->opcode);
346 5551e51d 2006-07-23 devnull break;
347 5551e51d 2006-07-23 devnull }
348 5551e51d 2006-07-23 devnull case FUSE_LOOKUP: {
349 5551e51d 2006-07-23 devnull fmtprint(fmt, "Lookup nodeid %#llux name %#q",
350 5551e51d 2006-07-23 devnull hdr->nodeid, a);
351 5551e51d 2006-07-23 devnull break;
352 5551e51d 2006-07-23 devnull }
353 5551e51d 2006-07-23 devnull case FUSE_FORGET: {
354 5551e51d 2006-07-23 devnull struct fuse_forget_in *tx = a;
355 5551e51d 2006-07-23 devnull /* nlookup (a ref count) is a vlong! */
356 5551e51d 2006-07-23 devnull fmtprint(fmt, "Forget nodeid %#llux nlookup %lld",
357 5551e51d 2006-07-23 devnull hdr->nodeid, tx->nlookup);
358 5551e51d 2006-07-23 devnull break;
359 5551e51d 2006-07-23 devnull }
360 5551e51d 2006-07-23 devnull case FUSE_GETATTR: {
361 5551e51d 2006-07-23 devnull fmtprint(fmt, "Getattr nodeid %#llux", hdr->nodeid);
362 5551e51d 2006-07-23 devnull break;
363 5551e51d 2006-07-23 devnull }
364 5551e51d 2006-07-23 devnull case FUSE_SETATTR: {
365 5551e51d 2006-07-23 devnull struct fuse_setattr_in *tx = a;
366 5551e51d 2006-07-23 devnull fmtprint(fmt, "Setattr nodeid %#llux", hdr->nodeid);
367 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_FH)
368 5551e51d 2006-07-23 devnull fmtprint(fmt, " fh %#llux", tx->fh);
369 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_SIZE)
370 5551e51d 2006-07-23 devnull fmtprint(fmt, " size %lld", tx->size);
371 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_ATIME)
372 5551e51d 2006-07-23 devnull fmtprint(fmt, " atime %.20g", tx->atime+tx->atimensec*1e-9);
373 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_MTIME)
374 5551e51d 2006-07-23 devnull fmtprint(fmt, " mtime %.20g", tx->mtime+tx->mtimensec*1e-9);
375 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_MODE)
376 5551e51d 2006-07-23 devnull fmtprint(fmt, " mode %#uo", tx->mode);
377 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_UID)
378 5551e51d 2006-07-23 devnull fmtprint(fmt, " uid %d", tx->uid);
379 5551e51d 2006-07-23 devnull if(tx->valid&FATTR_GID)
380 5551e51d 2006-07-23 devnull fmtprint(fmt, " gid %d", tx->gid);
381 5551e51d 2006-07-23 devnull break;
382 5551e51d 2006-07-23 devnull }
383 5551e51d 2006-07-23 devnull case FUSE_READLINK: {
384 5551e51d 2006-07-23 devnull fmtprint(fmt, "Readlink nodeid %#llux", hdr->nodeid);
385 5551e51d 2006-07-23 devnull break;
386 5551e51d 2006-07-23 devnull }
387 5551e51d 2006-07-23 devnull case FUSE_SYMLINK: {
388 5551e51d 2006-07-23 devnull char *old, *new;
389 fa325e9b 2020-01-10 cross
390 5551e51d 2006-07-23 devnull old = a;
391 5551e51d 2006-07-23 devnull new = a + strlen(a) + 1;
392 5551e51d 2006-07-23 devnull fmtprint(fmt, "Symlink nodeid %#llux old %#q new %#q",
393 5551e51d 2006-07-23 devnull hdr->nodeid, old, new);
394 5551e51d 2006-07-23 devnull break;
395 5551e51d 2006-07-23 devnull }
396 5551e51d 2006-07-23 devnull case FUSE_MKNOD: {
397 5551e51d 2006-07-23 devnull struct fuse_mknod_in *tx = a;
398 5551e51d 2006-07-23 devnull fmtprint(fmt, "Mknod nodeid %#llux mode %#uo rdev %#ux name %#q",
399 5551e51d 2006-07-23 devnull hdr->nodeid, tx->mode, tx->rdev, tx+1);
400 5551e51d 2006-07-23 devnull break;
401 5551e51d 2006-07-23 devnull }
402 5551e51d 2006-07-23 devnull case FUSE_MKDIR: {
403 5551e51d 2006-07-23 devnull struct fuse_mkdir_in *tx = a;
404 5551e51d 2006-07-23 devnull fmtprint(fmt, "Mkdir nodeid %#llux mode %#uo name %#q",
405 5551e51d 2006-07-23 devnull hdr->nodeid, tx->mode, tx+1);
406 5551e51d 2006-07-23 devnull break;
407 5551e51d 2006-07-23 devnull }
408 5551e51d 2006-07-23 devnull case FUSE_UNLINK: {
409 5551e51d 2006-07-23 devnull fmtprint(fmt, "Unlink nodeid %#llux name %#q",
410 5551e51d 2006-07-23 devnull hdr->nodeid, a);
411 5551e51d 2006-07-23 devnull break;
412 5551e51d 2006-07-23 devnull }
413 5551e51d 2006-07-23 devnull case FUSE_RMDIR: {
414 5551e51d 2006-07-23 devnull fmtprint(fmt, "Rmdir nodeid %#llux name %#q",
415 5551e51d 2006-07-23 devnull hdr->nodeid, a);
416 5551e51d 2006-07-23 devnull break;
417 5551e51d 2006-07-23 devnull }
418 5551e51d 2006-07-23 devnull case FUSE_RENAME: {
419 5551e51d 2006-07-23 devnull struct fuse_rename_in *tx = a;
420 5551e51d 2006-07-23 devnull char *old = (char*)(tx+1);
421 5551e51d 2006-07-23 devnull char *new = old + strlen(old) + 1;
422 5551e51d 2006-07-23 devnull fmtprint(fmt, "Rename nodeid %#llux old %#q newdir %#llux new %#q",
423 5551e51d 2006-07-23 devnull hdr->nodeid, old, tx->newdir, new);
424 5551e51d 2006-07-23 devnull break;
425 5551e51d 2006-07-23 devnull }
426 5551e51d 2006-07-23 devnull case FUSE_LINK: {
427 5551e51d 2006-07-23 devnull struct fuse_link_in *tx = a;
428 5551e51d 2006-07-23 devnull fmtprint(fmt, "Link oldnodeid %#llux nodeid %#llux name %#q",
429 5551e51d 2006-07-23 devnull tx->oldnodeid, hdr->nodeid, tx+1);
430 5551e51d 2006-07-23 devnull break;
431 5551e51d 2006-07-23 devnull }
432 5551e51d 2006-07-23 devnull case FUSE_OPEN: {
433 5551e51d 2006-07-23 devnull struct fuse_open_in *tx = a;
434 5551e51d 2006-07-23 devnull /* Should one or both of flags and mode be octal? */
435 5551e51d 2006-07-23 devnull fmtprint(fmt, "Open nodeid %#llux flags %#ux mode %#ux",
436 5551e51d 2006-07-23 devnull hdr->nodeid, tx->flags, tx->mode);
437 5551e51d 2006-07-23 devnull break;
438 5551e51d 2006-07-23 devnull }
439 5551e51d 2006-07-23 devnull case FUSE_READ: {
440 5551e51d 2006-07-23 devnull struct fuse_read_in *tx = a;
441 5551e51d 2006-07-23 devnull fmtprint(fmt, "Read nodeid %#llux fh %#llux offset %lld size %ud",
442 5551e51d 2006-07-23 devnull hdr->nodeid, tx->fh, tx->offset, tx->size);
443 5551e51d 2006-07-23 devnull break;
444 5551e51d 2006-07-23 devnull }
445 5551e51d 2006-07-23 devnull case FUSE_WRITE: {
446 5551e51d 2006-07-23 devnull struct fuse_write_in *tx = a;
447 5551e51d 2006-07-23 devnull fmtprint(fmt, "Write nodeid %#llux fh %#llux offset %lld size %ud flags %#ux",
448 5551e51d 2006-07-23 devnull hdr->nodeid, tx->fh, tx->offset, tx->size, tx->write_flags);
449 5551e51d 2006-07-23 devnull break;
450 5551e51d 2006-07-23 devnull }
451 5551e51d 2006-07-23 devnull case FUSE_STATFS: {
452 5551e51d 2006-07-23 devnull fmtprint(fmt, "Statfs");
453 5551e51d 2006-07-23 devnull break;
454 5551e51d 2006-07-23 devnull }
455 5551e51d 2006-07-23 devnull case FUSE_RELEASE: {
456 5551e51d 2006-07-23 devnull struct fuse_release_in *tx = a;
457 5551e51d 2006-07-23 devnull fmtprint(fmt, "Release nodeid %#llux fh %#llux flags %#ux",
458 fa325e9b 2020-01-10 cross hdr->nodeid, tx->fh, tx->flags);
459 5551e51d 2006-07-23 devnull break;
460 5551e51d 2006-07-23 devnull }
461 5551e51d 2006-07-23 devnull case FUSE_FSYNC: {
462 5551e51d 2006-07-23 devnull struct fuse_fsync_in *tx = a;
463 5551e51d 2006-07-23 devnull fmtprint(fmt, "Fsync nodeid %#llux fh %#llux flags %#ux",
464 5551e51d 2006-07-23 devnull hdr->nodeid, tx->fh, tx->fsync_flags);
465 5551e51d 2006-07-23 devnull break;
466 5551e51d 2006-07-23 devnull }
467 5551e51d 2006-07-23 devnull case FUSE_SETXATTR: {
468 5551e51d 2006-07-23 devnull struct fuse_setxattr_in *tx = a;
469 5551e51d 2006-07-23 devnull char *name = (char*)(tx+1);
470 5551e51d 2006-07-23 devnull char *value = name + strlen(name) + 1;
471 5551e51d 2006-07-23 devnull fmtprint(fmt, "Setxattr nodeid %#llux size %d flags %#ux name %#q value %#q",
472 5551e51d 2006-07-23 devnull hdr->nodeid, tx->size, tx->flags, name, value);
473 5551e51d 2006-07-23 devnull break;
474 5551e51d 2006-07-23 devnull }
475 5551e51d 2006-07-23 devnull case FUSE_GETXATTR: {
476 5551e51d 2006-07-23 devnull struct fuse_getxattr_in *tx = a;
477 5551e51d 2006-07-23 devnull fmtprint(fmt, "Getxattr nodeid %#llux size %d name %#q",
478 5551e51d 2006-07-23 devnull hdr->nodeid, tx->size, tx+1);
479 5551e51d 2006-07-23 devnull break;
480 5551e51d 2006-07-23 devnull }
481 5551e51d 2006-07-23 devnull case FUSE_LISTXATTR: {
482 5551e51d 2006-07-23 devnull struct fuse_getxattr_in *tx = a;
483 5551e51d 2006-07-23 devnull fmtprint(fmt, "Listxattr nodeid %#llux size %d",
484 5551e51d 2006-07-23 devnull hdr->nodeid, tx->size);
485 5551e51d 2006-07-23 devnull break;
486 5551e51d 2006-07-23 devnull }
487 5551e51d 2006-07-23 devnull case FUSE_REMOVEXATTR: {
488 5551e51d 2006-07-23 devnull fmtprint(fmt, "Removexattr nodeid %#llux name %#q",
489 5551e51d 2006-07-23 devnull hdr->nodeid, a);
490 5551e51d 2006-07-23 devnull break;
491 5551e51d 2006-07-23 devnull }
492 5551e51d 2006-07-23 devnull case FUSE_FLUSH: {
493 5551e51d 2006-07-23 devnull struct fuse_flush_in *tx = a;
494 5551e51d 2006-07-23 devnull fmtprint(fmt, "Flush nodeid %#llux fh %#llux flags %#ux",
495 5551e51d 2006-07-23 devnull hdr->nodeid, tx->fh, tx->flush_flags);
496 5551e51d 2006-07-23 devnull break;
497 5551e51d 2006-07-23 devnull }
498 5551e51d 2006-07-23 devnull case FUSE_INIT: {
499 5551e51d 2006-07-23 devnull struct fuse_init_in *tx = a;
500 5551e51d 2006-07-23 devnull fmtprint(fmt, "Init major %d minor %d",
501 5551e51d 2006-07-23 devnull tx->major, tx->minor);
502 5551e51d 2006-07-23 devnull break;
503 5551e51d 2006-07-23 devnull }
504 5551e51d 2006-07-23 devnull case FUSE_OPENDIR: {
505 5551e51d 2006-07-23 devnull struct fuse_open_in *tx = a;
506 5551e51d 2006-07-23 devnull fmtprint(fmt, "Opendir nodeid %#llux flags %#ux mode %#ux",
507 5551e51d 2006-07-23 devnull hdr->nodeid, tx->flags, tx->mode);
508 5551e51d 2006-07-23 devnull break;
509 5551e51d 2006-07-23 devnull }
510 5551e51d 2006-07-23 devnull case FUSE_READDIR: {
511 5551e51d 2006-07-23 devnull struct fuse_read_in *tx = a;
512 5551e51d 2006-07-23 devnull fmtprint(fmt, "Readdir nodeid %#llux fh %#llux offset %lld size %ud",
513 5551e51d 2006-07-23 devnull hdr->nodeid, tx->fh, tx->offset, tx->size);
514 5551e51d 2006-07-23 devnull break;
515 5551e51d 2006-07-23 devnull }
516 5551e51d 2006-07-23 devnull case FUSE_RELEASEDIR: {
517 5551e51d 2006-07-23 devnull struct fuse_release_in *tx = a;
518 5551e51d 2006-07-23 devnull fmtprint(fmt, "Releasedir nodeid %#llux fh %#llux flags %#ux",
519 fa325e9b 2020-01-10 cross hdr->nodeid, tx->fh, tx->flags);
520 5551e51d 2006-07-23 devnull break;
521 5551e51d 2006-07-23 devnull }
522 5551e51d 2006-07-23 devnull case FUSE_FSYNCDIR: {
523 5551e51d 2006-07-23 devnull struct fuse_fsync_in *tx = a;
524 5551e51d 2006-07-23 devnull fmtprint(fmt, "Fsyncdir nodeid %#llux fh %#llux flags %#ux",
525 5551e51d 2006-07-23 devnull hdr->nodeid, tx->fh, tx->fsync_flags);
526 5551e51d 2006-07-23 devnull break;
527 5551e51d 2006-07-23 devnull }
528 5551e51d 2006-07-23 devnull case FUSE_ACCESS: {
529 5551e51d 2006-07-23 devnull struct fuse_access_in *tx = a;
530 5551e51d 2006-07-23 devnull fmtprint(fmt, "Access nodeid %#llux mask %#ux",
531 5551e51d 2006-07-23 devnull hdr->nodeid, tx->mask);
532 5551e51d 2006-07-23 devnull break;
533 5551e51d 2006-07-23 devnull }
534 5551e51d 2006-07-23 devnull case FUSE_CREATE: {
535 5551e51d 2006-07-23 devnull struct fuse_open_in *tx = a;
536 5551e51d 2006-07-23 devnull fmtprint(fmt, "Create nodeid %#llx flags %#ux mode %#ux name %#q",
537 5551e51d 2006-07-23 devnull hdr->nodeid, tx->flags, tx->mode, tx+1);
538 5551e51d 2006-07-23 devnull break;
539 5551e51d 2006-07-23 devnull }
540 5551e51d 2006-07-23 devnull }
541 5551e51d 2006-07-23 devnull }else{ /* "%#G", reqhdr, hdr, arg - use reqhdr only for type */
542 5551e51d 2006-07-23 devnull struct fuse_out_header *ohdr = va_arg(fmt->args, void*);
543 5551e51d 2006-07-23 devnull void *a = va_arg(fmt->args, void*);
544 5551e51d 2006-07-23 devnull int len = ohdr->len - sizeof *ohdr;
545 5551e51d 2006-07-23 devnull fmtprint(fmt, "unique %#llux ", ohdr->unique);
546 5551e51d 2006-07-23 devnull if(ohdr->error){
547 5551e51d 2006-07-23 devnull fmtprint(fmt, "error %d %s", ohdr->error, strerror(-ohdr->error));
548 5551e51d 2006-07-23 devnull }else
549 5551e51d 2006-07-23 devnull switch(hdr->opcode){
550 5551e51d 2006-07-23 devnull default: {
551 5551e51d 2006-07-23 devnull fmtprint(fmt, "??? opcode %d", hdr->opcode);
552 5551e51d 2006-07-23 devnull break;
553 5551e51d 2006-07-23 devnull }
554 5551e51d 2006-07-23 devnull case FUSE_LOOKUP: {
555 5551e51d 2006-07-23 devnull /*
556 5551e51d 2006-07-23 devnull * For a negative entry, can send back ENOENT
557 fa325e9b 2020-01-10 cross * or rx->ino == 0.
558 5551e51d 2006-07-23 devnull * In protocol version 7.4 and before, can only use
559 5551e51d 2006-07-23 devnull * the ENOENT method.
560 5551e51d 2006-07-23 devnull * Presumably the benefit of sending rx->ino == 0
561 5551e51d 2006-07-23 devnull * is that you can specify the length of time to cache
562 5551e51d 2006-07-23 devnull * the negative result.
563 5551e51d 2006-07-23 devnull */
564 5551e51d 2006-07-23 devnull struct fuse_entry_out *rx;
565 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Lookup) ");
566 5551e51d 2006-07-23 devnull fmt_entry_out:
567 5551e51d 2006-07-23 devnull rx = a;
568 5551e51d 2006-07-23 devnull fmtprint(fmt, "nodeid %#llux gen %#llux entry_valid %.20g attr_valid %.20g ",
569 5551e51d 2006-07-23 devnull rx->nodeid, rx->generation,
570 5551e51d 2006-07-23 devnull rx->entry_valid+rx->entry_valid_nsec*1e-9,
571 5551e51d 2006-07-23 devnull rx->attr_valid+rx->attr_valid_nsec*1e-9);
572 5551e51d 2006-07-23 devnull fmtprint(fmt, " ino %#llux size %lld blocks %lld atime %.20g mtime %.20g ctime %.20g mode %#uo nlink %d uid %d gid %d rdev %#ux",
573 5551e51d 2006-07-23 devnull rx->attr.ino, rx->attr.size, rx->attr.blocks,
574 fa325e9b 2020-01-10 cross rx->attr.atime+rx->attr.atimensec*1e-9,
575 5551e51d 2006-07-23 devnull rx->attr.mtime+rx->attr.mtimensec*1e-9,
576 5551e51d 2006-07-23 devnull rx->attr.ctime+rx->attr.ctimensec*1e-9,
577 5551e51d 2006-07-23 devnull rx->attr.mode, rx->attr.nlink, rx->attr.uid,
578 5551e51d 2006-07-23 devnull rx->attr.gid, rx->attr.rdev);
579 5551e51d 2006-07-23 devnull break;
580 5551e51d 2006-07-23 devnull }
581 5551e51d 2006-07-23 devnull case FUSE_FORGET: {
582 5551e51d 2006-07-23 devnull /* Can't happen! No reply. */
583 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Forget) can't happen");
584 5551e51d 2006-07-23 devnull break;
585 5551e51d 2006-07-23 devnull }
586 5551e51d 2006-07-23 devnull case FUSE_GETATTR: {
587 5551e51d 2006-07-23 devnull struct fuse_attr_out *rx;
588 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Getattr) ");
589 5551e51d 2006-07-23 devnull fmt_attr_out:
590 5551e51d 2006-07-23 devnull rx = a;
591 5551e51d 2006-07-23 devnull fmtprint(fmt, "attr_valid %.20g",
592 5551e51d 2006-07-23 devnull rx->attr_valid+rx->attr_valid_nsec*1e-9);
593 5551e51d 2006-07-23 devnull fmtprint(fmt, " ino %#llux size %lld blocks %lld atime %.20g mtime %.20g ctime %.20g mode %#uo nlink %d uid %d gid %d rdev %#ux",
594 5551e51d 2006-07-23 devnull rx->attr.ino, rx->attr.size, rx->attr.blocks,
595 fa325e9b 2020-01-10 cross rx->attr.atime+rx->attr.atimensec*1e-9,
596 5551e51d 2006-07-23 devnull rx->attr.mtime+rx->attr.mtimensec*1e-9,
597 5551e51d 2006-07-23 devnull rx->attr.ctime+rx->attr.ctimensec*1e-9,
598 5551e51d 2006-07-23 devnull rx->attr.mode, rx->attr.nlink, rx->attr.uid,
599 5551e51d 2006-07-23 devnull rx->attr.gid, rx->attr.rdev);
600 5551e51d 2006-07-23 devnull break;
601 5551e51d 2006-07-23 devnull }
602 5551e51d 2006-07-23 devnull case FUSE_SETATTR: {
603 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Setattr) ");
604 5551e51d 2006-07-23 devnull goto fmt_attr_out;
605 5551e51d 2006-07-23 devnull break;
606 5551e51d 2006-07-23 devnull }
607 5551e51d 2006-07-23 devnull case FUSE_READLINK: {
608 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Readlink) %#.*q",
609 5551e51d 2006-07-23 devnull utfnlen(a, len), a);
610 5551e51d 2006-07-23 devnull break;
611 5551e51d 2006-07-23 devnull }
612 5551e51d 2006-07-23 devnull case FUSE_SYMLINK: {
613 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Symlink) ");
614 5551e51d 2006-07-23 devnull goto fmt_entry_out;
615 5551e51d 2006-07-23 devnull break;
616 5551e51d 2006-07-23 devnull }
617 5551e51d 2006-07-23 devnull case FUSE_MKNOD: {
618 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Mknod) ");
619 5551e51d 2006-07-23 devnull goto fmt_entry_out;
620 5551e51d 2006-07-23 devnull break;
621 5551e51d 2006-07-23 devnull }
622 5551e51d 2006-07-23 devnull case FUSE_MKDIR: {
623 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Mkdir) ");
624 5551e51d 2006-07-23 devnull goto fmt_entry_out;
625 5551e51d 2006-07-23 devnull break;
626 5551e51d 2006-07-23 devnull }
627 5551e51d 2006-07-23 devnull case FUSE_UNLINK: {
628 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Unlink)");
629 5551e51d 2006-07-23 devnull break;
630 5551e51d 2006-07-23 devnull }
631 5551e51d 2006-07-23 devnull case FUSE_RMDIR: {
632 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Rmdir)");
633 5551e51d 2006-07-23 devnull break;
634 5551e51d 2006-07-23 devnull }
635 5551e51d 2006-07-23 devnull case FUSE_RENAME: {
636 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Rename)");
637 5551e51d 2006-07-23 devnull break;
638 5551e51d 2006-07-23 devnull }
639 5551e51d 2006-07-23 devnull case FUSE_LINK: {
640 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Link) ");
641 5551e51d 2006-07-23 devnull goto fmt_entry_out;
642 5551e51d 2006-07-23 devnull break;
643 5551e51d 2006-07-23 devnull }
644 5551e51d 2006-07-23 devnull case FUSE_OPEN: {
645 5551e51d 2006-07-23 devnull struct fuse_open_out *rx;
646 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Open) ");
647 5551e51d 2006-07-23 devnull fmt_open_out:
648 5551e51d 2006-07-23 devnull rx = a;
649 5551e51d 2006-07-23 devnull fmtprint(fmt, "fh %#llux flags %#ux", rx->fh, rx->open_flags);
650 5551e51d 2006-07-23 devnull break;
651 5551e51d 2006-07-23 devnull }
652 5551e51d 2006-07-23 devnull case FUSE_READ: {
653 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Read) size %d", len);
654 5551e51d 2006-07-23 devnull break;
655 5551e51d 2006-07-23 devnull }
656 5551e51d 2006-07-23 devnull case FUSE_WRITE: {
657 5551e51d 2006-07-23 devnull struct fuse_write_out *rx = a;
658 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Write) size %d", rx->size);
659 5551e51d 2006-07-23 devnull break;
660 5551e51d 2006-07-23 devnull }
661 5551e51d 2006-07-23 devnull case FUSE_STATFS: {
662 5551e51d 2006-07-23 devnull /*
663 5551e51d 2006-07-23 devnull * Before protocol version 7.4, only first 48 bytes are used.
664 5551e51d 2006-07-23 devnull */
665 5551e51d 2006-07-23 devnull struct fuse_statfs_out *rx = a;
666 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Statfs) blocks %lld bfree %lld bavail %lld files %lld ffree %lld bsize %ud namelen %ud frsize %ud",
667 5551e51d 2006-07-23 devnull rx->st.blocks, rx->st.bfree, rx->st.bavail,
668 5551e51d 2006-07-23 devnull rx->st.files, rx->st.ffree, rx->st.bsize,
669 5551e51d 2006-07-23 devnull rx->st.namelen, rx->st.frsize);
670 5551e51d 2006-07-23 devnull break;
671 5551e51d 2006-07-23 devnull }
672 5551e51d 2006-07-23 devnull case FUSE_RELEASE: {
673 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Release)");
674 5551e51d 2006-07-23 devnull break;
675 5551e51d 2006-07-23 devnull }
676 5551e51d 2006-07-23 devnull case FUSE_FSYNC: {
677 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Fsync)");
678 5551e51d 2006-07-23 devnull break;
679 5551e51d 2006-07-23 devnull }
680 5551e51d 2006-07-23 devnull case FUSE_SETXATTR: {
681 d905d2f5 2012-09-08 rsc fmtprint(fmt, "(Setxattr)");
682 5551e51d 2006-07-23 devnull break;
683 5551e51d 2006-07-23 devnull }
684 5551e51d 2006-07-23 devnull case FUSE_GETXATTR: {
685 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Getxattr) size %d", len);
686 5551e51d 2006-07-23 devnull break;
687 5551e51d 2006-07-23 devnull }
688 5551e51d 2006-07-23 devnull case FUSE_LISTXATTR: {
689 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Lisrxattr) size %d", len);
690 5551e51d 2006-07-23 devnull break;
691 5551e51d 2006-07-23 devnull }
692 5551e51d 2006-07-23 devnull case FUSE_REMOVEXATTR: {
693 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Removexattr)");
694 5551e51d 2006-07-23 devnull break;
695 5551e51d 2006-07-23 devnull }
696 5551e51d 2006-07-23 devnull case FUSE_FLUSH: {
697 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Flush)");
698 5551e51d 2006-07-23 devnull break;
699 5551e51d 2006-07-23 devnull }
700 5551e51d 2006-07-23 devnull case FUSE_INIT: {
701 5551e51d 2006-07-23 devnull struct fuse_init_out *rx = a;
702 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Init) major %d minor %d max_write %d",
703 5551e51d 2006-07-23 devnull rx->major, rx->minor, rx->max_write);
704 5551e51d 2006-07-23 devnull break;
705 5551e51d 2006-07-23 devnull }
706 5551e51d 2006-07-23 devnull case FUSE_OPENDIR: {
707 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Opendir) ");
708 5551e51d 2006-07-23 devnull goto fmt_open_out;
709 5551e51d 2006-07-23 devnull break;
710 5551e51d 2006-07-23 devnull }
711 5551e51d 2006-07-23 devnull case FUSE_READDIR: {
712 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Readdir) size %d", len);
713 5551e51d 2006-07-23 devnull break;
714 5551e51d 2006-07-23 devnull }
715 5551e51d 2006-07-23 devnull case FUSE_RELEASEDIR: {
716 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Releasedir)");
717 5551e51d 2006-07-23 devnull break;
718 5551e51d 2006-07-23 devnull }
719 5551e51d 2006-07-23 devnull case FUSE_FSYNCDIR: {
720 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Fsyncdir)");
721 5551e51d 2006-07-23 devnull break;
722 5551e51d 2006-07-23 devnull }
723 5551e51d 2006-07-23 devnull case FUSE_ACCESS: {
724 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Access)");
725 5551e51d 2006-07-23 devnull break;
726 5551e51d 2006-07-23 devnull }
727 5551e51d 2006-07-23 devnull case FUSE_CREATE: {
728 5551e51d 2006-07-23 devnull struct fuse_create_out *rx = a;
729 5551e51d 2006-07-23 devnull fmtprint(fmt, "(Create) ");
730 5551e51d 2006-07-23 devnull fmtprint(fmt, "nodeid %#llux gen %#llux entry_valid %.20g attr_valid %.20g ",
731 5551e51d 2006-07-23 devnull rx->e.nodeid, rx->e.generation,
732 5551e51d 2006-07-23 devnull rx->e.entry_valid+rx->e.entry_valid_nsec*1e-9,
733 5551e51d 2006-07-23 devnull rx->e.attr_valid+rx->e.attr_valid_nsec*1e-9);
734 5551e51d 2006-07-23 devnull fmtprint(fmt, " ino %#llux size %lld blocks %lld atime %.20g mtime %.20g ctime %.20g mode %#uo nlink %d uid %d gid %d rdev %#ux",
735 5551e51d 2006-07-23 devnull rx->e.attr.ino, rx->e.attr.size, rx->e.attr.blocks,
736 fa325e9b 2020-01-10 cross rx->e.attr.atime+rx->e.attr.atimensec*1e-9,
737 5551e51d 2006-07-23 devnull rx->e.attr.mtime+rx->e.attr.mtimensec*1e-9,
738 5551e51d 2006-07-23 devnull rx->e.attr.ctime+rx->e.attr.ctimensec*1e-9,
739 5551e51d 2006-07-23 devnull rx->e.attr.mode, rx->e.attr.nlink, rx->e.attr.uid,
740 5551e51d 2006-07-23 devnull rx->e.attr.gid, rx->e.attr.rdev);
741 5551e51d 2006-07-23 devnull fmtprint(fmt, " fh %#llux flags %#ux", rx->o.fh, rx->o.open_flags);
742 5551e51d 2006-07-23 devnull break;
743 5551e51d 2006-07-23 devnull }
744 5551e51d 2006-07-23 devnull }
745 5551e51d 2006-07-23 devnull }
746 5551e51d 2006-07-23 devnull return 0;
747 5551e51d 2006-07-23 devnull }
748 9b3fcf01 2007-01-18 devnull
749 9b3fcf01 2007-01-18 devnull #if defined(__APPLE__)
750 9b3fcf01 2007-01-18 devnull #include <sys/param.h>
751 9b3fcf01 2007-01-18 devnull #include <sys/mount.h>
752 9b3fcf01 2007-01-18 devnull #endif
753 5551e51d 2006-07-23 devnull
754 143cdf57 2006-07-26 devnull /*
755 143cdf57 2006-07-26 devnull * Mounts a fuse file system on mtpt and returns
756 fa325e9b 2020-01-10 cross * a file descriptor for the corresponding fuse
757 143cdf57 2006-07-26 devnull * message conversation.
758 143cdf57 2006-07-26 devnull */
759 143cdf57 2006-07-26 devnull int
760 143cdf57 2006-07-26 devnull mountfuse(char *mtpt)
761 143cdf57 2006-07-26 devnull {
762 143cdf57 2006-07-26 devnull #if defined(__linux__)
763 143cdf57 2006-07-26 devnull int p[2], pid, fd;
764 143cdf57 2006-07-26 devnull char buf[20];
765 fa325e9b 2020-01-10 cross
766 143cdf57 2006-07-26 devnull if(socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
767 143cdf57 2006-07-26 devnull return -1;
768 143cdf57 2006-07-26 devnull pid = fork();
769 143cdf57 2006-07-26 devnull if(pid < 0)
770 143cdf57 2006-07-26 devnull return -1;
771 143cdf57 2006-07-26 devnull if(pid == 0){
772 143cdf57 2006-07-26 devnull close(p[1]);
773 143cdf57 2006-07-26 devnull snprint(buf, sizeof buf, "%d", p[0]);
774 143cdf57 2006-07-26 devnull putenv("_FUSE_COMMFD", buf);
775 143cdf57 2006-07-26 devnull execlp("fusermount", "fusermount", "--", mtpt, nil);
776 143cdf57 2006-07-26 devnull fprint(2, "exec fusermount: %r\n");
777 143cdf57 2006-07-26 devnull _exit(1);
778 143cdf57 2006-07-26 devnull }
779 143cdf57 2006-07-26 devnull close(p[0]);
780 143cdf57 2006-07-26 devnull fd = recvfd(p[1]);
781 143cdf57 2006-07-26 devnull close(p[1]);
782 143cdf57 2006-07-26 devnull return fd;
783 fd997ef0 2008-08-19 jas #elif defined(__FreeBSD__) && !defined(__APPLE__)
784 143cdf57 2006-07-26 devnull int pid, fd;
785 143cdf57 2006-07-26 devnull char buf[20];
786 fa325e9b 2020-01-10 cross
787 143cdf57 2006-07-26 devnull if((fd = open("/dev/fuse", ORDWR)) < 0)
788 143cdf57 2006-07-26 devnull return -1;
789 143cdf57 2006-07-26 devnull snprint(buf, sizeof buf, "%d", fd);
790 fa325e9b 2020-01-10 cross
791 143cdf57 2006-07-26 devnull pid = fork();
792 143cdf57 2006-07-26 devnull if(pid < 0)
793 143cdf57 2006-07-26 devnull return -1;
794 143cdf57 2006-07-26 devnull if(pid == 0){
795 143cdf57 2006-07-26 devnull execlp("mount_fusefs", "mount_fusefs", buf, mtpt, nil);
796 143cdf57 2006-07-26 devnull fprint(2, "exec mount_fusefs: %r\n");
797 143cdf57 2006-07-26 devnull _exit(1);
798 143cdf57 2006-07-26 devnull }
799 143cdf57 2006-07-26 devnull return fd;
800 9b3fcf01 2007-01-18 devnull #elif defined(__APPLE__)
801 f62d4c41 2021-02-01 crossd int i, pid, fd, r, p[2];
802 9b3fcf01 2007-01-18 devnull char buf[20];
803 9b3fcf01 2007-01-18 devnull struct vfsconf vfs;
804 d905d2f5 2012-09-08 rsc char *f, *v;
805 9f34853f 2017-02-10 rsc
806 9f34853f 2017-02-10 rsc if(getvfsbyname(v="osxfusefs", &vfs) < 0 &&
807 f62d4c41 2021-02-01 crossd getvfsbyname(v="macfuse", &vfs) < 0 &&
808 9f34853f 2017-02-10 rsc getvfsbyname(v="osxfuse", &vfs) < 0 &&
809 9f34853f 2017-02-10 rsc getvfsbyname(v="fusefs", &vfs) < 0){
810 d905d2f5 2012-09-08 rsc if(access((v="osxfusefs", f="/Library/Filesystems/osxfusefs.fs"
811 d905d2f5 2012-09-08 rsc "/Support/load_osxfusefs"), 0) < 0 &&
812 f62d4c41 2021-02-01 crossd access((v="macfuse", f="/Library/Filesystems/macfuse.fs"
813 f62d4c41 2021-02-01 crossd "/Contents/Resources/load_macfuse"), 0) < 0 &&
814 9f34853f 2017-02-10 rsc access((v="osxfuse", f="/Library/Filesystems/osxfuse.fs"
815 a5b24c22 2018-03-27 0intro "/Contents/Resources/load_osxfuse"), 0) < 0 &&
816 a5b24c22 2018-03-27 0intro access((v="osxfuse", f="/opt/local/Library/Filesystems/osxfuse.fs"
817 9f34853f 2017-02-10 rsc "/Contents/Resources/load_osxfuse"), 0) < 0 &&
818 d905d2f5 2012-09-08 rsc access((v="fusefs", f="/System/Library/Extensions/fusefs.kext"
819 d905d2f5 2012-09-08 rsc "/Contents/Resources/load_fusefs"), 0) < 0 &&
820 4c65127b 2007-01-24 devnull access(f="/Library/Extensions/fusefs.kext"
821 ebda53e1 2007-08-22 rsc "/Contents/Resources/load_fusefs", 0) < 0 &&
822 83ab7d88 2007-11-27 rsc access(f="/Library/Filesystems"
823 83ab7d88 2007-11-27 rsc "/fusefs.fs/Support/load_fusefs", 0) < 0 &&
824 ebda53e1 2007-08-22 rsc access(f="/System/Library/Filesystems"
825 ebda53e1 2007-08-22 rsc "/fusefs.fs/Support/load_fusefs", 0) < 0){
826 4c65127b 2007-01-24 devnull werrstr("cannot find load_fusefs");
827 4c65127b 2007-01-24 devnull return -1;
828 4c65127b 2007-01-24 devnull }
829 4c65127b 2007-01-24 devnull if((r=system(f)) < 0){
830 4c65127b 2007-01-24 devnull werrstr("%s: %r", f);
831 9b3fcf01 2007-01-18 devnull return -1;
832 9b3fcf01 2007-01-18 devnull }
833 9b3fcf01 2007-01-18 devnull if(r != 0){
834 9b3fcf01 2007-01-18 devnull werrstr("load_fusefs failed: exit %d", r);
835 9b3fcf01 2007-01-18 devnull return -1;
836 9b3fcf01 2007-01-18 devnull }
837 d905d2f5 2012-09-08 rsc if(getvfsbyname(v, &vfs) < 0){
838 d905d2f5 2012-09-08 rsc werrstr("getvfsbyname %s: %r", v);
839 9b3fcf01 2007-01-18 devnull return -1;
840 9b3fcf01 2007-01-18 devnull }
841 9b3fcf01 2007-01-18 devnull }
842 9f34853f 2017-02-10 rsc
843 f62d4c41 2021-02-01 crossd /* MacFUSE >=4 dropped support for passing fd */
844 f62d4c41 2021-02-01 crossd if (strcmp(v, "macfuse") == 0) {
845 f62d4c41 2021-02-01 crossd if(socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
846 f62d4c41 2021-02-01 crossd return -1;
847 f62d4c41 2021-02-01 crossd pid = fork();
848 f62d4c41 2021-02-01 crossd if(pid < 0)
849 f62d4c41 2021-02-01 crossd return -1;
850 f62d4c41 2021-02-01 crossd if(pid == 0){
851 f62d4c41 2021-02-01 crossd close(p[1]);
852 f62d4c41 2021-02-01 crossd snprint(buf, sizeof buf, "%d", p[0]);
853 f62d4c41 2021-02-01 crossd putenv("_FUSE_COMMFD", buf);
854 f62d4c41 2021-02-01 crossd putenv("_FUSE_COMMVERS", "2");
855 f62d4c41 2021-02-01 crossd putenv("_FUSE_CALL_BY_LIB", "1");
856 f62d4c41 2021-02-01 crossd putenv("_FUSE_DAEMON_PATH",
857 f62d4c41 2021-02-01 crossd "/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfus");
858 f62d4c41 2021-02-01 crossd execl("/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse",
859 f62d4c41 2021-02-01 crossd "mount_macfuse", mtpt, nil);
860 f62d4c41 2021-02-01 crossd fprint(2, "exec mount_macfuse: %r\n");
861 f62d4c41 2021-02-01 crossd _exit(1);
862 f62d4c41 2021-02-01 crossd }
863 f62d4c41 2021-02-01 crossd close(p[0]);
864 f62d4c41 2021-02-01 crossd fd = recvfd(p[1]);
865 f62d4c41 2021-02-01 crossd close(p[1]);
866 f62d4c41 2021-02-01 crossd return fd;
867 f62d4c41 2021-02-01 crossd }
868 f62d4c41 2021-02-01 crossd
869 9b3fcf01 2007-01-18 devnull /* Look for available FUSE device. */
870 9f34853f 2017-02-10 rsc /*
871 9f34853f 2017-02-10 rsc * We need to truncate `fs` from the end of the vfs name if
872 9f34853f 2017-02-10 rsc * it's present
873 9f34853f 2017-02-10 rsc */
874 9f34853f 2017-02-10 rsc int len;
875 9f34853f 2017-02-10 rsc if (strcmp(v, "osxfuse") == 0) {
876 9f34853f 2017-02-10 rsc len = strlen(v);
877 9f34853f 2017-02-10 rsc } else {
878 9f34853f 2017-02-10 rsc len = strlen(v)-2;
879 9f34853f 2017-02-10 rsc }
880 9b3fcf01 2007-01-18 devnull for(i=0;; i++){
881 9f34853f 2017-02-10 rsc snprint(buf, sizeof buf, "/dev/%.*s%d", len, v, i);
882 9b3fcf01 2007-01-18 devnull if(access(buf, 0) < 0){
883 9b3fcf01 2007-01-18 devnull werrstr("no available fuse devices");
884 9b3fcf01 2007-01-18 devnull return -1;
885 9b3fcf01 2007-01-18 devnull }
886 9b3fcf01 2007-01-18 devnull if((fd = open(buf, ORDWR)) >= 0)
887 9b3fcf01 2007-01-18 devnull break;
888 9b3fcf01 2007-01-18 devnull }
889 9b3fcf01 2007-01-18 devnull
890 9b3fcf01 2007-01-18 devnull pid = fork();
891 9b3fcf01 2007-01-18 devnull if(pid < 0)
892 9b3fcf01 2007-01-18 devnull return -1;
893 9b3fcf01 2007-01-18 devnull if(pid == 0){
894 9b3fcf01 2007-01-18 devnull snprint(buf, sizeof buf, "%d", fd);
895 9f34853f 2017-02-10 rsc /* OSXFUSE >=3.3 changed the name of the environment variable, set both */
896 9b3fcf01 2007-01-18 devnull putenv("MOUNT_FUSEFS_CALL_BY_LIB", "");
897 9f34853f 2017-02-10 rsc putenv("MOUNT_OSXFUSE_CALL_BY_LIB", "");
898 6654bd74 2007-06-20 devnull /*
899 9f34853f 2017-02-10 rsc * Different versions of OSXFUSE and MacFUSE put the
900 9f34853f 2017-02-10 rsc * mount_fusefs binary in different places. Try all.
901 6654bd74 2007-06-20 devnull */
902 9f34853f 2017-02-10 rsc /* OSXFUSE >=3.3 greater location */
903 9f34853f 2017-02-10 rsc putenv("MOUNT_OSXFUSE_DAEMON_PATH",
904 9f34853f 2017-02-10 rsc "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse");
905 9f34853f 2017-02-10 rsc execl("/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse",
906 9f34853f 2017-02-10 rsc "mount_osxfuse", buf, mtpt, nil);
907 a5b24c22 2018-03-27 0intro
908 a5b24c22 2018-03-27 0intro /* OSXFUSE >=3.3 from macports */
909 a5b24c22 2018-03-27 0intro putenv("MOUNT_OSXFUSE_DAEMON_PATH",
910 a5b24c22 2018-03-27 0intro "/opt/local/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse");
911 a5b24c22 2018-03-27 0intro execl("/opt/local/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse",
912 a5b24c22 2018-03-27 0intro "mount_osxfuse", buf, mtpt, nil);
913 9f34853f 2017-02-10 rsc
914 d905d2f5 2012-09-08 rsc /* Lion OSXFUSE location */
915 d905d2f5 2012-09-08 rsc putenv("MOUNT_FUSEFS_DAEMON_PATH",
916 d905d2f5 2012-09-08 rsc "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs");
917 d905d2f5 2012-09-08 rsc execl("/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs",
918 d905d2f5 2012-09-08 rsc "mount_osxfusefs", buf, mtpt, nil);
919 d905d2f5 2012-09-08 rsc
920 83ab7d88 2007-11-27 rsc /* Leopard location */
921 83ab7d88 2007-11-27 rsc putenv("MOUNT_FUSEFS_DAEMON_PATH",
922 83ab7d88 2007-11-27 rsc "/Library/Filesystems/fusefs.fs/Support/mount_fusefs");
923 83ab7d88 2007-11-27 rsc execl("/Library/Filesystems/fusefs.fs/Support/mount_fusefs",
924 83ab7d88 2007-11-27 rsc "mount_fusefs", buf, mtpt, nil);
925 83ab7d88 2007-11-27 rsc
926 83ab7d88 2007-11-27 rsc /* possible Tiger locations */
927 357cecc1 2007-01-18 devnull execl("/System/Library/Filesystems/fusefs.fs/mount_fusefs",
928 357cecc1 2007-01-18 devnull "mount_fusefs", buf, mtpt, nil);
929 6654bd74 2007-06-20 devnull execl("/System/Library/Filesystems/fusefs.fs/Support/mount_fusefs",
930 6654bd74 2007-06-20 devnull "mount_fusefs", buf, mtpt, nil);
931 9b3fcf01 2007-01-18 devnull fprint(2, "exec mount_fusefs: %r\n");
932 9b3fcf01 2007-01-18 devnull _exit(1);
933 9b3fcf01 2007-01-18 devnull }
934 9b3fcf01 2007-01-18 devnull return fd;
935 fa325e9b 2020-01-10 cross
936 143cdf57 2006-07-26 devnull #else
937 143cdf57 2006-07-26 devnull werrstr("cannot mount fuse on this system");
938 143cdf57 2006-07-26 devnull return -1;
939 143cdf57 2006-07-26 devnull #endif
940 a83ccf38 2006-07-27 devnull }
941 a83ccf38 2006-07-27 devnull
942 a83ccf38 2006-07-27 devnull void
943 a83ccf38 2006-07-27 devnull waitfuse(void)
944 a83ccf38 2006-07-27 devnull {
945 a83ccf38 2006-07-27 devnull waitpid();
946 143cdf57 2006-07-26 devnull }
947 143cdf57 2006-07-26 devnull
948 143cdf57 2006-07-26 devnull void
949 143cdf57 2006-07-26 devnull unmountfuse(char *mtpt)
950 143cdf57 2006-07-26 devnull {
951 143cdf57 2006-07-26 devnull int pid;
952 143cdf57 2006-07-26 devnull
953 143cdf57 2006-07-26 devnull pid = fork();
954 143cdf57 2006-07-26 devnull if(pid < 0)
955 143cdf57 2006-07-26 devnull return;
956 143cdf57 2006-07-26 devnull if(pid == 0){
957 143cdf57 2006-07-26 devnull #if defined(__linux__)
958 143cdf57 2006-07-26 devnull execlp("fusermount", "fusermount", "-u", "-z", "--", mtpt, nil);
959 143cdf57 2006-07-26 devnull fprint(2, "exec fusermount -u: %r\n");
960 143cdf57 2006-07-26 devnull #else
961 143cdf57 2006-07-26 devnull execlp("umount", "umount", mtpt, nil);
962 143cdf57 2006-07-26 devnull fprint(2, "exec umount: %r\n");
963 143cdf57 2006-07-26 devnull #endif
964 143cdf57 2006-07-26 devnull _exit(1);
965 143cdf57 2006-07-26 devnull }
966 143cdf57 2006-07-26 devnull waitpid();
967 143cdf57 2006-07-26 devnull }