Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Mar 2009 22:03:56 +0900 (YAKT)
From:      Alexander Logvinov <ports@logvinov.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        Alexander Logvinov <ports@logvinov.com>
Subject:   ports/132309: [new port] sysutils/afuse: An automounting file system implemented in user-space using FUSE
Message-ID:  <200903041303.n24D3u3m040469@blg.akavia.ru>
Resent-Message-ID: <200903041310.n24DA1m3090432@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         132309
>Category:       ports
>Synopsis:       [new port] sysutils/afuse: An automounting file system implemented in user-space using FUSE
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 04 13:10:00 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Alexander Logvinov
>Release:        FreeBSD 6.4-RELEASE i386
>Organization:
>Environment:

>Description:

Afuse is an automounting file system implemented in user-space using
FUSE. Afuse currently implements the most basic functionality that can
be expected by an automounter; that is it manages a directory of virtual
directories. If one of these virtual directories is accessed and is not
already automounted, afuse will attempt to mount a filesystem onto that
directory. If the mount succeeds the requested access proceeds as normal,
otherwise it will fail with an error..

The advantage of using afuse over traditional automounters is that afuse
is designed to run entirely in user-space by individual users. This way an
automounting action can take advantage of the invoking users environment,
for example allowing access to an ssh-agent for password-less sshfs
mounts, or allowing access to a graphical environment to get user input
to complete a mount (i.e. popping up a window asking for a password).

WWW: http://afuse.sourceforge.net/

>How-To-Repeat:

>Fix:

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	afuse
#	afuse/Makefile
#	afuse/distinfo
#	afuse/pkg-descr
#	afuse/files
#	afuse/files/patch-src_afuse.c
#	afuse/files/pkg-message.in
#	afuse/files/patch-afuse.1
#
echo c - afuse
mkdir -p afuse > /dev/null 2>&1
echo x - afuse/Makefile
sed 's/^X//' >afuse/Makefile << '416b85b4c6a572ca95e68de5466748c7'
X# New ports collection makefile for:	afuse
X# Date created: 			03 March 2009
X# Whom:					Alexander Logvinov <ports@logvinov.com>
X# $FreeBSD$
X#
X
XPORTNAME=	afuse
XPORTVERSION=	0.2
XCATEGORIES=	sysutils
XMASTER_SITES=	SF
X
XMAINTAINER=	ports@logvinov.com
XCOMMENT=	An automounting file system implemented in user-space using FUSE
X
XLIB_DEPENDS=	fuse.2:${PORTSDIR}/sysutils/fusefs-libs
X
XGNU_CONFIGURE=	yes
X
XPORTDOCS=	AUTHORS ChangeLog README
XPLIST_FILES=	bin/${PORTNAME}
X
XMAN1=		${PORTNAME}.1
X
X.if !defined(NOPORTDOCS)
XSUB_FILES=	pkg-message
X.endif
X
Xpost-install:
X	${INSTALL_MAN} ${WRKSRC}/${MAN1} ${MAN1PREFIX}/man/man1
X.if !defined(NOPORTDOCS)
X	@${MKDIR} ${DOCSDIR}
X.for i in ${PORTDOCS}
X	${INSTALL_DATA} ${WRKSRC}/${i} ${DOCSDIR}
X.endfor
X	@${CAT} ${PKGMESSAGE}
X.endif
X
X.include <bsd.port.mk>
416b85b4c6a572ca95e68de5466748c7
echo x - afuse/distinfo
sed 's/^X//' >afuse/distinfo << '8b365b92e4a45ed6ed842ef9f6182750'
XMD5 (afuse-0.2.tar.gz) = 97b58a768ecb30696fb6c33dd8435b83
XSHA256 (afuse-0.2.tar.gz) = 92faa853bfeaa1446b80edbc6bb29a29f8dcf07149958be5eafc2da0679342d2
XSIZE (afuse-0.2.tar.gz) = 100568
8b365b92e4a45ed6ed842ef9f6182750
echo x - afuse/pkg-descr
sed 's/^X//' >afuse/pkg-descr << '31932f0f76660a761d8e5734a9c8e643'
XAfuse is an automounting file system implemented in user-space using
XFUSE. Afuse currently implements the most basic functionality that can
Xbe expected by an automounter; that is it manages a directory of virtual
Xdirectories. If one of these virtual directories is accessed and is not
Xalready automounted, afuse will attempt to mount a filesystem onto that
Xdirectory. If the mount succeeds the requested access proceeds as normal,
Xotherwise it will fail with an error. 
X
XThe advantage of using afuse over traditional automounters is that afuse
Xis designed to run entirely in user-space by individual users. This way an
Xautomounting action can take advantage of the invoking users environment,
Xfor example allowing access to an ssh-agent for password-less sshfs
Xmounts, or allowing access to a graphical environment to get user input
Xto complete a mount (i.e. popping up a window asking for a password).
X
XWWW: http://afuse.sourceforge.net/
31932f0f76660a761d8e5734a9c8e643
echo c - afuse/files
mkdir -p afuse/files > /dev/null 2>&1
echo x - afuse/files/patch-src_afuse.c
sed 's/^X//' >afuse/files/patch-src_afuse.c << '559bfbccfb0f4a3953d94d5d920a5dd4'
X--- src/afuse.c.orig	2009-03-03 13:17:22.000000000 +0900
X+++ src/afuse.c	2009-03-03 13:17:27.000000000 +0900
X@@ -36,7 +36,6 @@
X #include <string.h>
X #include <stddef.h>
X #include <unistd.h>
X-#include <alloca.h>
X #include <fcntl.h>
X #include <dirent.h>
X #include <errno.h>
X@@ -280,14 +280,19 @@
X }
X 
X 
X-// !!FIXME!! allow escaping of %'s
X // Note: this method strips out quotes and applies them itself as should be appropriate
X-char *expand_template(const char *template, const char *mount_point, const char *root_name)
X+bool run_template(const char *template, const char *mount_point, const char *root_name)
X {
X 	int len = 0;
X+	int nargs = 1;
X 	int i;
X-	char *expanded_name;
X-	char *expanded_name_start;
X+	char *buf;
X+	char *p;
X+	char **args;
X+	char **arg;
X+	bool quote = false;
X+	pid_t pid;
X+	int status;
X 
X 	// calculate length
X 	for(i = 0; template[i]; i++)
X@@ -295,53 +300,100 @@
X 			switch(template[i + 1])
X 			{
X 				case 'm':
X-					len += strlen(mount_point) + 2;
X+					len += strlen(mount_point);
X 					i++;
X 					break;
X 				case 'r':
X-					len += strlen(root_name) + 2;
X+					len += strlen(root_name);
X+					i++;
X+					break;
X+				case '%':
X+					len++;
X 					i++;
X 					break;
X 			}
X-		} else if(template[i] != '"')
X+		} else if(template[i] == ' ' && !quote) {
X+			len++;
X+			nargs++;
X+		} else if(template[i] == '"')
X+			quote = !quote;
X+		else if(template[i] == '\\' && template[i + 1])
X+			len++, i++;
X+		else
X 			len++;
X 
X-	expanded_name_start = expanded_name = my_malloc(len + 1);
X+	buf = my_malloc(len + 1);
X+	args = my_malloc((nargs + 1) * sizeof(*args));
X+
X+	p = buf;
X+	arg = args;
X+	*arg++ = p;
X 
X 	for(i = 0; template[i]; i++)
X 		if(template[i] == '%') {
X-			int j = 0;
X 			switch(template[i + 1])
X 			{
X 				case 'm':
X-					*expanded_name++ = '"';
X-					while(mount_point[j])
X-						*expanded_name++ = mount_point[j++];
X-					*expanded_name++ = '"';
X+					strcpy(p, mount_point);
X+					p += strlen(mount_point);
X 					i++;
X 					break;
X 				case 'r':
X-					*expanded_name++ = '"';
X-					while(root_name[j])
X-						*expanded_name++ = root_name[j++];
X-					*expanded_name++ = '"';
X+					strcpy(p, root_name);
X+					p += strlen(root_name);
X+					i++;
X+					break;
X+				case '%':
X+					*p++ = '%';
X 					i++;
X 					break;
X 			}
X-		} else if(template[i] != '"')
X-			*expanded_name++ = template[i];
X-
X-	*expanded_name = '\0';
X-
X-	return expanded_name_start;
X+		} else if(template[i] == ' ' && !quote) {
X+			*p++ = '\0';
X+			*arg++ = p;
X+		} else if(template[i] == '"')
X+			quote = !quote;
X+		else if(template[i] == '\\' && template[i + 1])
X+			*p++ = template[++i];
X+		else
X+			*p++ = template[i];
X+
X+	*p = '\0';
X+	*arg = NULL;
X+
X+	pid = fork();
X+	if(pid == -1) {
X+		fprintf(stderr, "Failed to fork (%s)\n", strerror(errno));
X+		free(args);
X+		free(buf);
X+		return false;
X+	}
X+	if(pid == 0) {
X+		execvp(args[0], args);
X+		abort();
X+	}
X+	pid = waitpid(pid, &status, 0);
X+	if(pid == -1) {
X+		fprintf(stderr, "Failed to waitpid (%s)\n", strerror(errno));
X+		free(args);
X+		free(buf);
X+		return false;
X+	}
X+	if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
X+		fprintf(stderr, "Failed to invoke command: %s\n", args[0]);
X+		free(args);
X+		free(buf);
X+		return false;
X+	}
X+	free(args);
X+	free(buf);
X+	return true;
X }
X 
X mount_list_t *do_mount(const char *root_name)
X {
X 	char *mount_point;
X-	char *mount_command;
X 	mount_list_t *mount;
X-	int sysret;
X 
X 	fprintf(stderr, "Mounting: %s\n", root_name);
X 
X@@ -351,57 +403,33 @@
X 		return NULL;
X 	}
X 
X-	mount_command = expand_template(user_options.mount_command_template,
X-	                                mount_point, root_name);
X-	sysret = system(mount_command);
X-
X-	fprintf(stderr, "sysret: %.8x\n", sysret);
X-
X-	if(sysret) {
X-		fprintf(stderr, "Failed to invoke mount command: '%s' (%s)\n",
X-			mount_command, sysret != -1 ?
X-				"Error executing mount" :
X-				strerror(errno));
X-
X+	if(!run_template(user_options.mount_command_template,
X+			 mount_point, root_name)) {
X 		// remove the now unused directory
X 		if( rmdir(mount_point) == -1 )
X 			fprintf(stderr, "Failed to remove mount point dir: %s (%s)",
X 				mount_point, strerror(errno));
X 
X-		free(mount_command);
X 		free(mount_point);
X 		return NULL;
X 	}
X 
X 	mount = add_mount(root_name, mount_point);
X-
X-	free(mount_command);
X 	return mount;
X }
X 
X int do_umount(mount_list_t *mount)
X {
X-	char *unmount_command;
X-	int sysret;
X-
X 	fprintf(stderr, "Unmounting: %s\n", mount->root_name);
X 
X-	unmount_command = expand_template(user_options.unmount_command_template,
X-	                                  mount->mount_point, mount->root_name);
X-	sysret = system(unmount_command);
X-	if(sysret) {
X-		fprintf(stderr, "Failed to invoke unmount command: '%s' (%s)\n",
X-		        unmount_command, sysret != -1 ?
X-			               "Error executing mount" :
X-				       strerror(errno));
X-		/* Still unmount anyway */
X-	}
X+	run_template(user_options.unmount_command_template,
X+		     mount->mount_point, mount->root_name);
X+	/* Still unmount anyway */
X 
X 	if( rmdir(mount->mount_point) == -1 )
X 		fprintf(stderr, "Failed to remove mount point dir: %s (%s)",
X 				mount->mount_point, strerror(errno));
X 	remove_mount(mount);
X-	free(unmount_command);
X 	return 1;
X }
X 
X@@ -1504,7 +1504,8 @@
X 	fuse_opt_add_arg(&args, "-s");
X 
X 	// Adjust user specified timeout from seconds to microseconds as required
X-	user_options.auto_unmount_delay *= 1000000;
X+	if(user_options.auto_unmount_delay != UINT64_MAX)
X+	    user_options.auto_unmount_delay *= 1000000;
X 
X 	auto_unmount_ph_init(&auto_unmount_ph);
X 
559bfbccfb0f4a3953d94d5d920a5dd4
echo x - afuse/files/pkg-message.in
sed 's/^X//' >afuse/files/pkg-message.in << '497551fe26785cd8a0dafde1a9bb61f0'
X
X===============================================================================
X
XAdditional info about program usage can be found at
X%%DOCSDIR%%/README.
X
X===============================================================================
497551fe26785cd8a0dafde1a9bb61f0
echo x - afuse/files/patch-afuse.1
sed 's/^X//' >afuse/files/patch-afuse.1 << '4a6e63aec5c104138c99e3a39d306619'
X--- afuse.1.orig
X+++ afuse.1
X@@ -0,0 +1,95 @@
X+.TH AFUSE 1 "October 12, 2006"
X+.SH NAME
X+AFUSE \- automounting file system implemented in user-space using FUSE
X+.SH DESCRIPTION
X+usage: afuse mountpoint [options]
X+.SS "general options:"
X+.TP
X+\fB\-o\fR opt,[opt...]
X+mount options
X+.TP
X+\fB\-h\fR   \fB\-\-help\fR
X+print help
X+.TP
X+\fB\-V\fR   \fB\-\-version\fR
X+print FUSE version information
X+.SS "AFUSE options:"
X+.TP
X+\fB\-o\fR \fB\ mount_template=CMD\fR
X+template for CMD to execute to mount (*)
X+.TP
X+\fB\-o\fR \fB\ unmount_template=CMD\fR
X+template for CMD to execute to unmount (*) (**)
X+.TP
X+(*) - When executed, %r and %m are expanded in templates to the root
X+directory name for the new mount point, and the actual directory to
X+mount onto respectively to mount onto. Both templates are REQUIRED.
X+.TP
X+(**)- The unmount command must perform a lazy unmount operation. E.g. the
X+\-u \-z options to fusermount, or \-l for regular mount.
X+.SS "FUSE options:"
X+.TP
X+\fB\-d\fR   \fB\-o\fR debug
X+enable debug output (implies \fB\-f\fR)
X+.TP
X+\fB\-f\fR
X+foreground operation
X+.TP
X+\fB\-s\fR
X+disable multi\-threaded operation
X+.TP
X+\fB\-o\fR allow_other
X+allow access to other users
X+.TP
X+\fB\-o\fR allow_root
X+allow access to root
X+.TP
X+\fB\-o\fR nonempty
X+allow mounts over non\-empty file/dir
X+.HP
X+\fB\-o\fR default_permissions enable permission checking by kernel
X+.TP
X+\fB\-o\fR fsname=NAME
X+set filesystem name
X+.TP
X+\fB\-o\fR large_read
X+issue large read requests (2.4 only)
X+.TP
X+\fB\-o\fR max_read=N
X+set maximum size of read requests
X+.TP
X+\fB\-o\fR hard_remove
X+immediate removal (don't hide files)
X+.TP
X+\fB\-o\fR use_ino
X+let filesystem set inode numbers
X+.TP
X+\fB\-o\fR readdir_ino
X+try to fill in d_ino in readdir
X+.TP
X+\fB\-o\fR direct_io
X+use direct I/O
X+.TP
X+\fB\-o\fR kernel_cache
X+cache files in kernel
X+.TP
X+\fB\-o\fR umask=M
X+set file permissions (octal)
X+.TP
X+\fB\-o\fR uid=N
X+set file owner
X+.TP
X+\fB\-o\fR gid=N
X+set file group
X+.TP
X+\fB\-o\fR entry_timeout=T
X+cache timeout for names (1.0s)
X+.TP
X+\fB\-o\fR negative_timeout=T
X+cache timeout for deleted names (0.0s)
X+.TP
X+\fB\-o\fR attr_timeout=T
X+cache timeout for attributes (1.0s)
X+.SH AUTHOR
X+This manual page was written by Varun Hiremath <varunhiremath@gmail.com>,
X+for the Debian project (but may be used by others).
4a6e63aec5c104138c99e3a39d306619
exit
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903041303.n24D3u3m040469>