root/src/add-ons/kernel/file_systems/userlandfs/server/fuse/fuse_config.c
/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>

  This program can be distributed under the terms of the GNU LGPLv2.
  See the file COPYING.LIB
*/

#include "fuse_config.h"

#include <string.h>

enum {
        KEY_KERN_FLAG,
        KEY_KERN_OPT,
        KEY_FUSERMOUNT_OPT,
        KEY_SUBTYPE_OPT,
        KEY_MTAB_OPT,
        KEY_ALLOW_ROOT,
        KEY_RO,
        KEY_HELP,
        KEY_VERSION,
};

struct mount_opts {
        int allow_other;
        int allow_root;
        int ishelp;
        int flags;
        int nonempty;
        int blkdev;
        char *fsname;
        char *subtype;
        char *subtype_opt;
        char *mtab_opts;
        char *fusermount_opts;
        char *kernel_opts;
};

#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }

static const struct fuse_opt fuse_lib_opts[] = {
        FUSE_OPT_KEY("-h",                    KEY_HELP),
        FUSE_OPT_KEY("--help",                KEY_HELP),
        FUSE_OPT_KEY("debug",                 FUSE_OPT_KEY_KEEP),
        FUSE_OPT_KEY("-d",                    FUSE_OPT_KEY_KEEP),
        FUSE_LIB_OPT("debug",                 debug, 1),
        FUSE_LIB_OPT("-d",                    debug, 1),
        FUSE_LIB_OPT("hard_remove",           hard_remove, 1),
        FUSE_LIB_OPT("use_ino",               use_ino, 1),
        FUSE_LIB_OPT("readdir_ino",           readdir_ino, 1),
        FUSE_LIB_OPT("direct_io",             direct_io, 1),
        FUSE_LIB_OPT("kernel_cache",          kernel_cache, 1),
        FUSE_LIB_OPT("auto_cache",            auto_cache, 1),
        FUSE_LIB_OPT("noauto_cache",          auto_cache, 0),
        FUSE_LIB_OPT("umask=",                set_mode, 1),
        FUSE_LIB_OPT("umask=%o",              umask, 0),
        FUSE_LIB_OPT("uid=",                  set_uid, 1),
        FUSE_LIB_OPT("uid=%d",                uid, 0),
        FUSE_LIB_OPT("gid=",                  set_gid, 1),
        FUSE_LIB_OPT("gid=%d",                gid, 0),
        FUSE_LIB_OPT("entry_timeout=%lf",     entry_timeout, 0),
        FUSE_LIB_OPT("attr_timeout=%lf",      attr_timeout, 0),
        FUSE_LIB_OPT("ac_attr_timeout=%lf",   ac_attr_timeout, 0),
        FUSE_LIB_OPT("ac_attr_timeout=",      ac_attr_timeout_set, 1),
        FUSE_LIB_OPT("negative_timeout=%lf",  negative_timeout, 0),
        FUSE_LIB_OPT("intr",                  intr, 1),
        FUSE_LIB_OPT("intr_signal=%d",        intr_signal, 0),
        FUSE_LIB_OPT("modules=%s",            modules, 0),
        FUSE_OPT_END
};

#define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }

static const struct fuse_opt fuse_mount_opts[] = {
        FUSE_MOUNT_OPT("allow_other",       allow_other),
        FUSE_MOUNT_OPT("allow_root",        allow_root),
        FUSE_MOUNT_OPT("nonempty",          nonempty),
        FUSE_MOUNT_OPT("blkdev",            blkdev),
        FUSE_MOUNT_OPT("fsname=%s",         fsname),
        FUSE_MOUNT_OPT("subtype=%s",        subtype),
        FUSE_OPT_KEY("allow_other",         KEY_KERN_OPT),
        FUSE_OPT_KEY("allow_root",          KEY_ALLOW_ROOT),
        FUSE_OPT_KEY("nonempty",            KEY_FUSERMOUNT_OPT),
        FUSE_OPT_KEY("blkdev",              KEY_FUSERMOUNT_OPT),
        FUSE_OPT_KEY("fsname=",             KEY_FUSERMOUNT_OPT),
        FUSE_OPT_KEY("subtype=",            KEY_SUBTYPE_OPT),
        FUSE_OPT_KEY("large_read",          KEY_KERN_OPT),
        FUSE_OPT_KEY("blksize=",            KEY_KERN_OPT),
        FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT),
        FUSE_OPT_KEY("max_read=",           KEY_KERN_OPT),
        FUSE_OPT_KEY("max_read=",           FUSE_OPT_KEY_KEEP),
        FUSE_OPT_KEY("user=",               KEY_MTAB_OPT),
        FUSE_OPT_KEY("-r",                  KEY_RO),
        FUSE_OPT_KEY("ro",                  KEY_KERN_FLAG),
        FUSE_OPT_KEY("rw",                  KEY_KERN_FLAG),
        FUSE_OPT_KEY("suid",                KEY_KERN_FLAG),
        FUSE_OPT_KEY("nosuid",              KEY_KERN_FLAG),
        FUSE_OPT_KEY("dev",                 KEY_KERN_FLAG),
        FUSE_OPT_KEY("nodev",               KEY_KERN_FLAG),
        FUSE_OPT_KEY("exec",                KEY_KERN_FLAG),
        FUSE_OPT_KEY("noexec",              KEY_KERN_FLAG),
        FUSE_OPT_KEY("async",               KEY_KERN_FLAG),
        FUSE_OPT_KEY("sync",                KEY_KERN_FLAG),
        FUSE_OPT_KEY("dirsync",             KEY_KERN_FLAG),
        FUSE_OPT_KEY("atime",               KEY_KERN_FLAG),
        FUSE_OPT_KEY("noatime",             KEY_KERN_FLAG),
        FUSE_OPT_KEY("-h",                  KEY_HELP),
        FUSE_OPT_KEY("--help",              KEY_HELP),
        FUSE_OPT_KEY("-V",                  KEY_VERSION),
        FUSE_OPT_KEY("--version",           KEY_VERSION),
        FUSE_OPT_END
};


