10 int mountfuse(char *mtpt);
11 void unmountfuse(char *mtpt);
20 if((m = fusemsglist) != nil){
21 fusemsglist = m->next;
26 m = emalloc(sizeof(*m) + fusebufsize);
36 freefusemsg(FuseMsg *m)
39 m->next = fusemsglist;
52 * The FUSE kernel device apparently guarantees
53 * that this read will return exactly one message.
54 * You get an error return if you ask for just the
55 * length (first 4 bytes).
56 * FUSE returns an ENODEV error, not EOF,
57 * when the connection is unmounted.
61 n = read(fusefd, m->buf, fusebufsize);
62 }while(n < 0 && errno == EINTR);
65 sysfatal("readfusemsg: %r");
75 * FreeBSD FUSE sends a short length in the header
76 * for FUSE_INIT even though the actual read length
79 if(n == sizeof(*m->hdr)+sizeof(struct fuse_init_in)
80 && m->hdr->opcode == FUSE_INIT && m->hdr->len < n)
84 sysfatal("readfusemsg: got %d wanted %d",
86 m->hdr->len -= sizeof(*m->hdr);
90 * Make sure lengths are long enough.
91 * Make sure string arguments are NUL terminated.
92 * (I don't trust the kernel module.)
94 switch(m->hdr->opcode){
97 * Could sysfatal here, but can also let message go
98 * and assume higher-level code will return an
99 * "I don't know what you mean" error and recover.
105 case FUSE_REMOVEXATTR:
107 if(((char*)m->tx)[m->hdr->len-1] != 0)
109 sysfatal("readfusemsg: bad message");
112 if(m->hdr->len < sizeof(struct fuse_forget_in))
118 if(m->hdr->len < sizeof(struct fuse_setattr_in))
125 if(((char*)m->tx)[m->hdr->len-1] != 0
126 || memchr(m->tx, 0, m->hdr->len-1) == 0)
130 if(m->hdr->len <= sizeof(struct fuse_mknod_in)
131 || ((char*)m->tx)[m->hdr->len-1] != 0)
135 if(m->hdr->len <= sizeof(struct fuse_mkdir_in)
136 || ((char*)m->tx)[m->hdr->len-1] != 0)
140 /* a struct and two strings */
141 if(m->hdr->len <= sizeof(struct fuse_rename_in)
142 || ((char*)m->tx)[m->hdr->len-1] != 0
143 || memchr((uchar*)m->tx+sizeof(struct fuse_rename_in), 0, m->hdr->len-sizeof(struct fuse_rename_in)-1) == 0)
147 if(m->hdr->len <= sizeof(struct fuse_link_in)
148 || ((char*)m->tx)[m->hdr->len-1] != 0)
153 if(m->hdr->len < sizeof(struct fuse_open_in))
158 if(m->hdr->len < sizeof(struct fuse_read_in))
162 /* no strings, but check that write length is sane */
163 if(m->hdr->len < sizeof(struct fuse_write_in)+((struct fuse_write_in*)m->tx)->size)
169 case FUSE_RELEASEDIR:
170 if(m->hdr->len < sizeof(struct fuse_release_in))
175 if(m->hdr->len < sizeof(struct fuse_fsync_in))
179 /* struct, one string, and one binary blob */
180 if(m->hdr->len <= sizeof(struct fuse_setxattr_in))
182 nn = ((struct fuse_setxattr_in*)m->tx)->size;
183 if(m->hdr->len < sizeof(struct fuse_setxattr_in)+nn+1)
185 if(((char*)m->tx)[m->hdr->len-nn-1] != 0)
189 /* struct and one string */
190 if(m->hdr->len <= sizeof(struct fuse_getxattr_in)
191 || ((char*)m->tx)[m->hdr->len-1] != 0)
195 if(m->hdr->len < sizeof(struct fuse_getxattr_in))
199 if(m->hdr->len < sizeof(struct fuse_flush_in))
203 if(m->hdr->len < sizeof(struct fuse_init_in))
207 if(m->hdr->len < sizeof(struct fuse_access_in))
211 if(m->hdr->len <= sizeof(struct fuse_open_in)
212 || ((char*)m->tx)[m->hdr->len-1] != 0)
217 fprint(2, "FUSE -> %G\n", m->hdr, m->tx);
222 * Reply to FUSE request m using additonal
223 * argument buffer arg of size narg bytes.
224 * Perhaps should free the FuseMsg here?
227 replyfuse(FuseMsg *m, void *arg, int narg)
230 struct fuse_out_header hdr;
233 hdr.len = sizeof hdr + narg;
235 hdr.unique = m->hdr->unique;
237 fprint(2, "FUSE <- %#G\n", m->hdr, &hdr, arg);
239 vec[0].iov_base = &hdr;
240 vec[0].iov_len = sizeof hdr;
243 vec[1].iov_base = arg;
244 vec[1].iov_len = narg;
247 writev(fusefd, vec, nvec);
252 * Reply to FUSE request m with errno e.
255 replyfuseerrno(FuseMsg *m, int e)
257 struct fuse_out_header hdr;
259 hdr.len = sizeof hdr;
260 hdr.error = -e; /* FUSE sends negative errnos. */
261 hdr.unique = m->hdr->unique;
263 fprint(2, "FUSE <- %#G\n", m->hdr, &hdr, 0);
264 write(fusefd, &hdr, sizeof hdr);
269 replyfuseerrstr(FuseMsg *m)
271 replyfuseerrno(m, errstr2errno());
279 unmountfuse(fusemtpt);
286 struct fuse_init_in *tx;
287 struct fuse_init_out rx;
292 * The 4096 is for the message headers.
293 * It's a lot, but it's what the FUSE libraries ask for.
295 fusemaxwrite = getpagesize();
296 fusebufsize = 4096 + fusemaxwrite;
298 if((fusefd = mountfuse(mtpt)) < 0)
299 sysfatal("mountfuse: %r");
301 if((m = readfusemsg()) == nil)
302 sysfatal("readfusemsg: %r");
303 if(m->hdr->opcode != FUSE_INIT)
304 sysfatal("fuse: expected FUSE_INIT (26) got %d", m->hdr->opcode);
308 * Complain if the kernel is too new.
309 * We could forge ahead, but at least the one time I tried,
310 * the kernel rejected the newer version by making the
311 * writev fail in replyfuse, which is a much more confusing
312 * error message. In the future, might be nice to try to
313 * support older versions that differ only slightly.
315 if(tx->major < FUSE_KERNEL_VERSION
316 || (tx->major == FUSE_KERNEL_VERSION && tx->minor < FUSE_KERNEL_MINOR_VERSION))
317 sysfatal("fuse: too kernel version %d.%d older than program version %d.%d",
318 tx->major, tx->minor, FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
320 memset(&rx, 0, sizeof rx);
321 rx.major = FUSE_KERNEL_VERSION;
322 rx.minor = FUSE_KERNEL_MINOR_VERSION;
323 rx.max_write = fusemaxwrite;
324 replyfuse(m, &rx, sizeof rx);
328 * Print FUSE messages. Assuming it is installed as %G,
329 * use %G with hdr, arg arguments to format a request,
330 * and %#G with reqhdr, hdr, arg arguments to format a response.
331 * The reqhdr is necessary in the %#G form because the
332 * response does not contain an opcode tag.
337 struct fuse_in_header *hdr = va_arg(fmt->args, void*);
338 if((fmt->flags&FmtSharp) == 0){ /* "%G", hdr, arg */
339 void *a = va_arg(fmt->args, void*);
340 fmtprint(fmt, "len %d unique %#llux uid %d gid %d pid %d ",
341 hdr->len, hdr->unique, hdr->uid, hdr->gid, hdr->pid);
345 fmtprint(fmt, "??? opcode %d", hdr->opcode);
349 fmtprint(fmt, "Lookup nodeid %#llux name %#q",
354 struct fuse_forget_in *tx = a;
355 /* nlookup (a ref count) is a vlong! */
356 fmtprint(fmt, "Forget nodeid %#llux nlookup %lld",
357 hdr->nodeid, tx->nlookup);
361 fmtprint(fmt, "Getattr nodeid %#llux", hdr->nodeid);
365 struct fuse_setattr_in *tx = a;
366 fmtprint(fmt, "Setattr nodeid %#llux", hdr->nodeid);
367 if(tx->valid&FATTR_FH)
368 fmtprint(fmt, " fh %#llux", tx->fh);
369 if(tx->valid&FATTR_SIZE)
370 fmtprint(fmt, " size %lld", tx->size);
371 if(tx->valid&FATTR_ATIME)
372 fmtprint(fmt, " atime %.20g", tx->atime+tx->atimensec*1e-9);
373 if(tx->valid&FATTR_MTIME)
374 fmtprint(fmt, " mtime %.20g", tx->mtime+tx->mtimensec*1e-9);
375 if(tx->valid&FATTR_MODE)
376 fmtprint(fmt, " mode %#uo", tx->mode);
377 if(tx->valid&FATTR_UID)
378 fmtprint(fmt, " uid %d", tx->uid);
379 if(tx->valid&FATTR_GID)
380 fmtprint(fmt, " gid %d", tx->gid);
383 case FUSE_READLINK: {
384 fmtprint(fmt, "Readlink nodeid %#llux", hdr->nodeid);
391 new = a + strlen(a) + 1;
392 fmtprint(fmt, "Symlink nodeid %#llux old %#q new %#q",
393 hdr->nodeid, old, new);
397 struct fuse_mknod_in *tx = a;
398 fmtprint(fmt, "Mknod nodeid %#llux mode %#uo rdev %#ux name %#q",
399 hdr->nodeid, tx->mode, tx->rdev, tx+1);
403 struct fuse_mkdir_in *tx = a;
404 fmtprint(fmt, "Mkdir nodeid %#llux mode %#uo name %#q",
405 hdr->nodeid, tx->mode, tx+1);
409 fmtprint(fmt, "Unlink nodeid %#llux name %#q",
414 fmtprint(fmt, "Rmdir nodeid %#llux name %#q",
419 struct fuse_rename_in *tx = a;
420 char *old = (char*)(tx+1);
421 char *new = old + strlen(old) + 1;
422 fmtprint(fmt, "Rename nodeid %#llux old %#q newdir %#llux new %#q",
423 hdr->nodeid, old, tx->newdir, new);
427 struct fuse_link_in *tx = a;
428 fmtprint(fmt, "Link oldnodeid %#llux nodeid %#llux name %#q",
429 tx->oldnodeid, hdr->nodeid, tx+1);
433 struct fuse_open_in *tx = a;
434 /* Should one or both of flags and mode be octal? */
435 fmtprint(fmt, "Open nodeid %#llux flags %#ux mode %#ux",
436 hdr->nodeid, tx->flags, tx->mode);
440 struct fuse_read_in *tx = a;
441 fmtprint(fmt, "Read nodeid %#llux fh %#llux offset %lld size %ud",
442 hdr->nodeid, tx->fh, tx->offset, tx->size);
446 struct fuse_write_in *tx = a;
447 fmtprint(fmt, "Write nodeid %#llux fh %#llux offset %lld size %ud flags %#ux",
448 hdr->nodeid, tx->fh, tx->offset, tx->size, tx->write_flags);
452 fmtprint(fmt, "Statfs");
456 struct fuse_release_in *tx = a;
457 fmtprint(fmt, "Release nodeid %#llux fh %#llux flags %#ux",
458 hdr->nodeid, tx->fh, tx->flags);
462 struct fuse_fsync_in *tx = a;
463 fmtprint(fmt, "Fsync nodeid %#llux fh %#llux flags %#ux",
464 hdr->nodeid, tx->fh, tx->fsync_flags);
467 case FUSE_SETXATTR: {
468 struct fuse_setxattr_in *tx = a;
469 char *name = (char*)(tx+1);
470 char *value = name + strlen(name) + 1;
471 fmtprint(fmt, "Setxattr nodeid %#llux size %d flags %#ux name %#q value %#q",
472 hdr->nodeid, tx->size, tx->flags, name, value);
475 case FUSE_GETXATTR: {
476 struct fuse_getxattr_in *tx = a;
477 fmtprint(fmt, "Getxattr nodeid %#llux size %d name %#q",
478 hdr->nodeid, tx->size, tx+1);
481 case FUSE_LISTXATTR: {
482 struct fuse_getxattr_in *tx = a;
483 fmtprint(fmt, "Listxattr nodeid %#llux size %d",
484 hdr->nodeid, tx->size);
487 case FUSE_REMOVEXATTR: {
488 fmtprint(fmt, "Removexattr nodeid %#llux name %#q",
493 struct fuse_flush_in *tx = a;
494 fmtprint(fmt, "Flush nodeid %#llux fh %#llux flags %#ux",
495 hdr->nodeid, tx->fh, tx->flush_flags);
499 struct fuse_init_in *tx = a;
500 fmtprint(fmt, "Init major %d minor %d",
501 tx->major, tx->minor);
505 struct fuse_open_in *tx = a;
506 fmtprint(fmt, "Opendir nodeid %#llux flags %#ux mode %#ux",
507 hdr->nodeid, tx->flags, tx->mode);
511 struct fuse_read_in *tx = a;
512 fmtprint(fmt, "Readdir nodeid %#llux fh %#llux offset %lld size %ud",
513 hdr->nodeid, tx->fh, tx->offset, tx->size);
516 case FUSE_RELEASEDIR: {
517 struct fuse_release_in *tx = a;
518 fmtprint(fmt, "Releasedir nodeid %#llux fh %#llux flags %#ux",
519 hdr->nodeid, tx->fh, tx->flags);
522 case FUSE_FSYNCDIR: {
523 struct fuse_fsync_in *tx = a;
524 fmtprint(fmt, "Fsyncdir nodeid %#llux fh %#llux flags %#ux",
525 hdr->nodeid, tx->fh, tx->fsync_flags);
529 struct fuse_access_in *tx = a;
530 fmtprint(fmt, "Access nodeid %#llux mask %#ux",
531 hdr->nodeid, tx->mask);
535 struct fuse_open_in *tx = a;
536 fmtprint(fmt, "Create nodeid %#llx flags %#ux mode %#ux name %#q",
537 hdr->nodeid, tx->flags, tx->mode, tx+1);
541 }else{ /* "%#G", reqhdr, hdr, arg - use reqhdr only for type */
542 struct fuse_out_header *ohdr = va_arg(fmt->args, void*);
543 void *a = va_arg(fmt->args, void*);
544 int len = ohdr->len - sizeof *ohdr;
545 fmtprint(fmt, "unique %#llux ", ohdr->unique);
547 fmtprint(fmt, "error %d %s", ohdr->error, strerror(-ohdr->error));
551 fmtprint(fmt, "??? opcode %d", hdr->opcode);
556 * For a negative entry, can send back ENOENT
558 * In protocol version 7.4 and before, can only use
560 * Presumably the benefit of sending rx->ino == 0
561 * is that you can specify the length of time to cache
562 * the negative result.
564 struct fuse_entry_out *rx;
565 fmtprint(fmt, "(Lookup) ");
568 fmtprint(fmt, "nodeid %#llux gen %#llux entry_valid %.20g attr_valid %.20g ",
569 rx->nodeid, rx->generation,
570 rx->entry_valid+rx->entry_valid_nsec*1e-9,
571 rx->attr_valid+rx->attr_valid_nsec*1e-9);
572 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 rx->attr.ino, rx->attr.size, rx->attr.blocks,
574 rx->attr.atime+rx->attr.atimensec*1e-9,
575 rx->attr.mtime+rx->attr.mtimensec*1e-9,
576 rx->attr.ctime+rx->attr.ctimensec*1e-9,
577 rx->attr.mode, rx->attr.nlink, rx->attr.uid,
578 rx->attr.gid, rx->attr.rdev);
582 /* Can't happen! No reply. */
583 fmtprint(fmt, "(Forget) can't happen");
587 struct fuse_attr_out *rx;
588 fmtprint(fmt, "(Getattr) ");
591 fmtprint(fmt, "attr_valid %.20g",
592 rx->attr_valid+rx->attr_valid_nsec*1e-9);
593 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 rx->attr.ino, rx->attr.size, rx->attr.blocks,
595 rx->attr.atime+rx->attr.atimensec*1e-9,
596 rx->attr.mtime+rx->attr.mtimensec*1e-9,
597 rx->attr.ctime+rx->attr.ctimensec*1e-9,
598 rx->attr.mode, rx->attr.nlink, rx->attr.uid,
599 rx->attr.gid, rx->attr.rdev);
603 fmtprint(fmt, "(Setattr) ");
607 case FUSE_READLINK: {
608 fmtprint(fmt, "(Readlink) %#.*q",
613 fmtprint(fmt, "(Symlink) ");
618 fmtprint(fmt, "(Mknod) ");
623 fmtprint(fmt, "(Mkdir) ");
628 fmtprint(fmt, "(Unlink)");
632 fmtprint(fmt, "(Rmdir)");
636 fmtprint(fmt, "(Rename)");
640 fmtprint(fmt, "(Link) ");
645 struct fuse_open_out *rx;
646 fmtprint(fmt, "(Open) ");
649 fmtprint(fmt, "fh %#llux flags %#ux", rx->fh, rx->open_flags);
653 fmtprint(fmt, "(Read) size %d", len);
657 struct fuse_write_out *rx = a;
658 fmtprint(fmt, "(Write) size %d", rx->size);
663 * Before protocol version 7.4, only first 48 bytes are used.
665 struct fuse_statfs_out *rx = a;
666 fmtprint(fmt, "(Statfs) blocks %lld bfree %lld bavail %lld files %lld ffree %lld bsize %ud namelen %ud frsize %ud",
667 rx->st.blocks, rx->st.bfree, rx->st.bavail,
668 rx->st.files, rx->st.ffree, rx->st.bsize,
669 rx->st.namelen, rx->st.frsize);
673 fmtprint(fmt, "(Release)");
677 fmtprint(fmt, "(Fsync)");
680 case FUSE_SETXATTR: {
681 fmtprint(fmt, "(Setxattr)");
684 case FUSE_GETXATTR: {
685 fmtprint(fmt, "(Getxattr) size %d", len);
688 case FUSE_LISTXATTR: {
689 fmtprint(fmt, "(Lisrxattr) size %d", len);
692 case FUSE_REMOVEXATTR: {
693 fmtprint(fmt, "(Removexattr)");
697 fmtprint(fmt, "(Flush)");
701 struct fuse_init_out *rx = a;
702 fmtprint(fmt, "(Init) major %d minor %d max_write %d",
703 rx->major, rx->minor, rx->max_write);
707 fmtprint(fmt, "(Opendir) ");
712 fmtprint(fmt, "(Readdir) size %d", len);
715 case FUSE_RELEASEDIR: {
716 fmtprint(fmt, "(Releasedir)");
719 case FUSE_FSYNCDIR: {
720 fmtprint(fmt, "(Fsyncdir)");
724 fmtprint(fmt, "(Access)");
728 struct fuse_create_out *rx = a;
729 fmtprint(fmt, "(Create) ");
730 fmtprint(fmt, "nodeid %#llux gen %#llux entry_valid %.20g attr_valid %.20g ",
731 rx->e.nodeid, rx->e.generation,
732 rx->e.entry_valid+rx->e.entry_valid_nsec*1e-9,
733 rx->e.attr_valid+rx->e.attr_valid_nsec*1e-9);
734 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 rx->e.attr.ino, rx->e.attr.size, rx->e.attr.blocks,
736 rx->e.attr.atime+rx->e.attr.atimensec*1e-9,
737 rx->e.attr.mtime+rx->e.attr.mtimensec*1e-9,
738 rx->e.attr.ctime+rx->e.attr.ctimensec*1e-9,
739 rx->e.attr.mode, rx->e.attr.nlink, rx->e.attr.uid,
740 rx->e.attr.gid, rx->e.attr.rdev);
741 fmtprint(fmt, " fh %#llux flags %#ux", rx->o.fh, rx->o.open_flags);
749 #if defined(__APPLE__)
750 #include <sys/param.h>
751 #include <sys/mount.h>
755 * Mounts a fuse file system on mtpt and returns
756 * a file descriptor for the corresponding fuse
757 * message conversation.
760 mountfuse(char *mtpt)
762 #if defined(__linux__)
766 if(socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
773 snprint(buf, sizeof buf, "%d", p[0]);
774 putenv("_FUSE_COMMFD", buf);
775 execlp("fusermount", "fusermount", "--", mtpt, nil);
776 fprint(2, "exec fusermount: %r\n");
783 #elif defined(__FreeBSD__) && !defined(__APPLE__)
787 if((fd = open("/dev/fuse", ORDWR)) < 0)
789 snprint(buf, sizeof buf, "%d", fd);
795 execlp("mount_fusefs", "mount_fusefs", buf, mtpt, nil);
796 fprint(2, "exec mount_fusefs: %r\n");
800 #elif defined(__APPLE__)
801 int i, pid, fd, r, p[2];
806 if(getvfsbyname(v="osxfusefs", &vfs) < 0 &&
807 getvfsbyname(v="macfuse", &vfs) < 0 &&
808 getvfsbyname(v="osxfuse", &vfs) < 0 &&
809 getvfsbyname(v="fusefs", &vfs) < 0){
810 if(access((v="osxfusefs", f="/Library/Filesystems/osxfusefs.fs"
811 "/Support/load_osxfusefs"), 0) < 0 &&
812 access((v="macfuse", f="/Library/Filesystems/macfuse.fs"
813 "/Contents/Resources/load_macfuse"), 0) < 0 &&
814 access((v="osxfuse", f="/Library/Filesystems/osxfuse.fs"
815 "/Contents/Resources/load_osxfuse"), 0) < 0 &&
816 access((v="osxfuse", f="/opt/local/Library/Filesystems/osxfuse.fs"
817 "/Contents/Resources/load_osxfuse"), 0) < 0 &&
818 access((v="fusefs", f="/System/Library/Extensions/fusefs.kext"
819 "/Contents/Resources/load_fusefs"), 0) < 0 &&
820 access(f="/Library/Extensions/fusefs.kext"
821 "/Contents/Resources/load_fusefs", 0) < 0 &&
822 access(f="/Library/Filesystems"
823 "/fusefs.fs/Support/load_fusefs", 0) < 0 &&
824 access(f="/System/Library/Filesystems"
825 "/fusefs.fs/Support/load_fusefs", 0) < 0){
826 werrstr("cannot find load_fusefs");
829 if((r=system(f)) < 0){
830 werrstr("%s: %r", f);
834 werrstr("load_fusefs failed: exit %d", r);
837 if(getvfsbyname(v, &vfs) < 0){
838 werrstr("getvfsbyname %s: %r", v);
843 /* MacFUSE >=4 dropped support for passing fd */
844 if (strcmp(v, "macfuse") == 0) {
845 if(socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
852 snprint(buf, sizeof buf, "%d", p[0]);
853 putenv("_FUSE_COMMFD", buf);
854 putenv("_FUSE_COMMVERS", "2");
855 putenv("_FUSE_CALL_BY_LIB", "1");
856 putenv("_FUSE_DAEMON_PATH",
857 "/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfus");
858 execl("/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse",
859 "mount_macfuse", mtpt, nil);
860 fprint(2, "exec mount_macfuse: %r\n");
869 /* Look for available FUSE device. */
871 * We need to truncate `fs` from the end of the vfs name if
875 if (strcmp(v, "osxfuse") == 0) {
881 snprint(buf, sizeof buf, "/dev/%.*s%d", len, v, i);
882 if(access(buf, 0) < 0){
883 werrstr("no available fuse devices");
886 if((fd = open(buf, ORDWR)) >= 0)
894 snprint(buf, sizeof buf, "%d", fd);
895 /* OSXFUSE >=3.3 changed the name of the environment variable, set both */
896 putenv("MOUNT_FUSEFS_CALL_BY_LIB", "");
897 putenv("MOUNT_OSXFUSE_CALL_BY_LIB", "");
899 * Different versions of OSXFUSE and MacFUSE put the
900 * mount_fusefs binary in different places. Try all.
902 /* OSXFUSE >=3.3 greater location */
903 putenv("MOUNT_OSXFUSE_DAEMON_PATH",
904 "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse");
905 execl("/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse",
906 "mount_osxfuse", buf, mtpt, nil);
908 /* OSXFUSE >=3.3 from macports */
909 putenv("MOUNT_OSXFUSE_DAEMON_PATH",
910 "/opt/local/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse");
911 execl("/opt/local/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse",
912 "mount_osxfuse", buf, mtpt, nil);
914 /* Lion OSXFUSE location */
915 putenv("MOUNT_FUSEFS_DAEMON_PATH",
916 "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs");
917 execl("/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs",
918 "mount_osxfusefs", buf, mtpt, nil);
920 /* Leopard location */
921 putenv("MOUNT_FUSEFS_DAEMON_PATH",
922 "/Library/Filesystems/fusefs.fs/Support/mount_fusefs");
923 execl("/Library/Filesystems/fusefs.fs/Support/mount_fusefs",
924 "mount_fusefs", buf, mtpt, nil);
926 /* possible Tiger locations */
927 execl("/System/Library/Filesystems/fusefs.fs/mount_fusefs",
928 "mount_fusefs", buf, mtpt, nil);
929 execl("/System/Library/Filesystems/fusefs.fs/Support/mount_fusefs",
930 "mount_fusefs", buf, mtpt, nil);
931 fprint(2, "exec mount_fusefs: %r\n");
937 werrstr("cannot mount fuse on this system");
949 unmountfuse(char *mtpt)
957 #if defined(__linux__)
958 execlp("fusermount", "fusermount", "-u", "-z", "--", mtpt, nil);
959 fprint(2, "exec fusermount -u: %r\n");
961 execlp("umount", "umount", mtpt, nil);
962 fprint(2, "exec umount: %r\n");