Replace utils/mount.fuse "sh" script with a "C" program
authorMiklos Szeredi <miklos@szeredi.hu>
Wed, 18 Apr 2007 16:04:27 +0000 (16:04 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Wed, 18 Apr 2007 16:04:27 +0000 (16:04 +0000)
ChangeLog
util/Makefile.am
util/mount.fuse [deleted file]
util/mount.fuse.c [new file with mode: 0644]

index dc1cb57fb7873b0395a05141846b0494c005361c..c113245b608618adf0efeb6ad8c7ed8564f35c1d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2007-04-18  Miklos Szeredi <miklos@szeredi.hu>
+
+       * Replace utils/mount.fuse "sh" script with a "C" program
+
 2007-04-05  Miklos Szeredi <miklos@szeredi.hu>
 
        * Check for iconv.  Patch by Csaba Henk
index dcd69f6bc0b310c37d39532c5644064351698538..56046c0ab127f4a21e3bcece929e4fe082e1ebb9 100644 (file)
@@ -2,8 +2,10 @@
 
 AM_CPPFLAGS = -D_FILE_OFFSET_BITS=64 
 bin_PROGRAMS = fusermount ulockmgr_server
+noinst_PROGRAMS = mount.fuse
 
 fusermount_SOURCES = fusermount.c
+mount_fuse_SOURCES = mount.fuse.c
 
 ulockmgr_server_SOURCES = ulockmgr_server.c
 ulockmgr_server_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D_REENTRANT 
@@ -18,7 +20,7 @@ install-exec-hook:
                mknod $(DESTDIR)/dev/fuse -m 0666 c 10 229 || true; \
        fi
 
-EXTRA_DIST = mount.fuse udev.rules init_script
+EXTRA_DIST = udev.rules init_script
 
 MOUNT_FUSE_PATH = @MOUNT_FUSE_PATH@
 UDEV_RULES_PATH = @UDEV_RULES_PATH@
diff --git a/util/mount.fuse b/util/mount.fuse
deleted file mode 100644 (file)
index c4ff72f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-#
-# FUSE mount helper
-# Petr Klima <qaxi@seznam.cz>
-# Thanks to Miklos Szeredi <miklos@szeredi.hu>
-# to kick me to the right way
-#
-
-VERSION="0.0.2"
-PRGNAME=`basename $0`
-
-if [ -z "$HOME" ]; then
-    HOME=/root
-fi
-export HOME
-
-USAGE="${PRGNAME} version ${VERSION}
-usage: ${PRGNAME} fusefs_type#[mountpath] mountpoint [FUSE options]
-
-       example: ${PRGNAME} sshfs#root@tux:/ /mnt/tuxssh -o rw
-"
-
-function die {
-       echo -e "$PRGNAME# $1" >&2
-       [ -z "$2" ] && exit 128
-       exit "$2"
-}
-
-[ "$#" -ge 2 ] || die "${USAGE}"
-
-# for now i have to be same as FUSE mount binary
-# should be configurable
-eval `echo "$1" | sed -n 's,\(^[^#][^#]*\)\(#\(.*\)\)*,FSTYPE="\1" MOUNTPATH="\3",p'`
-
-export PATH
-FSBIN=`which ${FSTYPE} 2>/dev/null` \
-       || die "Can not find FUSE mount binary for FS ${FSTYPE}" 1
-
-# was there an # in $1
-[ "$1" = "$MOUNTPATH" ] && MOUNTPATH=""
-
-MOUNTPOINT="$2"
-[ -d "${MOUNTPOINT}" ] || die "Directory ${MOUNTPOINT} does not exist"
-
-shift
-shift
-
-eval `echo $@ | sed -n "s/\([^,]*,\)*setuid=\([^,]*\).*/SETUID=\2/p"`
-
-ignore_opts='\(-o\|user\|nouser\|users\|auto\|noauto\|_netdev\|setuid=[^,]*\)'
-
-# loop over each mount option and skip all that should be ignored
-IFS=","
-for OPT in $@; do
-       OPT=`echo $OPT | sed "s/^$ignore_opts$/IGNORE/"`
-       if [ "$OPT" == "IGNORE" ]; then continue; fi
-       OPTIONS="$OPTIONS$OPT,"
-done
-IFS=" "
-
-# add "-o " and remove trailing comma
-OPTIONS="-o `echo $OPTIONS | sed "s/,$//"`"
-
-if test -z "$SETUID"; then
-    ${FSTYPE} ${MOUNTPATH} ${MOUNTPOINT} ${OPTIONS}
-else
-    su - "$SETUID" -c "${FSTYPE} ${MOUNTPATH} ${MOUNTPOINT} ${OPTIONS}"
-fi
diff --git a/util/mount.fuse.c b/util/mount.fuse.c
new file mode 100644 (file)
index 0000000..d156009
--- /dev/null
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+static char *progname;
+
+
+static char *xstrdup(const char *s)
+{
+    char *t = strdup(s);
+    if (!t) {
+        fprintf(stderr, "%s: failed to allocate memory\n", progname);
+        exit(1);
+    }
+    return t;
+}
+
+static void *xrealloc(void *oldptr, size_t size)
+{
+    void *ptr = realloc(oldptr, size);
+    if (!ptr) {
+        fprintf(stderr, "%s: failed to allocate memory\n", progname);
+        exit(1);
+    }
+    return ptr;
+}
+
+static void add_arg(char **cmdp, const char *opt)
+{
+    size_t optlen = strlen(opt);
+    size_t cmdlen = *cmdp ? strlen(*cmdp) : 0;
+    char *cmd = xrealloc(*cmdp, cmdlen + optlen * 4 + 4);
+    char *s;
+    s = cmd + cmdlen;
+    if (*cmdp)
+        *s++ = ' ';
+
+    *s++ = '\'';
+    for (; *opt; opt++) {
+        if (*opt == '\'') {
+            *s++ = '\'';
+            *s++ = '\\';
+            *s++ = '\'';
+            *s++ = '\'';
+        } else
+            *s++ = *opt;
+    }
+    *s++ = '\'';
+    *s = '\0';
+    *cmdp = cmd;
+}
+
+int main(int argc, char *argv[])
+{
+    char *type;
+    char *source;
+    const char *mountpoint;
+    char *options = NULL;
+    char *command = NULL;
+    char *setuid = NULL;
+    int i;
+
+    progname = argv[0];
+    if (argc < 3) {
+        fprintf(stderr,
+                "usage: %s type#[source] mountpoint [-o opt[,opts...]]\n",
+                progname);
+        exit(1);
+    }
+
+    type = xstrdup(argv[1]);
+    source = strchr(type, '#');
+    if (source)
+        *source++ = '\0';
+
+    if (!type[0]) {
+        fprintf(stderr, "%s: empty filesystem type\n", progname);
+        exit(1);
+    }
+    mountpoint = argv[2];
+
+    for (i = 3; i < argc; i++) {
+        if (strcmp(argv[i], "-v") == 0)
+            continue;
+        if (strcmp(argv[i], "-o") == 0) {
+            char *opts;
+            char *opt;
+            i++;
+            if (i == argc)
+                break;
+
+            opts = xstrdup(argv[i]);
+            opt = strtok(opts, ",");
+            while (opt) {
+                int j;
+                int ignore = 0;
+                const char *ignore_opts[] = { "", "user", "nouser", "users",
+                                              "auto", "noauto", "_netdev",
+                                              NULL};
+                if (strncmp(opt, "setuid=", 7) == 0) {
+                    setuid = xstrdup(opt + 7);
+                    ignore = 1;
+                }
+                for (j = 0; ignore_opts[j]; j++)
+                    if (strcmp(opt, ignore_opts[j]) == 0)
+                        ignore = 1;
+
+                if (!ignore) {
+                    int oldlen = options ? strlen(options) : 0;
+                    options = xrealloc(options, oldlen + 1 + strlen(opt) + 1);
+                    if (!oldlen)
+                        strcpy(options, opt);
+                    else {
+                        strcat(options, ",");
+                        strcat(options, opt);
+                    }
+                }
+                opt = strtok(NULL, ",");
+            }
+        }
+    }
+
+    add_arg(&command, type);
+    if (source)
+        add_arg(&command, source);
+    add_arg(&command, mountpoint);
+    if (options) {
+        add_arg(&command, "-o");
+        add_arg(&command, options);
+    }
+
+    if (setuid && setuid[0]) {
+        char *sucommand = command;
+        command = NULL;
+        add_arg(&command, "su");
+        add_arg(&command, "-");
+        add_arg(&command, setuid);
+        add_arg(&command, "-c");
+        add_arg(&command, sucommand);
+    } else if (!getenv("HOME")) {
+        /* Hack to make filesystems work in the boot environment */
+        setenv("HOME", "/root", 0);
+    }
+
+    execl("/bin/sh", "/bin/sh", "-c", command, NULL);
+    fprintf(stderr, "%s: failed to execute /bin/sh: %s\n", progname,
+            strerror(errno));
+    return 1;
+}