static int
fuse_lib_opt_proc(void *data, const char *arg, int key,
        struct fuse_args *outargs)
{
        (void)data;
        (void)arg;
        (void)key;
        (void)outargs;

        return 1;
}


int
fuse_parse_lib_config_args(struct fuse_args* args, struct fuse_config* config)
{
        return fuse_opt_parse(args, config, fuse_lib_opts, fuse_lib_opt_proc) == 0;
}


int
fuse_is_lib_option(const char* opt)
{
        return /*fuse_lowlevel_is_lib_option(opt) ||*/
                fuse_opt_match(fuse_lib_opts, opt);
}


#if 0
struct mount_flags {
        const char *opt;
        unsigned long flag;
        int on;
};

static struct mount_flags mount_flags[] = {
        {"rw",      MS_RDONLY,      0},
        {"ro",      MS_RDONLY,      1},
        {"suid",    MS_NOSUID,      0},
        {"nosuid",  MS_NOSUID,      1},
        {"dev",     MS_NODEV,       0},
        {"nodev",   MS_NODEV,       1},
        {"exec",    MS_NOEXEC,      0},
        {"noexec",  MS_NOEXEC,      1},
        {"async",   MS_SYNCHRONOUS, 0},
        {"sync",    MS_SYNCHRONOUS, 1},
        {"atime",   MS_NOATIME,     0},
        {"noatime", MS_NOATIME,     1},
        {"dirsync", MS_DIRSYNC,     1},
        {NULL,      0,              0}
};
#endif  // 0

static void set_mount_flag(const char *s, int *flags)
{
#if 0
        int i;

        for (i = 0; mount_flags[i].opt != NULL; i++) {
                const char *opt = mount_flags[i].opt;
                if (strcmp(opt, s) == 0) {
                        if (mount_flags[i].on)
                                *flags |= mount_flags[i].flag;
                        else
                                *flags &= ~mount_flags[i].flag;
                        return;
                }
        }
        fprintf(stderr, "fuse: internal error, can't find mount flag\n");
        abort();
#endif
}

static int fuse_mount_opt_proc(void *data, const char *arg, int key,
                               struct fuse_args *outargs)
{
        struct mount_opts *mo = data;

        switch (key) {
        case KEY_ALLOW_ROOT:
                if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 ||
                    fuse_opt_add_arg(outargs, "-oallow_root") == -1)
                        return -1;
                return 0;

        case KEY_RO:
                arg = "ro";
                /* fall through */
        case KEY_KERN_FLAG:
                set_mount_flag(arg, &mo->flags);
                return 0;

        case KEY_KERN_OPT:
                return fuse_opt_add_opt(&mo->kernel_opts, arg);

        case KEY_FUSERMOUNT_OPT:
                return fuse_opt_add_opt(&mo->fusermount_opts, arg);

        case KEY_SUBTYPE_OPT:
                return fuse_opt_add_opt(&mo->subtype_opt, arg);

        case KEY_MTAB_OPT:
                return fuse_opt_add_opt(&mo->mtab_opts, arg);

        case KEY_HELP:
//              mount_help();
                mo->ishelp = 1;
                break;

        case KEY_VERSION:
//              mount_version();
                mo->ishelp = 1;
                break;
        }
        return 1;
}


int
fuse_parse_mount_config_args(struct fuse_args* args)
{
        struct mount_opts mo;
        memset(&mo, 0, sizeof(mo));

        return args == 0
                || fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == 0;
}