From owner-svn-src-all@FreeBSD.ORG Sat Oct 13 23:54:27 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 49DC0EBF; Sat, 13 Oct 2012 23:54:27 +0000 (UTC) (envelope-from attilio@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2F4FB8FC0A; Sat, 13 Oct 2012 23:54:27 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q9DNsREq034604; Sat, 13 Oct 2012 23:54:27 GMT (envelope-from attilio@svn.freebsd.org) Received: (from attilio@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q9DNsQLJ034593; Sat, 13 Oct 2012 23:54:26 GMT (envelope-from attilio@svn.freebsd.org) Message-Id: <201210132354.q9DNsQLJ034593@svn.freebsd.org> From: Attilio Rao Date: Sat, 13 Oct 2012 23:54:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r241519 - in head: . sbin sbin/mount_fusefs sys/conf sys/fs/fuse sys/modules sys/modules/fuse X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Oct 2012 23:54:27 -0000 Author: attilio Date: Sat Oct 13 23:54:26 2012 New Revision: 241519 URL: http://svn.freebsd.org/changeset/base/241519 Log: Import a FreeBSD port of the FUSE Linux module. This has been developed during 2 summer of code mandates and being revived by gnn recently. The functionality in this commit mirrors entirely content of fusefs-kmod port, which doesn't need to be installed anymore for -CURRENT setups. In order to get some sparse technical notes, please refer to: http://lists.freebsd.org/pipermail/freebsd-fs/2012-March/013876.html or to the project branch: svn://svn.freebsd.org/base/projects/fuse/ which also contains granular history of changes happened during port refinements. This commit does not came from the branch reintegration itself because it seems svn is not behaving properly for this functionaly at the moment. Partly Sponsored by: Google, Summer of Code program 2005, 2011 Originally submitted by: ilya, Csaba Henk In collabouration with: pho Tested by: flo, gnn, Gustau Perez, Kevin Oberman MFC after: 2 months Added: head/sbin/mount_fusefs/ head/sbin/mount_fusefs/Makefile (contents, props changed) head/sbin/mount_fusefs/mount_fusefs.8 (contents, props changed) head/sbin/mount_fusefs/mount_fusefs.c (contents, props changed) head/sys/fs/fuse/ head/sys/fs/fuse/fuse.h (contents, props changed) head/sys/fs/fuse/fuse_debug.h (contents, props changed) head/sys/fs/fuse/fuse_device.c (contents, props changed) head/sys/fs/fuse/fuse_file.c (contents, props changed) head/sys/fs/fuse/fuse_file.h (contents, props changed) head/sys/fs/fuse/fuse_internal.c (contents, props changed) head/sys/fs/fuse/fuse_internal.h (contents, props changed) head/sys/fs/fuse/fuse_io.c (contents, props changed) head/sys/fs/fuse/fuse_io.h (contents, props changed) head/sys/fs/fuse/fuse_ipc.c (contents, props changed) head/sys/fs/fuse/fuse_ipc.h (contents, props changed) head/sys/fs/fuse/fuse_kernel.h (contents, props changed) head/sys/fs/fuse/fuse_main.c (contents, props changed) head/sys/fs/fuse/fuse_node.c (contents, props changed) head/sys/fs/fuse/fuse_node.h (contents, props changed) head/sys/fs/fuse/fuse_param.h (contents, props changed) head/sys/fs/fuse/fuse_vfsops.c (contents, props changed) head/sys/fs/fuse/fuse_vnops.c (contents, props changed) head/sys/modules/fuse/ head/sys/modules/fuse/Makefile (contents, props changed) Modified: head/UPDATING head/sbin/Makefile head/sys/conf/NOTES head/sys/conf/files head/sys/conf/options head/sys/modules/Makefile Modified: head/UPDATING ============================================================================== --- head/UPDATING Sat Oct 13 22:22:53 2012 (r241518) +++ head/UPDATING Sat Oct 13 23:54:26 2012 (r241519) @@ -24,6 +24,9 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10 disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20121014: + Import the FUSE kernel and userland support into base system. + 20121013: The GNU sort(1) program has been removed since the BSD-licensed sort(1) has been the default for quite some time and no serious Modified: head/sbin/Makefile ============================================================================== --- head/sbin/Makefile Sat Oct 13 22:22:53 2012 (r241518) +++ head/sbin/Makefile Sat Oct 13 23:54:26 2012 (r241519) @@ -49,6 +49,7 @@ SUBDIR=adjkerntz \ mksnap_ffs \ mount \ mount_cd9660 \ + mount_fusefs \ mount_msdosfs \ mount_nfs \ mount_ntfs \ Added: head/sbin/mount_fusefs/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sbin/mount_fusefs/Makefile Sat Oct 13 23:54:26 2012 (r241519) @@ -0,0 +1,33 @@ +# $FreeBSD$ + +.if defined(DEBUG) +DEBUG_FLAGS+= -D_DEBUG -g +.endif + +.if defined(DEBUG2G) +DEBUG_FLAGS+= -D_DEBUG2G -g +.endif + +.if defined(DEBUG3G) +DEBUG_FLAGS+= -D_DEBUG3G -g +.endif + +.if defined(DEBUG_MSG) +DEBUG_FLAGS+= -D_DEBUG_MSG +.endif + +.if defined(F4BVERS) +DEBUG_FLAGS+= -DFUSE4BSD_VERSION="\"${F4BVERS}\"" +.endif + +PROG= mount_fusefs +SRCS= mount_fusefs.c getmntopts.c +MAN8= mount_fusefs.8 +NO_MANCOMPRESS?= yes + +MOUNT= ${.CURDIR}/../mount +CFLAGS+= -I${MOUNT} + +.PATH: ${MOUNT} + +.include Added: head/sbin/mount_fusefs/mount_fusefs.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sbin/mount_fusefs/mount_fusefs.8 Sat Oct 13 23:54:26 2012 (r241519) @@ -0,0 +1,363 @@ +.\" Copyright (c) 1980, 1989, 1991, 1993 +.\" The Regents of the University of California. +.\" Copyright (c) 2005, 2006 Csaba Henk +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 11, 2012 +.Dt MOUNT_FUSEFS 8 +.Os +.Sh NAME +.Nm mount_fusefs +.Nd mount a Fuse file system daemon +.Sh SYNOPSIS +.Nm +.Op Fl A +.Op Fl S +.Op Fl v +.Op Fl D Ar fuse_daemon +.Op Fl O Ar daemon_opts +.Op Fl s Ar special +.Op Fl m Ar node +.Op Fl h +.Op Fl V +.Op Fl o Ar option ... +.Ar special node +.Op Ar fuse_daemon ... +.Sh DESCRIPTION +Basic usage is to start a fuse daemon on the given +.Ar special +file. In practice, the daemon is assigned a +.Ar special +file automatically, which can then be indentified via +.Xr fstat 1 . +That special file can then be mounted by +.Nm . +.Pp +However, the procedure of spawning a daemon will usually be automated +so that it is performed by +.Nm . +If the command invoking a given +.Ar fuse_daemon +is appended to the list of arguments, +.Nm +will call the +.Ar fuse_daemon +via that command. In that way the +.Ar fuse_daemon +will be instructed to attach itself to +.Ar special . +From that on mounting goes as in the simple case. (See +.Sx DAEMON MOUNTS . ) +.Pp +The +.Ar special +argument normally will be treated as the path of the special file to mount. +.Pp +However, if +.Pa auto +is passed as +.Ar special , +then +.Nm +will look for a suitable free fuse device by itself. +.Pp +Finally, if +.Ar special +is an integer it will be interpreted as the number +of the file descriptor of an already open fuse device +(used when the Fuse library invokes +.Nm . +(See +.Sx DAEMON MOUNTS ) . +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl A , Ic --reject-allow_other +Prohibit the +.Cm allow_other +mount flag. Intended for use in scripts and the +.Xr sudoers 5 +file. +.It Fl S , Ic --safe +Run in safe mode (i.e. reject invoking a filesystem daemon) +.It Fl v +Be verbose +.It Fl D, Ic --daemon Ar daemon +Call the specified +.Ar daemon +.It Fl O, Ic --daemon_opts Ar opts +Add +.Ar opts +to the daemon's command line +.It Fl s, Ic --special Ar special +Use +.Ar special +as special +.It Fl m, Ic --mountpath Ar node +Mount on +.Ar node +.It Fl h, Ic --help +Show help +.It Fl V, Ic --version +Show version information +.It Fl o +Mount options are specified via +.Fl o . +The following options are available (and also their negated versions, +by prefixing them with +.Dq no ) : +.Bl -tag -width indent +.It Cm default_permissions +Enable traditional (file mode based) permission checking in kernel +.It Cm allow_other +Do not apply +.Sx STRICT ACCESS POLICY . +Only root can use this option +.It Cm max_read Ns = Ns Ar n +Limit size of read requests to +.Ar n +.It Cm private +Refuse shared mounting of the daemon. This is the default behaviour, +to allow sharing, expicitly use +.Fl o Cm noprivate +.It Cm neglect_shares +Don't refuse unmounting if there are secondary mounts +.It Cm push_symlinks_in +Prefix absolute symlinks with the mountpoint +.El +.Pp +.El +.Pp +Besides the above mount options, there is a set of pseudo-mount options which +are supported by the Fuse library. One can list these by passing +.Fl h +to a Fuse daemon. Most of these options have effect only on the behaviour of +the daemon (that is, their scope is limited to userspace). However, +there are some which do require in-kernel support. +Currently the options supported by the kernel are: +.Bl -tag -width indent +.It Cm direct_io +Bypass the buffer cache system +.It Cm kernel_cache +By default cached buffers of a given file are flushed at each +.Xr open 2 . +This option disables this behaviour +.El +.Sh DAEMON MOUNTS +Usually users don't need to use +.Nm +directly, as the Fuse library enables Fuse daemons to invoke +.Nm . +That is, +.Pp +.Dl fuse_daemon device mountpoint +.Pp +has the same effect as +.Pp +.Dl mount_fusefs auto mountpoint fuse_daemon +.Pp +This is the recommended usage when you want basic usage +(eg, run the daemon at a low privilege level but mount it as root). +.Sh STRICT ACCESS POLICY +The strict access policy for Fuse filesystems lets one to use the filesystem +only if the filesystem daemon has the same credentials (uid, real uid, gid, +real gid) as the user. +.Pp +This is applied for Fuse mounts by default and only root can mount without +the strict access policy (ie. the +.Cm allow_other +mount option). +.Pp +This is to shield users from the daemon +.Dq spying +on their I/O activities. +.Pp +Users might opt to willingly relax strict access policy (as far they +are concerned) by doing their own secondary mount (See +.Sx SHARED MOUNTS ) . +.Sh SHARED MOUNTS +A Fuse daemon can be shared (ie. mounted multiple times). +When doing the first (primary) mount, the spawner and the mounter of the daemon +must have the same uid, or the mounter should be the superuser. +.Pp +After the primary mount is in place, secondary mounts can be done by anyone +unless this feature is disabled by +.Cm private . +The behaviour of a secondary mount is analogous to that of symbolic +links: they redirect all filesystem operations to the primary mount. +.Pp +Doing a secondary mount is like signing an agreement: by this action, the mounter +agrees that the Fuse daemon can trace her I/O activities. From then on +she is not banned from using the filesystem (either via her own mount or +via the primary mount), regardless whether +.Cm allow_other +is used or not. +.Pp +The device name of a secondary mount is the device name of the corresponding +primary mount, followed by a '#' character and the index of the secondary +mount; e.g. +.Pa /dev/fuse0#3 . +.Sh SECURITY +System administrators might want to use a custom mount policy (ie., one going +beyond the +.Va vfs.usermount +sysctl). The primary tool for such purposes is +.Xr sudo 8 . +However, given that +.Nm +is capable of invoking an arbitrary program, one must be careful when doing this. +.Nm +is designed in a way such that it makes that easy. For this purpose, +there are options which disable certain risky features (ie. +.Fl S +and +.Fl A ) , +and command line parsing is done in a flexible way: mixing options and +non-options is allowed, but processing them stops at the third non-option +argument (after the first two has been utilized as device and mountpoint). +The rest of the command line specifies the daemon and its arguments. +(Alternatively, the daemon, the special and the mount path can be +specified using the respective options.) Note that +.Nm +ignores the environment variable +.Ev POSIXLY_CORRECT +and always behaves as described. +.Pp +In general, to be as scripting / +.Xr sudoers 5 +friendly as possible, no information has a fixed +position in the command line, but once a given piece of information is +provided, subsequent arguments/options cannot override it (with the +exception of some non-critical ones). +.Sh ENVIRONMENT +.Bl -tag -width ".Ev MOUNT_FUSEFS_SAFE" +.It Ev MOUNT_FUSEFS_SAFE +This has the same effect as the +.Fl S +option. +.It Ev MOUNT_FUSEFS_VERBOSE +This has the same effect as the +.Fl v +option. +.It Ev MOUNT_FUSEFS_IGNORE_UNKNOWN +If set, +.Nm +will ignore uknown mount options. +.It Ev MOUNT_FUSEFS_CALL_BY_LIB +Adjust behaviour to the needs of the FUSE library. Currently it effects +help output. +.El +.Pp +Although the following variables don't have any effect on +.Nm +itself, they affect the behaviour of fuse daemons: +.Bl -tag -width ".Ev FUSE_DEV_NAME" +.It Ev FUSE_DEV_NAME +Device to attach. If not set, the multiplexer path +.Ar /dev/fuse +is used. +.It Ev FUSE_DEV_FD +File desciptor of an opened Fuse device to use. Overrides +.Ev FUSE_DEV_NAME . +.It Ev FUSE_NO_MOUNT +If set, the library won't attempt to mount the filesystem, even +if a mountpoint argument is supplied. +.El +.Sh FILES +.Bl -tag -width /dev/fuse +.It Pa /dev/fuse +Fuse device with which the kernel and Fuse daemons can communicate. +.It Pa /dev/fuse +The multiplexer path. An +.Xr open 2 +performed on it automatically is passed to a free Fuse device by the kernel +(which might be created just for this puprose). +.El +.Sh EXAMPLES +Mount the example filesystem in the Fuse distribution (from its directory): +either +.Pp +.Dl ./fusexmp /mnt/fuse +.Pp +or +.Pp +.Dl mount_fusefs auto /mnt/fuse ./fusexmp +.Pp +Doing the same in two steps, using +.Pa /dev/fuse0 : +.Pp +.Dl FUSE_DEV_NAME=/dev/fuse ./fusexmp && +.Dl mount_fusefs /dev/fuse /mnt/fuse +.Pp +A script wrapper for fusexmp which ensures that +.Nm +doesn't call any external utility and also provides a hacky +(non race-free) automatic device selection: +.Pp +.Dl #!/bin/sh -e +.Pp +.Dl FUSE_DEV_NAME=/dev/fuse fusexmp +.Dl mount_fusefs -S /dev/fuse /mnt/fuse \(lq$@\(rq +.Sh SEE ALSO +.Xr fstat 1 , +.Xr mount 8 , +.Xr umount 8 , +.Xr sudo 8 +.Sh CAVEATS +Secondary mounts should be unmounted via their device name. If an attempt is +made to be unmount them via their filesystem root path, the unmount request +will be forwarded to the primary mount path. +In general, unmounting by device name is less error-prone than by mount path +(although the latter will also work under normal circumstances). +.Pp +If the daemon is specified via the +.Fl D +and +.Fl O +options, it will be invoked via +.Xr system 3 , +and the daemon's command line will also have an +.Dq & +control operator appended, so that we don't have to wait for its termination. +You should use a simple command line when invoking the daemon via these options. +.Sh HISTORY +.Nm +appears as the part of the FreeBSD implementation of the Fuse userspace filesystem +framework (see http://fuse.sourceforge.net). This user interface is FreeBSD specific. +.Sh BUGS +.Ar special +is treated as a multiplexer if and only if it is literally the same as +.Pa auto +or +.Pa /dev/fuse . +Other paths which are equivalent with +.Pa /dev/fuse +(eg., +.Pa /../dev/fuse ) +are not. Added: head/sbin/mount_fusefs/mount_fusefs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sbin/mount_fusefs/mount_fusefs.c Sat Oct 13 23:54:26 2012 (r241519) @@ -0,0 +1,504 @@ +/*- + * Copyright (c) 2005 Jean-Sebastien Pedron + * Copyright (c) 2005 Csaba Henk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mntopts.h" + +#ifndef FUSE4BSD_VERSION +#define FUSE4BSD_VERSION "0.3.9-pre1" +#endif + +void __usage_short(void); +void usage(void); +void helpmsg(void); +void showversion(void); +int init_backgrounded(void); + +struct mntopt mopts[] = { + #define ALTF_PRIVATE 0x01 + { "private", 0, ALTF_PRIVATE, 1 }, + { "neglect_shares", 0, 0x02, 1 }, + { "push_symlinks_in", 0, 0x04, 1 }, + { "allow_other", 0, 0x08, 1 }, + { "default_permissions", 0, 0x10, 1 }, + #define ALTF_MAXREAD 0x20 + { "max_read=", 0, ALTF_MAXREAD, 1 }, + #define ALTF_SUBTYPE 0x40 + { "subtype=", 0, ALTF_SUBTYPE, 1 }, + #define ALTF_SYNC_UNMOUNT 0x80 + { "sync_unmount", 0, ALTF_SYNC_UNMOUNT, 1 }, + /* Linux specific options, we silently ignore them */ + { "fsname=", 0, 0x00, 1 }, + { "fd=", 0, 0x00, 1 }, + { "rootmode=", 0, 0x00, 1 }, + { "user_id=", 0, 0x00, 1 }, + { "group_id=", 0, 0x00, 1 }, + { "large_read", 0, 0x00, 1 }, + /* "nonempty", just the first two chars are stripped off during parsing */ + { "nempty", 0, 0x00, 1 }, + MOPT_STDOPTS, + MOPT_END +}; + +struct mntval { + int mv_flag; + void *mv_value; + int mv_len; +}; + +struct mntval mvals[] = { + { ALTF_MAXREAD, NULL, 0 }, + { ALTF_SUBTYPE, NULL, 0 }, + { 0, NULL, 0 } +}; + +char *progname; + +#define DEFAULT_MOUNT_FLAGS ALTF_PRIVATE | ALTF_SYNC_UNMOUNT + +int +main(int argc, char *argv[]) +{ + struct iovec *iov; + char ch = '\0'; + int mntflags, iovlen, verbose = 0; + char *dev = NULL, *dir = NULL, mntpath[MAXPATHLEN]; + char *devo = NULL, *diro = NULL; + char ndev[128], fdstr[15]; + int i, done = 0, reject_allow_other = 0, safe_level = 0; + int altflags = DEFAULT_MOUNT_FLAGS; + int __altflags = DEFAULT_MOUNT_FLAGS; + struct mntopt *mo; + struct mntval *mv; + static struct option longopts[] = { + {"reject-allow_other", no_argument, NULL, 'A'}, + {"safe", no_argument, NULL, 'S'}, + {"daemon", required_argument, NULL, 'D'}, + {"daemon_opts", required_argument, NULL, 'O'}, + {"special", required_argument, NULL, 's'}, + {"mountpath", required_argument, NULL, 'm'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {0,0,0,0} + }; + int pid = 0; + int fd = -1, fdx; + char *ep; + char *daemon_str = NULL, *daemon_opts = NULL; + + progname = argv[0]; + + /* + * We want a parsing routine which is not sensitive to + * the position of args/opts; it should extract the + * first two args and stop at the beginning of the rest. + * (This makes it easier to call mount_fusefs from external + * utils than it is with a strict "util flags args" syntax.) + */ + + iov = NULL; + iovlen = 0; + mntflags = 0; + /* All in all, I feel it more robust this way... */ + unsetenv("POSIXLY_CORRECT"); + if (getenv("MOUNT_FUSEFS_IGNORE_UNKNOWN")) + getmnt_silent = 1; + if (getenv("MOUNT_FUSEFS_VERBOSE")) + verbose = 1; + + do { + for (i = 0; i < 3; i++) { + if (optind < argc && argv[optind][0] != '-') { + if (dir) { + done = 1; + break; + } + if (dev) + dir = argv[optind]; + else + dev = argv[optind]; + optind++; + } + } + switch(ch) { + case 'A': + reject_allow_other = 1; + break; + case 'S': + safe_level = 1; + break; + case 'D': + if (daemon_str) + errx(1, "daemon specified inconsistently"); + daemon_str = optarg; + break; + case 'O': + if (daemon_opts) + errx(1, "daemon opts specified inconsistently"); + daemon_opts = optarg; + break; + case 'o': + getmntopts(optarg, mopts, &mntflags, &altflags); + for (mv = mvals; mv->mv_flag; ++mv) { + if (! (altflags & mv->mv_flag)) + continue; + for (mo = mopts; mo->m_flag; ++mo) { + char *p, *q; + + if (mo->m_flag != mv->mv_flag) + continue; + p = strstr(optarg, mo->m_option); + if (p) { + p += strlen(mo->m_option); + q = p; + while (*q != '\0' && *q != ',') + q++; + mv->mv_len = q - p + 1; + mv->mv_value = malloc(mv->mv_len); + memcpy(mv->mv_value, p, mv->mv_len - 1); + ((char *)mv->mv_value)[mv->mv_len - 1] = '\0'; + break; + } + } + } + break; + case 's': + if (devo) + errx(1, "special specified inconsistently"); + devo = optarg; + break; + case 'm': + if (diro) + errx(1, "mount path specified inconsistently"); + diro = optarg; + break; + case 'v': + verbose = 1; + break; + case 'h': + helpmsg(); + break; + case 'V': + showversion(); + break; + case '\0': + break; + case '?': + default: + usage(); + } + if (done) + break; + } while ((ch = getopt_long(argc, argv, "AvVho:SD:O:s:m:", longopts, NULL)) != -1); + + argc -= optind; + argv += optind; + + if (devo) { + if (dev) + errx(1, "special specified inconsistently"); + dev = devo; + } else if (diro) + errx(1, "if mountpoint is given via an option, special should also be given via an option"); + + if (diro) { + if (dir) + errx(1, "mount path specified inconsistently"); + dir = diro; + } + + if ((! dev) && argc > 0) { + dev = *argv++; + argc--; + } + + if ((! dir) && argc > 0) { + dir = *argv++; + argc--; + } + + if (! (dev && dir)) + errx(1, "missing special and/or mountpoint"); + + for (mo = mopts; mo->m_flag; ++mo) { + if (altflags & mo->m_flag) { + int iov_done = 0; + + if (reject_allow_other && + strcmp(mo->m_option, "allow_other") == 0) + /* + * reject_allow_other is stronger than a + * negative of allow_other: if this is set, + * allow_other is blocked, period. + */ + errx(1, "\"allow_other\" usage is banned by respective option"); + + for (mv = mvals; mv->mv_flag; ++mv) { + if (mo->m_flag != mv->mv_flag) + continue; + if (mv->mv_value) { + build_iovec(&iov, &iovlen, mo->m_option, mv->mv_value, mv->mv_len); + iov_done = 1; + break; + } + } + if (! iov_done) + build_iovec(&iov, &iovlen, mo->m_option, + __DECONST(void *, ""), -1); + } + if (__altflags & mo->m_flag) { + char *uscore_opt; + + if (asprintf(&uscore_opt, "__%s", mo->m_option) == -1) + err(1, "failed to allocate memory"); + build_iovec(&iov, &iovlen, uscore_opt, + __DECONST(void *, ""), -1); + free(uscore_opt); + } + } + + if (getenv("MOUNT_FUSEFS_SAFE")) + safe_level = 1; + + if (safe_level > 0 && (argc > 0 || daemon_str || daemon_opts)) + errx(1, "safe mode, spawning daemon not allowed"); + + if ((argc > 0 && (daemon_str || daemon_opts)) || + (daemon_opts && ! daemon_str)) + errx(1, "daemon specified inconsistently"); + + /* + * Resolve the mountpoint with realpath(3) and remove unnecessary + * slashes from the devicename if there are any. + */ + if (checkpath(dir, mntpath) != 0) + err(1, "%s", mntpath); + (void)rmslashes(dev, dev); + + if (strcmp(dev, "auto") == 0) + dev = __DECONST(char *, "/dev/fuse"); + + if (strcmp(dev, "/dev/fuse") == 0) { + if (! (argc > 0 || daemon_str)) { + fprintf(stderr, "Please also specify the fuse daemon to run when mounting via the multiplexer!\n"); + usage(); + } + if ((fd = open(dev, O_RDWR)) < 0) + err(1, "failed to open fuse device"); + } else { + fdx = strtol(dev, &ep, 10); + if (*ep == '\0') + fd = fdx; + } + + /* Identifying device */ + if (fd >= 0) { + struct stat sbuf; + char *ndevbas, *lep; + + if (fstat(fd, &sbuf) == -1) + err(1, "cannot stat device file descriptor"); + + strcpy(ndev, _PATH_DEV); + ndevbas = ndev + strlen(_PATH_DEV); + devname_r(sbuf.st_rdev, S_IFCHR, ndevbas, + sizeof(ndev) - strlen(_PATH_DEV)); + + if (strncmp(ndevbas, "fuse", 4)) + errx(1, "mounting inappropriate device"); + + strtol(ndevbas + 4, &lep, 10); + if (*lep != '\0') + errx(1, "mounting inappropriate device"); + + dev = ndev; + } + + if (argc > 0 || daemon_str) { + char *fds; + + if (fd < 0 && (fd = open(dev, O_RDWR)) < 0) + err(1, "failed to open fuse device"); + + if (asprintf(&fds, "%d", fd) == -1) + err(1, "failed to allocate memory"); + setenv("FUSE_DEV_FD", fds, 1); + free(fds); + setenv("FUSE_NO_MOUNT", "1", 1); + + if (daemon_str) { + char *bgdaemon; + int len; + + if (! daemon_opts) + daemon_opts = __DECONST(char *, ""); + + len = strlen(daemon_str) + 1 + strlen(daemon_opts) + + 2 + 1; + bgdaemon = calloc(1, len); + + if (! bgdaemon) + err(1, "failed to allocate memory"); + + strlcpy(bgdaemon, daemon_str, len); + strlcat(bgdaemon, " ", len); + strlcat(bgdaemon, daemon_opts, len); + strlcat(bgdaemon, " &", len); + + if (system(bgdaemon)) + err(1, "failed to call fuse daemon"); + } else { + if ((pid = fork()) < 0) + err(1, "failed to fork for fuse daemon"); + + if (pid == 0) { + execvp(argv[0], argv); + err(1, "failed to exec fuse daemon"); + } + } + } + + if (fd >= 0 && ! init_backgrounded() && close(fd) < 0) { + if (pid) + kill(pid, SIGKILL); + err(1, "failed to close fuse device"); + } + + /* Prepare the options vector for nmount(). build_iovec() is declared + * in mntopts.h. */ + sprintf(fdstr, "%d", fd); + build_iovec(&iov, &iovlen, "fstype", __DECONST(void *, "fusefs"), -1); + build_iovec(&iov, &iovlen, "fspath", mntpath, -1); + build_iovec(&iov, &iovlen, "from", dev, -1); + build_iovec(&iov, &iovlen, "fd", fdstr, -1); + + if (verbose) + fprintf(stderr, "mounting fuse daemon on device %s\n", dev); + + if (nmount(iov, iovlen, mntflags) < 0) + err(EX_OSERR, "%s on %s", dev, mntpath); + + exit(0); +} + +void +__usage_short(void) { + fprintf(stderr, + "usage:\n%s [-A|-S|-v|-V|-h|-D daemon|-O args|-s special|-m node|-o option...] special node [daemon args...]\n\n", + basename(progname)); +} + +void +usage(void) +{ + struct mntopt *mo; + + __usage_short(); + + fprintf(stderr, "known options:\n"); + for (mo = mopts; mo->m_flag; ++mo) + fprintf(stderr, "\t%s\n", mo->m_option); + + fprintf(stderr, "\n(use -h for a detailed description of these options)\n"); + exit(EX_USAGE); +} + +void +helpmsg(void) +{ + if (! getenv("MOUNT_FUSEFS_CALL_BY_LIB")) { + __usage_short(); + fprintf(stderr, "description of options:\n"); + } + + /* + * The main use case of this function is giving info embedded in general + * FUSE lib help output. Therefore the style and the content of the output + * tries to fit there as much as possible. + */ + fprintf(stderr, + " -o allow_other allow access to other users\n" + /* " -o nonempty allow mounts over non-empty file/dir\n" */ + " -o default_permissions enable permission checking by kernel\n" + /* + " -o fsname=NAME set filesystem name\n" + " -o large_read issue large read requests (2.4 only)\n" + */ + " -o subtype=NAME set filesystem type\n" + " -o max_read=N set maximum size of read requests\n" + " -o noprivate allow secondary mounting of the filesystem\n" + " -o neglect_shares don't report EBUSY when unmount attempted\n" + " in presence of secondary mounts\n" + " -o push_symlinks_in prefix absolute symlinks with mountpoint\n" + " -o sync_unmount do unmount synchronously\n" + ); + exit(EX_USAGE); +} + +void +showversion(void) +{ + puts("mount_fusefs [fuse4bsd] version: " FUSE4BSD_VERSION); + exit(EX_USAGE); +} + +int +init_backgrounded(void) +{ + int ibg; + size_t len; + + len = sizeof(ibg); + + if (sysctlbyname("vfs.fuse.init_backgrounded", &ibg, &len, NULL, 0)) + return (0); + + return (ibg); +} Modified: head/sys/conf/NOTES ============================================================================== --- head/sys/conf/NOTES Sat Oct 13 22:22:53 2012 (r241518) +++ head/sys/conf/NOTES Sat Oct 13 23:54:26 2012 (r241519) @@ -1003,6 +1003,7 @@ options NFSCLIENT #Network File System # The rest are optional: options CD9660 #ISO 9660 filesystem options FDESCFS #File descriptor filesystem +options FUSE #FUSE support module options HPFS #OS/2 File system options MSDOSFS #MS DOS File System (FAT, FAT32) options NFSSERVER #Network File System server Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Sat Oct 13 22:22:53 2012 (r241518) +++ head/sys/conf/files Sat Oct 13 23:54:26 2012 (r241519) @@ -2317,6 +2317,15 @@ fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard +fs/fuse/fuse_device.c optional fuse +fs/fuse/fuse_file.c optional fuse +fs/fuse/fuse_internal.c optional fuse +fs/fuse/fuse_io.c optional fuse +fs/fuse/fuse_ipc.c optional fuse +fs/fuse/fuse_main.c optional fuse +fs/fuse/fuse_node.c optional fuse +fs/fuse/fuse_vfsops.c optional fuse +fs/fuse/fuse_vnops.c optional fuse fs/hpfs/hpfs_alsubr.c optional hpfs fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs Modified: head/sys/conf/options ============================================================================== --- head/sys/conf/options Sat Oct 13 22:22:53 2012 (r241518) +++ head/sys/conf/options Sat Oct 13 23:54:26 2012 (r241519) @@ -211,6 +211,7 @@ CODA opt_dontuse.h EXT2FS opt_dontuse.h FDESCFS opt_dontuse.h FFS opt_dontuse.h +FUSE opt_dontuse.h HPFS opt_dontuse.h MSDOSFS opt_dontuse.h NANDFS opt_dontuse.h Added: head/sys/fs/fuse/fuse.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/fs/fuse/fuse.h Sat Oct 13 23:54:26 2012 (r241519) @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2007-2009 Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***