perfuse.c revision 1.3 1 1.3 manu /* $NetBSD: perfuse.c,v 1.3 2010/08/28 03:46:21 manu Exp $ */
2 1.1 manu
3 1.1 manu /*-
4 1.1 manu * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
5 1.1 manu *
6 1.1 manu * Redistribution and use in source and binary forms, with or without
7 1.1 manu * modification, are permitted provided that the following conditions
8 1.1 manu * are met:
9 1.1 manu * 1. Redistributions of source code must retain the above copyright
10 1.1 manu * notice, this list of conditions and the following disclaimer.
11 1.1 manu * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 manu * notice, this list of conditions and the following disclaimer in the
13 1.1 manu * documentation and/or other materials provided with the distribution.
14 1.1 manu *
15 1.1 manu * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 1.1 manu * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 1.1 manu * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 1.1 manu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 1.1 manu * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 1.1 manu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 1.1 manu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 1.1 manu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 1.1 manu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 1.1 manu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 manu * POSSIBILITY OF SUCH DAMAGE.
26 1.1 manu */
27 1.1 manu
28 1.1 manu #include <stdio.h>
29 1.1 manu #include <unistd.h>
30 1.1 manu #include <stdlib.h>
31 1.1 manu #include <fcntl.h>
32 1.1 manu #include <string.h>
33 1.1 manu #include <errno.h>
34 1.1 manu #include <puffs.h>
35 1.1 manu #include <sys/types.h>
36 1.1 manu #include <sys/socket.h>
37 1.1 manu #include <sys/un.h>
38 1.1 manu
39 1.1 manu #define LIBPERFUSE
40 1.1 manu #include "perfuse.h"
41 1.1 manu #include "perfuse_if.h"
42 1.1 manu #include "perfuse_priv.h"
43 1.1 manu
44 1.1 manu int perfuse_diagflags = 0; /* global used only in DPRINTF/DERR/DWARN */
45 1.1 manu
46 1.1 manu static struct perfuse_state *init_state(void);
47 1.1 manu static int get_fd(const char *);
48 1.1 manu
49 1.1 manu static struct perfuse_state *
50 1.1 manu init_state(void)
51 1.1 manu {
52 1.1 manu struct perfuse_state *ps;
53 1.1 manu
54 1.1 manu if ((ps = malloc(sizeof(*ps))) == NULL)
55 1.1 manu DERR(EX_OSERR, "malloc failed");
56 1.1 manu
57 1.1 manu (void)memset(ps, 0, sizeof(*ps));
58 1.1 manu ps->ps_max_write = UINT_MAX;
59 1.1 manu ps->ps_max_readahead = UINT_MAX;
60 1.1 manu
61 1.1 manu return ps;
62 1.1 manu }
63 1.1 manu
64 1.1 manu
65 1.1 manu static int
66 1.1 manu get_fd(data)
67 1.1 manu const char *data;
68 1.1 manu {
69 1.1 manu char *string;
70 1.1 manu const char fdopt[] = "fd=";
71 1.1 manu char *lastp;
72 1.1 manu char *opt;
73 1.1 manu int fd = -1;
74 1.1 manu
75 1.1 manu if ((string = strdup(data)) == NULL)
76 1.1 manu return -1;
77 1.1 manu
78 1.1 manu for (opt = strtok_r(string, ",", &lastp);
79 1.1 manu opt != NULL;
80 1.1 manu opt = strtok_r(NULL, ",", &lastp)) {
81 1.1 manu if (strncmp(opt, fdopt, strlen(fdopt)) == 0) {
82 1.1 manu fd = atoi(opt + strlen(fdopt));
83 1.1 manu break;
84 1.1 manu }
85 1.1 manu }
86 1.1 manu
87 1.1 manu /*
88 1.1 manu * No file descriptor found
89 1.1 manu */
90 1.1 manu if (fd == -1)
91 1.1 manu errno = EINVAL;
92 1.1 manu
93 1.1 manu free(string);
94 1.1 manu return fd;
95 1.1 manu
96 1.1 manu }
97 1.1 manu
98 1.1 manu int
99 1.1 manu perfuse_open(path, flags, mode)
100 1.1 manu const char *path;
101 1.1 manu int flags;
102 1.1 manu mode_t mode;
103 1.1 manu {
104 1.2 manu int sv[2];
105 1.1 manu struct sockaddr_un sun;
106 1.1 manu struct sockaddr *sa;
107 1.2 manu char progname[] = _PATH_PERFUSED;
108 1.2 manu char minus_i[] = "-i";
109 1.2 manu char fdstr[16];
110 1.2 manu char *const argv[] = { progname, minus_i, fdstr, NULL};
111 1.2 manu char *const envp[] = { NULL };
112 1.1 manu
113 1.1 manu if (strcmp(path, _PATH_FUSE) != 0)
114 1.1 manu return open(path, flags, mode);
115 1.1 manu
116 1.2 manu if ((sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {
117 1.1 manu #ifdef PERFUSE_DEBUG
118 1.2 manu printf("%s:%d socket failed: %s\n",
119 1.1 manu __func__, __LINE__, strerror(errno));
120 1.1 manu #endif
121 1.1 manu return -1;
122 1.1 manu }
123 1.1 manu
124 1.1 manu sa = (struct sockaddr *)(void *)&sun;
125 1.1 manu sun.sun_len = sizeof(sun);
126 1.1 manu sun.sun_family = AF_LOCAL;
127 1.1 manu (void)strcpy(sun.sun_path, path);
128 1.1 manu
129 1.2 manu if (connect(sv[0], sa, (socklen_t)sun.sun_len) == 0)
130 1.2 manu return sv[0];
131 1.2 manu
132 1.2 manu
133 1.2 manu /*
134 1.2 manu * Attempt to run perfused on our own
135 1.2 manu * if it does not run yet; In that case
136 1.2 manu * we will talk using a socketpair
137 1.2 manu * instead of /dev/fuse.
138 1.2 manu */
139 1.2 manu if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) != 0) {
140 1.1 manu #ifdef PERFUSE_DEBUG
141 1.2 manu printf("%s:%d: socketpair failed: %s\n",
142 1.1 manu __func__, __LINE__, strerror(errno));
143 1.1 manu #endif
144 1.1 manu return -1;
145 1.1 manu }
146 1.1 manu
147 1.2 manu (void)sprintf(fdstr, "%d", sv[1]);
148 1.2 manu
149 1.2 manu switch(fork()) {
150 1.2 manu case -1:
151 1.2 manu #ifdef PERFUSE_DEBUG
152 1.2 manu printf("%s:%d: fork failed: %s\n",
153 1.2 manu __func__, __LINE__, strerror(errno));
154 1.2 manu #endif
155 1.2 manu return -1;
156 1.2 manu /* NOTREACHED */
157 1.2 manu break;
158 1.2 manu case 0:
159 1.2 manu (void)execve(argv[0], argv, envp);
160 1.2 manu #ifdef PERFUSE_DEBUG
161 1.2 manu printf("%s:%d: execve failed: %s\n",
162 1.2 manu __func__, __LINE__, strerror(errno));
163 1.2 manu #endif
164 1.2 manu return -1;
165 1.2 manu /* NOTREACHED */
166 1.2 manu break;
167 1.2 manu default:
168 1.2 manu break;
169 1.2 manu }
170 1.2 manu
171 1.2 manu return sv[0];
172 1.1 manu }
173 1.1 manu
174 1.1 manu
175 1.1 manu int
176 1.1 manu perfuse_mount(source, target, filesystemtype, mountflags, data)
177 1.1 manu const char *source;
178 1.1 manu const char *target;
179 1.1 manu const char *filesystemtype;
180 1.1 manu long mountflags;
181 1.1 manu const void *data;
182 1.1 manu {
183 1.1 manu int s;
184 1.1 manu #if 0
185 1.1 manu struct sockaddr_un sun;
186 1.1 manu #endif
187 1.1 manu size_t len;
188 1.1 manu struct perfuse_mount_out pmo;
189 1.1 manu
190 1.1 manu #ifdef PERFUSE_DEBUG
191 1.1 manu printf("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\")\n", __func__,
192 1.1 manu source, target, filesystemtype, mountflags, (const char *)data);
193 1.1 manu #endif
194 1.1 manu
195 1.1 manu #if 0
196 1.1 manu if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
197 1.1 manu err(EX_OSERR, "socket failed");
198 1.1 manu
199 1.1 manu sun.sun_len = sizeof(sun);
200 1.1 manu sun.sun_family = AF_LOCAL;
201 1.1 manu (void)strcpy(sun.sun_path, _PATH_FUSE);
202 1.1 manu
203 1.1 manu if (connect(s, (struct sockaddr *)&sun, sun.sun_len) == -1)
204 1.1 manu err(EX_UNAVAILABLE, "cannot connect to \"%s\"", _PATH_FUSE);
205 1.1 manu #endif
206 1.1 manu if ((s = get_fd(data)) == -1)
207 1.1 manu return -1;
208 1.1 manu
209 1.1 manu
210 1.1 manu pmo.pmo_len = sizeof(pmo);
211 1.1 manu pmo.pmo_len += source ? strlen(source) : 0;
212 1.1 manu pmo.pmo_len += target ? strlen(target) : 0;
213 1.1 manu pmo.pmo_len += filesystemtype ? strlen(filesystemtype) : 0;
214 1.1 manu pmo.pmo_len += data ? strlen(data) : 0;
215 1.1 manu pmo.pmo_error = 0;
216 1.1 manu pmo.pmo_unique = (uint64_t)-1;
217 1.1 manu
218 1.1 manu (void)strcpy(pmo.pmo_magic, PERFUSE_MOUNT_MAGIC);
219 1.1 manu pmo.pmo_source_len = source ? strlen(source) : 0;
220 1.1 manu pmo.pmo_target_len = target ? strlen(target) : 0;
221 1.1 manu pmo.pmo_filesystemtype_len =
222 1.1 manu filesystemtype ? strlen(filesystemtype) : 0;
223 1.1 manu pmo.pmo_mountflags = mountflags;
224 1.1 manu pmo.pmo_data_len = data ? strlen(data) : 0;
225 1.1 manu
226 1.1 manu
227 1.1 manu if (write(s, &pmo, sizeof(pmo)) != sizeof(pmo)) {
228 1.1 manu #ifdef PERFUSE_DEBUG
229 1.2 manu printf("%s:%d short write\n", __func__, __LINE__);
230 1.1 manu #endif
231 1.1 manu return -1;
232 1.1 manu }
233 1.1 manu
234 1.1 manu if (source) {
235 1.1 manu len = pmo.pmo_source_len;
236 1.1 manu if (write(s, source, len) != (ssize_t)len) {
237 1.1 manu #ifdef PERFUSE_DEBUG
238 1.2 manu printf("%s:%d short write\n", __func__, __LINE__);
239 1.1 manu #endif
240 1.1 manu return -1;
241 1.1 manu }
242 1.1 manu }
243 1.1 manu
244 1.1 manu if (target) {
245 1.1 manu len = pmo.pmo_target_len;
246 1.1 manu if (write(s, target, len) != (ssize_t)len) {
247 1.1 manu #ifdef PERFUSE_DEBUG
248 1.2 manu printf("%s:%d short write\n", __func__, __LINE__);
249 1.1 manu #endif
250 1.1 manu return -1;
251 1.1 manu }
252 1.1 manu }
253 1.1 manu
254 1.1 manu if (filesystemtype) {
255 1.1 manu len = pmo.pmo_filesystemtype_len;
256 1.1 manu if (write(s, filesystemtype, len) != (ssize_t)len) {
257 1.1 manu #ifdef PERFUSE_DEBUG
258 1.2 manu printf("%s:%d short write\n", __func__, __LINE__);
259 1.1 manu #endif
260 1.1 manu return -1;
261 1.1 manu }
262 1.1 manu }
263 1.1 manu
264 1.1 manu if (data) {
265 1.1 manu len = pmo.pmo_data_len;
266 1.1 manu if (write(s, data, len) != (ssize_t)len) {
267 1.1 manu #ifdef PERFUSE_DEBUG
268 1.2 manu printf("%s:%d short write\n", __func__, __LINE__);
269 1.1 manu #endif
270 1.1 manu return -1;
271 1.1 manu }
272 1.1 manu }
273 1.1 manu
274 1.1 manu return 0;
275 1.1 manu }
276 1.1 manu
277 1.1 manu
278 1.1 manu uint64_t
279 1.1 manu perfuse_next_unique(pu)
280 1.1 manu struct puffs_usermount *pu;
281 1.1 manu {
282 1.1 manu struct perfuse_state *ps;
283 1.1 manu
284 1.1 manu ps = puffs_getspecific(pu);
285 1.1 manu
286 1.1 manu return ps->ps_unique++;
287 1.1 manu }
288 1.1 manu
289 1.1 manu struct puffs_usermount *
290 1.1 manu perfuse_init(pc, pmi)
291 1.1 manu struct perfuse_callbacks *pc;
292 1.1 manu struct perfuse_mount_info *pmi;
293 1.1 manu {
294 1.1 manu struct perfuse_state *ps;
295 1.1 manu struct puffs_usermount *pu;
296 1.1 manu struct puffs_ops *pops;
297 1.1 manu char name[] = "perfuse";
298 1.1 manu unsigned int puffs_flags;
299 1.1 manu struct puffs_node *pn_root;
300 1.1 manu struct puffs_pathobj *po_root;
301 1.1 manu
302 1.1 manu ps = init_state();
303 1.2 manu ps->ps_owner_uid = pmi->pmi_uid;
304 1.1 manu
305 1.1 manu if (pmi->pmi_source)
306 1.1 manu ps->ps_source = strdup(pmi->pmi_source);
307 1.1 manu if (pmi->pmi_filesystemtype)
308 1.1 manu ps->ps_filesystemtype = strdup(pmi->pmi_filesystemtype);
309 1.1 manu ps->ps_target = strdup(pmi->pmi_target);
310 1.1 manu ps->ps_mountflags = pmi->pmi_mountflags;
311 1.1 manu
312 1.1 manu /*
313 1.1 manu * Some options are forbidden for non root users
314 1.1 manu */
315 1.2 manu if (ps->ps_owner_uid != 0)
316 1.1 manu ps->ps_mountflags |= MNT_NOSUID|MNT_NODEV;
317 1.1 manu
318 1.1 manu PUFFSOP_INIT(pops);
319 1.1 manu PUFFSOP_SET(pops, perfuse, fs, unmount);
320 1.1 manu PUFFSOP_SET(pops, perfuse, fs, statvfs);
321 1.1 manu PUFFSOP_SET(pops, perfuse, fs, sync);
322 1.1 manu PUFFSOP_SET(pops, perfuse, node, lookup);
323 1.1 manu PUFFSOP_SET(pops, perfuse, node, create);
324 1.1 manu PUFFSOP_SET(pops, perfuse, node, mknod);
325 1.1 manu PUFFSOP_SET(pops, perfuse, node, open);
326 1.1 manu PUFFSOP_SET(pops, perfuse, node, close);
327 1.1 manu PUFFSOP_SET(pops, perfuse, node, access);
328 1.1 manu PUFFSOP_SET(pops, perfuse, node, getattr);
329 1.1 manu PUFFSOP_SET(pops, perfuse, node, setattr);
330 1.1 manu PUFFSOP_SET(pops, perfuse, node, poll);
331 1.1 manu #if 0
332 1.1 manu PUFFSOP_SET(pops, perfuse, node, mmap);
333 1.1 manu #endif
334 1.1 manu PUFFSOP_SET(pops, perfuse, node, fsync);
335 1.1 manu PUFFSOP_SET(pops, perfuse, node, seek);
336 1.1 manu PUFFSOP_SET(pops, perfuse, node, remove);
337 1.1 manu PUFFSOP_SET(pops, perfuse, node, link);
338 1.1 manu PUFFSOP_SET(pops, perfuse, node, rename);
339 1.1 manu PUFFSOP_SET(pops, perfuse, node, mkdir);
340 1.1 manu PUFFSOP_SET(pops, perfuse, node, rmdir);
341 1.1 manu PUFFSOP_SET(pops, perfuse, node, symlink);
342 1.1 manu PUFFSOP_SET(pops, perfuse, node, readdir);
343 1.1 manu PUFFSOP_SET(pops, perfuse, node, readlink);
344 1.1 manu PUFFSOP_SET(pops, perfuse, node, reclaim);
345 1.1 manu PUFFSOP_SET(pops, perfuse, node, inactive);
346 1.1 manu PUFFSOP_SET(pops, perfuse, node, print);
347 1.1 manu PUFFSOP_SET(pops, perfuse, node, advlock);
348 1.1 manu PUFFSOP_SET(pops, perfuse, node, read);
349 1.1 manu PUFFSOP_SET(pops, perfuse, node, write);
350 1.1 manu
351 1.1 manu puffs_flags = PUFFS_FLAG_BUILDPATH | PUFFS_FLAG_HASHPATH;
352 1.1 manu if (perfuse_diagflags & PDF_PUFFS)
353 1.1 manu puffs_flags |= PUFFS_FLAG_OPDUMP;
354 1.1 manu
355 1.1 manu if ((pu = puffs_init(pops, _PATH_PUFFS, name, ps, puffs_flags)) == NULL)
356 1.1 manu DERR(EX_OSERR, "puffs_init failed");
357 1.1 manu
358 1.1 manu ps->ps_pu = pu;
359 1.1 manu
360 1.1 manu /*
361 1.1 manu * Setup filesystem root
362 1.1 manu */
363 1.1 manu pn_root = perfuse_new_pn(pu, NULL);
364 1.1 manu PERFUSE_NODE_DATA(pn_root)->pnd_ino = FUSE_ROOT_ID;
365 1.3 manu PERFUSE_NODE_DATA(pn_root)->pnd_parent = pn_root;
366 1.1 manu puffs_setroot(pu, pn_root);
367 1.1 manu ps->ps_fsid = pn_root->pn_va.va_fsid;
368 1.1 manu
369 1.1 manu po_root = puffs_getrootpathobj(pu);
370 1.1 manu if ((po_root->po_path = strdup("/")) == NULL)
371 1.1 manu DERRX(EX_OSERR, "perfuse_mount_start() failed");
372 1.1 manu
373 1.1 manu po_root->po_len = 1;
374 1.1 manu puffs_path_buildhash(pu, po_root);
375 1.1 manu
376 1.1 manu puffs_vattr_null(&pn_root->pn_va);
377 1.1 manu pn_root->pn_va.va_type = VDIR;
378 1.1 manu pn_root->pn_va.va_mode = 0755;
379 1.1 manu
380 1.1 manu ps->ps_root = pn_root;
381 1.1 manu
382 1.1 manu /*
383 1.1 manu * Callbacks
384 1.1 manu */
385 1.1 manu ps->ps_new_msg = pc->pc_new_msg;
386 1.1 manu ps->ps_xchg_msg = pc->pc_xchg_msg;
387 1.1 manu ps->ps_destroy_msg = pc->pc_destroy_msg;
388 1.1 manu ps->ps_get_inhdr = pc->pc_get_inhdr;
389 1.1 manu ps->ps_get_inpayload = pc->pc_get_inpayload;
390 1.1 manu ps->ps_get_outhdr = pc->pc_get_outhdr;
391 1.1 manu ps->ps_get_outpayload = pc->pc_get_outpayload;
392 1.1 manu
393 1.1 manu return pu;
394 1.1 manu }
395 1.1 manu
396 1.1 manu void
397 1.1 manu perfuse_setspecific(pu, priv)
398 1.1 manu struct puffs_usermount *pu;
399 1.1 manu void *priv;
400 1.1 manu {
401 1.1 manu struct perfuse_state *ps;
402 1.1 manu
403 1.1 manu ps = puffs_getspecific(pu);
404 1.1 manu ps->ps_private = priv;
405 1.1 manu
406 1.1 manu return;
407 1.1 manu }
408 1.1 manu
409 1.1 manu void *
410 1.1 manu perfuse_getspecific(pu)
411 1.1 manu struct puffs_usermount *pu;
412 1.1 manu {
413 1.1 manu struct perfuse_state *ps;
414 1.1 manu
415 1.1 manu ps = puffs_getspecific(pu);
416 1.1 manu
417 1.1 manu return ps->ps_private;
418 1.1 manu }
419 1.1 manu
420 1.1 manu int
421 1.1 manu perfuse_inloop(pu)
422 1.1 manu struct puffs_usermount *pu;
423 1.1 manu {
424 1.1 manu struct perfuse_state *ps;
425 1.1 manu
426 1.1 manu ps = puffs_getspecific(pu);
427 1.1 manu
428 1.1 manu return ps->ps_flags & PS_INLOOP;
429 1.1 manu }
430 1.1 manu
431 1.1 manu int
432 1.1 manu perfuse_mainloop(pu)
433 1.1 manu struct puffs_usermount *pu;
434 1.1 manu {
435 1.1 manu struct perfuse_state *ps;
436 1.1 manu
437 1.1 manu ps = puffs_getspecific(pu);
438 1.1 manu
439 1.1 manu ps->ps_flags |= PS_INLOOP;
440 1.1 manu if (puffs_mainloop(ps->ps_pu) != 0)
441 1.1 manu DERR(EX_OSERR, "puffs_mainloop failed");
442 1.1 manu DERR(EX_OSERR, "puffs_mainloop exit");
443 1.1 manu
444 1.1 manu /* NOTREACHED */
445 1.1 manu return -1;
446 1.1 manu }
447 1.1 manu
448 1.1 manu /* ARGSUSED0 */
449 1.1 manu uint64_t
450 1.1 manu perfuse_get_ino(pu, opc)
451 1.1 manu struct puffs_usermount *pu;
452 1.1 manu puffs_cookie_t opc;
453 1.1 manu {
454 1.1 manu return PERFUSE_NODE_DATA(opc)->pnd_ino;
455 1.1 manu }
456 1.2 manu
457 1.2 manu int
458 1.2 manu perfuse_unmount(pu)
459 1.2 manu struct puffs_usermount *pu;
460 1.2 manu {
461 1.2 manu struct perfuse_state *ps;
462 1.2 manu
463 1.2 manu ps = puffs_getspecific(pu);
464 1.2 manu
465 1.2 manu return unmount(ps->ps_target, MNT_FORCE);
466 1.2 manu }
467