Package: fuse Version: 2.7.4-1.1 Severity: normal Tags: patch
Can not mount locations like: lkajan,[EMAIL PROTECTED]:/home/groups/j/jb/jbio Both fuse and sshfs need to be patched to get the correct escaping/unescaping of ','. -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (500, 'testing'), (500, 'stable') Architecture: i386 (i686) Kernel: Linux 2.6.24-etchnhalf.1-686 (SMP w/2 CPU cores) Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash
diff -ur fuse-2.7.4/include/fuse_opt.h good.fuse-2.7.4/include/fuse_opt.h --- fuse-2.7.4/include/fuse_opt.h 2008-02-19 14:51:23.000000000 -0500 +++ good.fuse-2.7.4/include/fuse_opt.h 2008-10-17 22:31:14.000000000 -0400 @@ -212,6 +212,14 @@ int fuse_opt_add_opt(char **opts, const char *opt); /** + * Same as fuse_opt_add_opt except that '\\' and ',' are automatically escaped with '\\'. + * + */ +int fuse_opt_add_single_opt(char **opts, const char *opt); + +char *_nonesc_strchr(const char *__s, int __c, char **__ues, char **__escapes); + +/** * Add an argument to a NULL terminated argument vector * * @param args is the structure containing the current argument list diff -ur fuse-2.7.4/lib/fuse_opt.c good.fuse-2.7.4/lib/fuse_opt.c --- fuse-2.7.4/lib/fuse_opt.c 2008-02-19 14:51:26.000000000 -0500 +++ good.fuse-2.7.4/lib/fuse_opt.c 2008-10-17 22:38:33.000000000 -0400 @@ -109,9 +109,36 @@ return fuse_opt_add_arg(&ctx->outargs, arg); } +static char *escape_commas( const char *__s ) +{ + char *__es = calloc( strlen(__s)*2+1, sizeof(char) ); + const char *spos = __s; + char *espos = __es; + + if( !__es ) { + fprintf(stderr, "fuse: memory allocation failed\n"); + return NULL; + } + + while( *spos ) + { + switch ( *spos ) { + case '\\': + case ',': + *espos = '\\'; + ++espos; + default: + *espos = *spos; + ++espos; ++spos; + } + } + return __es; +} + int fuse_opt_add_opt(char **opts, const char *opt) { char *newopts; + if (!*opts) newopts = strdup(opt); else { @@ -129,9 +156,33 @@ return 0; } +int fuse_opt_add_single_opt(char **opts, const char *opt) +{ + char *newopts; + char *eopt = escape_commas( opt ); + + if (!*opts) + newopts = strdup(eopt); + else { + unsigned oldlen = strlen(*opts); + newopts = realloc(*opts, oldlen + 1 + strlen(eopt) + 1); + if (newopts) { + newopts[oldlen] = ','; + strcpy(newopts + oldlen + 1, eopt); + } + } + free( eopt ); + + if (!newopts) + return alloc_failed(); + + *opts = newopts; + return 0; +} + static int add_opt(struct fuse_opt_context *ctx, const char *opt) { - return fuse_opt_add_opt(&ctx->opts, opt); + return fuse_opt_add_single_opt(&ctx->opts, opt); } static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key, @@ -272,19 +323,60 @@ return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso); } -static int process_real_option_group(struct fuse_opt_context *ctx, char *opts) +char *_nonesc_strchr(const char *__s, int __c, char **__ues, char **__escapes) +{ + // find first non-escaped c + char *pos; + size_t s_len = strlen( __s ); + + *__escapes = calloc( s_len+1, sizeof(char) ); + if (!*__escapes) { + fprintf(stderr, "fuse: memory allocation failed\n"); + return NULL; + } + memset( *__escapes, ' ', sizeof(char) * s_len ); + pos = *__ues = strdup(__s); + if (!*__ues) { + fprintf(stderr, "fuse: memory allocation failed\n"); + return NULL; + } + + while( ( pos = strchr(pos,'\\') ) ) { + *( *__escapes + ( pos - *__ues ) ) = '\\'; + + memmove( pos, pos+1, strlen( pos ) * sizeof(char) ); // move the '\0' as well + + ++pos; + } + + pos = *__ues; + while( ( pos = strchr(pos,',') ) && *( *__escapes + ( pos - *__ues ) ) == '\\' ) ++pos; + + return pos; +} + +static int process_real_option_group(struct fuse_opt_context *ctx, char *__ueopts, char *__es) { char *sep; + int ptrdelta = 0; do { int res; - sep = strchr(opts, ','); - if (sep) - *sep = '\0'; - res = process_gopt(ctx, opts, 1); + char *pos = __ueopts; + while( ( sep = strchr(pos, ',') ) && *( __es + ( sep - __ueopts ) ) == '\\' ) ++pos; + + if (sep) { + ptrdelta = sep - __ueopts; + + *( __es + ptrdelta ) = *sep = '\0'; + } + res = process_gopt(ctx, __ueopts, 1); if (res == -1) return -1; - opts = sep + 1; + if( sep ) { + __ueopts = sep + 1; + __es = __es + ptrdelta + 1; + } } while (sep); return 0; @@ -293,18 +385,18 @@ static int process_option_group(struct fuse_opt_context *ctx, const char *opts) { int res; - char *copy; - const char *sep = strchr(opts, ','); + const char *sep = NULL; + char *ueopts = NULL; + char *escapes = NULL; + + sep = _nonesc_strchr(opts, ',', &ueopts, &escapes); + if (!sep) - return process_gopt(ctx, opts, 1); + return process_gopt(ctx, ueopts, 1); - copy = strdup(opts); - if (!copy) { - fprintf(stderr, "fuse: memory allocation failed\n"); - return -1; - } - res = process_real_option_group(ctx, copy); - free(copy); + res = process_real_option_group(ctx, ueopts, escapes); + free(escapes); + free(ueopts); return res; } diff -ur fuse-2.7.4/lib/mount.c good.fuse-2.7.4/lib/mount.c --- fuse-2.7.4/lib/mount.c 2008-02-19 14:51:27.000000000 -0500 +++ good.fuse-2.7.4/lib/mount.c 2008-10-17 22:31:17.000000000 -0400 @@ -197,16 +197,16 @@ return 0; case KEY_KERN_OPT: - return fuse_opt_add_opt(&mo->kernel_opts, arg); + return fuse_opt_add_single_opt(&mo->kernel_opts, arg); case KEY_FUSERMOUNT_OPT: - return fuse_opt_add_opt(&mo->fusermount_opts, arg); + return fuse_opt_add_single_opt(&mo->fusermount_opts, arg); case KEY_SUBTYPE_OPT: - return fuse_opt_add_opt(&mo->subtype_opt, arg); + return fuse_opt_add_single_opt(&mo->subtype_opt, arg); case KEY_MTAB_OPT: - return fuse_opt_add_opt(&mo->mtab_opts, arg); + return fuse_opt_add_single_opt(&mo->mtab_opts, arg); case KEY_HELP: mount_help(); diff -ur fuse-2.7.4/util/fusermount.c good.fuse-2.7.4/util/fusermount.c --- fuse-2.7.4/util/fusermount.c 2008-02-19 14:51:28.000000000 -0500 +++ good.fuse-2.7.4/util/fusermount.c 2008-10-17 22:31:17.000000000 -0400 @@ -10,6 +10,7 @@ #include <config.h> #include "mount_util.h" +#include "fuse_opt.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -385,6 +386,7 @@ char *optbuf; char *mnt_opts = NULL; const char *s; + const char *t; char *d; char *fsname = NULL; char *subtype = NULL; @@ -392,6 +394,8 @@ char *type = NULL; int check_empty = 1; int blkdev = 0; + char *ueopts = NULL; + char *escapes = NULL; optbuf = (char *) malloc(strlen(opts) + 128); if (!optbuf) { @@ -399,11 +403,13 @@ return -1; } - for (s = opts, d = optbuf; *s;) { + _nonesc_strchr(opts, ',', &ueopts, &escapes); + + for (s = ueopts, t = escapes, d = optbuf; *s && *t;) { unsigned len; const char *fsname_str = "fsname="; const char *subtype_str = "subtype="; - for (len = 0; s[len] && s[len] != ','; len++); + for (len = 0; s[len] && ( s[len] != ',' || t[len] == '\\' ); len++); if (begins_with(s, fsname_str)) { if (!get_string_opt(s, len, fsname_str, &fsname)) goto err; @@ -459,8 +465,12 @@ } } s += len; - if (*s) - s++; + t += len; + + if (*s && *t) { + ++s; + ++t; + } } *d = '\0'; res = get_mnt_opts(flags, optbuf, &mnt_opts); @@ -528,9 +538,14 @@ } free(optbuf); + free(ueopts); + free(escapes); + return res; err: + free(ueopts); + free(escapes); free(fsname); free(subtype); free(source); diff -ur fuse-2.7.4/util/Makefile.am good.fuse-2.7.4/util/Makefile.am --- fuse-2.7.4/util/Makefile.am 2008-02-19 14:51:28.000000000 -0500 +++ good.fuse-2.7.4/util/Makefile.am 2008-10-17 22:31:18.000000000 -0400 @@ -5,7 +5,7 @@ noinst_PROGRAMS = mount.fuse fusermount_SOURCES = fusermount.c -fusermount_LDADD = ../lib/mount_util.lo +fusermount_LDADD = ../lib/mount_util.lo ../lib/fuse_opt.lo fusermount_CPPFLAGS = -I../lib mount_fuse_SOURCES = mount.fuse.c diff -ur fuse-2.7.4/util/Makefile.in good.fuse-2.7.4/util/Makefile.in --- fuse-2.7.4/util/Makefile.in 2008-07-25 14:19:24.000000000 -0400 +++ good.fuse-2.7.4/util/Makefile.in 2008-10-17 22:38:45.000000000 -0400 @@ -53,7 +53,7 @@ PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_fusermount_OBJECTS = fusermount-fusermount.$(OBJEXT) fusermount_OBJECTS = $(am_fusermount_OBJECTS) -fusermount_DEPENDENCIES = ../lib/mount_util.lo +fusermount_DEPENDENCIES = ../lib/mount_util.lo ../lib/fuse_opt.lo am_mount_fuse_OBJECTS = mount.fuse.$(OBJEXT) mount_fuse_OBJECTS = $(am_mount_fuse_OBJECTS) mount_fuse_LDADD = $(LDADD) @@ -197,7 +197,7 @@ target_vendor = @target_vendor@ AM_CPPFLAGS = -D_FILE_OFFSET_BITS=64 fusermount_SOURCES = fusermount.c -fusermount_LDADD = ../lib/mount_util.lo +fusermount_LDADD = ../lib/mount_util.lo ../lib/fuse_opt.lo fusermount_CPPFLAGS = -I../lib mount_fuse_SOURCES = mount.fuse.c ulockmgr_server_SOURCES = ulockmgr_server.c @@ -541,7 +541,7 @@ $(INSTALL_PROGRAM) $(srcdir)/init_script $(DESTDIR)$(INIT_D_PATH)/fuse @if test -x /usr/sbin/update-rc.d; then \ echo "/usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true"; \ - /usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true; \ + # /usr/sbin/update-rc.d fuse start 34 S . start 41 0 6 . || true; \ fi install-data-local:
diff -ur sshfs-fuse-2.1/sshfs.c good.sshfs-fuse-2.1/sshfs.c --- sshfs-fuse-2.1/sshfs.c 2008-07-11 07:00:33.000000000 -0400 +++ good.sshfs-fuse-2.1/sshfs.c 2008-10-17 22:34:38.000000000 -0400 @@ -3091,12 +3091,39 @@ } } +static char *escape_commas( const char * __s ) +{ + char *__es = calloc( strlen(__s)*2+1, sizeof(char) ); + const char *spos = __s; + char *espos = __es; + + if( !__es ) { + fprintf(stderr, "sshfs: memory allocation failed\n"); + abort(); + } + + while( *spos ) + { + switch ( *spos ) { + case '\\': + case ',': + *espos = '\\'; + ++espos; + default: + *espos = *spos; + ++espos; ++spos; + } + } + return __es; +} + int main(int argc, char *argv[]) { int res; struct fuse_args args = FUSE_ARGS_INIT(argc, argv); char *tmp; char *fsname; + char *efsname = NULL; char *base_path; const char *sftp_server; int libver; @@ -3203,15 +3230,24 @@ if (fuse_is_lib_option("ac_attr_timeout=")) fuse_opt_insert_arg(&args, 1, "-oauto_cache,ac_attr_timeout=0"); + tmp = g_strdup_printf("-omax_read=%u", sshfs.max_read); fuse_opt_insert_arg(&args, 1, tmp); + g_free(tmp); + tmp = g_strdup_printf("-omax_write=%u", sshfs.max_write); fuse_opt_insert_arg(&args, 1, tmp); g_free(tmp); + #if FUSE_VERSION >= 27 libver = fuse_version(); assert(libver >= 27); - tmp = g_strdup_printf("-osubtype=sshfs,fsname=%s", fsname); + + // escape ',' in fsname + efsname = escape_commas( fsname ); + + tmp = g_strdup_printf("-osubtype=sshfs,fsname=%s", efsname); + free( efsname ); #else tmp = g_strdup_printf("-ofsname=sshfs#%s", fsname); #endif