diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 000000000..46ab357d9 --- /dev/null +++ b/src/main.c @@ -0,0 +1,363 @@ +/********************************************************** + * main.c + * + * Copyright (C) 2004, 2005 by Stefan Siegl <ssiegl@gmx.de>, Germany + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Publice License, + * version 2 or any later. The license is contained in the COPYING + * file that comes with the libfuse distribution. + * + * translator startup code (and argp handling) + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <unistd.h> +#include <stdio.h> +#include <error.h> +#include <hurd/netfs.h> + +#include "fuse_i.h" +#include "fuse.h" + +/* global variables, needed for netfs */ +char *netfs_server_name = PACKAGE; +char *netfs_server_version = VERSION; +int netfs_maxsymlinks = 12; + +/* libfuse filesystem configuration */ +struct _libfuse_params libfuse_params = { 0 }; + +/* pointer to the fuse_operations structure of this translator process */ +const struct fuse_operations *fuse_ops = NULL; +const struct fuse_operations_compat2 *fuse_ops_compat = NULL; + +/* the port where to write out debug messages to, NULL to omit these */ +FILE *debug_port = NULL; + +/* magic number, passed from fuse_mount to fuse_new */ +#define FUSE_MAGIC ((int) 0x66757365) + + + +/* Interpret a __single__ mount option + * The option itself `opt' may be modified during this call. + */ +static int +fuse_parse_opt(char *opt) +{ + char *ptrptr; + char *option = strtok_r(opt, "=", &ptrptr); + char *value = strtok_r(NULL, "=", &ptrptr); + + DEBUG("parse_opt", "option `%s' => `%s'\n", option, value); + + if(! strcmp(option, "use_ino")) + libfuse_params.use_ino = 1; + + else if(! strcmp(option, "default_permissions")) + libfuse_params.deflt_perms = 1; + + else if(! strcmp(option, "allow_other")) + libfuse_params.allow_other = 1; + + else if(! strcmp(option, "allow_root")) + libfuse_params.allow_root = 1; + + else if(! strcmp(option, "uid")) + { + char *endptr; + if(! value || (libfuse_params.uid = strtol(value, &endptr, 10), + endptr == value)) + { + fprintf(stderr, PACKAGE_NAME ": missing or invalid argument to " + "mount option '%s': %s\n", option, value); + return EINVAL; + } + + libfuse_params.force_uid = 1; + } + + else if(! strcmp(option, "gid")) + { + char *endptr; + if(! value || (libfuse_params.gid = strtol(value, &endptr, 10), + endptr == value)) + { + fprintf(stderr, PACKAGE_NAME ": missing or invalid argument to " + "mount option '%s': %s\n", option, value); + return EINVAL; + } + + libfuse_params.force_gid = 1; + } + + else if(! strcmp(option, "umask")) + { + char *endptr; + if(! value || (libfuse_params.umask = strtol(value, &endptr, 8), + endptr == value)) + { + fprintf(stderr, PACKAGE_NAME ": missing or invalid argument to " + "mount option '%s': %s\n", option, value); + return EINVAL; + } + + libfuse_params.force_umask = 1; + } + + else + { + fprintf(stderr, PACKAGE_NAME ": unsupported mount option: %s\n", option); + return EINVAL; + } + + return 0; +} + +/* Parse a single (or a comma-separated list) of mount options + * (those that are specified using `-o' on the command line for example) + */ +static int +fuse_parse_opts(const char *opts) +{ + if(! opts) return 0; /* ... why did'ya call us? */ + + char *copy = strdup(opts); /* copy string to allow strtok calls */ + if(! copy) return ENOMEM; + + char *ptrptr, *token, *tok_me = copy; + while((token = strtok_r(tok_me, ",", &ptrptr))) + { + tok_me = NULL; + if(fuse_parse_opt(token)) + { + free(copy); + return EINVAL; + } + } + + free(copy); + return 0; +} + + + +/* Parse the command line arguments given to fuse_main (or _compat function). + * If --help specified, output help string and call exit. If there are any + * options that shall be passed to the file system itself, return them. + */ +static void +fuse_parse_argv(int argc, char *argv[]) +{ + const char *translat_path = argv[0]; + + /* parse command line arguments */ + int opt; + FILE *opt_help = NULL; + + while((opt = getopt(argc, argv, "d::o:hs")) >= 0) + switch(opt) + { + case 'd': + if(optarg) + debug_port = fopen(optarg, "w"); + if(! debug_port) + debug_port = stderr; + + setvbuf(debug_port, NULL, _IONBF, 0); + fprintf(debug_port, "translator %s starting up.\n", translat_path); + break; + + case 'o': + assert(optarg); + if(fuse_parse_opts(optarg)) + exit(1); + break; + + case 'h': + opt_help = stdout; + break; + + case 's': + libfuse_params.disable_mt = 1; + break; + + case '?': + default: + opt_help = stderr; + break; + } + + if(opt_help) + { + fprintf(opt_help, + "usage: %s [FUSE options]\n\n" + "FUSE Options:\n" + " -d[FILENAME] " + "enable debug output (default=stderr)\n" + " -s disable multi-threaded operation\n" + /* " -r " + * "mount read only (equivalent to '-o ro')\n" */ + " -o opt,[opt...] mount options\n" + " -h print help\n" + "\n" + "Mount options:\n" + " default_permissions enable permission checking\n" + " allow_other allow access to other users\n" + " allow_root allow access to root\n" + " use_ino let filesystem set inode numbers\n" + /* " readdir_ino " + * "try to fill in d_ino in readdir\n" */ + " umask set file permissions (octal)\n" + " uid set file owner\n" + " gid set file group\n", + translat_path); + + exit(opt_help == stdout ? 0 : 1); + } +} + + + +/* Main function of FUSE. (compatibility one for old Fuse API) */ +int +fuse_main_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op) +{ + fuse_parse_argv(argc, argv); + + int fd = fuse_mount(NULL, NULL); + return (libfuse_params.disable_mt ? fuse_loop : fuse_loop_mt) + (fuse_new_compat2(fd, NULL, op)); +} + + + +/* Main function of FUSE. + * named fuse_main_real, since originial fuse.h defines a macro renaming it */ +int +fuse_main_real(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size) +{ + fuse_parse_argv(argc, argv); + + int fd = fuse_mount(NULL, NULL); + return (libfuse_params.disable_mt ? fuse_loop : fuse_loop_mt) + (fuse_new(fd, NULL, op, op_size)); +} + + + +/* Create a new FUSE filesystem, actually there's nothing for us to do + * on the Hurd. + * + * (Compatibility function for the old Fuse API) + */ +struct fuse * +fuse_new_compat2(int fd, const char *opts, + const struct fuse_operations_compat2 *op) +{ + if(fd != FUSE_MAGIC) + return NULL; + + if(fuse_parse_opts(opts)) + return NULL; + + fuse_ops_compat = op; + + return (void *) FUSE_MAGIC; /* we don't have a fuse structure, sorry. */ +} + + + +/* Create a new FUSE filesystem, actually there's nothing for us to do + * on the Hurd. + */ +struct fuse * +fuse_new(int fd, const char *opts, + const struct fuse_operations *op, size_t op_size) +{ + (void) op_size; /* FIXME, see what the real Fuse library does with + * this argument */ + + if(fd != FUSE_MAGIC) + return NULL; + + if(fuse_parse_opts(opts)) + return NULL; + + fuse_ops = op; + + return (void *) FUSE_MAGIC; /* we don't have a fuse structure, sorry. */ +} + + + +/* Create a new mountpoint for our fuse filesystem, i.e. do the netfs + * initialization stuff ... + */ +int +fuse_mount(const char *mountpoint, const char *opts) +{ + (void) mountpoint; /* we don't care for the specified mountpoint, as + * we need to be set up using settrans ... */ + + if(fuse_parse_opts(opts)) + return 0; + + mach_port_t bootstrap, ul_node; + + /* netfs initialization. */ + + task_get_bootstrap_port(mach_task_self(), &bootstrap); + + netfs_init(); + + ul_node = netfs_startup(bootstrap, 0); + + /* create our root node */ + { + struct netnode *root = fuse_make_netnode(NULL, "/"); + netfs_root_node = fuse_make_node(root); + } + + if(! netfs_root_node) + { + perror(PACKAGE ": cannot create rootnode"); + return -EAGAIN; + } + + return FUSE_MAGIC; +} + + + +int +fuse_loop(struct fuse *f) +{ + if(f != ((void *) FUSE_MAGIC)) + return -1; + + static int server_timeout = 1000 * 60 * 10; /* ten minutes, just like in + * init-loop.c of libnetfs */ + + ports_manage_port_operations_one_thread(netfs_port_bucket, + netfs_demuxer, + server_timeout); + return 0; +} + + +int +fuse_loop_mt(struct fuse *f) +{ + if(f != ((void *) FUSE_MAGIC)) + return -1; + + netfs_server_loop(); + return 0; +} |