From 3f854ace05e48378a522395ed764249b1079e9da Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 9 Jan 2006 16:51:06 +0000 Subject: fix --- ChangeLog | 7 +- Makefile.am | 7 +- cache.c | 2 +- compat/fuse_opt.c | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ compat/fuse_opt.h | 227 ++++++++++++++++++++++++++++++++++ configure.ac | 6 + sshfs.c | 100 ++++++++------- 7 files changed, 652 insertions(+), 56 deletions(-) create mode 100644 compat/fuse_opt.c create mode 100644 compat/fuse_opt.h diff --git a/ChangeLog b/ChangeLog index 80fad67..4b73c44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,10 @@ 2006-01-09 Miklos Szeredi - * Added 'workaround=symlink' option to "fix-up" absolute symlinks. - Patch by Paul Jarc + * Added 'transform_symlinks' option to "fix-up" absolute symlinks. + Patch by Paul Jarc + + * Add option parsing implementation, so linking with older than + 2.5.0 libfuse still works. 2005-12-09 Miklos Szeredi diff --git a/Makefile.am b/Makefile.am index 0b5298b..56a57bf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,10 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = sshfs -sshfs_SOURCES = sshfs.c cache.c cache.h + +if FUSE_OPT_COMPAT +compat_sources = compat/fuse_opt.c compat/fuse_opt.h +endif + +sshfs_SOURCES = sshfs.c cache.c cache.h $(compat_sources) sshfs_CPPFLAGS = -DFUSE_USE_VERSION=25 diff --git a/cache.c b/cache.c index af98ea1..fae5fd4 100644 --- a/cache.c +++ b/cache.c @@ -537,5 +537,5 @@ int cache_parse_options(struct fuse_args *args) cache.link_timeout = DEFAULT_CACHE_TIMEOUT; cache.on = 1; - return fuse_opt_parse(0, NULL, &cache, cache_opts, NULL, args); + return fuse_opt_parse(args, &cache, cache_opts, NULL); } diff --git a/compat/fuse_opt.c b/compat/fuse_opt.c new file mode 100644 index 0000000..2ac499c --- /dev/null +++ b/compat/fuse_opt.c @@ -0,0 +1,359 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPL. + See the file COPYING.LIB +*/ + +#include "fuse_opt.h" + +#include +#include +#include +#include + +struct fuse_opt_context { + void *data; + const struct fuse_opt *opt; + fuse_opt_proc_t proc; + int argctr; + int argc; + char **argv; + struct fuse_args outargs; + char *opts; + int nonopt; +}; + +void fuse_opt_free_args(struct fuse_args *args) +{ + if (args && args->argv && args->allocated) { + int i; + for (i = 0; i < args->argc; i++) + free(args->argv[i]); + free(args->argv); + args->argv = NULL; + args->allocated = 0; + } +} + +static int alloc_failed(void) +{ + fprintf(stderr, "fuse: memory allocation failed\n"); + return -1; +} + +int fuse_opt_add_arg(struct fuse_args *args, const char *arg) +{ + char **newargv; + char *newarg; + + assert(!args->argv || args->allocated); + + newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *)); + newarg = newargv ? strdup(arg) : NULL; + if (!newargv || !newarg) + return alloc_failed(); + + args->argv = newargv; + args->allocated = 1; + args->argv[args->argc++] = newarg; + args->argv[args->argc] = NULL; + return 0; +} + +static int next_arg(struct fuse_opt_context *ctx, const char *opt) +{ + if (ctx->argctr + 1 >= ctx->argc) { + fprintf(stderr, "fuse: missing argument after `%s'\n", opt); + return -1; + } + ctx->argctr++; + return 0; +} + +static int add_arg(struct fuse_opt_context *ctx, const char *arg) +{ + return fuse_opt_add_arg(&ctx->outargs, arg); +} + +int fuse_opt_add_opt(char **opts, const char *opt) +{ + char *newopts; + if (!*opts) + newopts = strdup(opt); + else { + unsigned oldlen = strlen(*opts); + newopts = realloc(*opts, oldlen + 1 + strlen(opt) + 1); + if (newopts) { + newopts[oldlen] = ','; + strcpy(newopts + oldlen + 1, opt); + } + } + 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); +} + +static int insert_arg(struct fuse_opt_context *ctx, int pos, const char *arg) +{ + assert(pos <= ctx->outargs.argc); + if (add_arg(ctx, arg) == -1) + return -1; + + if (pos != ctx->outargs.argc - 1) { + char *newarg = ctx->outargs.argv[ctx->outargs.argc - 1]; + memmove(&ctx->outargs.argv[pos + 1], &ctx->outargs.argv[pos], + sizeof(char *) * (ctx->outargs.argc - pos - 1)); + ctx->outargs.argv[pos] = newarg; + } + return 0; +} + +static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key, + int iso) +{ + if (ctx->proc) { + int res = ctx->proc(ctx->data, arg, key, &ctx->outargs); + if (res == -1 || !res) + return res; + } + if (iso) + return add_opt(ctx, arg); + else + return add_arg(ctx, arg); +} + +static int match_template(const char *t, const char *arg, unsigned *sepp) +{ + int arglen = strlen(arg); + const char *sep = strchr(t, '='); + sep = sep ? sep : strchr(t, ' '); + if (sep && (!sep[1] || sep[1] == '%')) { + int tlen = sep - t; + if (sep[0] == '=') + tlen ++; + if (arglen >= tlen && strncmp(arg, t, tlen) == 0) { + *sepp = sep - t; + return 1; + } + } + if (strcmp(t, arg) == 0) { + *sepp = 0; + return 1; + } + return 0; +} + +static const struct fuse_opt *find_opt(const struct fuse_opt *opt, + const char *arg, unsigned *sepp) +{ + for (; opt && opt->template; opt++) + if (match_template(opt->template, arg, sepp)) + return opt; + return NULL; +} + +int fuse_opt_match(const struct fuse_opt *opts, const char *opt) +{ + unsigned dummy; + return find_opt(opts, opt, &dummy) ? 1 : 0; +} + +static int process_opt_param(void *var, const char *format, const char *param, + const char *arg) +{ + assert(format[0] == '%'); + if (format[1] == 's') { + char *copy = strdup(param); + if (!copy) + return alloc_failed(); + + *(char **) var = copy; + } else { + if (sscanf(param, format, var) != 1) { + fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg); + return -1; + } + } + return 0; +} + +static int process_opt(struct fuse_opt_context *ctx, + const struct fuse_opt *opt, unsigned sep, + const char *arg, int iso) +{ + if (opt->offset == -1U) { + if (call_proc(ctx, arg, opt->value, iso) == -1) + return -1; + } else { + void *var = ctx->data + opt->offset; + if (sep && opt->template[sep + 1]) { + const char *param = arg + sep; + if (opt->template[sep] == '=') + param ++; + if (process_opt_param(var, opt->template + sep + 1, + param, arg) == -1) + return -1; + } else + *(int *)var = opt->value; + } + return 0; +} + +static int process_opt_sep_arg(struct fuse_opt_context *ctx, + const struct fuse_opt *opt, unsigned sep, + const char *arg, int iso) +{ + int res; + char *newarg; + char *param; + + if (next_arg(ctx, arg) == -1) + return -1; + + param = ctx->argv[ctx->argctr]; + newarg = malloc(sep + strlen(param) + 1); + if (!newarg) + return alloc_failed(); + + memcpy(newarg, arg, sep); + strcpy(newarg + sep, param); + res = process_opt(ctx, opt, sep, newarg, iso); + free(newarg); + + return res; +} + +static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso) +{ + unsigned sep; + const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep); + if (opt) { + for (; opt; opt = find_opt(opt + 1, arg, &sep)) { + int res; + if (sep && opt->template[sep] == ' ' && !arg[sep]) + res = process_opt_sep_arg(ctx, opt, sep, arg, iso); + else + res = process_opt(ctx, opt, sep, arg, iso); + if (res == -1) + return -1; + } + return 0; + } else + return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso); +} + +static int process_real_option_group(struct fuse_opt_context *ctx, char *opts) +{ + char *sep; + + do { + int res; + sep = strchr(opts, ','); + if (sep) + *sep = '\0'; + res = process_gopt(ctx, opts, 1); + if (res == -1) + return -1; + opts = sep + 1; + } while (sep); + + return 0; +} + +static int process_option_group(struct fuse_opt_context *ctx, const char *opts) +{ + int res; + char *copy; + const char *sep = strchr(opts, ','); + if (!sep) + return process_gopt(ctx, opts, 1); + + copy = strdup(opts); + if (!copy) { + fprintf(stderr, "fuse: memory allocation failed\n"); + return -1; + } + res = process_real_option_group(ctx, copy); + free(copy); + return res; +} + +static int process_one(struct fuse_opt_context *ctx, const char *arg) +{ + if (ctx->nonopt || arg[0] != '-') + return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0); + else if (arg[1] == 'o') { + if (arg[2]) + return process_option_group(ctx, arg + 2); + else { + if (next_arg(ctx, arg) == -1) + return -1; + + return process_option_group(ctx, ctx->argv[ctx->argctr]); + } + } else if (arg[1] == '-' && !arg[2]) { + if (add_arg(ctx, arg) == -1) + return -1; + ctx->nonopt = ctx->outargs.argc; + return 0; + } else + return process_gopt(ctx, arg, 0); +} + +static int opt_parse(struct fuse_opt_context *ctx) +{ + if (ctx->argc) { + if (add_arg(ctx, ctx->argv[0]) == -1) + return -1; + } + + for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) + if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) + return -1; + + if (ctx->opts) { + if (insert_arg(ctx, 1, "-o") == -1 || + insert_arg(ctx, 2, ctx->opts) == -1) + return -1; + } + if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc) + ctx->outargs.argv[--ctx->outargs.argc] = NULL; + + return 0; +} + +int fuse_opt_parse(struct fuse_args *args, void *data, + const struct fuse_opt opts[], fuse_opt_proc_t proc) +{ + int res; + struct fuse_opt_context ctx = { + .data = data, + .opt = opts, + .proc = proc, + }; + + if (!args || !args->argv || !args->argc) + return 0; + + ctx.argc = args->argc; + ctx.argv = args->argv; + + res = opt_parse(&ctx); + if (res != -1) { + struct fuse_args tmp = *args; + *args = ctx.outargs; + ctx.outargs = tmp; + } + free(ctx.opts); + fuse_opt_free_args(&ctx.outargs); + return res; +} diff --git a/compat/fuse_opt.h b/compat/fuse_opt.h new file mode 100644 index 0000000..2ef5d56 --- /dev/null +++ b/compat/fuse_opt.h @@ -0,0 +1,227 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. +*/ + +#ifndef _FUSE_OPT_H_ +#define _FUSE_OPT_H_ + +/* This file defines the option parsing interface of FUSE */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Option description + * + * This structure describes a single option, and and action associated + * with it, in case it matches. + * + * More than one such match may occur, in which case the action for + * each match is executed. + * + * There are three possible actions in case of a match: + * + * i) An integer (int or unsigned) variable determined by 'offset' is + * set to 'value' + * + * ii) The processing function is called, with 'value' as the key + * + * iii) An integer (any) or string (char *) variable determined by + * 'offset' is set to the value of an option parameter + * + * 'offset' should normally be either set to + * + * - 'offsetof(struct foo, member)' actions i) and iii) + * + * - -1 action ii) + * + * The 'offsetof()' macro is defined in the header. + * + * The template determines which options match, and also have an + * effect on the action. Normally the action is either i) or ii), but + * if a format is present in the template, then action iii) is + * performed. + * + * The types of templates are: + * + * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only + * themselves. Invalid values are "--" and anything beginning + * with "-o" + * + * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or + * the relevant option in a comma separated option list + * + * 3) "bar=", "--foo=", etc. These are variations of 1) and 2) + * which have a parameter + * + * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform + * action iii). + * + * 5) "-x ", etc. Matches either "-xparam" or "-x param" as + * two separate arguments + * + * 6) "-x %s", etc. Combination of 4) and 5) + * + * If the format is "%s", memory is allocated for the string unlike + * with scanf(). + */ +struct fuse_opt { + /** Matching template and optional parameter formatting */ + const char *template; + + /** + * Offset of variable within 'data' parameter of fuse_opt_parse() + * or -1 + */ + unsigned long offset; + + /** + * Value to set the variable to, or to be passed as 'key' to the + * processing function. Ignored if template a format + */ + int value; +}; + +/** + * Key option. In case of a match, the processing function will be + * called with the specified key. + */ +#define FUSE_OPT_KEY(template, key) { template, -1U, key } + +/** + * Last option. An array of 'struct fuse_opt' must end with a NULL + * template value + */ +#define FUSE_OPT_END { .template = NULL } + +/** + * Argument list + */ +struct fuse_args { + /** Argument count */ + int argc; + + /** Argument vector. NULL terminated */ + char **argv; + + /** Is 'argv' allocated? */ + int allocated; +}; + +/** + * Initializer for 'struct fuse_args' + */ +#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } + +/** + * Key value passed to the processing function if an option did not + * match any templated + */ +#define FUSE_OPT_KEY_OPT -1 + +/** + * Key value passed to the processing function for all non-options + * + * Non-options are the arguments beginning with a charater other than + * '-' or all arguments after the special '--' option + */ +#define FUSE_OPT_KEY_NONOPT -2 + +/** + * Processing function + * + * This function is called if + * - option did not match any 'struct fuse_opt' + * - argument is a non-option + * - option did match and offset was set to -1 + * + * The 'arg' parameter will always contain the whole argument or + * option including the parameter if exists. A two-argument option + * ("-x foo") is always converted to single arguemnt option of the + * form "-xfoo" before this function is called. + * + * Options of the form '-ofoo' are passed to this function without the + * '-o' prefix. + * + * The return value of this function determines whether this argument + * is to be inserted into the output argument vector, or discarded. + * + * @param data is the user data passed to the fuse_opt_parse() function + * @param arg is the whole argument or option + * @param key determines why the processing function was called + * @param outargs the current output argument list + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept + */ +typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, + struct fuse_args *outargs); + +/** + * Option parsing function + * + * If 'args' was returned from a previous call to fuse_opt_parse() or + * it was constructed from + * + * A NULL 'args' is equivalent to an empty argument vector + * + * A NULL 'opts' is equivalent to an 'opts' array containing a single + * end marker + * + * A NULL 'proc' is equivalent to a processing function always + * returning '1' + * + * @param args is the input and output argument list + * @param data is the user data + * @param opts is the option description array + * @param proc is the processing function + * @return -1 on error, 0 on success + */ +int fuse_opt_parse(struct fuse_args *args, void *data, + const struct fuse_opt opts[], fuse_opt_proc_t proc); + +/** + * Add an option to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt(char **opts, const char *opt); + +/** + * Add an argument to a NULL terminated argument vector + * + * @param args is the structure containing the current argument list + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_arg(struct fuse_args *args, const char *arg); + +/** + * Free the contents of argument list + * + * The structure itself is not freed + * + * @param args is the structure containing the argument list + */ +void fuse_opt_free_args(struct fuse_args *args); + + +/** + * Check if an option matches + * + * @param opts is the option description array + * @param opt is the option to match + * @return 1 if a match is found, 0 if not + */ +int fuse_opt_match(const struct fuse_opt opts[], const char *opt); + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_OPT_H_ */ diff --git a/configure.ac b/configure.ac index 314d00f..6366ec2 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,12 @@ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH PKG_CHECK_MODULES(SSHFS, [fuse >= 2.2 glib-2.0]) CFLAGS="$CFLAGS -Wall -W -D_REENTRANT $SSHFS_CFLAGS" LIBS="$SSHFS_LIBS" +have_fuse_opt_parse=no +AC_CHECK_FUNC([fuse_opt_parse], [have_fuse_opt_parse=yes]) +if test "$have_fuse_opt_parse" = no; then + CFLAGS="$CFLAGS -Icompat" +fi +AM_CONDITIONAL(FUSE_OPT_COMPAT, test "$have_fuse_opt_parse" = no) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/sshfs.c b/sshfs.c index c84cc10..c4d6fc4 100644 --- a/sshfs.c +++ b/sshfs.c @@ -145,9 +145,10 @@ struct sshfs { char *directport; char *ssh_command; char *sftp_server; + char *mountpoint; struct fuse_args ssh_args; int rename_workaround; - int symlink_workaround; + int transform_symlinks; int detect_uid; unsigned max_read; unsigned ssh_ver; @@ -226,7 +227,6 @@ enum { }; #define SSHFS_OPT(t, p, v) { t, offsetof(struct sshfs, p), v } -#define SSHFS_KEY(t, k) { t, FUSE_OPT_OFFSET_KEY, k } static struct fuse_opt sshfs_opts[] = { SSHFS_OPT("directport=%s", directport, 0), @@ -236,24 +236,22 @@ static struct fuse_opt sshfs_opts[] = { SSHFS_OPT("ssh_protocol=%u", ssh_ver, 0), SSHFS_OPT("-1", ssh_ver, 1), SSHFS_OPT("workaround=none", rename_workaround, 0), - SSHFS_OPT("workaround=none", symlink_workaround, 0), SSHFS_OPT("workaround=rename", rename_workaround, 1), - SSHFS_OPT("workaround=symlink", symlink_workaround, 1), SSHFS_OPT("workaround=all", rename_workaround, 1), - SSHFS_OPT("workaround=all", symlink_workaround, 1), SSHFS_OPT("idmap=none", detect_uid, 0), SSHFS_OPT("idmap=user", detect_uid, 1), SSHFS_OPT("sshfs_sync", sync_write, 1), SSHFS_OPT("no_readahead", sync_read, 1), SSHFS_OPT("sshfs_debug", debug, 1), SSHFS_OPT("reconnect", reconnect, 1), - - SSHFS_KEY("-p ", KEY_PORT), - SSHFS_KEY("-C", KEY_COMPRESS), - SSHFS_KEY("-V", KEY_VERSION), - SSHFS_KEY("--version", KEY_VERSION), - SSHFS_KEY("-h", KEY_HELP), - SSHFS_KEY("--help", KEY_HELP), + SSHFS_OPT("transform_symlinks", transform_symlinks, 1), + + FUSE_OPT_KEY("-p ", KEY_PORT), + FUSE_OPT_KEY("-C", KEY_COMPRESS), + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), FUSE_OPT_END }; @@ -1162,18 +1160,17 @@ static int sshfs_readlink(const char *path, char *linkbuf, size_t size) char *link; err = -EIO; if(buf_get_uint32(&name, &count) != -1 && count == 1 && - buf_get_string(&name, &link) != -1) { - if (size>0) { - if (link[0]=='/') { - size_t len=sshfs.symlink_prefix_len; - if (len>size-1) len=size-1; - memcpy(linkbuf, sshfs.symlink_prefix, len); - linkbuf+=len; - size-=len; - } - strncpy(linkbuf, link, size-1); - linkbuf[size-1] = '\0'; + buf_get_string(&name, &link) != -1 && size > 0) { + if (link[0] == '/' && sshfs.symlink_prefix_len) { + size_t len = sshfs.symlink_prefix_len; + if (len > size - 1) + len = size - 1; + memcpy(linkbuf, sshfs.symlink_prefix, len); + linkbuf += len; + size -= len; } + strncpy(linkbuf, link, size - 1); + linkbuf[size - 1] = '\0'; free(link); err = 0; } @@ -1912,8 +1909,12 @@ static void usage(const char *progname) fprintf(stderr, "usage: %s [user@]host:[dir]] mountpoint [options]\n" "\n" -"SSHFS Options:\n" -" -V show version information\n" +"general options:\n" +" -o opt,[opt...] mount options\n" +" -h --help print help\n" +" -V --version print version\n" +"\n" +"SSHFS options:\n" " -p PORT equivalent to '-o port=PORT'\n" " -C equivalent to '-o compression=yes'\n" " -1 equivalent to '-o ssh_protocol=1'\n" @@ -1928,7 +1929,6 @@ static void usage(const char *progname) " none no workarounds enabled (default)\n" " all all workarounds enabled\n" " rename work around problem renaming to existing file\n" -" symlink prepend mountpoint to absolute symlink targets\n" " -o idmap=TYPE user/group ID mapping, possible types are:\n" " none no translation of the ID space (default)\n" " user only translate UID of connecting user\n" @@ -1936,6 +1936,7 @@ static void usage(const char *progname) " -o ssh_protocol=N ssh protocol to use (default: 2)\n" " -o sftp_server=SERV path to sftp server or subsystem (default: sftp)\n" " -o directport=PORT directly connect to PORT bypassing ssh\n" +" -o transform_symlinks prepend mountpoint to absolute symlink targets\n" " -o SSHOPT=VAL ssh options (see man ssh_config)\n" "\n", progname); } @@ -1975,7 +1976,8 @@ static int sshfs_opt_proc(void *data, const char *arg, int key, if (!sshfs.host && strchr(arg, ':')) { sshfs.host = strdup(arg); return 0; - } + } else if (!sshfs.mountpoint) + sshfs.mountpoint = strdup(arg); return 1; case KEY_PORT: @@ -1996,6 +1998,10 @@ static int sshfs_opt_proc(void *data, const char *arg, int key, case KEY_VERSION: fprintf(stderr, "SSHFS version %s\n", PACKAGE_VERSION); +#if FUSE_VERSION >= 25 + fuse_opt_add_arg(outargs, "--version"); + fuse_main(outargs->argc, outargs->argv, &sshfs_oper.oper); +#endif exit(0); default: @@ -2007,7 +2013,7 @@ static int sshfs_opt_proc(void *data, const char *arg, int key, int main(int argc, char *argv[]) { int res; - struct fuse_args outargs; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); char *tmp; char *fsname; char *base_path; @@ -2021,8 +2027,7 @@ int main(int argc, char *argv[]) ssh_add_arg("-a"); ssh_add_arg("-oClearAllForwardings=yes"); - if (fuse_opt_parse(argc, argv, &sshfs, sshfs_opts, sshfs_opt_proc, - &outargs) == -1) + if (fuse_opt_parse(&args, &sshfs, sshfs_opts, sshfs_opt_proc) == -1) exit(1); if (!sshfs.host) { @@ -2073,7 +2078,7 @@ int main(int argc, char *argv[]) if (res == -1) exit(1); - res = cache_parse_options(&outargs); + res = cache_parse_options(&args); if (res == -1) exit(1); @@ -2082,37 +2087,28 @@ int main(int argc, char *argv[]) if (sshfs.max_read > 65536) sshfs.max_read = 65536; - if (sshfs.symlink_workaround && outargs.argv[1] == NULL) { - fprintf(stderr, "symlink workaround failed: no mountpoint given\n"); + if (sshfs.transform_symlinks && !sshfs.mountpoint) { + fprintf(stderr, "cannot transform symlinks: no mountpoint given\n"); exit(1); } - if (!sshfs.symlink_workaround) - sshfs.symlink_prefix_len=0; - else if (realpath(outargs.argv[1], sshfs.symlink_prefix)!=NULL) - sshfs.symlink_prefix_len=strlen(sshfs.symlink_prefix); + if (!sshfs.transform_symlinks) + sshfs.symlink_prefix_len = 0; + else if (realpath(sshfs.mountpoint, sshfs.symlink_prefix) != NULL) + sshfs.symlink_prefix_len = strlen(sshfs.symlink_prefix); else { - sshfs.symlink_prefix_len=strlen(outargs.argv[1]); - if (outargs.argv[1][sshfs.symlink_prefix_len-1]=='/') - --sshfs.symlink_prefix_len; - if (outargs.argv[1][0]=='/' && - sshfs.symlink_prefix_len<=sizeof sshfs.symlink_prefix) { - memcpy(sshfs.symlink_prefix, outargs.argv[1], - sshfs.symlink_prefix_len); - } else { - perror("unable to normalize mount path"); - exit(1); - } + perror("unable to normalize mount path"); + exit(1); } tmp = g_strdup_printf("-omax_read=%u", sshfs.max_read); - fuse_opt_add_arg(&outargs, tmp); + fuse_opt_add_arg(&args, tmp); g_free(tmp); tmp = g_strdup_printf("-ofsname=sshfs#%s", fsname); - fuse_opt_add_arg(&outargs, tmp); + fuse_opt_add_arg(&args, tmp); g_free(tmp); g_free(fsname); - res = fuse_main(outargs.argc, outargs.argv, cache_init(&sshfs_oper)); - fuse_opt_free_args(&outargs); + res = fuse_main(args.argc, args.argv, cache_init(&sshfs_oper)); + fuse_opt_free_args(&args); fuse_opt_free_args(&sshfs.ssh_args); free(sshfs.directport); -- cgit v1.2.3